matrix.c \ | matrix.c \ | ||||
led.c \ | led.c \ | ||||
serial_uart.c \ | serial_uart.c \ | ||||
suart.S \ | |||||
rn42.c \ | rn42.c \ | ||||
main.c | main.c | ||||
#endif | #endif | ||||
/* for debug */ | |||||
#define SUART_OUT_PORT PORTD | |||||
#define SUART_OUT_BIT 0 | |||||
#define SUART_IN_PIN PIND | |||||
#define SUART_IN_BIT 1 | |||||
/* | /* | ||||
* Feature disable options | * Feature disable options | ||||
* These options are also useful to firmware size reduction. | * These options are also useful to firmware size reduction. |
#include "action.h" | #include "action.h" | ||||
#include "action_util.h" | #include "action_util.h" | ||||
#include "wait.h" | #include "wait.h" | ||||
#include "suart.h" | |||||
bool config_mode = false; | bool config_mode = false; | ||||
static int8_t sendchar_func(uint8_t c) | |||||
{ | |||||
sendchar(c); // LUFA | |||||
xmit(c); // SUART | |||||
} | |||||
static void SetupHardware(void) | static void SetupHardware(void) | ||||
{ | { | ||||
/* Disable watchdog if enabled by bootloader/fuses */ | /* Disable watchdog if enabled by bootloader/fuses */ | ||||
// for Console_Task | // for Console_Task | ||||
USB_Device_EnableSOFEvents(); | USB_Device_EnableSOFEvents(); | ||||
print_set_sendchar(sendchar); | |||||
print_set_sendchar(sendchar_func); | |||||
// SUART PD0:output, PD1:input | |||||
DDRD |= (1<<0); | |||||
PORTD |= (1<<0); | |||||
DDRD &= ~(1<<1); | |||||
PORTD |= (1<<1); | |||||
// CTS control | |||||
CTS_INIT(); | |||||
} | } | ||||
static bool force_usb = false; | static bool force_usb = false; | ||||
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) { | ||||
/* | /* | ||||
int16_t c; | int16_t c; | ||||
if (config_mode) { | if (config_mode) { | ||||
while ((c = serial_recv2()) != -1) xprintf("%c", c); | |||||
while ((c = serial_recv2()) != -1) { | |||||
// without flow control it'll fail to receive data when flooded | |||||
CTS_HI(); | |||||
xprintf("%c", c); | |||||
CTS_LO(); | |||||
} | |||||
} else { | } else { | ||||
while ((c = serial_recv2()) != -1) { | while ((c = serial_recv2()) != -1) { | ||||
// LED Out report: 0xFE, 0x02, 0x01, <leds> | // LED Out report: 0xFE, 0x02, 0x01, <leds> | ||||
print("a: Bluetooth auto connect\n"); | print("a: Bluetooth auto connect\n"); | ||||
print("del: Bluetooth disconnect\n"); | print("del: Bluetooth disconnect\n"); | ||||
print("i: info\n"); | print("i: info\n"); | ||||
print("b: battery voltage\n"); | |||||
if (config_mode) { | if (config_mode) { | ||||
return true; | return true; | ||||
xprintf("rn42_ready(): %X\n", rn42_ready()); | xprintf("rn42_ready(): %X\n", rn42_ready()); | ||||
xprintf("config_mode: %X\n", config_mode); | xprintf("config_mode: %X\n", config_mode); | ||||
return true; | 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: | default: | ||||
if (config_mode) | if (config_mode) | ||||
return true; | return true; |
static void send_keyboard(report_keyboard_t *report) | static void send_keyboard(report_keyboard_t *report) | ||||
{ | { | ||||
// wake from deep sleep | // wake from deep sleep | ||||
/* | |||||
PORTD |= (1<<5); // high | PORTD |= (1<<5); // high | ||||
wait_ms(5); | wait_ms(5); | ||||
PORTD &= ~(1<<5); // low | PORTD &= ~(1<<5); // low | ||||
*/ | |||||
serial_send(0xFD); // Raw report mode | serial_send(0xFD); // Raw report mode | ||||
serial_send(9); // length | serial_send(9); // length | ||||
static void send_mouse(report_mouse_t *report) | static void send_mouse(report_mouse_t *report) | ||||
{ | { | ||||
// wake from deep sleep | // wake from deep sleep | ||||
/* | |||||
PORTD |= (1<<5); // high | PORTD |= (1<<5); // high | ||||
wait_ms(5); | wait_ms(5); | ||||
PORTD &= ~(1<<5); // low | PORTD &= ~(1<<5); // low | ||||
*/ | |||||
serial_send(0xFD); // Raw report mode | serial_send(0xFD); // Raw report mode | ||||
serial_send(5); // length | serial_send(5); // length |
#include <stdbool.h> | #include <stdbool.h> | ||||
// RN-42 CTS pin | |||||
#define CTS_INIT() (DDRD |= (1<<5)) | |||||
#define CTS_HI() (PORTD |= (1<<5)) | |||||
#define CTS_LO() (PORTD &= ~(1<<5)) | |||||
host_driver_t rn42_driver; | host_driver_t rn42_driver; | ||||
host_driver_t rn42_config_driver; | host_driver_t rn42_config_driver; | ||||
;---------------------------------------------------------------------------; | |||||
; Software implemented UART module ; | |||||
; (C)ChaN, 2005 (http://elm-chan.org/) ; | |||||
;---------------------------------------------------------------------------; | |||||
; Bit rate settings: | |||||
; | |||||
; 1MHz 2MHz 4MHz 6MHz 8MHz 10MHz 12MHz 16MHz 20MHz | |||||
; 2.4kbps 138 - - - - - - - - | |||||
; 4.8kbps 68 138 - - - - - - - | |||||
; 9.6kbps 33 68 138 208 - - - - - | |||||
; 19.2kbps - 33 68 102 138 173 208 - - | |||||
; 38.4kbps - - 33 50 68 85 102 138 172 | |||||
; 57.6kbps - - 21 33 44 56 68 91 114 | |||||
; 115.2kbps - - - - 21 27 33 44 56 | |||||
.nolist | |||||
#include <avr/io.h> | |||||
.list | |||||
#define BPS 44 /* Bit delay. (see above table) */ | |||||
#define BIDIR 0 /* 0:Separated Tx/Rx, 1:Shared Tx/Rx */ | |||||
#define OUT_1 sbi _SFR_IO_ADDR(SUART_OUT_PORT), SUART_OUT_BIT /* Output 1 */ | |||||
#define OUT_0 cbi _SFR_IO_ADDR(SUART_OUT_PORT), SUART_OUT_BIT /* Output 0 */ | |||||
#define SKIP_IN_1 sbis _SFR_IO_ADDR(SUART_IN_PIN), SUART_IN_BIT /* Skip if 1 */ | |||||
#define SKIP_IN_0 sbic _SFR_IO_ADDR(SUART_IN_PIN), SUART_IN_BIT /* Skip if 0 */ | |||||
#ifdef SPM_PAGESIZE | |||||
.macro _LPMI reg | |||||
lpm \reg, Z+ | |||||
.endm | |||||
.macro _MOVW dh,dl, sh,sl | |||||
movw \dl, \sl | |||||
.endm | |||||
#else | |||||
.macro _LPMI reg | |||||
lpm | |||||
mov \reg, r0 | |||||
adiw ZL, 1 | |||||
.endm | |||||
.macro _MOVW dh,dl, sh,sl | |||||
mov \dl, \sl | |||||
mov \dh, \sh | |||||
.endm | |||||
#endif | |||||
;---------------------------------------------------------------------------; | |||||
; Transmit a byte in serial format of N81 | |||||
; | |||||
;Prototype: void xmit (uint8_t data); | |||||
;Size: 16 words | |||||
.global xmit | |||||
.func xmit | |||||
xmit: | |||||
#if BIDIR | |||||
ldi r23, BPS-1 ;Pre-idle time for bidirectional data line | |||||
5: dec r23 ; | |||||
brne 5b ;/ | |||||
#endif | |||||
in r0, _SFR_IO_ADDR(SREG) ;Save flags | |||||
com r24 ;C = start bit | |||||
ldi r25, 10 ;Bit counter | |||||
cli ;Start critical section | |||||
1: ldi r23, BPS-1 ;----- Bit transferring loop | |||||
2: dec r23 ;Wait for a bit time | |||||
brne 2b ;/ | |||||
brcs 3f ;MISO = bit to be sent | |||||
OUT_1 ; | |||||
3: brcc 4f ; | |||||
OUT_0 ;/ | |||||
4: lsr r24 ;Get next bit into C | |||||
dec r25 ;All bits sent? | |||||
brne 1b ; no, coutinue | |||||
out _SFR_IO_ADDR(SREG), r0 ;End of critical section | |||||
ret | |||||
.endfunc | |||||
;---------------------------------------------------------------------------; | |||||
; Receive a byte | |||||
; | |||||
;Prototype: uint8_t rcvr (void); | |||||
;Size: 19 words | |||||
.global rcvr | |||||
.func rcvr | |||||
rcvr: | |||||
in r0, _SFR_IO_ADDR(SREG) ;Save flags | |||||
ldi r24, 0x80 ;Receiving shift reg | |||||
cli ;Start critical section | |||||
1: SKIP_IN_1 ;Wait for idle | |||||
rjmp 1b | |||||
2: SKIP_IN_0 ;Wait for start bit | |||||
rjmp 2b | |||||
ldi r25, BPS/2 ;Wait for half bit time | |||||
3: dec r25 | |||||
brne 3b | |||||
4: ldi r25, BPS ;----- Bit receiving loop | |||||
5: dec r25 ;Wait for a bit time | |||||
brne 5b ;/ | |||||
lsr r24 ;Next bit | |||||
SKIP_IN_0 ;Get a data bit into r24.7 | |||||
ori r24, 0x80 | |||||
brcc 4b ;All bits received? no, continue | |||||
out _SFR_IO_ADDR(SREG), r0 ;End of critical section | |||||
ret | |||||
.endfunc | |||||
; Not wait for start bit. This should be called after detecting start bit. | |||||
.global recv | |||||
.func recv | |||||
recv: | |||||
in r0, _SFR_IO_ADDR(SREG) ;Save flags | |||||
ldi r24, 0x80 ;Receiving shift reg | |||||
cli ;Start critical section | |||||
;1: SKIP_IN_1 ;Wait for idle | |||||
; rjmp 1b | |||||
;2: SKIP_IN_0 ;Wait for start bit | |||||
; rjmp 2b | |||||
ldi r25, BPS/2 ;Wait for half bit time | |||||
3: dec r25 | |||||
brne 3b | |||||
4: ldi r25, BPS ;----- Bit receiving loop | |||||
5: dec r25 ;Wait for a bit time | |||||
brne 5b ;/ | |||||
lsr r24 ;Next bit | |||||
SKIP_IN_0 ;Get a data bit into r24.7 | |||||
ori r24, 0x80 | |||||
brcc 4b ;All bits received? no, continue | |||||
ldi r25, BPS/2 ;Wait for half bit time | |||||
6: dec r25 | |||||
brne 6b | |||||
7: SKIP_IN_1 ;Wait for stop bit | |||||
rjmp 7b | |||||
out _SFR_IO_ADDR(SREG), r0 ;End of critical section | |||||
ret | |||||
.endfunc |
#ifndef SUART | |||||
#define SUART | |||||
void xmit(uint8_t); | |||||
uint8_t rcvr(void); | |||||
uint8_t recv(void); | |||||
#endif /* SUART */ |