ゲームコントローラとして、SparkFun Pro Micro(たぶん中華製互換機)を3つPCにつなげています。ひとつはKeyBoardとしての利用ですが、他の2つはUSBコントローラです。ちゃんと区別してPCが認識してくれるのか不安でしたが、問題なさそうです。
Pro Microのpinへのゲーム機能の割り付けは下表のようにしました。
Shifterの各スイッチは普通のdegital inputです。
Front Wiperスイッチはレバーの倒れによってRetarderの増減を実現するため、現在の位置とひとつ前の位置を比較します。レバーが増加方向に動いたのか、減少方向に動いたのかを現在とひとつ前の位置によって判断し、それに応じた処理を行います。
E/Gブレーキに割り振ったRear Wiperスイッチについても同様な処理をしています。
FrontのMistとRearのWash+ONは指を離せば元に戻るタイプのスイッチです。これを利用して、増(inc+1)を繰り返しできるようにスケッチを書きました。
#include <Joystick.h>
Joystick_ Joystick;
//--------------------------------------------------------------------
int keyWait = 20 ; //keyboardやbuttonを押した後の保持時間(待機時間)
const int Interval = 10 ; //msec, for prevrnt chattering
// Constant that maps the phyical pin to the joystick button.
// 利用する最小のpin number
const int pinToButtonMap = 0;
// Last state of the button
int lastButtonState[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
unsigned long prev[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int last_psi = 0; //Retarder, 一つ前のポジション
int cnt = 0; //wiper sw, off to mist の回数
boolean beforeState = false;
void setup() {
// Initialize Button Pins
pinMode(0, INPUT_PULLUP);
pinMode(1, INPUT_PULLUP);
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
pinMode(5, INPUT_PULLUP);
pinMode(6, INPUT_PULLUP);
pinMode(7, INPUT_PULLUP);
pinMode(8, INPUT_PULLUP);
pinMode(9, INPUT_PULLUP);
pinMode(10, INPUT_PULLUP);
pinMode(14, INPUT_PULLUP);
pinMode(15, INPUT_PULLUP);
pinMode(16, INPUT_PULLUP);
pinMode(18, INPUT_PULLUP);
pinMode(19, INPUT_PULLUP);
pinMode(20, INPUT_PULLUP);
pinMode(21, INPUT_PULLUP);
// Initialize Joystick Library
Joystick.begin();
Serial.begin(9600);
}
void loop() {
// Read pin values
for (int index = 0; index < 22; index++)
if (index > 10 && index < 14){continue;}
else if (index == 17) {continue;}
else {
// Serial.println((String)"index : "+index);
int currentButtonState = !digitalRead(index + pinToButtonMap);
if (currentButtonState != lastButtonState[index]) {
unsigned long cur = millis();
if (cur - prev[index] > Interval) {
//if (!beforeState) {Serial.println((String)"Button : "+index +" is pushed !!!");} beforeState!=beforeState;
//Retarder
// Retarder
//ワイパー動作分岐(リターダー用)
//リターダー減少は,joy (0)が押されたことにする
//リターダー増加は,joy (1) が押されたことにする
// Mist D4
// off D3
// Int D2
// Lo D1
// Hi D0
switch (index) { //0から始まるPin番号。
case 0:// Hi(OFF)
if (!beforeState && last_psi== 1){ //LoからHi(1st to OFF)
//Serial.println("LoからHi");
Joystick.pressButton( 0 );//joy (0)だから、リターダー減少。
delay(keyWait);
Joystick.releaseButton( 0 );
last_psi= index;
beforeState = true;
} else {
//Serial.println("current position is lost, so start at this position");
last_psi= index;
beforeState = false;
} break;
case 1:// Lo(1st)
if (!beforeState && last_psi== 2){ //INTからLo(2nd to 1st)
//Serial.println("INTからLo");
Joystick.pressButton( 0 );//joy (0)だから、リターダー減少。
delay(keyWait);
Joystick.releaseButton( 0 );
last_psi= index;
beforeState = true;
} else if (!beforeState && last_psi== 0){//HiからLo(OFF to 1st)
//Serial.println("HiからLo");
Joystick.pressButton( 1 );
delay(keyWait);
Joystick.releaseButton( 1 );
last_psi= index;
beforeState = true;
} else {
//Serial.println("current position is lost, so start at this position");
last_psi= index;
beforeState = false;
} break;
case 2:// INT(2nd)
if (!beforeState && last_psi== 3){ //OFFからINT(3rd to 2nd)
//Serial.println("OFFからINT");
for ( int j = 0; j < cnt+1; j++) {
Joystick.pressButton( 0 );//joy (0)だから、リターダー減少。
delay(keyWait);
Joystick.releaseButton( 0 );
delay(keyWait);
}
cnt = 0;
last_psi= index;
beforeState = true;
} else if (!beforeState && last_psi== 1){ //LoからINT(1st to 2nd)
//Serial.println("LOからINT");
Joystick.pressButton( 1 );
delay(keyWait);
Joystick.releaseButton( 1 );
last_psi= index;
beforeState = true;
} else {
//Serial.println("current position is lost, so start at this position");
last_psi= index;
beforeState = false;
} break;
case 3: //OFF(3rd)
if (!beforeState && last_psi== 2) { //INTからOFF(2nd to 3rd)
//Serial.println("INTからOFF");
Joystick.pressButton( 1 );//joy (1)だから、リターダー増加。
delay(keyWait);
Joystick.releaseButton( 1 );
last_psi= index;
beforeState = true;
} else if (!beforeState && last_psi== 4){ //MISTからOFF
//Serial.println("MISTからOFF");
last_psi= index;
beforeState = true;
} else {
//Serial.println("current position is lost, so start at this position");
last_psi= index;
beforeState = false;
} break;
case 4: //Mist(4,5th)
if (!beforeState && last_psi==3){ //OFFからMist(3rd to 4,5th)
cnt = cnt +1; //wiper sw, off to mist の回数
if ( cnt >3 ) { cnt=3;
//Serial.println((String)"cnt: "+cnt);
//Serial.println("OFFからMist");
Joystick.pressButton( 1 );//joy (1)だから、リターダー増加。
delay(keyWait);
Joystick.releaseButton( 1 );
last_psi= index;
}
beforeState = true;
} else {
//Serial.println("current position is lost, so start at this position");
last_psi= index;
beforeState = false;
} break;
// Engine Brake
case 6:// at ON position (BROWN)
if (!beforeState && currentButtonState && !lastButtonState[6] && !lastButtonState[7]) {
// OFF ---> ON: Brake +1
//Serial.print ("6_1 at ON, OFF ---> ON: Brake +1 ");
//Serial.println ((String)"index: "+index+" currentButtonState: "+currentButtonState+" beforeState: "+beforeState);
Joystick.setButton(index + pinToButtonMap, currentButtonState);
delay(Interval);
Joystick.setButton(index + pinToButtonMap, 0);
lastButtonState[index] = currentButtonState;
beforeState = true;
} else if (!beforeState && !currentButtonState && lastButtonState[6] && !lastButtonState[7]) {
// ON ---> OFF: Brake -3
//Serial.print ("6_2 at OFF, ON ---> OFF: Brake -3 ");
//Serial.println ((String)"index: "+index+" currentButtonState: "+currentButtonState+" beforeState: "+beforeState);
Joystick.pressButton(index +1 + pinToButtonMap);
delay(Interval);
Joystick.releaseButton(index +1 + pinToButtonMap);
delay(Interval);
Joystick.pressButton(index +1 + pinToButtonMap);
delay(Interval);
Joystick.releaseButton(index +1 + pinToButtonMap);
delay(Interval);
Joystick.pressButton(index +1 + pinToButtonMap);
delay(Interval);
Joystick.releaseButton(index +1 + pinToButtonMap);
lastButtonState[index] = currentButtonState;
beforeState = true;
} break;
case 7:// at wash or wash+ON (BROWN/WHITE)
if ( !beforeState && currentButtonState && !lastButtonState[6] && !lastButtonState[7]) {
// at wash, OFF ---> wash: declease
//Serial.print ("7_1 at wash, OFF ---> wash: 減少 declease ");
//Serial.println ((String)"index: "+index+" currentButtonState: "+currentButtonState+" beforeState: "+beforeState);
Joystick.setButton(index + pinToButtonMap, currentButtonState);
lastButtonState[index] = currentButtonState;
beforeState = true;
} else if ( !beforeState && currentButtonState && lastButtonState[6] && !lastButtonState[7] ) {
// at wash+ON, ON ---> wash+ON: Brake +1(繰り返し許可)
//Serial.print ("7_2 at wash+ON, ON ---> wash+ON: Brake +1(繰り返し許可) ");
//Serial.println ((String)"index: "+index+" currentButtonState: "+currentButtonState+" beforeState: "+beforeState);
Joystick.setButton( index - 1 + pinToButtonMap, currentButtonState);
delay(Interval);
Joystick.setButton( index - 1 + pinToButtonMap, 0);
lastButtonState[index] = currentButtonState;
beforeState = true;
} else if ( !beforeState && !currentButtonState && lastButtonState[6] && lastButtonState[7] ) {
// at ON, wash+ON ---> ON 何もしない
//Serial.print ("6_3 at ON, wash+ON ---> ON 何もしない ");
//Serial.println ((String)"index: "+index+" currentButtonState: "+currentButtonState+" beforeState: "+beforeState);
lastButtonState[index] = currentButtonState;
beforeState = true;
} else if ( !beforeState && !currentButtonState && !lastButtonState[6] && lastButtonState[7] ) {
// at OFF, wash ---> OFF ボタンをOFFする(消す)
//Serial.print ("7_4 at OFF, wash ---> OFF ボタンをOFFする(消す) ");
//Serial.println ((String)"index: "+index+" currentButtonState: "+currentButtonState+" beforeState: "+beforeState);
Joystick.setButton( index + pinToButtonMap, 0);
lastButtonState[index] = currentButtonState;
beforeState = true;
} break;
default:
//general statment
//Serial.println ("general process");
Joystick.setButton(index, currentButtonState);
lastButtonState[index] = currentButtonState;
beforeState = true;
prev[index] = cur;
}
}
if(beforeState) {
//Keyboard.releaseAll();
beforeState = false;
}
}
}
//delay(1000);
}