Arduino PS / 2キーボードエミュレーターの問題


10

はい、Arduino.ccフォーラムとここを検索しました。はい、ps2devライブラリに関する記事を見つけました。はい、私はこのWebサイトで決定的なPS / 2インターフェイスの記事を読みました(大丈夫、一部は私が読み飛ばしました)。はい、私はこれがちょっと働いています。完全に機能するように飛躍させるためのアイデアが必要です。:)

いいえ、USB HIDキーボードをエミュレートしてそのままにすることはできません。PS/ 2キーボードエミュレーションである必要があります。はい、適切なmake信号とbreak信号を送信しています。これは、非常に複雑なキーストロークの組み合わせも処理します。現在のところ、Arduino用に記述されたコード(技術的にはFreeduino 1.22)があり、シリアルモニターまたはPuTTYターミナルを介して、および実際に送信する便利なPythonラッパー/ドライバーを使用してキーストロークを送信しましたPS / 2のスキャンコード情報-そして一般的に私の人生をずっと簡単にします-Arduinoからの負荷の一部も取り除きます。

現在、PS / 2キーボードをエミュレートするスケッチをArduinoで実行しています。当然、「ターゲット」マシン(PS / 2プラグインが入るマシン)を起動する必要があり、「ハンドシェイク」が行われているのがわかります。WinDozeを起動し、メモ帳を開き、Pythonドライバーを使用して(正常に)画面にキーストロークを入力します。(ドライバーは単にシリアルモニター/ PuTTYターミナルの代わりになり、PySerialと呼ばれるモジュールを使用してシリアルポートに読み取り/書き込みを行います。)これはすべてASUSマザーボードの「ターゲット」のAMDで行われます。

現在の目標は、Intelマザーボードベースの「ターゲット」でIntelで動作させることです。プラグインして起動し、ダイスはありません。そこで、スケッチを少し変更して、Ardyの小さな友達で実際に起こっていることを頭に上げてみます。改造後のバージョンを以下に表示します。私が理解しているように(コードは別のArduino.ccフォーラムの投稿からここに借用されました)、PS / 2を介して最初に「ターゲット」との接続を確立し、オンボードLEDを0.5秒間隔で点滅させます。接続が確立されました。Intelターゲットが.5秒の点滅を超えず、シリアル接続が「ホスト」で確立されることはありません。

私の質問はこれです:ps / 2キーボードがターゲットマシンとの通信を確立する方法に大きな違いはありますか?それは本当にデザインの違いですか、それともここで問題となっているより基本的なものを探しているのですか?データ/クロック入力にプルアップ抵抗が必要になることについて何か聞いたことがありますが、コードで処理する必要があります。特に、必要なものではなく、別のターゲットで機能しているためです。

何か案は?私はこれをできるだけ早く動作させたいと思っています。デバッグを続けます。ポインタや提案があれば、大歓迎です。私はこの問題に新鮮な目を向ける必要があるので、彼らはすべて十分に検討されます。おそらく、ps2devライブラリのより良い実装が必要ですか?

#include "ps2dev.h" // to emulate a PS/2 device

// Orange = 2
// Blue = 3
// Red = 5V (3 in)
// Black = GND (4 in)
// EXT Power, USB for COM only

PS2dev keyboard(3,2); // PS2dev object (2:data, 3:clock)
int enabled = 0; // pseudo variable for state of "keyboard"
boolean serialConnected = false;
int incomingByte = 0;

void ack() {
  //acknowledge commands
  while(keyboard.write(0xFA));
}

int kbdCmd(int command) {
  unsigned char val;
  switch (command) {
  case 0xFF: //reset
    ack();
    //the while loop lets us wait for the host to be ready
    while(keyboard.write(0xAA)!=0);
    break;
  case 0xFE: //resend
    ack();
    break;
  case 0xF6: //set defaults
    //enter stream mode
    ack();
    break;
  case 0xF5: //disable data reporting
    //FM
    enabled = 0;
    ack();
    break;
  case 0xF4: //enable data reporting
    //FM
    enabled = 1;
    ack();
    break;
  case 0xF3: //set typematic rate
    ack();
    keyboard.read(&val); //do nothing with the rate
    ack();
    break;
  case 0xF2: //get device id
    ack();
    keyboard.write(0xAB);
    keyboard.write(0x83);
    break;
  case 0xF0: //set scan code set
    ack();
    keyboard.read(&val); //do nothing with the rate
    ack();
    break;
  case 0xEE: //echo
    //ack();
    keyboard.write(0xEE);
    break;
  case 0xED: //set/reset LEDs
    ack();
    keyboard.read(&val); //do nothing with the rate
    ack();
    break;
  }
}

void connectHost() {
  while (Serial.available() <= 0) {
    Serial.print('A');   // send a capital A
    delay(300);
  }
}

void setup() {
  pinMode(13, OUTPUT);
  //establish serial connection with host
  Serial.begin(9600);
  // establish ps/2 connection with target
  while(keyboard.write(0xAA)!=0){
    digitalWrite(13, HIGH);
    delay(500); 
    digitalWrite(13, LOW);
    delay(500);
  }
  delay(100);  
  
  connectHost();
  Serial.println("\nSerial Host Connected");
  Serial.flush();
}

void loop() {
  unsigned char c;
  if( (digitalRead(3)==LOW) || (digitalRead(2) == LOW)) {
    if(digitalRead(3)==LOW){
      Serial.println("pin 3  is LOW");
    } else {
      Serial.println("pin 2 is LOW");
    }
    while(keyboard.read(&c));
    kbdCmd(c);
    Serial.print("Target: 0x");
    Serial.println(c, HEX);
  }  
  else {//if host device wants to send a command:
    //echo ASCII code from terminal and write to ps/2
    if(Serial.available() > 0) {
      incomingByte = Serial.read();
      keyboard.write(incomingByte);      
      Serial.print("Host: 0x");
      Serial.print(incomingByte, HEX);
      Serial.print(" ");
      Serial.print(incomingByte);
      Serial.print(" ");
      Serial.println(incomingByte, BIN);
    }
  }
}

いくつかの質問:「スケッチ」は「プログラム」のArduino-lingoですか?このpythonドライバーはターゲットマシンから独立していますよね?あなたの問題は、それが一方のターゲットマシンで機能し、他方では機能しないことですよね?PS / 2キーボードを接続して動作しないターゲットを起動してから、Arduinoと交換しましたか?
AndreKR

はい、Ardu-lingoのSketch ==プログラム。これを試しましたが、うまくいかなかったようです(ただし、ターゲットからのACKを待ってからキャラクターを送信しないようにスケッチを変更する必要があります)。テストする機会があったらお知らせします今日あとで。
chisaipete

だから、私はあなたが提案したようにプログラムをテストしました、そしてそれはうまくいきます!最後に、キーボードエミュレータがインストールされた状態でターゲットの電源を入れ直し、BIOS設定を変更できるようにしたいと考えています。だから、私はスタートアップハンドシェイクがオフになっていると思いますか?
chisaipete

はい、たぶん。computer-engineering.org/ps2keyboardの最下部に初期化シーケンスが表示されましたか?私のシーケンスをそれと比較することから始めます。
AndreKR 2011年

1
申し訳ありませんが、このスレッドを古くしました-AndreKRのソリューションを試す時間はありませんでした。さらに、私はプルアップ抵抗を使用していないため、プルアップ抵抗がない端を判別することは困難です:)
chisaipete

回答:


5

私が理解しているように、あなたはArduinoを2つの異なるターゲットマシンに接続し、一方は機能し、もう一方は機能しません。

したがって、2台のマシンの初期化要件には違いがあるようです。で、このページ最下部に可能な初期化シーケンスのリストがあります。まず、初期化とその初期化を比較します。

ロジックアナライザーを使用すると、はるかに簡単になります。私はIntronix Logicportを使用していますが、同時に安価ではありませんが、より優れたものもあります。

オープンコレクターのバスを利用するのは、どのデバイスが話しているのかわからないため、少し面倒です。ただし、プルアップのない端に直列抵抗を挿入すると、バスを押し下げているデバイスが電圧レベルでわかります。(PS / 2のような)すべてのオープンコレクタバスにはプルアップ抵抗が必要です。通常、それらはPCに組み込まれています。DSOでさまざまな電圧レベルを簡単に確認できます。LAだけで、異なるしきい値電圧で2回記録する必要があります。


誰が賞金を与えるかの決定は私が予想したよりも困難でしたが、あなたの回答が最も多くの票を獲得しました。私は皆に報酬を与えたでしょう!
Kortuk、2009

3

プロジェクトが1つのマザーボードで機能し、別のマザーボードでは機能しないことを考えると、プロジェクトで、場合によってはマザーボードの1つでさえ、「部分的な仕様への準拠」という古典的なケースがあるようです。しかし、ほとんどのキーボードはどのマザーボードでも機能するため、堅牢な実装は移植可能でなければなりません。課題は、自分がそうでない理由を理解する必要があることです。

あなたは問題をじっと見つめてそれがどのように機能することになっているのかを考えることでこれを行うことができるかもしれません(多分休憩の後-またはある日、答えはシャワーであなたを襲います)、あなたが監視できればより効果的です何が起こっている。スコープを意味する電気的問題については、プロトコル問題についてはロジックアナライザーです。その領域で利用できる安価なオプションがいくつかあります。たとえば、キーボードプロトコルに特定の機能を備えた「バス海賊版」ボードや、より長いキャプチャバッファーを持つ可能性のあるFPGAベースの何か(sump.orgを参照)などです。

マイクロコントローラーまたはFPGAのいずれかである別のデバイスを使用してキーボードホストを構築し、それを使用してプロジェクトを仕様の限界に向けてテストすることもできます。


2

私はps2devライブラリを調べて、それがどのように機能するかを正確に確認していませんが、1つのことが飛び飛びです。

現時点では、「ホスト」コンピュータへの接続が1回試行されます。それが失敗すると、別の試行が行われる前に、1秒間待機します(LEDが0.5秒、LEDが0.5秒オフ)。

Intelマザーボードがキーボードを検出するのに十分な時間待機していない場合は、ブートシーケンスを続行する前に接続試行が行われない可能性があります。

待機時間を0.1秒に減らす(delay(500)行をdelay(50)に変更する)と、運が良くなる可能性があります。

そうでない場合は、さらに速く試してください。地獄、遅滞なくそれを試してみて、それがどうなるか見てください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.