#define RST 4 // リセット要求 #define RDY 5 // 送信可能 #define RXD 1 // データ送信 #define RTY 6 // 再送要求 //キーボード #define DATA 8 #define CLOCK 2 // 割り込みに使用 #define BUFFER_SIZE 32 static volatile uint8_t keyBuffer[BUFFER_SIZE]; static volatile uint8_t head, tail; // PS2スキャンコード → 98キーコード const PROGMEM uint8_t onebyte[] = { 0, 0x6A, 0, 0x66, 0x64, 0x62, 0x63, 0x53, //00-07 0, 0x6B, 0x69, 0x67, 0x65, 0x0F, 0x60, 0, //08-0F 0, 0x73, 0x70, 0, 0x74, 0x10, 0x01, 0, //10-17 0, 0, 0x29, 0x1E, 0x1D, 0x11, 0x02, 0xE3, //18-1F 0, 0x2B, 0x2A, 0x1F, 0x12, 0x04, 0x03, 0xE7, //20-27 0, 0x34, 0x2C, 0x20, 0x14, 0x13, 0x05, 0x65, //28-2F 0, 0x2E, 0x2D, 0x22, 0x21, 0x15, 0x06, 0, //30-37 0, 0, 0x2F, 0x23, 0x16, 0x07, 0x08, 0, //38-3F 0, 0x30, 0x24, 0x17, 0x18, 0x0A, 0x09, 0, //40-47 0, 0x31, 0x32, 0x25, 0x26, 0x19, 0x0B, 0, //48-4F 0, 0x33, 0x27, 0, 0x1A, 0x0C, 0, 0, //50-57 0, 0x70, 0x1C, 0x1B, 0, 0x28, 0, 0, //58-5F 0, 0, 0, 0, 0x35, 0, 0x0E, 0x51, //60-67 0, 0x4A, 0x0D, 0x46, 0x42, 0, 0, 0, //68-6F 0x4E, 0x50, 0x4B, 0x47, 0x48, 0x43, 0x00, 0x3E, //70-77 0x52, 0x49, 0x4C, 0x40, 0x45, 0x44, 0x55, 0, //78-7F 0, 0, 0, 0x68, 0x46 }; //80-84 const PROGMEM uint8_t twobyte[] = { 0, 0, 0, 0, 0, 0, 0, 0, //00-07 0, 0, 0, 0, 0, 0, 0, 0, //08-0F 0, 0x73, 0xFF, 0, 0x74, 0, 0, 0, //10-17 0, 0, 0, 0, 0, 0, 0, 0x34, //18-1F 0, 0, 0, 0, 0, 0, 0, 0x56, //20-27 0, 0, 0, 0, 0, 0, 0, 0x61, //28-2F 0, 0, 0, 0, 0, 0, 0, 0, //30-37 0, 0, 0, 0, 0, 0, 0, 0, //38-3F 0, 0, 0, 0, 0, 0, 0, 0, //40-47 0, 0, 0x41, 0, 0, 0, 0, 0, //48-4F 0, 0, 0, 0, 0, 0, 0, 0, //50-57 0, 0, 0x1C, 0, 0, 0, 0, 0, //58-5F 0, 0, 0, 0, 0, 0, 0, 0, //60-67 0, 0x3F, 0, 0x3B, 0x5E, 0, 0, 0, //68-6F 0x38, 0x39, 0x3D, 0, 0x3C, 0x3A, 0, 0, //70-77 0, 0, 0x37, 0, 0x54, 0x36, 0, 0, //78-7F }; void (*keyConv[256])(); uint8_t ps2code; bool keybreak, e0code, capsON, kanaON; void setup() { pinMode(RST, INPUT); pinMode(RDY, INPUT); pinMode(RTY, INPUT); pinMode(CLOCK, INPUT_PULLUP); pinMode(DATA, INPUT_PULLUP); head = 0; tail = 0; keybreak = false; e0code = false; capsON = false; kanaON = false; // デフォルトのキー変換ルーチンのポインタ収納 for(int i=0; i<256; i++) keyConv[i] = convCode; // コード別のキー変換ルーチンのポインタ収納 keyConv[0x00] = noop; keyConv[0xAA] = noop; keyConv[0xEE] = noop; keyConv[0xFC] = noop; keyConv[0xFD] = noop; keyConv[0xFE] = noop; keyConv[0xFA] = noop; keyConv[0xFF] = noop; keyConv[0x13] = kanaLock; keyConv[0x58] = capsLock; keyConv[0xE0] = twobyteCode; keyConv[0xE1] = pauseCode; keyConv[0xF0] = keyBreak; // シリアル初期化 // 19.2kbps 8ビット 奇数パリティ ストップビット1ビット Serial.begin(19200, SERIAL_8O1); Serial.write(0); // 何故か必要(キーボードタイプの送信か?) attachInterrupt(digitalPinToInterrupt(CLOCK), keyCodeInt, FALLING); } void loop() { // PC98の状態 while(digitalRead(RDY) == HIGH) // 送信不可 delayMicroseconds(1); if(digitalRead(RTY) == LOW) // 再送要求 Serial.write(0); //ダミーデータ if(digitalRead(RST) == LOW) // リセット要求 delayMicroseconds(30); // キー入力 ps2code = getKeyCode(); (*keyConv[ps2code])(); } void convCode() // コード変換 { if(e0code) // E0コードの2バイト目 { if(keybreak) { Serial.write(pgm_read_byte(twobyte + ps2code) | 0x80); keybreak = false; } else { Serial.write(pgm_read_byte(twobyte + ps2code)); } e0code = false; } else { if(keybreak) { Serial.write(pgm_read_byte(onebyte + ps2code) | 0x80); keybreak = false; } else Serial.write(pgm_read_byte(onebyte + ps2code)); } } void twobyteCode() // 2バイト以上のコード { e0code = true; } void kanaLock() { if(keybreak) { if(kanaON) { Serial.write(0x72 | 0x80); kanaON = false; } else { Serial.write(0x72); kanaON = true; } keybreak = false; } } void capsLock() { if(keybreak) { if(capsON) { Serial.write(0x71 | 0x80); capsON = false; } else { Serial.write(0x71); capsON = true; } keybreak = false; } } void pauseCode() // Pauseキー(Breakコードが出力されない) { waitKeyin(); // 次のコードを待つ if(ps2code != 0x14) return; waitKeyin(); if(ps2code != 0x77) return; waitKeyin(); if(ps2code != 0xE1) return; waitKeyin(); if(ps2code != 0xF0) return; waitKeyin(); if(ps2code != 0x14) return; waitKeyin(); if(ps2code != 0xF0) return; waitKeyin(); if(ps2code != 0x77) return; Serial.write(0x56); delay(500); Serial.write(0x56 | 0x80); } void keyBreak() // キーリリース { keybreak = true; } void noop() // 何もしない {} // キー入力待ち void waitKeyin() { ps2code = 0xFF; while(ps2code == 0xFF) ps2code = getKeyCode(); } // キーコードのバッファからコードを取り出す static inline uint8_t getKeyCode(void) { uint8_t ret; if (head == tail) return 0xFF; ret = keyBuffer[head++]; if (head == BUFFER_SIZE) { head = 0; } return ret; } // キーボードからキーコードを受け取る(割り込みエントリ) void keyCodeInt(void) { static uint8_t past = 0; static uint8_t counter = 0; static uint8_t code; static uint8_t parity; uint8_t now, onebit, p; onebit = digitalRead(DATA); now = millis(); if (now - past > 250) counter = 0; past = now; switch (counter++) { case 0: // スタートビット code = 0; parity = 0; break; case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: code |= onebit << counter - 2; parity += onebit; break; case 9: if (onebit == (~parity & 1)) { //キーバッファにコードを入れる p = tail; keyBuffer[p++] = code; if (p == BUFFER_SIZE) p = 0; if (p == head) p = tail; else tail = p; } break; case 10: // ストップビット counter = 0; break; } }