Add software UART and battery monitor
parent
01fa462e2c
commit
862f519e24
|
@ -53,6 +53,7 @@ SRC += keymap_common.c \
|
||||||
matrix.c \
|
matrix.c \
|
||||||
led.c \
|
led.c \
|
||||||
serial_uart.c \
|
serial_uart.c \
|
||||||
|
suart.S \
|
||||||
rn42.c \
|
rn42.c \
|
||||||
main.c
|
main.c
|
||||||
|
|
||||||
|
|
|
@ -76,6 +76,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#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.
|
||||||
|
|
|
@ -12,10 +12,16 @@
|
||||||
#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 */
|
||||||
|
@ -32,7 +38,16 @@ static void SetupHardware(void)
|
||||||
|
|
||||||
// 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;
|
||||||
|
@ -70,6 +85,12 @@ 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) {
|
||||||
/*
|
/*
|
||||||
|
@ -89,7 +110,12 @@ int main(void)
|
||||||
|
|
||||||
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>
|
||||||
|
@ -146,6 +172,7 @@ bool command_extra(uint8_t code)
|
||||||
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;
|
||||||
|
@ -208,6 +235,22 @@ bool command_extra(uint8_t code)
|
||||||
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;
|
||||||
|
|
|
@ -70,9 +70,11 @@ static uint8_t keyboard_leds(void) { return 0; }
|
||||||
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
|
||||||
|
@ -90,9 +92,11 @@ static void send_keyboard(report_keyboard_t *report)
|
||||||
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
|
||||||
|
|
|
@ -3,6 +3,11 @@
|
||||||
|
|
||||||
#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;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,156 @@
|
||||||
|
;---------------------------------------------------------------------------;
|
||||||
|
; 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
|
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef SUART
|
||||||
|
#define SUART
|
||||||
|
|
||||||
|
void xmit(uint8_t);
|
||||||
|
uint8_t rcvr(void);
|
||||||
|
uint8_t recv(void);
|
||||||
|
|
||||||
|
#endif /* SUART */
|
Loading…
Reference in New Issue