USBキーボードをMDにつなげてみた その2

キーボードでゲームが出来ても、実用的ではないので文字入力の仕様について考えてみます。

#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();
}