前書き
自作キーボード作成のために、入力された複数のスイッチのON/OFFを1つの入力で受ける必要がある。(74HC595でマトリクスのY軸を1ピンだけで実現しており、折角なのでX軸側も同じ仕組みを使いたかった)
目的
前回の調査に従い、SC(入力/シフト)、SL(入力保持)の動作を確認する。
わかったこと
-
読み取るときはSLピンをLOWにし、読み取らないときはHIGHにしておく
-
出力(QH)ピンはHピンの内容が出力されるため、入力の全てを保持する場合は、LastInFastOutでデータを保持しないといけない。
-
TC74HC595にあったSCLRピンがない(後述)
-
シフトすると、SIの入力が先頭ビット列に入ってくる。TC74HC595のように、シグナルだけでは単純にビット列をぐるぐる回す事はできない。1
SIが0だった場合…
SI=0 bit_array=10010101 QH=1 //初期状態
SI=0 bit_array=01001010 QH=0 //1bitシフト1回目
〜
SI=0 bit_array=00000010 QH=0 //1bitシフト6回目
SI=0 bit_array=00000001 QH=1 //1bitシフト7回目
SI=0 bit_array=00000000 QH=0 //2週目 -
SIの入力だけは常に受け付ける。そのため、常時QHからSIに通電するように経路を立てておけば、ぐるぐるビット列は回せる事は可能
-
ShiftIN関数はあまり使えないぽい
キーボード制作に向けて
なので、8ビット分のパラレル入力を獲得したい場合は、
SL(LOW)⇨入力ビット列準備⇨SL(HIGH)⇨CK⇨読み取り⇨CK⇨読み取り⇨CK⇨読み取り⇨CK⇨読み取り⇨CK⇨読み取り⇨CK⇨読み取り⇨CK⇨読み取り
とめんどくさい事をしなければいけないが、実は
ShiftIn関数というものがあるらしい。
byte incoming = shiftIn(dataPin, clockPin, bitOrder)
8ビットシフトインとのことなので、104キーボードを作りたいキーマトリクスを準備する場合は、ShiftInを二回実行する必要がありそう。
こちらが丁寧に説明されています。
http://easylabo.com/2015/04/arduino/8339/
ShifIn関数を試した
手作りでビットを回すより、ShiftIn関数を利用したほうがいいのかなと思い、ShiftIn関数のリターンを確認した。
そもそも、MSBFIRSTとLSBFIRSTという言葉と、「まずclockPinがHIGHになり、dataPinから次のビットが読み込まれ、clockPinがLOWに戻ります。」という仕組みを正しく理解するため動作確認した。
前述を踏まえ、ビットの動きが分かりそうなソースを組んだ。(が、検証結果を編集の過程で紛失した…orz)
ソースの結果からわかった事は下記の通り。(事実ベースだが、この考察結果が正しいのか、かなり自信がない)
- リターンは、入力の状態の「1bitシフト後」が返ってくる
- MSBFIRST 右に1ビットシフトしたものを読み、「A~Hの入力順を反転したリターン」を返す
- LSBFIRST 右に1ビットシフトしたものをそのまま読み取ったリターンを返す
- リターン値はビット列のため、先頭ビットが0の場合、入力した桁数に対して足りなくなることがある。(リターンが「00000010」の場合、先頭の0が落ちる。Serial.printだと2が返ってくる)
- 8bitシフトしかしないので、65キー以上のキーを使用したい場合、ShiftIN関数を二回続けないといけない。(8×8の正方形キーマトリクスを単純に大きくした場合の事、入力の判定を8つ以内に抑えればこれでもいいかもしれない。)
こういうパターンならOKかも。
出力A ++++++++
出力B ++++++++
~
出力I ++++++++
出力J ++++++++
入力 12345678
結局、SLピンは制御しないといけないし、「1bitシフトしたもの」が出力になるので、キーマトリクスの入力捜査は向いてないのかもしれない。
Serial.print("input=");
Serial.println("10000000");
setInput("10000000");
Serial.println(shiftIn(input,SCKPin,MSBFIRST));
setInput("10000000");
Serial.println(shiftIn(input,SCKPin,MSBFIRST),BIN);
setInput("10000000");
Serial.println(shiftIn(input,SCKPin,LSBFIRST));
setInput("10000000");
Serial.println(shiftIn(input,SCKPin,LSBFIRST),BIN);
Serial.print("input=");
Serial.println("00000001");
setInput("00000001");
Serial.println(shiftIn(input,SCKPin,MSBFIRST));
setInput("00000001");
Serial.println(shiftIn(input,SCKPin,MSBFIRST),BIN);
setInput("00000001");
Serial.println(shiftIn(input,SCKPin,LSBFIRST));
setInput("00000001");
Serial.println(shiftIn(input,SCKPin,LSBFIRST),BIN);
Serial.print("input=");
Serial.println("00000010");
setInput("00000010");
Serial.println(shiftIn(input,SCKPin,MSBFIRST));
setInput("00000010");
Serial.println(shiftIn(input,SCKPin,MSBFIRST),BIN);
setInput("00000010");
Serial.println(shiftIn(input,SCKPin,LSBFIRST));
setInput("00000010");
Serial.println(shiftIn(input,SCKPin,LSBFIRST),BIN);
Serial.print("input=");
Serial.println("10100000");
setInput("01010000");
Serial.println(shiftIn(input,SCKPin,MSBFIRST));
setInput("01010000");
Serial.println(shiftIn(input,SCKPin,MSBFIRST),BIN);
setInput("010100000");
Serial.println(shiftIn(input,SCKPin,LSBFIRST));
setInput("010100000");
Serial.println(shiftIn(input,SCKPin,LSBFIRST),BIN);
TC74HC165確認ソース
int input=0;
int SLPin=4;
int SCKPin=3;
int BitA=6;
int BitB=7;
int BitC=8;
int BitD=9;
int BitE=10;
int BitF=11;
int BitG=12;
int BitH=13;
String inputArray=("10001010");
String tmp="dummy";
void setup() {
Serial.begin(9600);
pinMode(BitA, OUTPUT);
pinMode(BitB, OUTPUT);
pinMode(BitC, OUTPUT);
pinMode(BitD, OUTPUT);
pinMode(BitE, OUTPUT);
pinMode(BitF, OUTPUT);
pinMode(BitG, OUTPUT);
pinMode(BitH, OUTPUT);
pinMode(input, INPUT);
pinMode(SLPin, OUTPUT);
pinMode(SCKPin, OUTPUT);
}
void loop() {
delay(1000);
Serial.print("input=");
Serial.println(inputArray);
setInput(inputArray);
printOut("first");
printOut("2nd");
printOut("3rd");
printOut("4th");
printOut("5th");
printOut("6th");
printOut("7th");
printOut("last");
//while(1); //block repeat
}
//TC74HC165の出力
void printOut(String guide){
String outPutData="";
for(int i=0;i<8;i++){
outPutData = String(outPutData + digitalRead(input));
Serial.println(digitalRead(input));
putSCK();
}
Serial.print(guide);
Serial.print("=");
Serial.print(outPutData);
Serial.println();
delay(1000);
}
//SCK信号送出
void putSCK(){
digitalWrite(SCKPin,LOW);
digitalWrite(SCKPin,HIGH);
}
//インプット設定ピンの調整
//2回使うので別関数に切り出した
void setInput(String inputArray){
//LOWはinputを有効にする
digitalWrite(SLPin,LOW);
//インプットの桁数だけ繰り返す
for(int i=0;i<inputArray.length();i++){
//インプットのi桁数が1のとき、インプット用ピンをHIGHにする
//インプット用ピンは6から始まるので、i+6がインプット用ピン位置。
tmp=inputArray[i];
if(tmp.equals("1")){
digitalWrite(i+6,HIGH);
}else{
digitalWrite(i+6,LOW);
}
}
//HIGHはinputを無効化する(LOWだったときを保持する)
digitalWrite(SLPin,HIGH);
}
-
よく考えたら、74HC165の入力は不定なのでグルグル回す必要なかった ↩