- /*--------------------------------------
- NEC配列テンキー制御用スケッチ
- ----------------------------------------
- ・コンパイル等について
- Arduino IDE 1.8.5 で動作検証しています。
- コンパイルには、 Arduino IDEに2つのライブラリをインストールする必要があります。
- 「スケッチ」→「ライブラリをインクルード」→「ライブラリを管理」 で検索するか、
- または、 各配布先urlからライブラリをzip形式でDownloadしてから、
- 「スケッチ」→「ライブラリをインクルード」→「.ZIP形式のライブラリをインストールする」を
- 実施して下さい。
-
- NumLock非連動機能が必要な場合は、コンパイルオプション(__NUM_LOCK_UNSYNC)を0→1に変更して
- コンパイルします。 ノートPC等のテンキー操作を一部のキーで代用している環境で便利になると
- 思います。
-
- 制御的には、テンキー操作毎にNumLock/NumLock解除が切り替わる(=キーコード送信数が増加する)
- ため、数値入力等の一般用途向けの操作性向上が目的で、ゲーム向けにはあまり出番が無いかも、
- と言うことで初期設定ではOffにしています。
-
- ・キー操作時のチャタリング制御について
- チャタリングキャンセルのため、スキャン周期(KEY_SCAN_TIME)を5msにしています。
- key_scan()条件は、一定周期でキー状態を読んで一致したかどうかのみ見ており、Timerも利用して
- いないので、結構アバウトな制御です。
-
- と言いつつ、
- HIDライブラリ側でも同じキーコードが検出された場合に、1つにまとめる等の対策を施してあり、
- 実のところあまりチャタリング制御を意識する必要はないのかもしれません。
-
- キー操作(まっすぐ押下or爪が引っ掛かった)等でも状況が変わりますが、1回の操作で複数回の
- 入力がされる等の症状が頻発する場合は、この値を増加させて(5→10など)様子を見てください。
- 逆に、操作したのに入力が抜ける場合は、この値を減らす等を試してみる事になりますが、
- 結構、キースイッチのはんだ付け不良ということがありました。(私の工作が悪いという話でした)
- 特定キーのみでチャタリングが発生する場合は、まずはその辺りのご確認をオススメします・・。
-
- ・キーリピート/Nキーロールオーバー対応について
- 基本的にライブラリ任せです。
- 後者はライブラリのexamples(NKROKeyboard.ino)にも記載がありますが、利用環境(OSやドライバ等)
- に依存するかもしれません。(何かあればBootKeyboard制御に戻す予定ですのでご連絡ください)
-
- 2018.8.12 あお( mail: qze12045@nifty.com )
- */
- /* ----- ヘッダ ----- */
- //(1)シリアルLEDライブラリ(配布先 https://github.com/adafruit/Adafruit_NeoPixel)
- #include <Adafruit_NeoPixel.h>
- //(2)Arduino HID Project 2.4.4(配布先 https://github.com/NicoHood/HID#arduino-hid-project-244)
- #include <HID-Project.h>
- #include <HID-Settings.h>
- /* ----- 定数 ----- */
- //コンパイルオプション
- #define __NUM_LOCK_UNSYNC 0 //NumLock動作をホスト側と連動しない(0:無効、1:有効)
- //チャタリング判定用
- #define KEY_SCAN_TIME 5 //キースキャン周期(ms)
- #define KEY_SEND_TIME 1 //キーコード送信時間(ms)
- //LED制御用 I/O定義
- #define NUMPIXELS 1 // シリアルLED個数
- #define NUM_LOCK_LED 21 // NumLock/動作モード状態LEDポート番号
- //動作モード定義
- enum{
- MODE1 = 0 , //モード1( JIS )
- MODE2 , //モード2( US )
- MODE3 , //モード3( USER )
- MODE_MAX
- };
- //KEY定義
- // 各コードは、独自定義した修飾子(上位8bit)と、キーコード(下位8bit)で構成しており、
- // キーコードはHID資料( http://www.usb.org/developers/hidpage/Hut1_12v2.pdf )の
- // 「10 Keyboard/Keypad Page (0x07)」より、RAW送信用データとして利用しています。
- // メディアキー(C_MEDIA)とモードキー(C_MODE)の下位8bitは独自コードとしており、
- // key_code_send()で処理を分けています。
- //キー修飾コード(特殊キーや同時押し指定など)
- #define C_SHIFT 0x1000 // SHIFT+ 指定コード
- #define C_MEDIA 0x2000 // メディアキー(コンシューマー機能用)
- #define C_MODE 0x4000 // 動作モード切替(ユーザー定義)
- #if __NUM_LOCK_UNSYNC
- #define C_PAD 0x8000 // キーパッド制御(NumLock非連動) 有効
- #else
- #define C_PAD 0 // キーパッド制御(NumLock非連動) 無効
- #endif
- //動作モード指定キー
- #define KC_DUMMY (C_MODE | 0x0 ) // Dummy
- #define KC_MODE1 (C_MODE | 0x1 ) // MODE1
- #define KC_MODE2 (C_MODE | 0x2 ) // MODE2
- #define KC_MODE3 (C_MODE | 0x3 ) // MODE3
- //メディアキー(Windowsのみ?)
- #define KC_CALC (C_MEDIA | 0x1 ) // 電卓キー
- //シフトキー
- #define KC_LSHIFT 0xe1 // 左 SHIFT
- //キーコード
- #define KC_DOT ( C_PAD | 0x63 ) // Keypad [.]
- #define KC_P0 ( C_PAD | 0x62 ) // Keypad [0]
- #define KC_P9 ( C_PAD | 0x61 ) // Keypad [9]
- #define KC_P8 ( C_PAD | 0x60 ) // Keypad [8]
- #define KC_P7 ( C_PAD | 0x5f ) // Keypad [7]
- #define KC_P6 ( C_PAD | 0x5e ) // Keypad [6]
- #define KC_P5 ( C_PAD | 0x5d ) // Keypad [5]
- #define KC_P4 ( C_PAD | 0x5c ) // Keypad [4]
- #define KC_P3 ( C_PAD | 0x5b ) // Keypad [3]
- #define KC_P2 ( C_PAD | 0x5a ) // Keypad [2]
- #define KC_P1 ( C_PAD | 0x59 ) // Keypad [1]
- #define KC_ENTER 0x58 // Keypad [Enter]
- #define KC_PLUS 0x57 // Keypad [+]
- #define KC_MINS 0x56 // Keypad [-]
- #define KC_ASTR 0x55 // Keypad [*]
- #define KC_DIV 0x54 // Keypad [/]
- #define KC_NUML 0x53 // [NUM LOCK]
- #define KC_UP 0x52 // Keyboard [UP]
- #define KC_RIGHT 0x4f // Keyboard [RIGHT]
- #define KC_HOME 0x4a // Keyboard [HOME]
- #define KC_COMMA 0x36 // Keyboard [,]
- #define KC_EQLU 0x2e // Keyboard [=] ( US配列 )
- #define KC_EQLJ (C_SHIFT | 0x2d) // Keyboard [=] (JIS配列 [SHIFT]+[-])
- #define KC_TAB 0x2b // [TAB]
- #define KC_BS 0x2a // [BACK SPACE]
- #define KC_ESC 0x29 // [ESC]
- #define KC_0 (C_SHIFT | 0x27) // Keyboard [0] ( US配列[(] [SHIFT]+[0])
- #define KC_9 (C_SHIFT | 0x26) // Keyboard [9] (JIS配列[(] or US配列[)] [SHIFT]+[9])
- #define KC_8 (C_SHIFT | 0x25) // Keyboard [8] (JIS配列[)] [SHIFT]+[8])
- /* ----- 固定データ・他 ----- */
- //KEY MAP定義(動作モード単位で記述する)
- #define ROW_NUM 7 //KEY MAP行数
- #define COL_NUM 4 //KEY MAP桁数
- const unsigned int key_map[MODE_MAX][ROW_NUM][COL_NUM] =
- {
- {//MODE1 定義(JIS配列)
- { KC_DUMMY, KC_MODE1 , KC_MODE2 , KC_MODE3 }, //Dummy M1 M2 M3
- { KC_NUML , KC_CALC , KC_ESC , KC_BS }, //NML CALC ESC BS
- { KC_8 , KC_9 , KC_MINS , KC_DIV }, // ( ) - /
- { KC_P7 , KC_P8 , KC_P9 , KC_ASTR }, // 7 8 9 *
- { KC_P4 , KC_P5 , KC_P6 , KC_PLUS }, // 4 5 6 +
- { KC_P1 , KC_P2 , KC_P3 , KC_EQLJ }, // 1 2 3 =
- { KC_P0 , KC_COMMA , KC_DOT , KC_ENTER } // 0 , . RET
- },
- {//MODE2 定義(US配列)
- { KC_DUMMY, KC_MODE1 , KC_MODE2 , KC_MODE3 }, //Dummy M1 M2 M3
- { KC_NUML , KC_CALC , KC_ESC , KC_BS }, //NML CALC ESC BS
- { KC_9 , KC_0 , KC_MINS , KC_DIV }, // ( ) - /
- { KC_P7 , KC_P8 , KC_P9 , KC_ASTR }, // 7 8 9 *
- { KC_P4 , KC_P5 , KC_P6 , KC_PLUS }, // 4 5 6 +
- { KC_P1 , KC_P2 , KC_P3 , KC_EQLU }, // 1 2 3 =
- { KC_P0 , KC_COMMA , KC_DOT , KC_ENTER } // 0 , . RET
- },
- {//MODE3 定義(ユーザー定義:PC-8001/J80モード)
- { KC_DUMMY, KC_MODE1 , KC_MODE2 , KC_MODE3 }, //Dummy M1 M2 M3
- { KC_NUML , KC_CALC , KC_ESC , KC_BS }, //NML CALC ESC BS
- { KC_HOME , KC_UP , KC_RIGHT , KC_BS }, //HOME UP -> BS
- { KC_P7 , KC_P8 , KC_P9 , KC_ASTR }, // 7 8 9 *
- { KC_P4 , KC_P5 , KC_P6 , KC_PLUS }, // 4 5 6 +
- { KC_P1 , KC_P2 , KC_P3 , KC_MINS }, // 1 2 3 -
- { KC_P0 , KC_DIV , KC_DOT , KC_ENTER } // 0 / . RET
- }
- };
- //KEY SCAN用 I/O定義
- const int rowPins[ROW_NUM] = { 2, 3, 4, 5, 6, 7, 8 }; // OUTPUT指定ポート番号
- const int colPins[COL_NUM] = { 9, 10, 16, 14 }; // INPUT_PULLUP指定ポート番号
- //シリアルLED定義
- // RGB指定は、LED型番により適時変更が必要です。
- // D2812 = NEO_RGB
- // WS2812B = NEO_GRB
- Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, NUM_LOCK_LED, NEO_RGB + NEO_KHZ800); //NumLock LED制御Pin初期化
- /* ----- 変数 ----- */
- //動作モード制御
- int key_mode; //動作モード
- int old_key_mode; //前回動作モード
- //キーチャタリング判定
- int scan_cnt; //キースキャンカウント値(0<->1 トグル動作)
- bool key_scan_sts[2][ROW_NUM][COL_NUM]; //周期的にキースキャンを実施し、キーを離したor前回と一致した場合にカレントに登録する。
- //KEY状態を前回と最新状態で比較して、変化があった場合にキーコードを送信する
- bool cur_key_sts[ROW_NUM][COL_NUM]; //最新のKEY状態
- bool old_key_sts[ROW_NUM][COL_NUM]; //前回のKEY状態
- //SHIFT同時押し
- int shift; //SHIFT制御状態(0:なし、0以外:SHIFT押下中)
- //NumLock・LED制御
- int cur_led_sts; //現在のホストLED状態(NumLock制御用)
- int old_led_sts; //前回のホストLED状態(NumLock制御用)
- int R[MODE_MAX]; // LED色 Red (0?255)
- int G[MODE_MAX]; // LED色 Green(0?255)
- int B[MODE_MAX]; // LED色 Blue (0?255)
- #if __NUM_LOCK_UNSYNC
- //NumLock非連動制御
- int num_lock; //NumLock制御状態(0:なし、1:制御中)
- int cur_num_lock; //現在のNumLock
- int old_num_lock; //前回のNumLock
- #endif
- ///////////////////////////////////////////////////////////////////////////////
- //動作モード取得処理
- //キーコードに従い、動作モードを返す
- //入力:キーコード
- //出力:動作モード(MODE1?MODE3)
- ///////////////////////////////////////////////////////////////////////////////
- int get_mode(unsigned int key)
- {
- switch(key)
- {
- // MODE1
- case KC_MODE1:
- return MODE1;
- // MODE2
- case KC_MODE2:
- return MODE2;
- // MODE3
- case KC_MODE3:
- return MODE3;
- default:
- return key_mode;
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- //キーコード取得処理
- //動作モード(key_mode)に従い、キーマップを(JIS/US/他に)切り替えて、
- //指定されたスキャン位置(row,col)のキーコードを返す
- //入力:スキャン位置 row,col
- //出力:なし
- ///////////////////////////////////////////////////////////////////////////////
- unsigned int get_key(int row,int col)
- {
- //現在の動作モードのキーコードを返す
- return key_map[key_mode][row][col];
- }
- ///////////////////////////////////////////////////////////////////////////////
- //キー押下状態の確認処理
- //現在のキー状態状態マップ(cur_key_sts[])の押下状態を調べる。
- //maskに該当するキーが押下されている場合、1を返却。該当なしの場合0を返す
- //入力:mask
- //出力:0:該当なし、1:該当キーの押下検出
- ///////////////////////////////////////////////////////////////////////////////
- int cur_key_check(int mask)
- {
- // KEY MAP状態チェック
- for (int row = 0; row < ROW_NUM; row++)
- {
- //各キー状態チェック
- for (int col = 0; col < COL_NUM; col++)
- {
- //現在のキー状態は押下である
- if( cur_key_sts[row][col] == LOW )
- {
- //キーコード取得
- unsigned int key_code = get_key(row,col);
-
- //対象キーが検出された
- if( key_code & mask )
- {
- //該当有り
- return 1;
- }
- }
- }
- }
- //該当なし
- return 0;
- }
- #if __NUM_LOCK_UNSYNC
- ///////////////////////////////////////////////////////////////////////////////
- //NumLockコード送信/ホスト完了待ち処理
- //NumLockキーコードを送信し、ホスト側のNumLock状態が変化するまで待つ。
- //入力:なし
- //出力:なし
- ///////////////////////////////////////////////////////////////////////////////
- void num_lock_wait(void)
- {
- int time = 0; //タイムアウトカウンタ初期化
- int led_sts_save; //元のホストLED状態(NumLock制御用)
- int led_sts; //最新のホストLED状態(NumLock制御用)
- //SHIFT制御中
- if( shift && (cur_key_check( C_SHIFT ) == 1) )
- {
- //NumLock状態切り替え前に、キー押下状態を破棄する
- NKROKeyboard.releaseAll();
- delay(KEY_SCAN_TIME);
- shift_release();
- }
- //HOST側のNumLock状態を保存する
- led_sts_save = BootKeyboard.getLeds();
- //NumLockキーを押下(+コード送信)
- NKROKeyboard.press(KeyboardKeycode(KC_NUML));
- //ホスト側NumLock状態が変化するまで待つ(最長1秒)
- while( time++ < 999 )
- {
- //ホスト側NumLock状態読み出し
- led_sts = BootKeyboard.getLeds();
-
- //ホスト側NumLock状態が変化
- if( (led_sts & LED_NUM_LOCK) != (led_sts_save & LED_NUM_LOCK) )
- {
- break;
- }
- //押下キー送信待ち
- delay(KEY_SEND_TIME);
- }
- //NumLockキーをリリースする
- NKROKeyboard.release(KeyboardKeycode(KC_NUML));
- }
- ///////////////////////////////////////////////////////////////////////////////
- //NumLockモード制御設定処理
- //状態フラグ(num_lock)および、ホスト側の状態により、NumLockモード制御を行う。
- //num_lock=0なら、キーマップ状態をチェックし、対象キーが押下されていたら、
- //NumLockキーコードを送信し、num_lock=1(制御状態)とする。
- //入力:なし
- //出力:なし
- ///////////////////////////////////////////////////////////////////////////////
- void num_lock_set(void)
- {
- //NumLock制御中は処理しない
- if( num_lock )
- {
- //NumLock解除待ちとする
- return;
- }
- //HOST側のNumLock状態を読み出す
- cur_led_sts = BootKeyboard.getLeds();
- //ホスト側とテンキー側でNumLock状態が一致
- if( cur_num_lock == (cur_led_sts & LED_NUM_LOCK) )
- {
- //NumLock制御を行わない
- return;
- }
- //NumLock制御対象キーの押下有り
- if( cur_key_check( C_PAD ) == 1)
- {
- //NumLock制御コード送信/ホスト完了待ち
- num_lock_wait();
- //NumLock制御開始
- num_lock++;
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- //NumLockモード制御解除処理
- //状態フラグ(num_lock)により、NumLockモード制御状態の解除を行う。
- //num_lock=0以外なら、キーマップ状態をチェックし、全てリリースされていたら
- //NumLockキーコードを送信し、num_lock=0(解除状態)とする。
- //入力:なし
- //出力:なし
- ///////////////////////////////////////////////////////////////////////////////
- void num_lock_release(void)
- {
- int led_sts_save; //元のホストLED状態(NumLock制御用)
- int led_sts; //最新のホストLED状態(NumLock制御用)
- //NumLock制御実施済み
- if( num_lock || shift )
- {
- //NumLock制御対象キーの押下有り
- if( cur_key_check( C_SHIFT|C_PAD ) == 1)
- {
- //対象キーが1つでも押されていたら、NumLock解除しない
- return;
- }
- //NumLock制御コード送信/ホスト完了待ち
- num_lock_wait();
-
- //NumLock制御終了
- num_lock = 0;
- }
- }
- #endif
- ///////////////////////////////////////////////////////////////////////////////
- //SHIFT制御設定
- //シフト対象キーが押されたら、左シフトキーを押下する
- ///////////////////////////////////////////////////////////////////////////////
- void shift_set(void)
- {
- //SHIFT制御中ではない
- if(!shift)
- {
- //SHIFT制御対象キーの押下有り
- if( cur_key_check( C_SHIFT ) == 1)
- {
- //SHIFTを押下する(+コード送信)
- NKROKeyboard.press(KeyboardKeycode(KC_LSHIFT));
- delay(KEY_SEND_TIME);
- //SHIFT制御開始
- shift++;
- }
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- //SHIFT制御解除
- //シフト状態を解除する
- ///////////////////////////////////////////////////////////////////////////////
- void shift_release(void)
- {
- //SHIFT制御中である
- if(shift)
- {
- //SHIFTキーを離す(コード登録のみで送信は行わない)
- NKROKeyboard.remove(KeyboardKeycode(KC_LSHIFT));
- //SHIFT制御終了
- shift = 0;
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- //条件付き キーコード送信処理
- //有効キーのうち、前回のキー入力結果と差分があり、かつ、maskで除外指定された
- //種別以外のキーコードをホストに送信する。
- //入力:除外キー種別(mask) 、0:除外なし
- //出力:なし
- ///////////////////////////////////////////////////////////////////////////////
- void key_code_send( int mask )
- {
- //KEY更新状態クリア
- int chg = 0; //通常キー(NKROKeyboard.send()対象)
- int media = 0; //メディアキー(Consumer.write()対象)
-
- // KEY MAP状態チェック
- for (int row = 0; row < ROW_NUM; row++)
- {
- //各キー状態チェック
- for (int col = 0; col < COL_NUM; col++)
- {
- // 前回の状態と変化あり?
- if (cur_key_sts[row][col] != old_key_sts[row][col])
- {
- //キーコード取得
- unsigned int key_code = get_key(row,col);
- //マスク指定されたキー種別は除外(=処理しない)
- if( !(key_code & mask) )
- {
- //キー状態は押下
- if( cur_key_sts[row][col] == LOW )
- {
- #if __NUM_LOCK_UNSYNC
- //NumLock押下
- if( key_code == KC_NUML )
- {
- //テンキー側 NumLock状態ON<-->OFF切り替え(次回スキャン以降有効)
- cur_num_lock ^= LED_NUM_LOCK;
- }
- else
- #endif
- //動作モード変更キー指定?
- if(key_code & C_MODE)
- {
- //動作モード切り替え
- key_mode = get_mode(key_code);
- }
- else
- {
- //メディアキー指定?
- if(key_code & C_MEDIA)
- {
- //機能キー押下
- media++;
- }
- else
- {
- //キー押下する
- NKROKeyboard.add(KeyboardKeycode(key_code & 0xff));
- //KEY更新有り
- chg++;
- }
- }
- }
- //キーは離された
- else
- {
- #if __NUM_LOCK_UNSYNC
- //NumLock解除
- if( key_code == KC_NUML )
- {
- //何もしない
- ;
- }
- else
- #endif
- //モード/メディアキー指定?
- if(key_code & (C_MEDIA|C_MODE))
- {
- //キーリリース時は何もしない
- ;
- }
- else
- {
- //キーリリース
- NKROKeyboard.remove(KeyboardKeycode(key_code & 0xff));
- //KEY更新有り
- chg++;
- }
- }
- //現在のキー状態を前回の状態にコピーする(コード送信済みとする)
- old_key_sts[row][col] = cur_key_sts[row][col];
- }
- }
- }
- }
- //メディアキー押下
- if( media )
- {
- //電卓キーを送信する
- Consumer.write(ConsumerKeycode(CONSUMER_CALCULATOR));
- }
- //KEY更新有り
- if( chg )
- {
- //ホスト側に変化したキーコードを送信する
- NKROKeyboard.send();
- #if __NUM_LOCK_UNSYNC
- //キーコード送信待ち(要検証:次スキャン先頭で必ずWaitが入るので、このWaitは無くせそうですが・・。)
- while(chg--)
- {
- delay(KEY_SEND_TIME);
- }
- #endif
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- //キースキャン処理(+チャタリングの除去)
- //KEY SCAN用I/Oポートを走査してキーの状態を読み出す。
- //前回スキャンした状態と一致するか、キーを離した場合に有効キーとして登録する。
- //実行条件:なるべく一定周期(KEY_SCAN_TIME)毎に実行する。
- ///////////////////////////////////////////////////////////////////////////////
- void key_scan(void)
- {
- // key matrix scan
- for (int row = 0; row < ROW_NUM; row++)
- {
- // 行指定LOW出力:キースキャン開始
- digitalWrite(rowPins[row], LOW);
- //キースキャン実施
- for (int col = 0; col < COL_NUM; col++)
- {
- // 列指定:キー状態読み出し(押下:LOW)
- key_scan_sts[scan_cnt][row][col] = digitalRead(colPins[col]);
- //チャタリングの除去条件
- //キーを離したか、前回の状態と一致?
- if (( key_scan_sts[scan_cnt][row][col]==HIGH )||
- ( key_scan_sts[0][row][col] == key_scan_sts[1][row][col] ))
- {
- //現在のキー状態に登録する
- cur_key_sts[row][col] = key_scan_sts[scan_cnt][row][col];
- }
- }
- // 行指定HIGH出力:キースキャン終了
- digitalWrite(rowPins[row], HIGH);
- }
- //スキャンカウント更新
- scan_cnt = (scan_cnt + 1)&0x1;
- }
- ///////////////////////////////////////////////////////////////////////////////
- //キーコード判定処理
- //有効キーとして登録されたキーが、前回のキー状態から変化した場合に、
- //キーコードに応じた処理を行う。
- ///////////////////////////////////////////////////////////////////////////////
- void key_check(void)
- {
- #if __NUM_LOCK_UNSYNC
- //NumLock制御状態に遷移する
- num_lock_set();
- #endif
- //SHIFT対象キー、メディアキー、モードキー「以外」を先に処理する
- key_code_send(C_MEDIA|C_MODE|C_SHIFT);
- //SHIFT制御状態に遷移する
- shift_set();
- //残り(SHIFT対象キー、メディアキー、モードキー)を送付する。
- key_code_send(0);
- //シフト状態を解除する
- shift_release();
- #if __NUM_LOCK_UNSYNC
- //NumLock制御状態を解除する
- num_lock_release();
- #endif
- }
- ///////////////////////////////////////////////////////////////////////////////
- //LED表示制御
- //テンキーの動作モードまたは、NumLock状態が変化した場合に、LED表示を更新する
- ///////////////////////////////////////////////////////////////////////////////
- void led_display(void)
- {
- #if __NUM_LOCK_UNSYNC
- //LED点灯状態または、動作モード変化あり
- if(( cur_num_lock != old_num_lock )||( key_mode != old_key_mode ))
- {
- //NumLock状態ON
- if( cur_num_lock & LED_NUM_LOCK )
- #else
- //ホスト側のLED状態を取得
- cur_led_sts = BootKeyboard.getLeds();
-
- //LED点灯状態または、動作モード変化あり
- if(( cur_led_sts != old_led_sts )||( key_mode != old_key_mode ))
- {
- //ホスト側NumLock状態ON
- if( cur_led_sts & LED_NUM_LOCK )
- #endif
- {
- //LED点灯(key_modeに従いRGB指定する)
- pixels.setPixelColor(0, pixels.Color(R[key_mode],G[key_mode],B[key_mode]));
- }
- else
- {
- //LED消灯(黒)
- pixels.setPixelColor(0, pixels.Color(0,0,0));
- }
- //LED出力
- pixels.show();
- //ホスト側のLED状態変化あり
- if( cur_led_sts != old_led_sts )
- {
- //ホスト側のLED状態を保存する
- old_led_sts = cur_led_sts;
- }
- //動作モード変化あり
- if( key_mode != old_key_mode )
- {
- //動作モードを保存する
- old_key_mode = key_mode;
- }
- #if __NUM_LOCK_UNSYNC
- //NumLock状態変化あり
- if( cur_num_lock != old_num_lock )
- {
- //NumLock状態を保存する
- old_num_lock = cur_num_lock;
- }
- #endif
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- //初期化処理(起動時に1回だけ動作する)
- ///////////////////////////////////////////////////////////////////////////////
- void setup()
- {
- // put your setup code here, to run once:
- //動作モード初期化
- key_mode = MODE1;
- old_key_mode = MODE1;
- //LED表示初期化(各動作モード別にRGBで色指定する)
- //MODE1=緑
- R[MODE1]=0;
- G[MODE1]=10;
- B[MODE1]=0;
- //MODE2=青
- R[MODE2]=0;
- G[MODE2]=0;
- B[MODE2]=10;
- //MODE3=黄
- R[MODE3]=15;
- G[MODE3]=15;
- B[MODE3]=0;
- //キースキャン行のI/O Pinを初期化(OUTPUT指定)
- for (int i = 0; i < ROW_NUM; i++)
- {
- pinMode(rowPins[i], OUTPUT);
- }
- //キースキャン列のI/O Pinを初期化(INPUT_PULLUP指定)
- for (int i = 0; i < COL_NUM; i++)
- {
- pinMode(colPins[i], INPUT_PULLUP);
- }
- //キー押下状態を初期化する
- for (int row = 0; row < ROW_NUM; row++)
- {
- //キー状態を「リリース」とする
- for (int c = 0; c < COL_NUM; c++)
- {
- key_scan_sts[0][row][c] = HIGH;
- key_scan_sts[1][row][c] = HIGH;
- cur_key_sts[row][c] = HIGH;
- old_key_sts[row][c] = HIGH;
- }
- //キースキャン行のI/O PinをHIGH(inactive)にする
- digitalWrite(rowPins[row], HIGH);
- }
- //シリアルLEDライブラリ初期化
- pixels.begin();
- //HIDデバイス初期化(ホストLED状態取得用)
- BootKeyboard.begin();
- //Nキーロールオーバー対応
- NKROKeyboard.begin();
- //メディアキー機能
- Consumer.begin();
- #if __NUM_LOCK_UNSYNC
- //NumLock制御状態クリア
- num_lock = 0;
- //NumLockモード初期化
- cur_num_lock = LED_NUM_LOCK;
- old_num_lock = 0;
- #endif
- //シフト状態クリア
- shift = 0;
- //キースキャン開始
- scan_cnt = 0;
- key_scan();
- }
- ///////////////////////////////////////////////////////////////////////////////
- //メインループ処理
- ///////////////////////////////////////////////////////////////////////////////
- void loop()
- {
- // put your main code here, to run repeatedly:
- //前回のキースキャンから一定時間遅延させる。
- delay(KEY_SCAN_TIME);
- //キースキャン処理(+チャタリングの除去)
- key_scan();
- //キー判定処理
- key_check();
- //LED表示制御
- led_display();
- }