はじめに
前回でセガサターン用キーボードの全貌が明らかになった。
今回はサターンキーボード用デコーダの作製といっても良い(よくない)。
キーコードの手打ちが厄介だったぞ。
それじゃぁいくぜ!!
前回のおさらい
サターンキーボードのキーを押す/離すとMake/Brakeがその瞬間だけ1になる。
その時キーコードも出てくる。
上図はZを押しながらXを押したときの信号。
キーコードB001001 = 0x22はXのもの。
やったことまとめ
方針
- サターンからキーボードへの入力(TR,TH)を完コピする。
- Make/Brakeが1になった時キーコードを読む。
- ライブラリに頼る。
ピンアサイン
ProMicroにはこうつなぐ。
今回THは使用していないのでオープンで良い。
VDDとGNDは勝手につないでください。
キーボードのVDDは5 Vなので3.3 VのProMicroを買っちゃダメよ。
スケッチ
Keyboardライブラリは英字用なので困った。
偉大な人がKeyboard_jpライブラリを作っておられる[1]のでそれを導入した。
ありがとうございます。
#include "Keyboard_jp.h" //pin assign const int L = 3; const int R = 4; const int TL = 5; // not used in this sketch const int TR = 6; const int TH = 7; const int U = 8; const int D = 9; int BK = 0; // 1 at brake moment only int MK = 0; // 1 at make moment only byte KC[8]; // 8bit keycode from keyboard(this is address for key map) byte CKC = B00000000; //combined KC int i; //KeyMap[address] output is UsageIndex, address is keycode from SegaSaturn const byte KM[144] = { 0x00, 0x39, 0x3e, 0x3c, 0x3a, 0x3b, 0x45, 0x00, 0x43, 0x41, 0x3f, 0x3d, 0x00, 0x2b, 0x35, 0x00, 0x00, 0xe2, 0xe1, 0x88, 0xe0, 0x14, 0x1e, 0xe6, 0xe4, 0x00, 0x1d, 0x16, 0x04, 0x1a, 0x1f, 0x00, 0x00, 0x06, 0x1b, 0x07, 0x08, 0x21, 0x20, 0x00, 0x00, 0x2c, 0x19, 0x09, 0x17, 0x15, 0x22, 0x00, 0x00, 0x11, 0x05, 0x0b, 0x0a, 0x1c, 0x23, 0x00, 0x00, 0x00, 0x10, 0x0d, 0x18, 0x24, 0x25, 0x00, 0x00, 0x36, 0x0e, 0x0c, 0x12, 0x27, 0x26, 0x00, 0x00, 0x37, 0x38, 0x0f, 0x33, 0x13, 0x2d, 0x00, 0x00, 0x87, 0x34, 0x00, 0x2f, 0x2e, 0x00, 0x00, 0x39, 0xe5, 0x28, 0x30, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x2a, 0x8b, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x49, 0x48, 0x40, 0x46, 0x4c, 0x50, 0x4a, 0x4d, 0x52, 0x51, 0x4b, 0x4e, 0x4f, 0x00, 0x00 }; //function for pulse making void dWD(int pinout, int HL, int delaytime) { if (HL == HIGH) { digitalWrite(pinout, HIGH); } else { digitalWrite(pinout, LOW); } delayMicroseconds(delaytime); } void setup() { pinMode(U, INPUT); pinMode(D, INPUT); pinMode(L, INPUT); pinMode(R, INPUT); pinMode(TL, OUTPUT); pinMode(TR, OUTPUT); pinMode(TH, OUTPUT); Keyboard.begin(); } void loop() { dWD(TH, LOW, 0); // #2 dWD(TR, HIGH, 0); // #2 dWD(TR, HIGH, 60); // #2 dWD(TR, LOW, 8); // x dWD(TR, LOW, 16); // #3 dWD(TR, HIGH, 13); // x dWD(TR, HIGH, 28); // #4 dWD(TR, LOW, 9); // x dWD(TR, LOW, 15); // #5 dWD(TR, HIGH, 11); // x dWD(TR, HIGH, 54); // #6 dWD(TR, LOW, 11); // x dWD(TR, LOW, 13); // #7 dWD(TR, HIGH, 13); // x dWD(TR, HIGH, 37); // #8 dWD(TR, LOW, 12); // x dWD(TR, LOW, 12); // #9 dWD(TR, HIGH, 13); // x dWD(TR, HIGH, 37); // #10 BK = digitalRead(U); // break check MK = digitalRead(R); // make check dWD(TR, LOW, 9); // x dWD(TR, LOW, 15); // #11 if (MK == HIGH || BK == HIGH) { KC[7] = digitalRead(R); // getting keycode from D7-D4 KC[6] = digitalRead(L); KC[5] = digitalRead(D); KC[4] = digitalRead(U); } dWD(TR, HIGH, 14); // x dWD(TR, HIGH, 41); // #12 if (MK == HIGH || BK == HIGH) { KC[3] = digitalRead(R); // getting keycode from D3-D0 KC[2] = digitalRead(L); KC[1] = digitalRead(D); KC[0] = digitalRead(U); } dWD(TR, LOW, 13); // x dWD(TR, LOW, 11); // #13 dWD(TR, LOW, 14); // x dWD(TR, HIGH, 125); // #14 dWD(TH, HIGH, 0); // end & #1 if (MK == HIGH) { for (i = 0; i < 8; i++) { CKC += KC[i] << i; // combining 1bit discrete keycodes to 8bit keycode } Keyboard.pressRaw(KM[CKC]); //press check } else if (BK == HIGH) { for (i = 0; i < 8; i++) { CKC += KC[i] << i; // combining 1bit discrete keycodes to 8bit keycode } Keyboard.releaseRaw(KM[CKC]); // release check } MK = 0; BK = 0; CKC = B00000000; delay(16); delayMicroseconds(600); }
loop内でTRとTHを変化させて信号を作る。
スケッチ内の#2とかは下の信号番号に対応しているぞ。
#10のR/UがMake(MK)/Brake(BK)に対応してるのでそれを読む。
#11でKeyCode(KC)の頭4ビット
#12でおしり4ビットを読む。
dWD(pinout, HL, delaytime)は見やすさのために作った。
[pinout]を[HL]状態にした後[delaytime] microseconds待つという関数。
これ見やすいか?
loopの終わりでMK or BK = 1の場合のみ何押したか判定を行う。
その際KeyMap(KM[KeyCode])を使う。
サターンからのキーコードをUsageIndexにするためのものです。
Keyboardライブラリを使う場合ASCIIコードでpress/release判定を行う。
今回はKeyboard_jpライブラリでKeyboard.pressRaw/releaseRawを使う。
そのため引数がUsageIndexになっている[1]。注意してください。
最後の16.6 msのdelayはサターン実機がそのくらいだからいれた。
どのくらい早くできるかはわかんないゾ。
暇人はやってみてね。
苦労話
キーコードを1bitでとってきてるので8bitに結合しなきゃいけなかった。
「powでいけるッショ」と思った。
でも誤差が狂ったように出ていけなかった。
何でですかね?
だからビットシフトで2倍にして足したぞ。
ちょっとデジタル知ってる感出してイキりたかったわけではないぞ。
まとめ
サターンのキーボードがPCで動いてみんなうれしいだろう?
普通に打てるから私はビビっておしっこもらしました。
みんなもSEGAのキーボードを机の上においてイキろう!!!!!
参考
[1] Arduino Leonardoで\記号を打つ:メガギガテラス:So-netブログ
ありがとうございました。これがないとヤバかったです。
おまけ
keymap用表
キー名の下がUsageIndexになっている。
もしくはこれをエクセルかなんかで開こう。
,0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F, 00,,F9,F5,F3,F1,F2,F12,,F10,F8,F6,F4,,tab,hankaku,,,,,,,,,,,,,,,,, ,0x00,0x39,0x3e,0x3c,0x3a,0x3b,0x45,0x00,0x43,0x41,0x3f,0x3d,0x00,0x2b,0x35,0x00, 10,,alt,shit,katakana,ctrl,Q,1,alt,ctrl,,Z,S,A,W,2,,,,,,,,,,,,,,,,, ,0x00,0xe2,0xe1,0x88,0xe0,0x14,0x1e,0xe6,0xe4,0x00,0x1d,0x16,0x04,0x1a,0x1f,0x00, 20,,C,X,D,E,4,3,,,space,V,F,T,R,5,,,,,,,,,,,,,,,,, ,0x00,0x06,0x1b,0x07,0x08,0x21,0x20,0x00,0x00,0x2c,0x19,0x09,0x17,0x15,0x22,0x00, 30,,N,B,H,G,Y,6,,,,M,J,U,7,8,,,,,,,,,,,,,,,,, ,0x00,0x11,0x05,0x0b,0x0a,0x1c,0x23,0x00,0x00,0x00,0x10,0x0d,0x18,0x24,0x25,0x00, 40,,<,K,I,O,0,9,,,>,?,L,;,P,-,,,,,,,,,,,,,,,,, ,0x00,0x36,0x0e,0x0c,0x12,0x27,0x26,0x00,0x00,0x37,0x38,0x0f,0x33,0x13,0x2d,0x00, 50,,_,:,,@,^,,,capsl,shift,enter,[,,],,,,,,,,,,,,,,,,,, ,0x00,0x87,0x34,0x00,0x2f,0x2e,0x00,0x00,0x39,0xe5,0x28,0x30,0x00,0x31,0x00,0x00, 60,,,,,henkan,,back,muhenkan,,,bslash,,,,,,,,,,,,,,,,,,,,, ,0x00,0x00,0x00,0x00,0x8a,0x00,0x2a,0x8b,0x00,0x00,0x89,0x00,0x00,0x00,0x00,0x00, 70,,,,,,,esc,,F11,,,,,,scrl,,,,,,,,,,,,,,,,, ,0x00,0x00,0x00,0x00,0x00,0x00,0x29,0x00,0x44,0x00,0x00,0x00,0x00,0x00,0x47,0x00, 80,,ins,pause,F7,print,del,left,home,end,up,down,pup,pdown,right,,,,,,,,,,,,,,,,,, ,0x00,0x49,0x48,0x40,0x46,0x4c,0x50,0x4a,0x4d,0x52,0x51,0x4b,0x4e,0x4f,0x00,0x00,
つなぐヤツの外装
こじゃれた外装でライバルに差をつけろ!!
おうちにある余った箱で激エモなヤツをつくろう!!
出来たらみせてね。
中身
キーボード比較コーナー
SEGAのキーボードとREALFORCEを並べてみた。
外見上の違いはテンキー、Windowsキー、アプリケーションキーがないこと。
それ以外は似ている。もうどっちがREALFORCEか私にはわかんないよ。
タイプした感じはSEGAFORCEのほうがデカい音を発する。
スコスコ感があるためタイプ時の爽快感が非常によろしい。
おわり