NicoKeyboardのスイッチ同時読み


NicoKeyboardはスイッチの同時読みに対応しているかどうかについて、お問い合わせがあったので、ココに書いておきます。
まず、ハードの説明から、、

NicoKeyboardの回路図の一部です。8x8のキーマトリックスです。
ic側の出力は8行のうち、どれか1行がLowになります。
個々のスイッチにダイオードが入っていないので、3つ以上スイッチのを
「特殊な組み合わせ」で同時に押すと誤動作します。


たとえば、↑のような状態。
Q、A、Sを同時押しすると赤い部分がLowになり、押してないはずのDが押されてしまいます。
こういうのが「特殊な組み合わせ」です。



ただし、行や列がバラバラの場合には、3つ以上同時に押しても問題ありません。
たとえば、1列全部押すとか、1行を全部押すのは問題ありません。


ここまではハードの話で、今度はソフトの話。

NicoKeyboardのソフトはちょっと機能を節約してまして、
alt、ctrl、shiftの3つだけが同時押しに対応しています。

現時点のver.7のソースの一部、スイッチの読み取り部分です。

swnum=SWNUM_NONE;
sw2num=SWNUM_NONE;
for(rownum=0; rownum<8; rownum++)
{
	if(mode==MODE_PS2)
		ps2_recvbyte();

	//1行〜8行のうち1つをLow
	if(rownum==0){
		PORTD &= ~ID_DAT;	//(74HC164)DAT
	}else{
		PORTD |= ID_DAT;	//(74HC164)DAT
	}
	timer_wait(TCNT_50US);		//50uSec
	PORTD |=  IC_CLK;	//(74HC164)CLK
	PORTD &= ~IC_CLK;	//(74HC164)CLK
    	timer_wait(TCNT_50US);		//50uSec

	for(colnum=0; colnum<8; colnum++){
		if(((0x80 >> colnum)& PINB)==0){	//Lowを検出した場合、スイッチが押された
			PORTD |= MASK_LED;	//LED
			swnum = colnum+(rownum *8);

			if(swnum <= SWNUM_SHIFT){	//Alt/Shift/Ctrlは同時押し用変数に格納
				sw2num = swnum;
				swnum = SWNUM_NONE;
			}
			PORTD &= ~MASK_LED;	//LED
		}
	}
}

sw2numとswnumにスイッチ番号が入ります。
sw2numがAlt/Shift/Ctrl同時押し用です。
それ以外はスイッチ番号の大きいほうを優先して、swnumに上書きします。
たとえば、dとsを同時に押したらsしか検出しません。

これがイヤな場合は、swnumを64個全部のスイッチ分用意すれば解決できます。
8bitx8行、8バイトのバッファがあればいいだけです。
ソースはサイトで公開していますので、改造してみてください。
あと、チャタリング除去も簡単にできるので、よかったらやってみてください。