Add rn42_task
parent
fa545c87f7
commit
b4e4f599df
|
@ -1,9 +1,13 @@
|
||||||
Roving RN-42
|
Roving RN-42
|
||||||
============
|
============
|
||||||
|
07/16 After fix of voltage dividor on GPIO6, had a trouble that it could not send a char to BT module, though could receive.
|
||||||
|
Found R8 had wrong 1K resistor and changed to 10K, after that it can send to the module again. Not sure how it had sent with the wrong 1K before.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
TODO
|
TODO
|
||||||
----
|
----
|
||||||
|
- Factroy reset doesn't work; need to test again. 10K pull-up is too high?
|
||||||
- Lipo voltage ADC sensing
|
- Lipo voltage ADC sensing
|
||||||
- Lipo charger configuration: fast charge time: USB charger spec?
|
- Lipo charger configuration: fast charge time: USB charger spec?
|
||||||
- Low voltage alarm: LED indcates voltage of Lipo
|
- Low voltage alarm: LED indcates voltage of Lipo
|
||||||
|
@ -28,39 +32,6 @@ DONE:
|
||||||
|
|
||||||
Configuration
|
Configuration
|
||||||
-------------
|
-------------
|
||||||
Ver 6.15 04/26/2013
|
|
||||||
(c) Roving Networks
|
|
||||||
***Settings***
|
|
||||||
BTA=0006664B3AE3
|
|
||||||
BTName=tmkBT-3AE3
|
|
||||||
Baudrt(SW4)=115K
|
|
||||||
Mode =Pair
|
|
||||||
Authen=2
|
|
||||||
Bonded=1
|
|
||||||
Rem=001BDC06415B
|
|
||||||
***ADVANCED Settings***
|
|
||||||
SrvName= keyboard/mouse
|
|
||||||
SrvClass=0000
|
|
||||||
DevClass=05C0
|
|
||||||
InqWindw=0100
|
|
||||||
PagWindw=0100
|
|
||||||
CfgTimer=255
|
|
||||||
StatuStr=NULL
|
|
||||||
HidFlags=3f
|
|
||||||
DTRtimer=8
|
|
||||||
KeySwapr=0
|
|
||||||
***OTHER Settings***
|
|
||||||
Profile= HID
|
|
||||||
CfgChar= $
|
|
||||||
SniffEna=0
|
|
||||||
LowPower=0
|
|
||||||
TX Power=4
|
|
||||||
IOPorts= 0
|
|
||||||
IOValues=0
|
|
||||||
Sleeptmr=0
|
|
||||||
DebugMod=0
|
|
||||||
RoleSwch=0
|
|
||||||
|
|
||||||
Ver 6.15 04/26/2013
|
Ver 6.15 04/26/2013
|
||||||
(c) Roving Networks
|
(c) Roving Networks
|
||||||
***Settings***
|
***Settings***
|
||||||
|
@ -70,7 +41,7 @@ Baudrt(SW4)=115K
|
||||||
Mode =DTR
|
Mode =DTR
|
||||||
Authen=2
|
Authen=2
|
||||||
Bonded=0
|
Bonded=0
|
||||||
Rem=BCF5AC9BCB7E
|
Rem=000000000000
|
||||||
***ADVANCED Settings***
|
***ADVANCED Settings***
|
||||||
SrvName= keyboard/mouse
|
SrvName= keyboard/mouse
|
||||||
SrvClass=0000
|
SrvClass=0000
|
||||||
|
@ -79,15 +50,15 @@ InqWindw=0100
|
||||||
PagWindw=0100
|
PagWindw=0100
|
||||||
CfgTimer=255
|
CfgTimer=255
|
||||||
StatuStr=NULL
|
StatuStr=NULL
|
||||||
HidFlags=3f
|
HidFlags=3c
|
||||||
DTRtimer=8
|
DTRtimer=8
|
||||||
KeySwapr=0
|
KeySwapr=0
|
||||||
***OTHER Settings***
|
***OTHER Settings***
|
||||||
Profile= HID
|
Profile= HID
|
||||||
CfgChar= $
|
CfgChar= $
|
||||||
SniffEna=0
|
SniffEna=8010
|
||||||
LowPower=0
|
LowPower=0
|
||||||
TX Power=ffe8
|
TX Power=0
|
||||||
IOPorts= 0
|
IOPorts= 0
|
||||||
IOValues=0
|
IOValues=0
|
||||||
Sleeptmr=0
|
Sleeptmr=0
|
||||||
|
@ -95,27 +66,38 @@ DebugMod=0
|
||||||
RoleSwch=0
|
RoleSwch=0
|
||||||
|
|
||||||
|
|
||||||
command mode
|
|
||||||
------------
|
|
||||||
To enter command mode disconnect the module from host and type '$$$'.(you will see 'CMD')
|
|
||||||
To exit type '---'.(you will see 'END')
|
|
||||||
|
|
||||||
|
Serial connection
|
||||||
|
-----------------
|
||||||
Serial line: 115200bps, 8bit, 1-stopbit, non-parity, no flow control
|
Serial line: 115200bps, 8bit, 1-stopbit, non-parity, no flow control
|
||||||
SSP: 115200bps, 8bit, 1-stopbit, non-parity, no flow control(via Bluetooth)
|
SSP: 115200bps, 8bit, 1-stopbit, non-parity, no flow control(via Bluetooth)
|
||||||
|
|
||||||
|
To enter command mode disconnect the module from host and type '$$$'.(you will see 'CMD')
|
||||||
|
To exit type '---'(you will see 'END') and '+' to get local echo.
|
||||||
|
|
||||||
S-,tmkBT // Device name
|
|
||||||
SH,0038 // HID register
|
|
||||||
|
Setting command mode
|
||||||
|
--------------------
|
||||||
|
S-,tmkBT // Device name
|
||||||
|
SS,keyboard/mouse // service name
|
||||||
|
SM,4 // Auto Connect DTR mode
|
||||||
|
SW,8010 // Sniff enable 0x10*0.625ms=10ms; 50ms is laggish and not much power save
|
||||||
|
S~,6 // HID profile
|
||||||
|
SH,003C // HID register
|
||||||
|
SY,0004 // Transmit power
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Other options:
|
||||||
SC,0000 // COD: 000005C0 (see HID spec/Bluegiga doc)
|
SC,0000 // COD: 000005C0 (see HID spec/Bluegiga doc)
|
||||||
SD,05C0 // bit 12-8 7 6 5-0
|
SD,05C0 // bit 12-8 7 6 5-0
|
||||||
// 00101 1 1 0
|
// 00101 1 1 0
|
||||||
// peripheral pointing keybaord joystick, gamepad, ...
|
// peripheral pointing keybaord joystick, gamepad, ...
|
||||||
S~,6 // HID profile
|
|
||||||
SS,keyboard/mouse // service name
|
|
||||||
SM,6 // Pairing mode: auto connect
|
SM,6 // Pairing mode: auto connect
|
||||||
SM,4 // Master mode: Connection can be controled with GPIO6
|
SM,4 // Master mode: Connection can be controled with GPIO6
|
||||||
|
|
||||||
SY,FEE8 // lower power -20dbM
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -197,7 +179,7 @@ Sniff mode Transmit
|
||||||
|
|
||||||
Deep sleep Idle (3.1.2)
|
Deep sleep Idle (3.1.2)
|
||||||
In this mode the module shuts down completly and only draws about 300uA. To enable this set the most signifant bit(0x8000) of Sniff interaval timer.
|
In this mode the module shuts down completly and only draws about 300uA. To enable this set the most signifant bit(0x8000) of Sniff interaval timer.
|
||||||
SW,8320 // deep sleep enable(interval=0x320*0.625ms)
|
SW,8320 // deep sleep enable(interval=0x320*0.625=500ms)
|
||||||
In normal sleep the firmware is still running in idle mode, and wakes up about 20 times per second to check ports, update LEDs, etc. During deep sleep, the firmware actually stops runnig some tasks and the LEDs only update about once per second.
|
In normal sleep the firmware is still running in idle mode, and wakes up about 20 times per second to check ports, update LEDs, etc. During deep sleep, the firmware actually stops runnig some tasks and the LEDs only update about once per second.
|
||||||
To wake from deep sleep there are three ways: (in worst case wake up takes 5ms)
|
To wake from deep sleep there are three ways: (in worst case wake up takes 5ms)
|
||||||
*send a charactor to the UART(first charactor will be lost)
|
*send a charactor to the UART(first charactor will be lost)
|
||||||
|
|
|
@ -55,6 +55,7 @@ SRC += keymap_common.c \
|
||||||
serial_uart.c \
|
serial_uart.c \
|
||||||
suart.S \
|
suart.S \
|
||||||
rn42.c \
|
rn42.c \
|
||||||
|
rn42_task.c \
|
||||||
main.c
|
main.c
|
||||||
|
|
||||||
ifdef KEYMAP
|
ifdef KEYMAP
|
||||||
|
|
|
@ -20,7 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
#define VENDOR_ID 0xFEED
|
#define VENDOR_ID 0xFEED
|
||||||
#define PRODUCT_ID 0xCAFE
|
#define PRODUCT_ID 0x4242
|
||||||
#define DEVICE_VER 0x0104
|
#define DEVICE_VER 0x0104
|
||||||
#define MANUFACTURER t.m.k.
|
#define MANUFACTURER t.m.k.
|
||||||
#define PRODUCT HHKB mod
|
#define PRODUCT HHKB mod
|
||||||
|
|
|
@ -5,21 +5,20 @@
|
||||||
#include "print.h"
|
#include "print.h"
|
||||||
#include "sendchar.h"
|
#include "sendchar.h"
|
||||||
#include "rn42.h"
|
#include "rn42.h"
|
||||||
|
#include "rn42_task.h"
|
||||||
#include "serial.h"
|
#include "serial.h"
|
||||||
#include "keyboard.h"
|
#include "keyboard.h"
|
||||||
#include "command.h"
|
|
||||||
#include "keycode.h"
|
#include "keycode.h"
|
||||||
#include "action.h"
|
#include "action.h"
|
||||||
#include "action_util.h"
|
#include "action_util.h"
|
||||||
#include "wait.h"
|
#include "wait.h"
|
||||||
#include "suart.h"
|
#include "suart.h"
|
||||||
|
|
||||||
bool config_mode = false;
|
|
||||||
|
|
||||||
static int8_t sendchar_func(uint8_t c)
|
static int8_t sendchar_func(uint8_t c)
|
||||||
{
|
{
|
||||||
sendchar(c); // LUFA
|
sendchar(c); // LUFA
|
||||||
xmit(c); // SUART
|
xmit(c); // SUART
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetupHardware(void)
|
static void SetupHardware(void)
|
||||||
|
@ -47,7 +46,6 @@ static void SetupHardware(void)
|
||||||
PORTD |= (1<<1);
|
PORTD |= (1<<1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool force_usb = false;
|
|
||||||
int main(void) __attribute__ ((weak));
|
int main(void) __attribute__ ((weak));
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
@ -67,6 +65,7 @@ int main(void)
|
||||||
print("USB configured.\n");
|
print("USB configured.\n");
|
||||||
|
|
||||||
rn42_init();
|
rn42_init();
|
||||||
|
rn42_task_init();
|
||||||
print("RN-42 init\n");
|
print("RN-42 init\n");
|
||||||
|
|
||||||
/* init modules */
|
/* init modules */
|
||||||
|
@ -82,22 +81,14 @@ int main(void)
|
||||||
sleep_led_init();
|
sleep_led_init();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// ADC for battery
|
|
||||||
//ADMUX = (1<<REFS0); // Ref:AVCC, Input:ADC0(PF0)
|
|
||||||
ADMUX = (1<<REFS1) | (1<<REFS0); // Ref:AVCC, Input:ADC0(PF0)
|
|
||||||
ADCSRA = (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); // Prescale:128
|
|
||||||
ADCSRA |= (1<<ADEN); // enable ADC
|
|
||||||
|
|
||||||
print("Keyboard start.\n");
|
print("Keyboard start.\n");
|
||||||
while (1) {
|
while (1) {
|
||||||
/*
|
|
||||||
while (USB_DeviceState == DEVICE_STATE_Suspended) {
|
while (USB_DeviceState == DEVICE_STATE_Suspended) {
|
||||||
suspend_power_down();
|
suspend_power_down();
|
||||||
if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
|
if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
|
||||||
USB_Device_SendRemoteWakeup();
|
USB_Device_SendRemoteWakeup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
keyboard_task();
|
keyboard_task();
|
||||||
|
|
||||||
|
@ -105,214 +96,6 @@ int main(void)
|
||||||
USB_USBTask();
|
USB_USBTask();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int16_t c;
|
rn42_task();
|
||||||
if (config_mode) {
|
|
||||||
while ((c = serial_recv2()) != -1) {
|
|
||||||
// without flow control it'll fail to receive data when flooded
|
|
||||||
rn42_cts_hi();
|
|
||||||
xprintf("%c", c);
|
|
||||||
rn42_cts_lo();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
while ((c = serial_recv2()) != -1) {
|
|
||||||
// LED Out report: 0xFE, 0x02, 0x01, <leds>
|
|
||||||
// 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<<ADEN) | (1<<ADSC);
|
|
||||||
while (ADCSRA & (1<<ADSC)) ;
|
|
||||||
uint16_t bat = ADCL;
|
|
||||||
bat = ADCH<<8 | bat;
|
|
||||||
xprintf("BAT: %04X\n", bat);
|
|
||||||
|
|
||||||
ADCSRA |= (1<<ADEN) | (1<<ADSC);
|
|
||||||
while (ADCSRA & (1<<ADSC)) ;
|
|
||||||
bat = ADCL;
|
|
||||||
bat = ADCH<<8 | bat;
|
|
||||||
xprintf("BAT: %04X\n", bat);
|
|
||||||
|
|
||||||
ADCSRA &= ~(1<<ADEN);
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
if (config_mode)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false; // exec default command
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t code2asc(uint8_t code);
|
|
||||||
bool command_console_extra(uint8_t code)
|
|
||||||
{
|
|
||||||
switch (code) {
|
|
||||||
default:
|
|
||||||
rn42_putc(code2asc(code));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// convert keycode into ascii charactor
|
|
||||||
static uint8_t code2asc(uint8_t code)
|
|
||||||
{
|
|
||||||
bool shifted = (get_mods() & (MOD_BIT(KC_LSHIFT)|MOD_BIT(KC_RSHIFT))) ? true : false;
|
|
||||||
switch (code) {
|
|
||||||
case KC_A: return (shifted ? 'A' : 'a');
|
|
||||||
case KC_B: return (shifted ? 'B' : 'b');
|
|
||||||
case KC_C: return (shifted ? 'C' : 'c');
|
|
||||||
case KC_D: return (shifted ? 'D' : 'd');
|
|
||||||
case KC_E: return (shifted ? 'E' : 'e');
|
|
||||||
case KC_F: return (shifted ? 'F' : 'f');
|
|
||||||
case KC_G: return (shifted ? 'G' : 'g');
|
|
||||||
case KC_H: return (shifted ? 'H' : 'h');
|
|
||||||
case KC_I: return (shifted ? 'I' : 'i');
|
|
||||||
case KC_J: return (shifted ? 'J' : 'j');
|
|
||||||
case KC_K: return (shifted ? 'K' : 'k');
|
|
||||||
case KC_L: return (shifted ? 'L' : 'l');
|
|
||||||
case KC_M: return (shifted ? 'M' : 'm');
|
|
||||||
case KC_N: return (shifted ? 'N' : 'n');
|
|
||||||
case KC_O: return (shifted ? 'O' : 'o');
|
|
||||||
case KC_P: return (shifted ? 'P' : 'p');
|
|
||||||
case KC_Q: return (shifted ? 'Q' : 'q');
|
|
||||||
case KC_R: return (shifted ? 'R' : 'r');
|
|
||||||
case KC_S: return (shifted ? 'S' : 's');
|
|
||||||
case KC_T: return (shifted ? 'T' : 't');
|
|
||||||
case KC_U: return (shifted ? 'U' : 'u');
|
|
||||||
case KC_V: return (shifted ? 'V' : 'v');
|
|
||||||
case KC_W: return (shifted ? 'W' : 'w');
|
|
||||||
case KC_X: return (shifted ? 'X' : 'x');
|
|
||||||
case KC_Y: return (shifted ? 'Y' : 'y');
|
|
||||||
case KC_Z: return (shifted ? 'Z' : 'z');
|
|
||||||
case KC_1: return (shifted ? '!' : '1');
|
|
||||||
case KC_2: return (shifted ? '@' : '2');
|
|
||||||
case KC_3: return (shifted ? '#' : '3');
|
|
||||||
case KC_4: return (shifted ? '$' : '4');
|
|
||||||
case KC_5: return (shifted ? '%' : '5');
|
|
||||||
case KC_6: return (shifted ? '^' : '6');
|
|
||||||
case KC_7: return (shifted ? '&' : '7');
|
|
||||||
case KC_8: return (shifted ? '*' : '8');
|
|
||||||
case KC_9: return (shifted ? '(' : '9');
|
|
||||||
case KC_0: return (shifted ? ')' : '0');
|
|
||||||
case KC_ENTER: return '\n';
|
|
||||||
case KC_ESCAPE: return 0x1B;
|
|
||||||
case KC_BSPACE: return '\b';
|
|
||||||
case KC_TAB: return '\t';
|
|
||||||
case KC_SPACE: return ' ';
|
|
||||||
case KC_MINUS: return (shifted ? '_' : '-');
|
|
||||||
case KC_EQUAL: return (shifted ? '+' : '=');
|
|
||||||
case KC_LBRACKET: return (shifted ? '{' : '[');
|
|
||||||
case KC_RBRACKET: return (shifted ? '}' : ']');
|
|
||||||
case KC_BSLASH: return (shifted ? '|' : '\\');
|
|
||||||
case KC_NONUS_HASH: return (shifted ? '|' : '\\');
|
|
||||||
case KC_SCOLON: return (shifted ? ':' : ';');
|
|
||||||
case KC_QUOTE: return (shifted ? '"' : '\'');
|
|
||||||
case KC_GRAVE: return (shifted ? '~' : '`');
|
|
||||||
case KC_COMMA: return (shifted ? '<' : ',');
|
|
||||||
case KC_DOT: return (shifted ? '>' : '.');
|
|
||||||
case KC_SLASH: return (shifted ? '?' : '/');
|
|
||||||
case KC_DELETE: return '\0'; // Delete to disconnect
|
|
||||||
default: return ' ';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include <avr/io.h>
|
||||||
#include "host.h"
|
#include "host.h"
|
||||||
#include "host_driver.h"
|
#include "host_driver.h"
|
||||||
#include "serial.h"
|
#include "serial.h"
|
||||||
|
|
|
@ -0,0 +1,255 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "keycode.h"
|
||||||
|
#include "serial.h"
|
||||||
|
#include "host.h"
|
||||||
|
#include "action.h"
|
||||||
|
#include "action_util.h"
|
||||||
|
#include "lufa.h"
|
||||||
|
#include "rn42_task.h"
|
||||||
|
#include "print.h"
|
||||||
|
#include "timer.h"
|
||||||
|
#include "command.h"
|
||||||
|
|
||||||
|
static bool config_mode = false;
|
||||||
|
static bool force_usb = false;
|
||||||
|
|
||||||
|
static void battery_adc_init(void)
|
||||||
|
{
|
||||||
|
ADMUX = (1<<REFS1) | (1<<REFS0); // Ref:2.56V band-gap, Input:ADC0(PF0)
|
||||||
|
ADCSRA = (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); // Prescale:128 16MHz/128=125KHz
|
||||||
|
ADCSRA |= (1<<ADEN); // enable ADC
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t battery_adc(void)
|
||||||
|
{
|
||||||
|
volatile uint16_t bat;
|
||||||
|
ADCSRA |= (1<<ADEN);
|
||||||
|
|
||||||
|
// discard first result
|
||||||
|
ADCSRA |= (1<<ADSC);
|
||||||
|
while (ADCSRA & (1<<ADSC)) ;
|
||||||
|
bat = ADC;
|
||||||
|
|
||||||
|
// discard second result
|
||||||
|
ADCSRA |= (1<<ADSC);
|
||||||
|
while (ADCSRA & (1<<ADSC)) ;
|
||||||
|
bat = ADC;
|
||||||
|
|
||||||
|
ADCSRA |= (1<<ADSC);
|
||||||
|
while (ADCSRA & (1<<ADSC)) ;
|
||||||
|
bat = ADC;
|
||||||
|
|
||||||
|
ADCSRA &= ~(1<<ADEN);
|
||||||
|
return bat;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void rn42_task_init(void)
|
||||||
|
{
|
||||||
|
battery_adc_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void rn42_task(void)
|
||||||
|
{
|
||||||
|
int16_t c;
|
||||||
|
if (config_mode) {
|
||||||
|
// Config mode: print output from RN-42
|
||||||
|
while ((c = serial_recv2()) != -1) {
|
||||||
|
// without flow control it'll fail to receive data when flooded
|
||||||
|
rn42_cts_hi();
|
||||||
|
xprintf("%c", c);
|
||||||
|
rn42_cts_lo();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Raw mode: interpret output report of LED state
|
||||||
|
while ((c = serial_recv2()) != -1) {
|
||||||
|
// LED Out report: 0xFE, 0x02, 0x01, <leds>
|
||||||
|
// 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("%02X\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: %02X\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: enter/exit config mode(auto_connect/disconnect)\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()) {
|
||||||
|
prev_driver = host_get_driver();
|
||||||
|
clear_keyboard();
|
||||||
|
_delay_ms(500);
|
||||||
|
host_set_driver(&rn42_config_driver); // null driver; not to send a key to host
|
||||||
|
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;
|
||||||
|
} 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
|
||||||
|
xprintf("BAT: %04X(%08lX)\n", battery_adc(), timer_read32());
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
if (config_mode)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false; // exec default command
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t code2asc(uint8_t code);
|
||||||
|
bool command_console_extra(uint8_t code)
|
||||||
|
{
|
||||||
|
switch (code) {
|
||||||
|
default:
|
||||||
|
rn42_putc(code2asc(code));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert keycode into ascii charactor
|
||||||
|
static uint8_t code2asc(uint8_t code)
|
||||||
|
{
|
||||||
|
bool shifted = (get_mods() & (MOD_BIT(KC_LSHIFT)|MOD_BIT(KC_RSHIFT))) ? true : false;
|
||||||
|
switch (code) {
|
||||||
|
case KC_A: return (shifted ? 'A' : 'a');
|
||||||
|
case KC_B: return (shifted ? 'B' : 'b');
|
||||||
|
case KC_C: return (shifted ? 'C' : 'c');
|
||||||
|
case KC_D: return (shifted ? 'D' : 'd');
|
||||||
|
case KC_E: return (shifted ? 'E' : 'e');
|
||||||
|
case KC_F: return (shifted ? 'F' : 'f');
|
||||||
|
case KC_G: return (shifted ? 'G' : 'g');
|
||||||
|
case KC_H: return (shifted ? 'H' : 'h');
|
||||||
|
case KC_I: return (shifted ? 'I' : 'i');
|
||||||
|
case KC_J: return (shifted ? 'J' : 'j');
|
||||||
|
case KC_K: return (shifted ? 'K' : 'k');
|
||||||
|
case KC_L: return (shifted ? 'L' : 'l');
|
||||||
|
case KC_M: return (shifted ? 'M' : 'm');
|
||||||
|
case KC_N: return (shifted ? 'N' : 'n');
|
||||||
|
case KC_O: return (shifted ? 'O' : 'o');
|
||||||
|
case KC_P: return (shifted ? 'P' : 'p');
|
||||||
|
case KC_Q: return (shifted ? 'Q' : 'q');
|
||||||
|
case KC_R: return (shifted ? 'R' : 'r');
|
||||||
|
case KC_S: return (shifted ? 'S' : 's');
|
||||||
|
case KC_T: return (shifted ? 'T' : 't');
|
||||||
|
case KC_U: return (shifted ? 'U' : 'u');
|
||||||
|
case KC_V: return (shifted ? 'V' : 'v');
|
||||||
|
case KC_W: return (shifted ? 'W' : 'w');
|
||||||
|
case KC_X: return (shifted ? 'X' : 'x');
|
||||||
|
case KC_Y: return (shifted ? 'Y' : 'y');
|
||||||
|
case KC_Z: return (shifted ? 'Z' : 'z');
|
||||||
|
case KC_1: return (shifted ? '!' : '1');
|
||||||
|
case KC_2: return (shifted ? '@' : '2');
|
||||||
|
case KC_3: return (shifted ? '#' : '3');
|
||||||
|
case KC_4: return (shifted ? '$' : '4');
|
||||||
|
case KC_5: return (shifted ? '%' : '5');
|
||||||
|
case KC_6: return (shifted ? '^' : '6');
|
||||||
|
case KC_7: return (shifted ? '&' : '7');
|
||||||
|
case KC_8: return (shifted ? '*' : '8');
|
||||||
|
case KC_9: return (shifted ? '(' : '9');
|
||||||
|
case KC_0: return (shifted ? ')' : '0');
|
||||||
|
case KC_ENTER: return '\n';
|
||||||
|
case KC_ESCAPE: return 0x1B;
|
||||||
|
case KC_BSPACE: return '\b';
|
||||||
|
case KC_TAB: return '\t';
|
||||||
|
case KC_SPACE: return ' ';
|
||||||
|
case KC_MINUS: return (shifted ? '_' : '-');
|
||||||
|
case KC_EQUAL: return (shifted ? '+' : '=');
|
||||||
|
case KC_LBRACKET: return (shifted ? '{' : '[');
|
||||||
|
case KC_RBRACKET: return (shifted ? '}' : ']');
|
||||||
|
case KC_BSLASH: return (shifted ? '|' : '\\');
|
||||||
|
case KC_NONUS_HASH: return (shifted ? '|' : '\\');
|
||||||
|
case KC_SCOLON: return (shifted ? ':' : ';');
|
||||||
|
case KC_QUOTE: return (shifted ? '"' : '\'');
|
||||||
|
case KC_GRAVE: return (shifted ? '~' : '`');
|
||||||
|
case KC_COMMA: return (shifted ? '<' : ',');
|
||||||
|
case KC_DOT: return (shifted ? '>' : '.');
|
||||||
|
case KC_SLASH: return (shifted ? '?' : '/');
|
||||||
|
case KC_DELETE: return '\0'; // Delete to disconnect
|
||||||
|
default: return ' ';
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
#ifndef RN42_TASK_H
|
||||||
|
#define RN42_TASK_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "rn42.h"
|
||||||
|
|
||||||
|
void rn42_task(void);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue