CH9329 でPS/2キーボードをUSBキーボードとして現役復帰

>

PS/2Keyboard_CH9329
<前回、CH9329をモジュール化して、シリアル入力からUSBのキー入力ができるようになったので、これにPS/2キーボードをつないでUSBキーボードとして使えるようにしてみました。
PS/2キーボードのデータの読み取りは、こちらのサイトを参考にさせていただき、ほとんどそのまま使わせて頂いています。
説明も詳しく、キーボードのLEDも点灯できて、とても助かりました。
okiraku-camera.tokyo
接続は、PS/2キーボード→5v/3.3vレベル変換→ATOM Lite→CH9329→USB/PC の順で、
間にATOM Liteをかましていますが、オーバースペックだし、3.3Vなので、5Vからの変換も必要なので、ゆくゆくは、PICかAVRのようなマイコンに置き換えようと思っています。5Vのマイコンを使えば、レベル変換もいらなくなりますしね。
接続のピンは、以下のような感じ。

モジュール間の接続ピン

レベル変換は、FETで以下のような回路を組んでいます。 
レベル変換も、CH9329も安いモジュールが沢山出ているから、それらを利用してもいいですね。

レベル変換

ATOM Liteのスケッチは、前述のPS/2のキーコードを受け取り、受け取ったデータに応じて該当するコードに変換してシリアルでCH9329に送るだけです。
一応、手持ちのキーボードでは、全部のキーコードがカバーできていると思います。


スペルミスは、ご愛敬ということで…。

以下、ATOM Liteのスケッチ。(余計なコードやら、エラーがあるかもしれませんがとりあえず、こんな感じ…。)
お決まりのお約束ですが、追試される方は、自己責任で…。よろしく

#define TXPIN       19
#define RXPIN       22
#define PS2_DATA    21
#define PS2_CLK     25
#define CLK_INT     25
#define LED         23

void show_error(int ms) {
  digitalWrite(LED, 1);
  delay(ms);
  digitalWrite(LED, 0);
  delay(ms);
}

static const uint8_t KBD_BUFFER_SIZE = 12;
volatile uint8_t kbd_in, kbd_out;
uint8_t kbd_buffer[KBD_BUFFER_SIZE];  //  fifo key buffer

void clear_buffer() {
  cli();
  kbd_in = kbd_out = 0;
  sei();
}

bool put_buffer(uint8_t s) {
  uint8_t rx = kbd_in + 1;
  if (rx >= KBD_BUFFER_SIZE) rx = 0;
  if (rx == kbd_out) return false; // buffer is full.
  kbd_buffer[kbd_in] = s;
  kbd_in = rx;
  return true;
}

uint8_t get_buffer() {
  if (kbd_in == kbd_out) return 0;  // empty.
  uint8_t s = kbd_buffer[kbd_out];
  cli();
  if (++kbd_out >= KBD_BUFFER_SIZE) kbd_out = 0;
  sei();
  return s;
}

uint8_t cmd_to_send;

typedef enum { None = 0, Idle, Receiving, WaitForStart, Sending }  bus_state_t;
volatile bus_state_t bus_state;

void  clk_interrupt() {
  volatile static uint8_t data = 0;
  volatile static uint8_t clocks = 0;
  volatile static uint8_t par = 0;
  switch (bus_state) {
    case Idle:
      clocks = 0;
      data = 0;
      digitalWrite(LED, 1);
      bus_state = Receiving; // found Start bit
      break;
    case Receiving:
      clocks++;
      if (clocks < 9) {
        data = data >> 1 | (digitalRead(PS2_DATA) ? 0x80 : 0);
        if (clocks == 8)   // パリティとストップビットは無視。
          put_buffer(data); // とりあえずバッファフルは見ない。
      } else if (clocks == 10) {    // STOP bit.
        bus_state = Idle;
        digitalWrite(LED, 0);
      }
      break;
    case WaitForStart:   // Start bit will be fetched. (DATA is LOW)
      par = 0;
      clocks = 0;
      data = cmd_to_send;
      bus_state = Sending;
      break;
    case Sending:
      clocks++;
      if (clocks == 9)  // parity
        digitalWrite(PS2_DATA, par & 1 ? LOW : HIGH);
      else if (clocks == 10)  // STOP bit timing.
        pinMode(PS2_DATA, INPUT); // release DATA
      else if (clocks == 11)  // ACK bit from keyboard.
        bus_state = Idle;
      else if (clocks > 0 && clocks < 9) {  // send data bits.
        if (data & 1) {
          digitalWrite(PS2_DATA, HIGH);
          par++;
        } else
          digitalWrite(PS2_DATA, LOW);
        data = data >> 1;
      }
      break;
  }
}

bool send_command(uint8_t cmd, uint8_t resp_count = 1, uint8_t* resp = 0) {
  int timeout = 15;
  unsigned long start = millis();
  while (bus_state != Idle && millis() - start < timeout)
    delayMicroseconds(200);
  clear_buffer();
  cmd_to_send = cmd;
  bus_state = WaitForStart;
  pinMode(PS2_CLK, OUTPUT);  //
  digitalWrite(PS2_CLK, 0);  // drive LOW.
  delayMicroseconds(100);    // at least 100usec.
  pinMode(PS2_DATA, OUTPUT);  // drive LOW (START bit)
  digitalWrite(PS2_DATA , 0);
  delayMicroseconds(50);
  pinMode(PS2_CLK, INPUT);  // release clock. CLK goes to HIGH.

  start = millis();
  while (bus_state != Idle && millis() - start < timeout)
    delayMicroseconds(100);

  uint8_t ret = 0;
  for (int8_t i = 0; i < resp_count; i++) {
    char tmp[20];
    start = millis();
    if (cmd == 0xff && i == 1)
      timeout = 500;  // for Basic Assuarance Test.
    while ((ret = get_buffer()) == 0 && millis() - start < timeout) // タイムアウトチェックする
      ;
    if (resp)
      resp[i] = ret;
    sprintf(tmp, "cmd=%02X, resp=%02X", cmd, ret);
    Serial.println(tmp);
  }
  return (ret == 0xfa);
}

bool kbd_reset() {
  uint8_t tmp[2];
  send_command(0xff, 2, tmp); // reset keyboard.
  if (tmp[0] == 0xfa && tmp[1] == 0xaa)
    return true;
  return false;
}

#define PS2_LED_CAPSLOCK  4
#define PS2_LED_NUMLOCK   2
#define PS2_LED_SCRLOCK   1

uint8_t kbd_led_state = 0;
bool kbd_led(uint8_t led) {
  bool f = send_command(0xed); // LED
  if (f) {
    kbd_led_state = led;
    send_command(led); // LED parameter.
  } else
    kbd_reset();
  return f;
}

void toggle_led(uint8_t led) {
  uint8_t new_led = kbd_led_state;
  if (new_led & led)  new_led &= ~led;
  else                new_led |= led;
  kbd_led(new_led);
}

const uint8_t pattern[] = {0, 2, 4, 1, 0, 1, 4, 2, 0, 2, 6, 7, 5, 1, 0, 7};
void led_demo() {
  kbd_reset();
  delay(50);
  for (int j = 0; j < 5; j++) {
    for (uint8_t i = 0; i < sizeof(pattern); i++) {
      kbd_led(pattern[i] & 7);
      delay(200);
    }
  }
  kbd_led(0);
}

void sendKeyPacket(uint8_t ckey, uint8_t ukey) {
  uint8_t sum      = 0x10C + ckey + ukey;
  uint8_t packet[14] = {0x57, 0xAB, 0x00, 0x02, 0x08, ckey, 0x00,
              ukey, 0x00, 0x00, 0x00, 0x00, 0x00, sum};
  for(int i = 0; i < 14; i++) {
    Serial2.write(packet[i]);
  }
}

void press1key(uint8_t ckey, uint8_t ukey) {
  sendKeyPacket(ckey, ukey);
  //  __delay_ms(1);
  sendKeyPacket(0x00, 0x00);
}

void setup() {
  Serial.begin(115200);
  delay(100);
  Serial.println("CH9329_PS2_Kyboard converter");
  Serial2.begin(9600, SERIAL_8N1, RXPIN, TXPIN);
  pinMode(LED, OUTPUT);
  digitalWrite(LED, 0);
  pinMode(PS2_DATA, INPUT);
  pinMode(PS2_CLK, INPUT);
  attachInterrupt(CLK_INT, clk_interrupt, FALLING);
  delay(50);
  if (!kbd_reset())
    show_error(300);
  toggle_led(PS2_LED_NUMLOCK);
}

  uint8_t pckey = 0x00;

void loop() {
  uint8_t scan_code = get_buffer();
  static bool e0_prefix = false;
  static bool f0_prefix = false;
  static bool e1_prefix = false;
  
  if (scan_code) {
    char tmp[20];
    sprintf(tmp, "%02X ", scan_code);
    Serial.println(tmp);
    switch(scan_code) {
      case 0x1C :                 //a
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x04);
        break;
      case 0x32 :                 //b
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x05);
        break;
      case 0x21 :                 //c
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x06);
        break;
      case 0x23 :                 //d
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x07);
        break;
      case 0x24 :                 //e
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x08);
        break;
      case 0x2B :                 //f
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x09);
        break;
      case 0x34 :                 //g
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x0A);
        break;
      case 0x33 :                 //h
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x0B);
        break;
      case 0x43 :                 //i
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x0C);
        break;
      case 0x3B :                 //j
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x0D);
        break;
      case 0x42 :                 //k
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x0E);
        break;
      case 0x4B :                 //l
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x0F);
        break;
      case 0x3A :                 //m
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x10);
        break;
      case 0x31 :                 //n
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x11);
        break;
      case 0x44 :                 //o
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x12);
        break;
      case 0x4D :                 //p
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x13);
        break;
      case 0x15 :                 //q
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x14);
        break;
      case 0x2D :                 //r
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x15);
        break;
      case 0x1B :                 //s
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x16);
        break;
      case 0x2C :                 //t
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x17);
        break;
      case 0x3C :                 //u
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x18);
        break;
      case 0x2A :                 //v
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x19);
        break;
      case 0x1D :                 //w
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x1A);
        break;
      case 0x22 :                 //x
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x1B);
        break;
      case 0x35 :                 //y
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x1C);
        break;
      case 0x1A :                 //z
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x1D);
        break;
      case 0x16 :                 //1
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x1E);
        break;
      case 0x1E :                 //2
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x1F);
        break;
      case 0x26 :                 //3
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x20);
        break;
      case 0x25 :                 //4
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x21);
        break;
      case 0x2E :                 //5
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x22);
        break;
      case 0x36 :                 //6
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x23);
        break;
      case 0x3D :                 //7
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x24);
        break;
      case 0x3E :                 //8
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x25);
        break;
      case 0x46 :                 //9
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x26);
        break;
      case 0x45 :                 //0
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x27);
        break;
      case 0x4E :                 //-
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x2D);
        break;
      case 0x55 :                 //^
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x2E);
        break;
      case 0x6A :                 // back slash
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x89);
        break;
     case 0x54 :                 //@
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x2F);
        break;
     case 0x5B :                 //[
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x30);
        break;
     case 0x4C :                 //;
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x33);
        break;
     case 0x52 :                 //:
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x34);
        break;
     case 0x5D :                 //]
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x31);
        break;
     case 0x41 :                 //,
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x36);
        break;
     case 0x49 :                 //.
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x37);
        break;
     case 0x4A :                 ///
        if(!f0_prefix) { 
          if(!e0_prefix)
            sendKeyPacket(pckey, 0x38);
           else
            sendKeyPacket(pckey, 0x54);
        }
        break;
     case 0x51 :                 // back slash
        if(!f0_prefix) 
          sendKeyPacket(pckey, 0x87);
        break;
     case 0x29 :                 //Space
        if(!f0_prefix) 
          sendKeyPacket(pckey, 0x2C);
        break;
      case 0x76 :                 //ESC
        if(!f0_prefix) 
          sendKeyPacket(pckey, 0x29);
        break;
// Function Key
     case 0x05 :                 //F1
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x3A);
        break;
     case 0x06 :                 //F2
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x3B);
        break;
     case 0x04 :                 //F3
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x3C);
        break;
     case 0x0C :                 //F4
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x3D);
        break;
     case 0x03 :                 //F5
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x3E);
        break;
     case 0x0B :                 //F6
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x3F);
        break;
     case 0x83 :                 //F7
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x40);
        break;
     case 0x0A :                 //F8
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x41);
        break;
     case 0x01 :                 //F9
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x42);
        break;
     case 0x09 :                 //F10
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x43);
        break;
     case 0x78 :                 //F11
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x44);
        break;
     case 0x07 :                 //F12
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x45);
        break;

// Ten Key
     case 0x70 :                 //0
        if(!f0_prefix) {
          if(!e0_prefix)
            sendKeyPacket(pckey, 0x62);
          else 
            sendKeyPacket(pckey, 0x49); //Insert
        }
        break;
     case 0x69 :                 //1
        if(!f0_prefix) {
          if(!e0_prefix)
            sendKeyPacket(pckey, 0x59);
          else 
            sendKeyPacket(pckey, 0x4D);   //End
        }
        break;
     case 0x72 :                 //2
        if(!f0_prefix) {
          if(!e0_prefix)
            sendKeyPacket(pckey, 0x5A);
          else 
            sendKeyPacket(pckey, 0x51);   //Down
        }
        break;
     case 0x7A :                 //3
        if(!f0_prefix) {
          if(!e0_prefix)
            sendKeyPacket(pckey, 0x5B);
          else 
            sendKeyPacket(pckey, 0x4E);   //PgDn
        }
        break;
     case 0x6B :                 //4
        if(!f0_prefix) {
          if(!e0_prefix)
            sendKeyPacket(pckey, 0x5C);
          else 
            sendKeyPacket(pckey, 0x50);   //Left
        }
        break;
     case 0x73 :                 //5
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x5D);
        break;
     case 0x74 :                 //6
        if(!f0_prefix) {
          if(!e0_prefix)
            sendKeyPacket(pckey, 0x5E);
          else 
            sendKeyPacket(pckey, 0x4F);   //Right
        }
       break;
     case 0x6C :                 //7
        if(!f0_prefix) {
          if(!e0_prefix)
            sendKeyPacket(pckey, 0x5F);
          else 
            sendKeyPacket(pckey, 0x4A);   //Home
        }
        break;
     case 0x75 :                 //8
        if(!f0_prefix) {
          if(!e0_prefix)
            sendKeyPacket(pckey, 0x60);
          else 
            sendKeyPacket(pckey, 0x52);   //Up
        }
        break;
     case 0x7D :                 //9
        if(!f0_prefix) {
          if(!e0_prefix)
            sendKeyPacket(pckey, 0x61);
          else 
            sendKeyPacket(pckey, 0x4B);   //PgUp
        }
        break;
     case 0x71 :                 //.
        if(!f0_prefix) {
          if(!e0_prefix) 
            sendKeyPacket(pckey, 0x63);
          else 
            sendKeyPacket(pckey, 0x4C);   //Delete
        }
        break;
     case 0x7C :                 //*
        if(!f0_prefix) {
          if(!e0_prefix) 
            sendKeyPacket(pckey, 0x55);
          else 
            sendKeyPacket(pckey, 0x46);   //Prt Sc
        }
        break;
     case 0x7B :                 //-
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x56);
        break;
     case 0x79 :                 //+
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x57);
        break;
     case 0x77 :                 //NumLk
        if(!f0_prefix && !e1_prefix) 
        sendKeyPacket(pckey, 0x53);
        break;
     case 0x7E :                 //Scr Lk
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x47);
        break;

        
//other Key
     case 0x58 :                 //CAPS
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x39);
        break;
      case 0x0E :                //半角全角
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x35);
        break;
      case 0x0D :                 //Tab
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x2B);
        break;
      case 0x5A :                //Enter
        if(!f0_prefix) {
          if(!e0_prefix)
            sendKeyPacket(pckey, 0x28);
          else
            sendKeyPacket(pckey, 0x58);
        }
        break;
      case 0x66 :                //BackSpace
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x2A);
        break;
      case 0x1F :                //L_Win
        if(!f0_prefix) {
          if(e0_prefix) 
            sendKeyPacket(pckey, 0xE3);
            pckey = pckey | 0x08;   //L_Win
        }
        else {
          pckey = 0;
        }
        break;
      case 0x27 :                //R_Win
        if(!f0_prefix) {
          if(e0_prefix) 
            sendKeyPacket(pckey, 0xE7);
            pckey = pckey | 0x08;   
        }
        else {
          pckey = 0;
        }
        break;
      case 0x67 :                 //無変換
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x8B);
        break;
      case 0x64 :                 //変換
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x8A);
        break;
      case 0x13 :                 //カタひらローマ
        if(!f0_prefix) 
        sendKeyPacket(pckey, 0x88);
        break;
      case 0x2F :                //Application
        if(!f0_prefix) {
          if(e0_prefix) 
            sendKeyPacket(pckey, 0x65);
        }
        break;
      case 0xE1 :                //Pause
        if(!f0_prefix) {
            sendKeyPacket(pckey, 0x48);
        }
        break;
 
        
//Special Key
      case 0x12 :                 //L_shift
        if(!f0_prefix) {
          if(!e0_prefix)
            pckey = pckey | 0x02;
        }
         else
          pckey = 0;
        break;
      case 0x59 :                 //R_Shift
        if(!f0_prefix) 
        pckey = pckey | 0x20;
         else
          pckey = 0;
        break;
      case 0x14 :   
        if(!e1_prefix){              
        if(!f0_prefix) {
          if(!e0_prefix)
            pckey = pckey | 0x01;   //L_Ctrl
          else
            pckey = pckey | 0x10;   //R_Ctrl
        }
        else {
          pckey = 0;
        }
        }
        break;  
      case 0x11 :                 
        if(!f0_prefix) {
          if(!e0_prefix)
            pckey = pckey | 0x04;   //L_Alt
          else
            pckey = pckey | 0x40;   //R_Alt
        }
        else {
          pckey = 0;
        }
        break;  
         
     
     case 0xf0 :               //Key Release
        f0_prefix = true;
        sendKeyPacket(0x00, 0x00);
        break;

    }
   
    if (scan_code == 0xf0)
      f0_prefix = true;
    else if (scan_code == 0xe0)
      e0_prefix = true;
    else if (scan_code == 0xe1){
      e1_prefix = true;
      uint8_t scan_code = get_buffer();
      if (scan_code) {
        sprintf(tmp, ": %02X : ", scan_code);
        Serial.println(tmp);
      }
    }
    else if (!f0_prefix && !e0_prefix && !e1_prefix) { // LED.
      if (scan_code == 0x77 )  // Num Lock
        toggle_led(PS2_LED_NUMLOCK);
      else if (scan_code == 0x58) // CAPS
        toggle_led(PS2_LED_CAPSLOCK);
      else if (scan_code == 0x7E) // SCROLL
        toggle_led(PS2_LED_SCRLOCK);
      //else if (scan_code == 0x77) // Num Lock
        //led_demo();
    }
    if (scan_code != 0xe0 && scan_code != 0xf0 && scan_code != 0xe1) {
      if (e0_prefix) e0_prefix = false;
      if (f0_prefix) f0_prefix = false;
      if (e1_prefix && scan_code == 0x77) e1_prefix = false;
    }
  }
}