1. //(1)シリアルLEDライブラリ(配布先 https://github.com/adafruit/Adafruit_NeoPixel)
  2. #include <Adafruit_NeoPixel.h>
  3. //(2)Arduino HID Project 2.4.4(配布先 https://github.com/NicoHood/HID#arduino-hid-project-244)
  4. #include <HID-Project.h>
  5. #include <HID-Settings.h>
  6. //キーコード指定
  7. #define C_SHIFT        0x1000        // SHIFT+ 指定コード
  8. #define    C_MEDIA        0x2000        // メディアキー(コンシューマー機能用)
  9. #define    KC_CALC    (C_MEDIA | 0x1 )    // 電卓キー
  10. #define KC_SHIFT    0xe1        // 左 SHIFT
  11. #define    KC_DOT        0x63        // Keypad [.]
  12. #define    KC_P0        0x62        // Keypad [0]
  13. #define    KC_P9        0x61        // Keypad [9]
  14. #define    KC_P8        0x60        // Keypad [8]
  15. #define    KC_P7        0x5f        // Keypad [7]
  16. #define    KC_P6        0x5e        // Keypad [6]
  17. #define    KC_P5        0x5d        // Keypad [5]
  18. #define    KC_P4        0x5c        // Keypad [4]
  19. #define    KC_P3        0x5b        // Keypad [3]
  20. #define    KC_P2        0x5a        // Keypad [2]
  21. #define    KC_P1        0x59        // Keypad [1]
  22. #define    KC_ENTER    0x58        // Keypad [Enter]
  23. #define    KC_PLUS        0x57        // Keypad [+]
  24. #define    KC_MINS        0x56        // Keypad [-]
  25. #define    KC_ASTR        0x55        // Keypad [*]
  26. #define    KC_DIV        0x54        // Keypad [/]
  27. #define KC_NUML        0x53        // [NUM LOCK]
  28. #define    KC_COMMA    0x36        // Keyboard [,]
  29. #define    KC_EQL    (C_SHIFT | 0x2d)    // Keyboard [=] ([SHIFT]+[-])
  30. #define    KC_BS        0x2a        // [BACK SPACE]
  31. #define    KC_ESC        0x29        // [ESC]
  32. #define    KC_9    (C_SHIFT | 0x26)    // Keyboard [)] ([SHIFT]+[9])
  33. #define    KC_8    (C_SHIFT | 0x25)    // Keyboard [(] ([SHIFT]+[8])
  34. //KEY SCAN用 I/O定義
  35. #define ROW_NUM 7
  36. #define COL_NUM 4
  37. const int rowPins[ROW_NUM] = { 2, 3, 4, 5, 6, 7, 8 }; // OUTPUT指定
  38. const int colPins[COL_NUM] = { 9, 10, 16, 14 }; // INPUT_PULLUP指定
  39. //KEY MAP定義(JISコード)
  40. const unsigned int keyMap[ROW_NUM][COL_NUM] = {
  41.   { KC_NUML    , KC_NUML    , KC_NUML    , KC_NUML    }, //MODEキーはダミー
  42.   { KC_NUML    , KC_CALC    , KC_ESC    , KC_BS        }, //NML CALC ESC BS
  43.   { KC_8    , KC_9        , KC_MINS    , KC_DIV    }, // ( ) - /
  44.   { KC_P7    , KC_P8        , KC_P9        , KC_ASTR    }, // 7 8 9 *
  45.   { KC_P4    , KC_P5        , KC_P6        , KC_PLUS    }, // 4 5 6 +
  46.   { KC_P1    , KC_P2        , KC_P3        , KC_EQL    }, // 1 2 3 =
  47.   { KC_P0    , KC_COMMA    , KC_DOT    , KC_ENTER    } // 0 , . RET
  48. };
  49. //LED制御用 I/O定義
  50. #define NUMPIXELS 1 // シリアルLED個数
  51. #define NUM_LOCK_LED 21 // NumLock/動作モード状態LEDポート番号
  52. //シリアルLED定義
  53. // D2812 = NEO_RGB
  54. // WS2812B = NEO_GRB
  55. Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, NUM_LOCK_LED, NEO_GRB + NEO_KHZ800); //NumLock LED制御Pin初期化
  56. //NumLock・LED制御
  57. int R[3]; // LED色 Red (0-255)
  58. int G[3]; // LED色 Green(0-255)
  59. int B[3]; // LED色 Blue (0-255)
  60. //KEY状態制御用配列定義
  61. //KEY状態を前回と最新状態で比較して、変化があった場合にキーコードを送信する
  62. bool cur_key_sts[ROW_NUM][COL_NUM]; //最新のKEY状態
  63. bool old_key_sts[ROW_NUM][COL_NUM]; //前回のKEY状態
  64. void setup()
  65. {
  66.   // put your setup code here, to run once:
  67.   //キースキャン行のPinを初期化する
  68.   for (int i = 0; i < ROW_NUM; i++)
  69.   {
  70.     pinMode(rowPins[i], OUTPUT);
  71.   }
  72.   //キースキャン列のPinを初期化する
  73.   for (int i = 0; i < COL_NUM; i++)
  74.   {
  75.     pinMode(colPins[i], INPUT_PULLUP);
  76.   }
  77.   //キー状態を初期化する
  78.   for (int row = 0; row < ROW_NUM; row++)
  79.   {
  80.     //キー状態を「リリース」とする
  81.     for (int c = 0; c < COL_NUM; c++)
  82.     {
  83.       cur_key_sts[row][c] = HIGH;
  84.       old_key_sts[row][c] = HIGH;
  85.     }
  86.     //キースキャン行のPinをHIGH(inactive)にする
  87.     digitalWrite(rowPins[row], HIGH);
  88.   }
  89.   //LED表示初期化(各動作モード別にRGBで色指定する)
  90.   //色1=緑
  91.   R[0]=0;
  92.   G[0]=10;
  93.   B[0]=0;
  94.   //シリアルLEDライブラリ初期化
  95.   pixels.begin();
  96.   //HIDデバイス初期化(ホストLED状態取得用)
  97.   BootKeyboard.begin();
  98.   //コンシューマー機能初期化
  99.   Consumer.begin();
  100. }
  101. void loop()
  102. {
  103.   // put your main code here, to run repeatedly:
  104.   static int mode = 0;//色変更用
  105.   //キー押下状態変化なしとする(フラグ初期化)
  106.   int chg = 0;        //通常キー
  107.   int media = 0;    //メディアキー
  108.   // key matrix scan
  109.   for (int row = 0; row < ROW_NUM; row++)
  110.   {
  111.     // 行指定:キースキャン開始(LOW出力)
  112.     digitalWrite(rowPins[row], LOW);
  113.     for (int col = 0; col < COL_NUM; col++)
  114.     {
  115.       // 列指定:キー状態読み出し(押下:LOW)
  116.       cur_key_sts[row][col] = digitalRead(colPins[col]);
  117.       // 前回の状態と変化あり?
  118.       if (cur_key_sts[row][col] != old_key_sts[row][col])
  119.       {
  120.         //「キー押下状態変化あり」とする
  121.         chg = 1;
  122.       
  123.       //キーコードをマップから取得
  124.       unsigned int key_code = keyMap[row][col];
  125.       
  126.         // キーが押下されている?
  127.         if (cur_key_sts[row][col] == LOW)
  128.         {
  129.           //メディアキー指定?
  130.           if(key_code & C_MEDIA)
  131.           {
  132.             //メディアキー押下ありとする。
  133.             media = 1;
  134.           }
  135.           else
  136.           {
  137.             //SHIFT+同時押し指定?
  138.             if(key_code & C_SHIFT)
  139.             {
  140.               // SHIFTキー押下
  141.               BootKeyboard.add(KeyboardKeycode(KC_SHIFT));
  142.             }
  143.             // キーコード追加(押下)
  144.             BootKeyboard.add(KeyboardKeycode(key_code&0xff));
  145.           }
  146.         }
  147.         else
  148.         {
  149.           //メディアキー指定?
  150.           if(key_code & C_MEDIA)
  151.           {
  152.             //メディアキーリリース時は何もしない
  153.             ;
  154.           }
  155.           else
  156.           {
  157.             // キーコード削除(リリース)
  158.             BootKeyboard.remove(KeyboardKeycode(key_code&0xff));
  159.             //SHIFT+同時押し指定?
  160.             if(key_code & C_SHIFT)
  161.             {
  162.               // SHIFTキーリリース
  163.               BootKeyboard.remove(KeyboardKeycode(KC_SHIFT));
  164.             }
  165.           }
  166.         }
  167.         //現在のキー状態を前回の状態にコピーする
  168.         old_key_sts[row][col] = cur_key_sts[row][col];
  169.       }
  170.     }
  171.     // 行指定:キースキャン終了(HIGHに戻す)
  172.     digitalWrite(rowPins[row], HIGH);
  173.   }
  174.   //メディアキー押下あり?
  175.   if( media==1 )
  176.   {
  177.     //電卓キーを送信する
  178.     Consumer.write(ConsumerKeycode(CONSUMER_CALCULATOR));
  179.   }
  180.   //キー押下状態変化あり?
  181.   if ( chg == 1 )
  182.   {
  183.     //ホスト側に変化したキーコードを送信する
  184.     BootKeyboard.send();
  185.   }
  186.   //ホスト側のLED状態を取得
  187.   int cur_led_sts = BootKeyboard.getLeds();
  188.   
  189.   //ホスト側NumLock状態はONか
  190.   if( cur_led_sts & LED_NUM_LOCK )
  191.   {
  192.     //LED点灯(key_modeに従いRGB指定する)
  193.     pixels.setPixelColor(0, pixels.Color(R[mode],G[mode],B[mode]));
  194.   }
  195.   else
  196.   {
  197.     //LED消灯(黒)
  198.     pixels.setPixelColor(0, pixels.Color(0,0,0));
  199.   }
  200.   //LED出力
  201.   pixels.show();
  202. }