キーボードでゲームが出来ても、実用的ではないので文字入力の仕様について考えてみます。
#define BUTTON_UP 0x0001 #define BUTTON_DOWN 0x0002 #define BUTTON_LEFT 0x0004 #define BUTTON_RIGHT 0x0008 #define BUTTON_A 0x0040 #define BUTTON_B 0x0010 #define BUTTON_C 0x0020 #define BUTTON_START 0x0080
入力がない状態を0x00と考えると、
S A C B R L D U 0 0 0 0 0 0 0 0
スタートボタンのみ押されてる状態が0x80これをENTERと解釈します。
S A C B R L D U 1 0 0 0 0 0 0 0
スタートボタンが押されていない状態で、上下左右はカーソルキーと解釈します。同様に0x00~0x7Fの範囲で、 AはDEL
S A C B R L D U 0 1 0 0 0 0 0 0
BはBACKSPACE
S A C B R L D U 0 0 0 1 0 0 0 0
CはSPACEと解釈します。
S A C B R L D U 0 0 1 0 0 0 0 0
スタートボタンとの同時押し、すなわち0x81~0xFFの範囲を0x7FでANDした値をASCIIコードとします。
#include <hidboot.h> #include <usbhub.h> // Satisfy the IDE, which needs to see the include statment in the ino too. #ifdef dobogusinclude #include <spi4teensy3.h> #endif #include <SPI.h> class KbdRptParser : public KeyboardReportParser { void PrintKey(uint8_t mod, uint8_t key); protected: void OnControlKeysChanged(uint8_t before, uint8_t after); void OnKeyDown (uint8_t mod, uint8_t key); void OnKeyUp (uint8_t mod, uint8_t key); void OnKeyPressed(uint8_t key); }; void KbdRptParser::PrintKey(uint8_t m, uint8_t key) { MODIFIERKEYS mod; *((uint8_t*)&mod) = m; Serial.print((mod.bmLeftCtrl == 1) ? "C" : " "); Serial.print((mod.bmLeftShift == 1) ? "S" : " "); Serial.print((mod.bmLeftAlt == 1) ? "A" : " "); Serial.print((mod.bmLeftGUI == 1) ? "G" : " "); Serial.print(" >"); PrintHex<uint8_t>(key, 0x80); Serial.print("< "); Serial.print((mod.bmRightCtrl == 1) ? "C" : " "); Serial.print((mod.bmRightShift == 1) ? "S" : " "); Serial.print((mod.bmRightAlt == 1) ? "A" : " "); Serial.println((mod.bmRightGUI == 1) ? "G" : " "); }; void KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key) { Serial.print("DN "); PrintKey(mod, key); uint8_t c = OemToAscii(mod, key); if (c) OnKeyPressed(c); if (key==0x52) pinMode(4, OUTPUT); // UP if (key==0x51) pinMode(5, OUTPUT); // DOWN if (key==0x50) pinMode(6, OUTPUT); // LEFT if (key==0x4F) pinMode(7, OUTPUT); // RIGHT if (key>=0x04 && key<=0x1d) { // A-Z if ((key-3) & 0x01) pinMode(4, OUTPUT); // bit 0 if ((key-3) & 0x02) pinMode(5, OUTPUT); // bit 1 if ((key-3) & 0x04) pinMode(6, OUTPUT); // bit 2 if ((key-3) & 0x08) pinMode(7, OUTPUT); // bit 3 if ((key-3) & 0x10) pinMode(14, OUTPUT); // bit 4 pinMode(15, OUTPUT); // bit 5 pinMode(8, OUTPUT); // bit 6 pinMode(16, OUTPUT); // bit 7 } if (key==0x4c) pinMode(8, OUTPUT); // DEL if (key==0x2a) pinMode(14, OUTPUT); // BS if (key==0x2c) pinMode(15, OUTPUT); // SPACE if (key==0x28) pinMode(16, OUTPUT); // ENTER } void KbdRptParser::OnControlKeysChanged(uint8_t before, uint8_t after) { MODIFIERKEYS beforeMod; *((uint8_t*)&beforeMod) = before; MODIFIERKEYS afterMod; *((uint8_t*)&afterMod) = after; if (beforeMod.bmLeftCtrl != afterMod.bmLeftCtrl) { Serial.println("LeftCtrl changed"); } if (beforeMod.bmLeftShift != afterMod.bmLeftShift) { Serial.println("LeftShift changed"); } if (beforeMod.bmLeftAlt != afterMod.bmLeftAlt) { Serial.println("LeftAlt changed"); } if (beforeMod.bmLeftGUI != afterMod.bmLeftGUI) { Serial.println("LeftGUI changed"); } if (beforeMod.bmRightCtrl != afterMod.bmRightCtrl) { Serial.println("RightCtrl changed"); } if (beforeMod.bmRightShift != afterMod.bmRightShift) { Serial.println("RightShift changed"); } if (beforeMod.bmRightAlt != afterMod.bmRightAlt) { Serial.println("RightAlt changed"); } if (beforeMod.bmRightGUI != afterMod.bmRightGUI) { Serial.println("RightGUI changed"); } } void KbdRptParser::OnKeyUp(uint8_t mod, uint8_t key) { Serial.print("UP "); PrintKey(mod, key); if (key==0x52) pinMode(4, INPUT); // UP if (key==0x51) pinMode(5, INPUT); // DOWN if (key==0x50) pinMode(6, INPUT); // LEFT if (key==0x4F) pinMode(7, INPUT); // RIGHT if (key>=0x04 && key<=0x1d) { // A-Z pinMode(4, INPUT); // bit 0 pinMode(5, INPUT); // bit 1 pinMode(6, INPUT); // bit 2 pinMode(7, INPUT); // bit 3 pinMode(8, INPUT); // bit 4 pinMode(14, INPUT); // bit 5 pinMode(15, INPUT); // bit 6 pinMode(16, INPUT); // bit 7 } if (key==0x4c) pinMode(8, INPUT); // DEL if (key==0x2a) pinMode(14, INPUT); // BS if (key==0x2c) pinMode(15, INPUT); // SPACE if (key==0x28) pinMode(16, INPUT); // ENTER } void KbdRptParser::OnKeyPressed(uint8_t key) { Serial.print("ASCII: "); Serial.println((char)key); }; USB Usb; //USBHub Hub(&Usb); HIDBoot<USB_HID_PROTOCOL_KEYBOARD> HidKeyboard(&Usb); KbdRptParser Prs; void setup() { Serial.begin( 115200 ); #if !defined(__MIPSEL__) while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection #endif Serial.println("Start"); digitalWrite(4,LOW); digitalWrite(5,LOW); digitalWrite(6,LOW); digitalWrite(7,LOW); digitalWrite(8,LOW); digitalWrite(14,LOW); digitalWrite(15,LOW); digitalWrite(16,LOW); pinMode(4, INPUT); pinMode(5, INPUT); pinMode(6, INPUT); pinMode(7, INPUT); pinMode(8, INPUT); pinMode(14, INPUT); pinMode(15, INPUT); pinMode(16, INPUT); if (Usb.Init() == -1) Serial.println("OSC did not start."); delay( 200 ); HidKeyboard.SetReportParser(0, &Prs); } void loop() { Usb.Task(); }