arduinoでPS/2キーボードのエミュレーションを行う
IchigoJam用の仮想キーボードでも作ろうと思い、
まずはarduinoでPS/2キーボードのエミュレーションを行ってみました。
まずは、上の図の感じでパソコン上でIchigoJamのキーボードをパソコンで
完全操作できるようにしてみます。
arduinoでPS/2インタフェースのキーボードやマウスを実装は、
公開されている ps2dev というライブラリを利用することで比較的簡単に実現できます。
ps2devライブラリ PS2 mouse interface for Arduino
パソコンでPS2/2キーボードとして利用する例がありました。
内容的は大変参考になりました。
また、PS/2インタフェース、JISキーボードのスキャンコード関連の情報として
下記の情報を参考にさせて頂きました。
・Sazanami Online PS/2 インターフェイスの研究
・PS/2キーボードインターフェース http://www.technoveins.co.jp/technical/keyboard/
・O-Family JIS配列 PS/2 キーボード スキャンコード表
取りあえず、動作確認の試作として
TeraTermで入力した文字をシリアル通信経由でarduinoに送信し、
その文字に対応するキーコード(スキャンコード)をPS/2インタフェースで
IchigoJamに送信するプログラムを作ってみました。
結線はこんな感じです。IchigoJamoとの接続は3線(GND,KBD1,KBD2)です。
arduinoは3.3Vで稼働させています。
KBD1、KBD2、GNDを接続
実際に動かしてみると、簡単にエミュレーションできました。
取りあえず、半角英数記号と、バックスペース、Enterキー、ESCを使えるようにしました。
全てのキーには対応していませんが、いけそうです。
これならIchigoJam BASICのINKEY()にも対応できます。ゲームパッドも作成可能です。
ps2devライブラリを見ると、LPC810にも移植可能そうです。
最終的にはLPC810を使った小型モジュール化LPC810で動かしてみたいと思います。
ただし、TeraTermではALTキーなのど特殊キーのコードを拾うのは無理なので、
Windows上でキーイベントを拾ってシリアル通信でキーコードを送信する
アプリケーションの作成も必要になりますね。
#include "ps2dev.h" #define TM_PRESS 2 // スキャンコード(A-Zのキー) uint8_t kcode[]= { 0x1c,0x32,0x21,0x23,0x24,0x2b,0x34,0x33,0x43,0x3b, 0x42,0x4b,0x3a,0x31,0x44,0x4d,0x15,0x2d,0x1b,0x2c, 0x3c,0x2a,0x1d,0x22,0x35,0x1a }; // スキャンコード(0-9のキー or '!'-')'の文字) uint8_t kcode_num[]= { 0x45,0x16,0x1e,0x26,0x25,0x2e,0x36,0x3d,0x3e,0x46 }; PS2dev keyboard(3,2); int enabled =0; int code; void ack() { while(keyboard.write(0xFA)); } int keyboardcommand(int command) { unsigned char val; switch (command) { case 0xFF: ack(); while(keyboard.write(0xAA)!=0); break; case 0xFE: // Reset: キーボードリセットコマンド。正しく受け取った場合ACKを返す。その後キーボードはセルフテストを実行する。 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/delay : 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 :キーボードが接続されている場合、キーボードはパソコンへ応答(ECHO Responce)を返す。 //ack(); keyboard.write(0xEE); break; case 0xED: //set/reset LEDs :キーボードのLEDの点灯/消灯要求。これに続くオプションバイトでLEDを指定する。 ack(); keyboard.read(&val); //do nothing with the rate ack(); break; } } void setup() { Serial.begin(115200); // send the keyboard start up while(keyboard.write(0xAA)!=0); } void loop() { unsigned char c; // PCからの送信データ uint8_t inkey; // シリアルポートからの取得文字コード uint8_t code; // シーケンスコード uint8_t shifton; // シフトキーの状態 if( (digitalRead(3)==LOW) || (digitalRead(2) == LOW)) { while(keyboard.read(&c)) ; Serial.println(c,HEX); keyboardcommand(c); } else { if (Serial.available()>0 ) { code = 0; inkey = Serial.read(); Serial.write(inkey); Serial.write(':'); Serial.println(inkey,HEX); if ( inkey >='a' && inkey <='z') { // a-zの文字 shifton = 0; code = kcode[inkey - 'a']; } else if (inkey >='A' && inkey <='Z') { // A-Zの文字 shifton = 1; code = kcode[inkey - 'A']; } else if (inkey >='0' && inkey <='9') { // 0-9の文字 shifton = 0; code = kcode_num[inkey - '0']; } else if (inkey >='!' && inkey <=')') { // '!'-')'の文字 shifton = 1; code = kcode_num[inkey - '!'+1]; } else { code = 0; shifton = 0; switch(inkey) { case 0x2d: code = 0x4e; break; // - case 0x5e: code = 0x55; break; // ^ case 0x5c: code = 0x6a; break; // \ case 0x40: code = 0x54; break; // @ case 0x5b: code = 0x5b; break; // [ case 0x3b: code = 0x4c; break; // ; case 0x3a: code = 0x52; break; // : case 0x5d: code = 0x5d; break; // ] case 0x2c: code = 0x41; break; // ] case 0x2e: code = 0x49; break; // ` case 0x2f: code = 0x4a; break; // / //case 0x5c: code = 0x51; break; // \ ' case 0x20: code = 0x29; break; // \ ' case 0x08: code = 0x66; break; // Bksp case 0x0d: code = 0x5a; break; // enter case 0x1b: code = 0x76; break; // ESC } if (!code) { shifton = 1; switch(inkey) { case 0x3d: code = 0x4e; break; // = case 0x7e: code = 0x55; break; // ~ case 0x7c: code = 0x6a; break; // | case 0x60: code = 0x54; break; // ` case 0x7b: code = 0x5b; break; // { case 0x2b: code = 0x4c; break; // + case 0x2a: code = 0x52; break; // * case 0x7d: code = 0x5d; break; // ] case 0x3c: code = 0x41; break; // } case 0x3e: code = 0x49; break; // < case 0x3f: code = 0x4a; break; // > case 0x5f: code = 0x51; break; // _ } } } // PCに押したキーのシーケンスコードを送信 if (code) { if (shifton) { keyboard.write(0x12); // シフトキーを押した } else { keyboard.write(0xF0); // シフトキーを離した keyboard.write(0x12); } keyboard.write(code); // キーを押した delay(TM_PRESS); keyboard.write(0xF0); // キーを離した keyboard.write(code); } } } }
関連記事
« Nexx WT3020FをOpenWrt化しました | トップページ | 書籍「ボクのLPC810工作ノート」届きました »
「arduino」カテゴリの記事
- Arduino IDE+Arduino STM32環境で指定と異なるgccが使われてしまう(2025.01.23)
- Zorin OSでArduino Uno互換機(CH340)が認識しない(2025.01.19)
- Arduino IDE 2.3.4でArduino STM32を利用する(2025.01.12)
- Arduino用 SKK日本語変換ライブラリの開発 その1(2024.12.28)
- NeoPixel(WS2812B)の制御 その5(2024.09.15)
「IchigoJam」カテゴリの記事
- Ichigojam Rが届きました(2021.02.05)
- β版 IchigoJam Rを予約注文しました(2021.01.23)
- IchigoJamのファームウェア 1.4.1が正式に公開されました(2019.12.10)
- 「ichigoツール」をGithubにて公開しました(2019.11.09)
- ichigojamのファームウェアを1.4b13にアップデートしました(2019.11.06)
« Nexx WT3020FをOpenWrt化しました | トップページ | 書籍「ボクのLPC810工作ノート」届きました »
コメント