Keyboard firmwares for Atmel AVR and Cortex-M
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
10 yıl önce
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. #include <stdint.h>
  2. #include <string.h>
  3. #include <avr/pgmspace.h>
  4. #include <avr/eeprom.h>
  5. #include "keycode.h"
  6. #include "serial.h"
  7. #include "host.h"
  8. #include "action.h"
  9. #include "action_util.h"
  10. #include "lufa.h"
  11. #include "rn42_task.h"
  12. #include "print.h"
  13. #include "debug.h"
  14. #include "timer.h"
  15. #include "wait.h"
  16. #include "command.h"
  17. #include "battery.h"
  18. static bool config_mode = false;
  19. static bool force_usb = false;
  20. static void status_led(bool on)
  21. {
  22. if (on) {
  23. DDRE |= (1<<6);
  24. PORTE &= ~(1<<6);
  25. } else {
  26. DDRE |= (1<<6);
  27. PORTE |= (1<<6);
  28. }
  29. }
  30. void rn42_task_init(void)
  31. {
  32. battery_init();
  33. }
  34. void rn42_task(void)
  35. {
  36. int16_t c;
  37. // Raw mode: interpret output report of LED state
  38. while ((c = rn42_getc()) != -1) {
  39. // LED Out report: 0xFE, 0x02, 0x01, <leds>
  40. // To get the report over UART set bit3 with SH, command.
  41. static enum {LED_INIT, LED_FE, LED_02, LED_01} state = LED_INIT;
  42. switch (state) {
  43. case LED_INIT:
  44. if (c == 0xFE) state = LED_FE;
  45. else {
  46. if (0x0 <= c && c <= 0x7f) xprintf("%c", c);
  47. else xprintf(" %02X", c);
  48. }
  49. break;
  50. case LED_FE:
  51. if (c == 0x02) state = LED_02;
  52. else state = LED_INIT;
  53. break;
  54. case LED_02:
  55. if (c == 0x01) state = LED_01;
  56. else state = LED_INIT;
  57. break;
  58. case LED_01:
  59. dprintf("LED status: %02X\n", c);
  60. rn42_set_leds(c);
  61. state = LED_INIT;
  62. break;
  63. default:
  64. state = LED_INIT;
  65. }
  66. }
  67. /* Bluetooth mode when ready */
  68. if (!config_mode && !force_usb) {
  69. if (!rn42_rts() && host_get_driver() != &rn42_driver) {
  70. clear_keyboard();
  71. host_set_driver(&rn42_driver);
  72. } else if (rn42_rts() && host_get_driver() != &lufa_driver) {
  73. clear_keyboard();
  74. host_set_driver(&lufa_driver);
  75. }
  76. }
  77. static uint16_t prev_timer = 0;
  78. uint16_t e = timer_elapsed(prev_timer);
  79. if (e > 1000) {
  80. /* every second */
  81. prev_timer += e/1000*1000;
  82. /* Low voltage alert */
  83. uint8_t bs = battery_status();
  84. if (bs == LOW_VOLTAGE) {
  85. battery_led(LED_ON);
  86. } else {
  87. battery_led(LED_CHARGER);
  88. }
  89. /* every minute */
  90. uint32_t t = timer_read32()/1000;
  91. if (t%60 == 0) {
  92. uint16_t v = battery_voltage();
  93. uint8_t h = t/3600;
  94. uint8_t m = t%3600/60;
  95. uint8_t s = t%60;
  96. dprintf("%02u:%02u:%02u\t%umV\n", h, m, s, v);
  97. /* TODO: xprintf doesn't work for this.
  98. xprintf("%02u:%02u:%02u\t%umV\n", (t/3600), (t%3600/60), (t%60), v);
  99. */
  100. }
  101. }
  102. /* Connection monitor */
  103. if (!rn42_rts() && rn42_linked()) {
  104. status_led(true);
  105. } else {
  106. status_led(false);
  107. }
  108. }
  109. /******************************************************************************
  110. * Command
  111. ******************************************************************************/
  112. static host_driver_t *prev_driver = &rn42_driver;
  113. static void enter_command_mode(void)
  114. {
  115. prev_driver = host_get_driver();
  116. clear_keyboard();
  117. host_set_driver(&rn42_config_driver); // null driver; not to send a key to host
  118. rn42_disconnect();
  119. while (rn42_linked()) ;
  120. print("Entering config mode ...\n");
  121. wait_ms(1100); // need 1 sec
  122. SEND_COMMAND("$$$");
  123. wait_ms(600); // need 1 sec
  124. rn42_print_response();
  125. const char *s = SEND_COMMAND("v\r\n");
  126. if (strncmp("v", s, 1) != 0) SEND_COMMAND("+\r\n"); // local echo on
  127. }
  128. static void exit_command_mode(void)
  129. {
  130. print("Exiting config mode ...\n");
  131. SEND_COMMAND("---\r\n"); // exit
  132. rn42_autoconnect();
  133. clear_keyboard();
  134. host_set_driver(prev_driver);
  135. }
  136. static void init_rn42(void)
  137. {
  138. // RN-42 configure
  139. if (!config_mode) enter_command_mode();
  140. SEND_COMMAND("SF,1\r\n"); // factory defaults
  141. SEND_COMMAND("S-,TmkBT\r\n");
  142. SEND_COMMAND("SS,Keyboard/Mouse\r\n");
  143. SEND_COMMAND("SM,4\r\n"); // auto connect(DTR)
  144. SEND_COMMAND("SW,8000\r\n"); // Sniff disable
  145. SEND_COMMAND("S~,6\r\n"); // HID profile
  146. SEND_COMMAND("SH,003C\r\n"); // combo device, out-report, 4-reconnect
  147. SEND_COMMAND("SY,FFF4\r\n"); // transmit power -12
  148. SEND_COMMAND("R,1\r\n");
  149. if (!config_mode) exit_command_mode();
  150. }
  151. #if 0
  152. // Switching connections
  153. // NOTE: Remote Address doesn't work in the way manual says.
  154. // EEPROM address for link store
  155. #define RN42_LINK0 (uint8_t *)128
  156. #define RN42_LINK1 (uint8_t *)140
  157. #define RN42_LINK2 (uint8_t *)152
  158. #define RN42_LINK3 (uint8_t *)164
  159. static void store_link(uint8_t *eeaddr)
  160. {
  161. enter_command_mode();
  162. SEND_STR("GR\r\n"); // remote address
  163. const char *s = rn42_gets(500);
  164. if (strcmp("GR", s) == 0) s = rn42_gets(500); // ignore local echo
  165. xprintf("%s(%d)\r\n", s, strlen(s));
  166. if (strlen(s) == 12) {
  167. for (int i = 0; i < 12; i++) {
  168. eeprom_write_byte(eeaddr+i, *(s+i));
  169. dprintf("%c ", *(s+i));
  170. }
  171. dprint("\r\n");
  172. }
  173. exit_command_mode();
  174. }
  175. static void restore_link(const uint8_t *eeaddr)
  176. {
  177. enter_command_mode();
  178. SEND_COMMAND("SR,Z\r\n"); // remove remote address
  179. SEND_STR("SR,"); // set remote address from EEPROM
  180. for (int i = 0; i < 12; i++) {
  181. uint8_t c = eeprom_read_byte(eeaddr+i);
  182. rn42_putc(c);
  183. dprintf("%c ", c);
  184. }
  185. dprintf("\r\n");
  186. SEND_COMMAND("\r\n");
  187. SEND_COMMAND("R,1\r\n"); // reboot
  188. exit_command_mode();
  189. }
  190. static const char *get_link(uint8_t * eeaddr)
  191. {
  192. static char s[13];
  193. for (int i = 0; i < 12; i++) {
  194. uint8_t c = eeprom_read_byte(eeaddr+i);
  195. s[i] = c;
  196. }
  197. s[12] = '\0';
  198. return s;
  199. }
  200. #endif
  201. static void pairing(void)
  202. {
  203. enter_command_mode();
  204. SEND_COMMAND("SR,Z\r\n"); // remove remote address
  205. SEND_COMMAND("R,1\r\n"); // reboot
  206. exit_command_mode();
  207. }
  208. bool command_extra(uint8_t code)
  209. {
  210. uint32_t t;
  211. uint16_t b;
  212. switch (code) {
  213. case KC_H:
  214. case KC_SLASH: /* ? */
  215. print("\n\n----- Bluetooth RN-42 Help -----\n");
  216. print("i: RN-42 info\n");
  217. print("b: battery voltage\n");
  218. print("Del: enter/exit RN-42 config mode\n");
  219. print("Slck: RN-42 initialize\n");
  220. #if 0
  221. print("1-4: restore link\n");
  222. print("F1-F4: store link\n");
  223. #endif
  224. print("p: pairing\n");
  225. if (config_mode) {
  226. return true;
  227. } else {
  228. print("u: toggle Force USB mode\n");
  229. return false; // to display default command help
  230. }
  231. case KC_P:
  232. pairing();
  233. return true;
  234. #if 0
  235. /* Store link address to EEPROM */
  236. case KC_F1:
  237. store_link(RN42_LINK0);
  238. return true;
  239. case KC_F2:
  240. store_link(RN42_LINK1);
  241. return true;
  242. case KC_F3:
  243. store_link(RN42_LINK2);
  244. return true;
  245. case KC_F4:
  246. store_link(RN42_LINK3);
  247. return true;
  248. /* Restore link address to EEPROM */
  249. case KC_1:
  250. restore_link(RN42_LINK0);
  251. return true;
  252. case KC_2:
  253. restore_link(RN42_LINK1);
  254. return true;
  255. case KC_3:
  256. restore_link(RN42_LINK2);
  257. return true;
  258. case KC_4:
  259. restore_link(RN42_LINK3);
  260. return true;
  261. #endif
  262. case KC_I:
  263. print("\n----- RN-42 info -----\n");
  264. xprintf("protocol: %s\n", (host_get_driver() == &rn42_driver) ? "RN-42" : "LUFA");
  265. xprintf("force_usb: %X\n", force_usb);
  266. xprintf("rn42: %s\n", rn42_rts() ? "OFF" : (rn42_linked() ? "CONN" : "ON"));
  267. xprintf("rn42_autoconnecting(): %X\n", rn42_autoconnecting());
  268. xprintf("config_mode: %X\n", config_mode);
  269. xprintf("USB State: %s\n",
  270. (USB_DeviceState == DEVICE_STATE_Unattached) ? "Unattached" :
  271. (USB_DeviceState == DEVICE_STATE_Powered) ? "Powered" :
  272. (USB_DeviceState == DEVICE_STATE_Default) ? "Default" :
  273. (USB_DeviceState == DEVICE_STATE_Addressed) ? "Addressed" :
  274. (USB_DeviceState == DEVICE_STATE_Configured) ? "Configured" :
  275. (USB_DeviceState == DEVICE_STATE_Suspended) ? "Suspended" : "?");
  276. xprintf("battery: ");
  277. switch (battery_status()) {
  278. case FULL_CHARGED: xprintf("FULL"); break;
  279. case CHARGING: xprintf("CHARG"); break;
  280. case DISCHARGING: xprintf("DISCHG"); break;
  281. case LOW_VOLTAGE: xprintf("LOW"); break;
  282. default: xprintf("?"); break;
  283. };
  284. xprintf("\n");
  285. xprintf("RemoteWakeupEnabled: %X\n", USB_Device_RemoteWakeupEnabled);
  286. xprintf("VBUS: %X\n", USBSTA&(1<<VBUS));
  287. t = timer_read32()/1000;
  288. uint8_t d = t/3600/24;
  289. uint8_t h = t/3600;
  290. uint8_t m = t%3600/60;
  291. uint8_t s = t%60;
  292. xprintf("uptime: %02u %02u:%02u:%02u\n", d, h, m, s);
  293. #if 0
  294. xprintf("LINK0: %s\r\n", get_link(RN42_LINK0));
  295. xprintf("LINK1: %s\r\n", get_link(RN42_LINK1));
  296. xprintf("LINK2: %s\r\n", get_link(RN42_LINK2));
  297. xprintf("LINK3: %s\r\n", get_link(RN42_LINK3));
  298. #endif
  299. return true;
  300. case KC_B:
  301. // battery monitor
  302. t = timer_read32()/1000;
  303. b = battery_voltage();
  304. xprintf("BAT: %umV\t", b);
  305. xprintf("%02u:", t/3600);
  306. xprintf("%02u:", t%3600/60);
  307. xprintf("%02u\n", t%60);
  308. return true;
  309. case KC_U:
  310. if (config_mode) return false;
  311. if (force_usb) {
  312. print("Auto mode\n");
  313. force_usb = false;
  314. } else {
  315. print("USB mode\n");
  316. force_usb = true;
  317. clear_keyboard();
  318. host_set_driver(&lufa_driver);
  319. }
  320. return true;
  321. case KC_DELETE:
  322. /* RN-42 Command mode */
  323. if (rn42_autoconnecting()) {
  324. enter_command_mode();
  325. command_state = CONSOLE;
  326. config_mode = true;
  327. } else {
  328. exit_command_mode();
  329. command_state = ONESHOT;
  330. config_mode = false;
  331. }
  332. return true;
  333. case KC_SCROLLLOCK:
  334. init_rn42();
  335. return true;
  336. default:
  337. if (config_mode)
  338. return true;
  339. else
  340. return false; // yield to default command
  341. }
  342. return true;
  343. }
  344. /*
  345. * RN-42 Command mode
  346. * sends charactors to the module
  347. */
  348. static uint8_t code2asc(uint8_t code);
  349. bool command_console_extra(uint8_t code)
  350. {
  351. rn42_putc(code2asc(code));
  352. return true;
  353. }
  354. // convert keycode into ascii charactor
  355. static uint8_t code2asc(uint8_t code)
  356. {
  357. bool shifted = (get_mods() & (MOD_BIT(KC_LSHIFT)|MOD_BIT(KC_RSHIFT))) ? true : false;
  358. switch (code) {
  359. case KC_A: return (shifted ? 'A' : 'a');
  360. case KC_B: return (shifted ? 'B' : 'b');
  361. case KC_C: return (shifted ? 'C' : 'c');
  362. case KC_D: return (shifted ? 'D' : 'd');
  363. case KC_E: return (shifted ? 'E' : 'e');
  364. case KC_F: return (shifted ? 'F' : 'f');
  365. case KC_G: return (shifted ? 'G' : 'g');
  366. case KC_H: return (shifted ? 'H' : 'h');
  367. case KC_I: return (shifted ? 'I' : 'i');
  368. case KC_J: return (shifted ? 'J' : 'j');
  369. case KC_K: return (shifted ? 'K' : 'k');
  370. case KC_L: return (shifted ? 'L' : 'l');
  371. case KC_M: return (shifted ? 'M' : 'm');
  372. case KC_N: return (shifted ? 'N' : 'n');
  373. case KC_O: return (shifted ? 'O' : 'o');
  374. case KC_P: return (shifted ? 'P' : 'p');
  375. case KC_Q: return (shifted ? 'Q' : 'q');
  376. case KC_R: return (shifted ? 'R' : 'r');
  377. case KC_S: return (shifted ? 'S' : 's');
  378. case KC_T: return (shifted ? 'T' : 't');
  379. case KC_U: return (shifted ? 'U' : 'u');
  380. case KC_V: return (shifted ? 'V' : 'v');
  381. case KC_W: return (shifted ? 'W' : 'w');
  382. case KC_X: return (shifted ? 'X' : 'x');
  383. case KC_Y: return (shifted ? 'Y' : 'y');
  384. case KC_Z: return (shifted ? 'Z' : 'z');
  385. case KC_1: return (shifted ? '!' : '1');
  386. case KC_2: return (shifted ? '@' : '2');
  387. case KC_3: return (shifted ? '#' : '3');
  388. case KC_4: return (shifted ? '$' : '4');
  389. case KC_5: return (shifted ? '%' : '5');
  390. case KC_6: return (shifted ? '^' : '6');
  391. case KC_7: return (shifted ? '&' : '7');
  392. case KC_8: return (shifted ? '*' : '8');
  393. case KC_9: return (shifted ? '(' : '9');
  394. case KC_0: return (shifted ? ')' : '0');
  395. case KC_ENTER: return '\n';
  396. case KC_ESCAPE: return 0x1B;
  397. case KC_BSPACE: return '\b';
  398. case KC_TAB: return '\t';
  399. case KC_SPACE: return ' ';
  400. case KC_MINUS: return (shifted ? '_' : '-');
  401. case KC_EQUAL: return (shifted ? '+' : '=');
  402. case KC_LBRACKET: return (shifted ? '{' : '[');
  403. case KC_RBRACKET: return (shifted ? '}' : ']');
  404. case KC_BSLASH: return (shifted ? '|' : '\\');
  405. case KC_NONUS_HASH: return (shifted ? '|' : '\\');
  406. case KC_SCOLON: return (shifted ? ':' : ';');
  407. case KC_QUOTE: return (shifted ? '"' : '\'');
  408. case KC_GRAVE: return (shifted ? '~' : '`');
  409. case KC_COMMA: return (shifted ? '<' : ',');
  410. case KC_DOT: return (shifted ? '>' : '.');
  411. case KC_SLASH: return (shifted ? '?' : '/');
  412. case KC_DELETE: return '\0'; // Delete to disconnect
  413. default: return ' ';
  414. }
  415. }