やっと最終記事です。GitHubは以下です
キーボードパーサーでNotify属性のデータ処理とPC-98へ送信
キーボードのデータ処理はほとんどがUSBのそれと一緒です。またPC-98への送信は全く一緒ですw。
USB Host Sheildのライブラリから必要な部分の処理や定義を拝借して実装を行います。Pc98BLEKbdRptParser.hpp、Pc98BLEKbdRptParser.cppで記述しています。長いのでGitHubで眺めてください。
PC-98への送信部分やブートモードの話はUSBの時に書いた通りです。もう書きたくないのでそっち読むかコードを追ってください。下にUSBの時のキーボードパーサーのリンクを入れときます。
USBの時と違うのはParse()の部分です。ちなみにBLEキーボードをたたいた時に来るデータですが、「1・ぬ」を2回押すと以下のレポートがでます。
1 2 3 4 |
Notification from dd:77:54:88:bc:2e: Service = 0x1812, Characteristic = 0x2a4d,length = 8, Value = 00 00 1e 00 00 00 00 00 Notification from dd:77:54:88:bc:2e: Service = 0x1812, Characteristic = 0x2a4d,length = 8, Value = 00 00 00 00 00 00 00 00 Notification from dd:77:54:88:bc:2e: Service = 0x1812, Characteristic = 0x2a4d,length = 8, Value = 00 00 1e 00 00 00 00 00 Notification from dd:77:54:88:bc:2e: Service = 0x1812, Characteristic = 0x2a4d,length = 8, Value = 00 00 00 00 00 00 00 00 |
8バイトのレポートですが、HIDなのでUSBキーボードと同じです。ということはUSB HostSheild Libraryのキーボードパーサーの継承元であるKeyboardReportParserのクラスのParse処理をパクればいいわけです。というわけで、Parse部分を移植しUSBHIDは不要なので削除し、必要な構造体MODIFIERKEYS,KBDINFOをhppで宣言しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
//パーサー パケ長8byte hidboot.cpp KeyboardReportParser::Parse部移植 void Pc98BLEKbdRptParser::Parse(uint8_t len __attribute__((unused)), uint8_t *buf) { // On error - return if (buf[2] == 1) return; //KBDINFO *pki = (KBDINFO*)buf; // provide event for changed control key state if (prevState.bInfo[0x00] != buf[0x00]) { OnControlKeysChanged(prevState.bInfo[0x00], buf[0x00]); } for (uint8_t i = 2; i < 8; i++) { bool down = false; bool up = false; for (uint8_t j = 2; j < 8; j++) { if (buf[i] == prevState.bInfo[j] && buf[i] != 1) down = true; if (buf[j] == prevState.bInfo[i] && prevState.bInfo[i] != 1) up = true; } if (!down) { //HandleLockingKeys(hid, buf[i]); OnKeyDown(*buf, buf[i]); } if (!up) OnKeyUp(prevState.bInfo[0], prevState.bInfo[i]); } for (uint8_t i = 0; i < 8; i++) prevState.bInfo[i] = buf[i]; }; |
98キーボードへのピンアサインに変更はないです。これでほぼ動きました。
が…3COINのクセつよキーボードのせいで以下の点で修正が必要になりました。
- 「\・ろ」キーがなんか変
- 「]・む」キーがなんか変
上のキーの位置もおかしいし、エンターが長いとか…
メチャクチャ誤入力しちゃうぜ!!
安物買いのなんとかですけど、BLEキーボードが、これしかないので進めざるえません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
#ifdef BLE_3COIN_KB //3COINキーボード \ -> YENへ if(c == 0x33 && !p_shift && !p_ctrl){ c = 0x0D; } #endif #ifdef BLE_3COIN_KB //3COINキーボード \ -> YENへ if(c == 0x33 && !p_shift && !p_ctrl){ c = 0x0D; } #endif #ifdef BLE_3COIN_KB codeArray[0x31] = 0x28; // ] ※BLE 3COINキーボードでは0x32と同じ #else codeArray[0x31] = 0xFF; // ?? #endif |
KeyDown,KeyUpの部分とcodeArray部の一部変更を行っています。あとは標準のUSBキーボードのキーコードでよさそうです。
[2024/04/29] ダイソーでBLEのフルサイズキーボードが売っていてそっちのほうが操作感はいいです。記事リンク貼っときます
マウスパーサーでNotify属性のデータ処理とPC-98へ送信
次はマウスパーサーです。マウスを動かすと以下のレポートがきます
1 2 |
Notification from dc:00:a8:2c:13:00: Service = 0x1812, Characteristic = 0x2a4d,length = 7, Value = 00 0d 00 fd ff 00 00 Notification from dc:00:a8:2c:13:00: Service = 0x1812, Characteristic = 0x2a4d,length = 7, Value = 00 08 00 fe ff 00 00 |
マウスはデータ長でチョイチョイ情報が違います。
USBのときは3byteのデータで来てましたが、今回は7byteです。USBの時も色々なマウスで試しました。7byteもありましたし、ほかの長さもありました。そんなに難しいデータ構造ではないのでパーサー部を書き直します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
bool Pc98BLEMouseReportParser::ParseMouseData(MOUSEINFO_EX &pmi,uint32_t len, uint8_t *buf){ //データ長 7byte if(len != 7) return false; //ボタン uint8_t btn = buf[0]; pmi.bmLeftButton = ((btn & 0x01) == 0x01 ) ? 1:0; pmi.bmRightButton = ((btn & 0x02) == 0x02 ) ? 1:0; pmi.bmMiddleButton = ((btn & 0x04) == 0x04 ) ? 1:0; //X方向の移動 uint8_t x_val = buf[1]; bool x_dire = (buf[2] > 0 ) ? true : false; //右向きならtrue; if(x_dire){ pmi.dX = x_val; }else{ pmi.dX = - (256 - x_val); } //Y方向の移動 uint8_t y_val = buf[3]; bool y_dire = (buf[4] > 0 ) ? true : false; //下向きならtrue; if(y_dire){ pmi.dY = y_val; }else{ pmi.dY = - (256 - y_val); } /* //スクロール uint8_t sc = buf[6]; if(sc == 0x01){ pmi.wheel = 1; }else if(sc == 0xFF){ pmi.wheel = -1; }else{ pmi.wheel = 0; } */ pmi.wheel = 0; return true; } |
とあえずこんな感じです。なんか三項演算子使わなくてもいいところがありますが戻り値アピールの為そのままにしますw。実際には下のPaeseから呼び出され各種イベントが起きるようになります。マウスが変わったときにはParseMouseDataを書き換えます。前にも書きましたが文字列処理などは重くなるので極力控えます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
void Pc98BLEMouseReportParser::Parse(uint8_t len, uint8_t *buf){ MOUSEINFO_EX pmi; bool f = ParseMouseData(pmi,len,buf); #ifdef OUTPUT_MOUSE_DATA if (len && buf) { Serial.print(F("MouseData")); Serial.print(F(": ")); for (uint8_t i = 0; i < len; i++) { if (buf[i] < 16) Serial.print(F("0")); Serial.print(buf[i], HEX); Serial.print(F(" ")); } Serial.println(""); } #endif if(!f) return; if (prev_mInfo.bmLeftButton == 0 && pmi.bmLeftButton == 1) OnLeftButtonDown(&pmi); if (prev_mInfo.bmLeftButton == 1 && pmi.bmLeftButton == 0) OnLeftButtonUp(&pmi); if (prev_mInfo.bmRightButton == 0 && pmi.bmRightButton == 1) OnRightButtonDown(&pmi); if (prev_mInfo.bmRightButton == 1 && pmi.bmRightButton == 0) OnRightButtonUp(&pmi); if (prev_mInfo.bmMiddleButton == 0 && pmi.bmMiddleButton == 1) OnMiddleButtonDown(&pmi); if (prev_mInfo.bmMiddleButton == 1 && pmi.bmMiddleButton == 0) OnMiddleButtonUp(&pmi); if(pmi.wheel != 0){ ( pmi.wheel > 0 ) ? OnScrollUp(&pmi) : OnScrollDown(&pmi); } if (pmi.dX != 0 || pmi.dY != 0) OnMouseMove(&pmi); prev_mInfo = pmi; } |
イベントの処理はUSBの時と一緒です。
テストしたPC-98はPC-9821V166(ジャンパで200Mhz動作)青札。CF、SSD換装、FDDシミュレーター(SFR1M44-U100×2)。リセットボタンがなくて色々と不満がありますが…。マウスキーボードはMiniDinの丸コネクタです。OSはWin2000、MS-DOS6、Win98SEです。
Win2000、Win98SEはコンパネのマウスで調整をしています。DOSマウスドライバを起動してDOSシェルです。ゲームも試しましたが問題なく動いています。
ガシェットはUSBの時と同じ機材を使っています。USH Host Sheildは必要ありません。もっとコンパクトにできると思います。CAPS,NumLK,カナのLEDにも対応しているつもりです。BLEのほうが安定して接続できるような気がしますね。