#include #include #include #include "lufa.h" #include "print.h" #include "sendchar.h" #include "rn42.h" #include "serial.h" #include "keyboard.h" #include "command.h" #include "keycode.h" #include "action.h" #include "action_util.h" #include "wait.h" #include "suart.h" bool config_mode = false; static int8_t sendchar_func(uint8_t c) { sendchar(c); // LUFA xmit(c); // SUART } static void SetupHardware(void) { /* Disable watchdog if enabled by bootloader/fuses */ MCUSR &= ~(1 << WDRF); wdt_disable(); /* Disable clock division */ clock_prescale_set(clock_div_1); // Leonardo needs. Without this USB device is not recognized. USB_Disable(); USB_Init(); // for Console_Task USB_Device_EnableSOFEvents(); print_set_sendchar(sendchar_func); // SUART PD0:output, PD1:input DDRD |= (1<<0); PORTD |= (1<<0); DDRD &= ~(1<<1); PORTD |= (1<<1); } static bool force_usb = false; int main(void) __attribute__ ((weak)); int main(void) { SetupHardware(); sei(); /* wait for USB startup to get ready for debug output */ uint8_t timeout = 255; // timeout when USB is not available(Bluetooth) while (timeout-- && USB_DeviceState != DEVICE_STATE_Configured) { wait_ms(4); #if defined(INTERRUPT_CONTROL_ENDPOINT) ; #else USB_USBTask(); #endif } print("USB configured.\n"); rn42_init(); print("RN-42 init\n"); /* init modules */ keyboard_init(); if (!rn42_rts()) { host_set_driver(&rn42_driver); } else { host_set_driver(&lufa_driver); } #ifdef SLEEP_LED_ENABLE sleep_led_init(); #endif // ADC for battery //ADMUX = (1< // To get the report over UART set bit3 with SH, command. static enum {LED_INIT, LED_FE, LED_02, LED_01} state = LED_INIT; xprintf("%X\n", c); switch (state) { case LED_INIT: if (c == 0xFE) state = LED_FE; else state = LED_INIT; break; case LED_FE: if (c == 0x02) state = LED_02; else state = LED_INIT; break; case LED_02: if (c == 0x01) state = LED_01; else state = LED_INIT; break; case LED_01: // TODO: move to rn42.c and make accessible with keyboard_leds() xprintf("LED status: %X\n", c); state = LED_INIT; break; default: state = LED_INIT; } } } /* Bluetooth mode when ready */ if (!config_mode && !force_usb) { if (!rn42_rts() && host_get_driver() != &rn42_driver) { clear_keyboard(); host_set_driver(&rn42_driver); } else if (rn42_rts() && host_get_driver() != &lufa_driver) { clear_keyboard(); host_set_driver(&lufa_driver); } } } } /****************************************************************************** * Command ******************************************************************************/ bool command_extra(uint8_t code) { static host_driver_t *prev_driver = &rn42_driver; switch (code) { case KC_H: case KC_SLASH: /* ? */ print("\n\n----- Bluetooth RN-42 Help -----\n"); print("Del: auto_connect/disconnect(enter/exit config mode)\n"); print("i: RN-42 info\n"); print("b: battery voltage\n"); if (config_mode) { return true; } else { print("u: Force USB mode\n"); return false; // to display default command help } case KC_DELETE: if (rn42_autoconnecting()) { rn42_disconnect(); print("\nRN-42: disconnect\n"); print("Enter config mode\n"); print("type $$$ to start and + for local echo\n"); command_state = CONSOLE; config_mode = true; prev_driver = host_get_driver(); clear_keyboard(); host_set_driver(&rn42_config_driver); // null driver; not to send a key to host } else { rn42_autoconnect(); print("\nRN-42: auto_connect\n"); print("Exit config mode\n"); command_state = ONESHOT; config_mode = false; clear_keyboard(); host_set_driver(prev_driver); } return true; case KC_U: if (config_mode) return false; if (force_usb) { print("Auto mode\n"); force_usb = false; } else { print("USB mode\n"); force_usb = true; clear_keyboard(); host_set_driver(&lufa_driver); } return true; case KC_I: print("\n----- RN-42 info -----\n"); xprintf("protocol: %s\n", (host_get_driver() == &rn42_driver) ? "RN-42" : "LUFA"); xprintf("force_usb: %X\n", force_usb); xprintf("rn42_autoconnecting(): %X\n", rn42_autoconnecting()); xprintf("rn42_rts(): %X\n", rn42_rts()); xprintf("config_mode: %X\n", config_mode); return true; case KC_B: // battery monitor ADCSRA |= (1<' : '.'); case KC_SLASH: return (shifted ? '?' : '/'); case KC_DELETE: return '\0'; // Delete to disconnect default: return ' '; } }