mirror of
https://github.com/qmk/qmk_firmware
synced 2024-11-13 07:25:44 +00:00
Add software UART and battery monitor
This commit is contained in:
parent
01fa462e2c
commit
862f519e24
7 changed files with 227 additions and 3 deletions
|
@ -53,6 +53,7 @@ SRC += keymap_common.c \
|
|||
matrix.c \
|
||||
led.c \
|
||||
serial_uart.c \
|
||||
suart.S \
|
||||
rn42.c \
|
||||
main.c
|
||||
|
||||
|
|
|
@ -76,6 +76,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#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
|
||||
* These options are also useful to firmware size reduction.
|
||||
|
|
|
@ -12,10 +12,16 @@
|
|||
#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 */
|
||||
|
@ -32,7 +38,16 @@ static void SetupHardware(void)
|
|||
|
||||
// for Console_Task
|
||||
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;
|
||||
|
@ -70,6 +85,12 @@ int main(void)
|
|||
sleep_led_init();
|
||||
#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");
|
||||
while (1) {
|
||||
/*
|
||||
|
@ -89,7 +110,12 @@ int main(void)
|
|||
|
||||
int16_t c;
|
||||
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 {
|
||||
while ((c = serial_recv2()) != -1) {
|
||||
// LED Out report: 0xFE, 0x02, 0x01, <leds>
|
||||
|
@ -146,6 +172,7 @@ bool command_extra(uint8_t code)
|
|||
print("a: Bluetooth auto connect\n");
|
||||
print("del: Bluetooth disconnect\n");
|
||||
print("i: info\n");
|
||||
print("b: battery voltage\n");
|
||||
|
||||
if (config_mode) {
|
||||
return true;
|
||||
|
@ -208,6 +235,22 @@ bool command_extra(uint8_t code)
|
|||
xprintf("rn42_ready(): %X\n", rn42_ready());
|
||||
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;
|
||||
|
|
|
@ -70,9 +70,11 @@ static uint8_t keyboard_leds(void) { return 0; }
|
|||
static void send_keyboard(report_keyboard_t *report)
|
||||
{
|
||||
// wake from deep sleep
|
||||
/*
|
||||
PORTD |= (1<<5); // high
|
||||
wait_ms(5);
|
||||
PORTD &= ~(1<<5); // low
|
||||
*/
|
||||
|
||||
serial_send(0xFD); // Raw report mode
|
||||
serial_send(9); // length
|
||||
|
@ -90,9 +92,11 @@ static void send_keyboard(report_keyboard_t *report)
|
|||
static void send_mouse(report_mouse_t *report)
|
||||
{
|
||||
// wake from deep sleep
|
||||
/*
|
||||
PORTD |= (1<<5); // high
|
||||
wait_ms(5);
|
||||
PORTD &= ~(1<<5); // low
|
||||
*/
|
||||
|
||||
serial_send(0xFD); // Raw report mode
|
||||
serial_send(5); // length
|
||||
|
|
|
@ -3,6 +3,11 @@
|
|||
|
||||
#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_config_driver;
|
||||
|
||||
|
|
156
keyboard/hhkb_rn42/suart.S
Normal file
156
keyboard/hhkb_rn42/suart.S
Normal file
|
@ -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
|
8
keyboard/hhkb_rn42/suart.h
Normal file
8
keyboard/hhkb_rn42/suart.h
Normal file
|
@ -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 a new issue