usb_keypad1.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. #include <stdio.h>
  2. #include "pico/stdlib.h"
  3. #include "hardware/pio.h"
  4. #include "bsp/board_api.h"
  5. #include "tusb.h"
  6. #include "usb_descriptors.h"
  7. #include "keypad.h"
  8. #include "keymap.h"
  9. #include "display.h"
  10. #define KEYBOARD_REPORT_COUNT 6
  11. uint8_t key_report[KEYBOARD_REPORT_COUNT] = {0,0,0,0,0,0};
  12. char report_str[OLED_WIDTH/FONT_WIDTH + 1]; // キーボードレポート表示用
  13. char indicator_str[OLED_WIDTH/FONT_WIDTH + 1]; // LEDインジケーター表示用
  14. char debug_str[OLED_WIDTH/FONT_WIDTH + 1];
  15. // レポート配列をクリア
  16. inline void clear_key_report(void)
  17. {
  18. for(int i = 0; i < KEYBOARD_REPORT_COUNT; i++){
  19. key_report[i] = 0;
  20. }
  21. }
  22. // USBデバイスがマウントされた
  23. void tud_mount_cb(void)
  24. {
  25. clear_key_report();
  26. }
  27. // USBデバイスがアンマウントされた
  28. void tud_umount_cb(void)
  29. {
  30. clear_key_report();
  31. }
  32. // サスペンド状態に移行した
  33. void tud_suspend_cb(bool remote_wakeup_en)
  34. {
  35. (void) remote_wakeup_en;
  36. // 何もしない
  37. }
  38. // レジュームした
  39. void tud_resume_cb(void)
  40. {
  41. // 何もしない
  42. }
  43. // REPORTが完了したら呼び出される
  44. // 次のREPORTを送るのに使える
  45. void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint16_t len)
  46. {
  47. (void) instance;
  48. (void) len;
  49. (void) report;
  50. // 何もしない
  51. }
  52. // コントロールリクエストGET_REPORT
  53. // キーボードではキーレポートを返すことになっている
  54. // だがこないみたいだぞ?
  55. uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen)
  56. {
  57. (void) instance;
  58. (void) report_id;
  59. (void) report_type;
  60. if(reqlen < sizeof(hid_keyboard_report_t) ) {
  61. buffer[0] = 0;
  62. return 1; // とにかく何か返さないと駄目
  63. }
  64. else {
  65. hid_keyboard_report_t report;
  66. report.modifier = 0; // 修飾キー情報
  67. report.reserved = 0;
  68. memcpy(report.keycode, key_report, KEYBOARD_REPORT_COUNT );
  69. memcpy(buffer, &report, sizeof(hid_keyboard_report_t));
  70. return sizeof(hid_keyboard_report_t);
  71. }
  72. }
  73. // コントロールリクエストSET_REPORT
  74. // キーボードではCAPS LOCK等オンボードLEDの制御情報がホストから送られる
  75. void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize)
  76. {
  77. (void) instance;
  78. if( bufsize < 1 ) return; // バッファゼロなら何もしない
  79. if(report_type == HID_REPORT_TYPE_OUTPUT) { // ホスト->デバイス
  80. if(report_id == REPORT_ID_KEYBOARD) { // キーボードレポート
  81. uint8_t leds = buffer[0]; // LED制御情報
  82. sprintf(indicator_str, "%s %s %s",
  83. leds & KEYBOARD_LED_CAPSLOCK ? "CAP" : " ",
  84. leds & KEYBOARD_LED_NUMLOCK ? "NUM" : " ",
  85. leds & KEYBOARD_LED_SCROLLLOCK ? "SCR" : " "
  86. // leds & KEYBOARD_LED_COMPOSE
  87. // leds & KEYBOARD_LED_KANA
  88. );
  89. display_putstr(indicator_str, 0, 0, false);
  90. }
  91. }
  92. }
  93. // キーボードレポート表示
  94. void display_report(void)
  95. {
  96. sprintf(report_str,"%02x%02x%02x%02x%02x%02x", key_report[0],key_report[1],key_report[2],key_report[3],key_report[4],key_report[5]);
  97. display_putstr(report_str, 0, 3, false);
  98. }
  99. // メイン
  100. int main()
  101. {
  102. // TinyUSBの初期化
  103. board_init();
  104. tud_init(BOARD_TUD_RHPORT);
  105. if (board_init_after_tusb) {
  106. board_init_after_tusb();
  107. }
  108. // シリアルコンソール
  109. stdio_init_all();
  110. // OLED表示
  111. display_init();
  112. display_report();
  113. // キーパッド
  114. keypad_init();
  115. while (true) {
  116. tud_task(); // TinyUSB定期的に呼び出す必要がある
  117. key_t key = get_key();
  118. if(tud_mounted()) { // USBデバイスとしてマウントされていれば
  119. if(key.state != KEYPAD_INVALID) { // キー状態に変化あり
  120. uint8_t scancode = keymap[key.code];
  121. if(tud_suspended()) // サスペンド状態なら起こす
  122. tud_remote_wakeup();
  123. if(key.state == KEYPAD_PUSH) { // キーが押された
  124. for(int i = 0; i < KEYBOARD_REPORT_COUNT; i++) {
  125. if(key_report[i] == 0) {
  126. key_report[i] = scancode;
  127. break;
  128. }
  129. }
  130. }
  131. else { // キーオフ
  132. for(int i = 0; i < KEYBOARD_REPORT_COUNT; i++) {
  133. if(key_report[i] == scancode)
  134. key_report[i] = 0;
  135. }
  136. }
  137. // キーボードレポートをOLEDに表示する
  138. display_report();
  139. // 空きがあればキーボードレポート送信
  140. if(tud_hid_ready())
  141. tud_hid_keyboard_report(REPORT_ID_KEYBOARD,0, key_report);
  142. }
  143. }
  144. }
  145. }