/*デバッグメモ デバッグ中に修正した箇所には//debugというタグを付けてメモを書く
・最初のメッセージが「gam」になっている こちらは最後の1文字が欠けている →修正完了
・一回モード切替ボタンを押すと、永遠に「extoftame」をループ もう一度押しても止まらない こっちは最初の1文字がかけている →リセット忘れてたため行っても相変わらず
どちらもSerial.writeのループ条件の設定ミスな気がする 下についてはループから抜けられていないっぽい?
つまりは最初のメッセージが1文字抜けた結果1バイトズレて、その結果次回以降の送信の2byteで送る分が1byteに吸われて無効化されたっぽい →こっちは解決っぽい
↓
モードを切り替えようとすると tex/soft/game/xte/soft/gaem/tex/soft/agme/tex/soft/game/ts となる 押しっぱなしにしていると Ctrl+Shift+t になる
発覚した問題は3つ(推測含む)
・下位バイトから入れていっても、必ずしもその順に押されたと認識する訳ではない →修正
・なぜかバイトがズレるっぽい? →gameとsoftは正常に送れているため、textだけの問題
・textが必ず1つ欠ける →バラバラに送信するようにしたが改善した?
↓
長押しで同じのを繰り返し出力するのは継続 さらにsoftが(に置き換わる でも、バイトがズレてCtrl+Shift+Tに置き換わることはなかった
gametext(gametext(gametext(gametext(gametext(gametext(gametext(gametext(gametext(gametext(gametext(
キーコードリストによると(は9と同じ26 chromebookは8と同じ!? →しかしキーコード25も26も送信しないはず デバッグ環境がlinuxなのが原因? windowsならバグらなかった可能性も
→おそらくJSとENのキーボードの違い JSキーボードはENキーボードと配列が違い、HIDレポートはENを基準にしているため
・長押しで繰り返されるのは修正されたはず func_resetup内で前回送信分もまとめて初期化していたことが原因(現在はコメントアウトして修正済)
・(が混ざり込むのは今までは送信できていたのも含め意味不明 バイトがズレた可能性はかなり低い ただし、どこかで変に数バイトだけ送信されてしまった可能性もあり 専用のプログラムを書いてテスト
(だとしても、「バイトがズレると(が送られる」というのは意味不明だが)
"("のキーコードは [0x02or0x20(1byte)]or[0xE1or0xE5(2byte~)]+0x26 とりあえず謎のShiftは置いといて、0x26がどこから来たのか モード指定式が2の場合におかしくなる?
uintにたいして-nをしてるせいで逆方向にオーバーフローしている箇所があるかも→問題なし(0はありえない状況で-1や、0が想定される箇所ではintにしてる そのintも比較だけだから-行っても問題なし)
↓
"修正したはずのループ含め"何も変わらず
↓
前回送信バックアップの代入が右辺と左辺で逆になっていた
修正したらループは解消
ただし、押したときだけでなく離したときも送信されるようになった→func_modeは押されているか判定する条件式を忘れてた
↓
送信回数の問題は全て解決
残りはsoftが"("に置き換わる問題のみ
↓
必要だと思われる範囲だけ抜き出したら "←"に? ただ、ピッタリ左端で止まるため不規則な連打ではなく、上に行があってもそっちには行かないため"↑"ではない
↓
送信内容直書きではちゃんとsoftと送れた
配列まで再現しても問題なし
↓
モードカウンターをインクリメントする&オーバーフロー防止の処理を追記したらバグ再発
十中八九オーバーフロー防止処理が悪さしてる
↓
mode切り替え関係はクリア!
↓
ほぼ正常に動作
しかしCtrlが機能していない(致命的)
↓
まさかの条件式の右辺書き忘れだった にしても、右辺がない場合はとりあえず実行というわけではなかったらしい
↓
完成!!!!!!!!
※そろそろ3Dモデル作ったほうがいいかも プログラム書き上げてから3Dモデル作って、さらにそこからFabLabに行くというタイムラグがあると、自分の性格的に飽きる可能性がある
※ファブラボに持っていくときは3Dプリンターで 詳細をサイトで確認してから行く
*/
/*自作フットスイッチ
4スイッチ+モード切替用1スイッチ
ハードウェア
・ElegooUnoR3(ATmega16U2)
・タクトスイッチ×5
モード
・0 game F13,F14,F15,F16(Steamが対応していない場合はCtrl,Space,Q,>などに変更)→今更だがF1~12を使っても問題ない
・1 text Ctrl+X,Ctrl+V,Enter,backspace
・2 soft Ctrl+Z,Ctrl+Y,F13,F14
スイッチ
・足は左から LO LC RC RO,手はHに呼称を統一する */
/* ショートカット 初期設定:dfu-setup 通常:dfu-def キーボード:dfu-key
sudo su
cd /home/antares/Arduino
通常 dfu-programmer atmega16u2 erase ; dfu-programmer atmega16u2 flash UNO-dfu_and_usbserial_combined.hex
キーボード dfu-programmer atmega16u2 erase ; dfu-programmer atmega16u2 flash Arduino-keyboard-0.3.hex */
//配列,定数,変数宣言
//変数
uint8_t ary_pin_sta [5][2] = {{0,0},{0,0},{0,0},{0,0},{0,0}}; //2次元配列を宣言 5ピン×(1平均+1前回)
uint16_t ary_buffer_def [4] = {0,0,0,0}; //8byte
uint8_t ary_buffer_spe [8] ={0,0,0,0,0,0,0,0};
uint16_t ary_keylist_spe [8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//修飾キー
uint8_t var_mode_pieces = 0; //モード数
uint8_t var_mode_now = 0; //現在のモード番号
//定数 可読性のために別関数で初期化
uint8_t ary_pin_number [5]; //ピン番号 LO,LC,RC,RO,Hの順
uint16_t ary_keylist [3][4][2]; //3次元配列を宣言 3モード×4スイッチ×2送信枠(0はCtrlを使うか、1はキーコード)
uint16_t ary_mode_name [3][6]; //モード数×モード名の文字数
void setup () {
Serial.begin ( 9600 );
delay (2000); //PC側の認識待機時間 不必要な気もする
func_arysetup ();
for (uint8_t setup_i=0; setup_i < 5 ; setup_i++) { //ピンモード設定
pinMode( ary_pin_number [setup_i], INPUT_PULLUP);
}
for(uint8_t setup_i=0; setup_i < 6; setup_i++){
Serial.write(0x00);
Serial.write(0x00);
Serial.write(ary_mode_name[var_mode_now][setup_i]);
Serial.write(0x00);
Serial.write(0x00);
Serial.write(0x00);
Serial.write(0x00);
Serial.write(0x00);
}
for(uint8_t setup_i =0; setup_i < 8; setup_i++){
Serial.write(0x00);
}
}
void loop () {
func_pin(); //メイン処理は勝手に連鎖
func_resetup(); //どちらが呼び出されてもリセットする 必要かは分からないが一応
delay (10);
}
void func_arysetup () { //定数配列設定
//ピン番号
ary_pin_number [0] = 8; //LO //debug
ary_pin_number [1] = 9; //LC //debug
ary_pin_number [2] = 10; //RC //debug
ary_pin_number [3] = 11; //RO //debug
ary_pin_number [4] = 12; //H //debug
//モード数設定
var_mode_pieces = 3;
//モード名
//モード0 game
ary_mode_name [0] [0] = 0x0A;
ary_mode_name [0] [1] = 0x04;
ary_mode_name [0] [2] = 0x10;
ary_mode_name [0] [3] = 0x08;
ary_mode_name [0] [4] = 0x00;
ary_mode_name [0] [5] = 0x00;
//モード1 text
ary_mode_name [1] [0] = 0x17;
ary_mode_name [1] [1] = 0x08;
ary_mode_name [1] [2] = 0x1B;
ary_mode_name [1] [3] = 0x17;
ary_mode_name [1] [4] = 0x00;
ary_mode_name [1] [5] = 0x00;
//モード2 soft
ary_mode_name [2] [0] = 0x16;
ary_mode_name [2] [1] = 0x12;
ary_mode_name [2] [2] = 0x09;
ary_mode_name [2] [3] = 0x17;
ary_mode_name [2] [4] = 0x00;
ary_mode_name [2] [5] = 0x00;
//キーコードリスト [n][n][0]をctrl使用かではなく使用する修飾キーのbyte数(0スタートで指定)ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
//debug 欠陥発見!!! Lctrlも修飾キー不使用も、どっちも0になってる!
/* 修飾キーの指定リスト ※不使用との区別のため+1する
0 L ctrl
1 L shift
2 L alt
3 L super
4 R ctrl
5 R shift
6 R alt
7 R super
*/
//モード0 F6/F7/F8/F9
ary_keylist [0] [0] [0] = 0;
ary_keylist [0] [0] [1] = 0x3F;
ary_keylist [0] [1] [0] = 0;
ary_keylist [0] [1] [1] = 0x40;
ary_keylist [0] [2] [0] = 0;
ary_keylist [0] [2] [1] = 0x41;
ary_keylist [0] [3] [0] = 0;
ary_keylist [0] [3] [1] = 0x42;
//モード1 Ctrl+X/Ctrl+V/enter/backspace
ary_keylist [1] [0] [0] = 1;
ary_keylist [1] [0] [1] = 0x1B;
ary_keylist [1] [1] [0] = 1;
ary_keylist [1] [1] [1] = 0x19;
ary_keylist [1] [2] [0] = 0;
ary_keylist [1] [2] [1] = 0x28;
ary_keylist [1] [3] [0] = 0;
ary_keylist [1] [3] [1] = 0x2A;
//モード2 Ctrl+Z/Ctrl+Y/F6/F7
ary_keylist [2] [0] [0] = 1;
ary_keylist [2] [0] [1] = 0x1D;
ary_keylist [2] [1] [0] = 1;
ary_keylist [2] [1] [1] = 0x1C;
ary_keylist [2] [2] [0] = 0;
ary_keylist [2] [2] [1] = 0x3F;
ary_keylist [2] [3] [0] = 0;
ary_keylist [2] [3] [1] = 0x40;
}
void func_pin () { //ピン読み&フロー分類
for (uint8_t pin_i=0; pin_i < 5 ; pin_i++) {
if (digitalRead (ary_pin_number [pin_i]) == LOW ) {
ary_pin_sta [ pin_i ] [ 0 ] = 1;
}
}
if(ary_pin_sta[4][0] != ary_pin_sta[4][1] &&ary_pin_sta[4][0] ==1 ){
func_mode();
}else if(ary_pin_sta[4][0] != ary_pin_sta[4][1]){
//スルー
} else {
func_send();
}
}
void func_mode () { //モード切替
var_mode_now++;
if ( var_mode_now == var_mode_pieces) { //debug モード数-1にしなければならなかった ←間違い あくまでも「超えた(過去形)場合に該当するものにリセット」という処理のため
var_mode_now = var_mode_now - var_mode_pieces;
}
for(uint8_t mode_i =0; mode_i <6; mode_i++){
Serial.write(0x00);
Serial.write(0x00);
Serial.write(ary_mode_name [var_mode_now] [mode_i]);
Serial.write(0x00);
Serial.write(0x00);
Serial.write(0x00);
Serial.write(0x00);
Serial.write(0x00);
}
for(uint8_t setup_i=0; setup_i < 8; setup_i++){
Serial.write(0x00);
}
} //関数終端
void func_send () { //送信
int8_t buffer_ctr =0;
for(uint8_t buffer_i =0;buffer_i <4; buffer_i++){
if(ary_pin_sta[buffer_i][0]==1){
if(ary_keylist[var_mode_now][buffer_i][0] !=0 ){ //キーコードリストの修飾キー指定は1~8の使用バイト ※不使用との区別のため+1
ary_buffer_spe[ary_keylist[var_mode_now][buffer_i][0]-1] = 1; //要素数として渡すのはキーリスト配列に記述された番号 これは未使用との区別のために+1されているため-1する必要が
}
if(ary_keylist[var_mode_now][buffer_i][1] !=0 ){ //通常キー代入
ary_buffer_def[buffer_ctr]=ary_keylist[var_mode_now][buffer_i][1];
buffer_ctr++; //これはそのまま何バイト送るかに使える
}
}
}
uint16_t spe_send =0;
for(uint8_t spe_i =0; spe_i <8; spe_i++){
if(ary_buffer_spe[spe_i] ==1){ //debug まさかの条件書き忘れw
spe_send = spe_send + ary_keylist_spe[spe_i] ;
}
}
Serial.write(spe_send); //0
Serial.write(0x00); //1
for(int8_t send_i =0; send_i < 4;send_i++){ //buffer_ctrは0スタート 通常キーが無い場合は0、それ以外は送信数を1スタートでカウント 2~5
if( send_i > buffer_ctr -1){ //超えた場合 send_iは0スタート、buffer_ctrは1スタート(0はスルー)
Serial.write(0x00);
} else {
Serial.write(ary_buffer_def[send_i]);
}
}
Serial.write(0x00); //6
Serial.write(0x00); //7
}
void func_resetup () { //配列なとのリセット
for (uint8_t i=0; i < 5 ; i++) {
ary_pin_sta [ i ] [ 1 ] = ary_pin_sta [ i ] [ 0 ] ; //debug 代入の左右が逆だった
}
//uint8_t ary_pin_sta [5][2] = {{0,0},{0,0},{0,0},{0,0},{0,0}}; debug これのせいで、押しっぱなしの間は「前回と違う」と判定されていた
for(uint8_t reset_i =0;reset_i <5; reset_i++){
ary_pin_sta[reset_i][0]=0;
}
for(uint8_t reset_i =0;reset_i <4;reset_i++){
ary_buffer_def[reset_i]=0;
}
for(uint8_t reset_i =0;reset_i <8;reset_i++){
ary_buffer_spe[reset_i] =0;
}
}