summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortmk <nobody@nowhere>2014-07-14 15:20:10 +0900
committertmk <nobody@nowhere>2014-07-30 14:38:26 +0900
commit862f519e241b83113566eebde71841958b2d00b7 (patch)
tree4b44327cdb97014244c5ff357ddd2a3df9b53100
parent01fa462e2c26c8dcd2db205faf3a3835b509ac95 (diff)
Add software UART and battery monitor
-rw-r--r--keyboard/hhkb_rn42/Makefile1
-rw-r--r--keyboard/hhkb_rn42/config.h7
-rw-r--r--keyboard/hhkb_rn42/main.c49
-rw-r--r--keyboard/hhkb_rn42/rn42.c4
-rw-r--r--keyboard/hhkb_rn42/rn42.h5
-rw-r--r--keyboard/hhkb_rn42/suart.S156
-rw-r--r--keyboard/hhkb_rn42/suart.h8
7 files changed, 227 insertions, 3 deletions
diff --git a/keyboard/hhkb_rn42/Makefile b/keyboard/hhkb_rn42/Makefile
index 8cfe3f1184..9e1acfa442 100644
--- a/keyboard/hhkb_rn42/Makefile
+++ b/keyboard/hhkb_rn42/Makefile
@@ -53,6 +53,7 @@ SRC += keymap_common.c \
matrix.c \
led.c \
serial_uart.c \
+ suart.S \
rn42.c \
main.c
diff --git a/keyboard/hhkb_rn42/config.h b/keyboard/hhkb_rn42/config.h
index a0ab878eb8..5e6d7a6436 100644
--- a/keyboard/hhkb_rn42/config.h
+++ b/keyboard/hhkb_rn42/config.h
@@ -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.
diff --git a/keyboard/hhkb_rn42/main.c b/keyboard/hhkb_rn42/main.c
index a2c217a2d3..0b455193fb 100644
--- a/keyboard/hhkb_rn42/main.c
+++ b/keyboard/hhkb_rn42/main.c
@@ -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;
diff --git a/keyboard/hhkb_rn42/rn42.c b/keyboard/hhkb_rn42/rn42.c
index c25e193719..89ecb199ca 100644
--- a/keyboard/hhkb_rn42/rn42.c
+++ b/keyboard/hhkb_rn42/rn42.c
@@ -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
diff --git a/keyboard/hhkb_rn42/rn42.h b/keyboard/hhkb_rn42/rn42.h
index 3e4c2fbe7d..a967a70d8a 100644
--- a/keyboard/hhkb_rn42/rn42.h
+++ b/keyboard/hhkb_rn42/rn42.h
@@ -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;
diff --git a/keyboard/hhkb_rn42/suart.S b/keyboard/hhkb_rn42/suart.S
new file mode 100644
index 0000000000..9fa5452928
--- /dev/null
+++ b/keyboard/hhkb_rn42/suart.S
@@ -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
diff --git a/keyboard/hhkb_rn42/suart.h b/keyboard/hhkb_rn42/suart.h
new file mode 100644
index 0000000000..72725b998f
--- /dev/null
+++ b/keyboard/hhkb_rn42/suart.h
@@ -0,0 +1,8 @@
+#ifndef SUART
+#define SUART
+
+void xmit(uint8_t);
+uint8_t rcvr(void);
+uint8_t recv(void);
+
+#endif /* SUART */