]> git.donarmstrong.com Git - tmk_firmware.git/commitdiff
Add software UART and battery monitor
authortmk <nobody@nowhere>
Mon, 14 Jul 2014 06:20:10 +0000 (15:20 +0900)
committertmk <nobody@nowhere>
Wed, 30 Jul 2014 05:38:26 +0000 (14:38 +0900)
keyboard/hhkb_rn42/Makefile
keyboard/hhkb_rn42/config.h
keyboard/hhkb_rn42/main.c
keyboard/hhkb_rn42/rn42.c
keyboard/hhkb_rn42/rn42.h
keyboard/hhkb_rn42/suart.S [new file with mode: 0644]
keyboard/hhkb_rn42/suart.h [new file with mode: 0644]

index 8cfe3f11841e465ad56be15f2755a61f2fc8bf71..9e1acfa442eddd93cebed59a1eabf02ed2db81f1 100644 (file)
@@ -53,6 +53,7 @@ SRC +=        keymap_common.c \
        matrix.c \
        led.c \
        serial_uart.c \
+       suart.S \
        rn42.c \
        main.c
 
index a0ab878eb80fc3db06073f4b6682f47bc0f11c12..5e6d7a64361fb5999a287004c40226d555d46a3f 100644 (file)
@@ -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.
index a2c217a2d30ae041e6c8c51f257ae0b3c78e1c81..0b455193fb9fefed7a4956e9e9acff3bd3ef34ae 100644 (file)
 #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;
index c25e193719c2956cb2a521a06040e1538af2a6b3..89ecb199cab9eb852d70cdf47b0f0e50331d6373 100644 (file)
@@ -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
index 3e4c2fbe7d3e18db9509d340d1ca986bb121f4a7..a967a70d8a05a18f2369cf2761c61efa92805e12 100644 (file)
@@ -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 (file)
index 0000000..9fa5452
--- /dev/null
@@ -0,0 +1,156 @@
+;---------------------------------------------------------------------------;\r
+; Software implemented UART module                                          ;\r
+; (C)ChaN, 2005 (http://elm-chan.org/)                                      ;\r
+;---------------------------------------------------------------------------;\r
+; Bit rate settings:\r
+;\r
+;            1MHz  2MHz  4MHz  6MHz  8MHz  10MHz  12MHz  16MHz  20MHz\r
+;   2.4kbps   138     -     -     -     -      -      -      -      -\r
+;   4.8kbps    68   138     -     -     -      -      -      -      -\r
+;   9.6kbps    33    68   138   208     -      -      -      -      -\r
+;  19.2kbps     -    33    68   102   138    173    208      -      -\r
+;  38.4kbps     -     -    33    50    68     85    102    138    172\r
+;  57.6kbps     -     -    21    33    44     56     68     91    114\r
+; 115.2kbps     -     -     -     -    21     27     33     44     56\r
+\r
+.nolist\r
+#include <avr/io.h>\r
+.list\r
+\r
+#define        BPS     44      /* Bit delay. (see above table) */\r
+#define        BIDIR   0       /* 0:Separated Tx/Rx, 1:Shared Tx/Rx */\r
+\r
+#define        OUT_1           sbi _SFR_IO_ADDR(SUART_OUT_PORT), SUART_OUT_BIT /* Output 1 */\r
+#define        OUT_0           cbi _SFR_IO_ADDR(SUART_OUT_PORT), SUART_OUT_BIT /* Output 0 */\r
+#define        SKIP_IN_1       sbis _SFR_IO_ADDR(SUART_IN_PIN), SUART_IN_BIT   /* Skip if 1 */\r
+#define        SKIP_IN_0       sbic _SFR_IO_ADDR(SUART_IN_PIN), SUART_IN_BIT   /* Skip if 0 */\r
+\r
+\r
+\r
+#ifdef SPM_PAGESIZE\r
+.macro _LPMI   reg\r
+       lpm     \reg, Z+\r
+.endm\r
+.macro _MOVW   dh,dl, sh,sl\r
+       movw    \dl, \sl\r
+.endm\r
+#else\r
+.macro _LPMI   reg\r
+       lpm\r
+       mov     \reg, r0\r
+       adiw    ZL, 1\r
+.endm\r
+.macro _MOVW   dh,dl, sh,sl\r
+       mov     \dl, \sl\r
+       mov     \dh, \sh\r
+.endm\r
+#endif\r
+\r
+\r
+\r
+;---------------------------------------------------------------------------;\r
+; Transmit a byte in serial format of N81\r
+;\r
+;Prototype: void xmit (uint8_t data);\r
+;Size: 16 words\r
+\r
+.global xmit\r
+.func xmit\r
+xmit:\r
+#if BIDIR\r
+       ldi     r23, BPS-1      ;Pre-idle time for bidirectional data line\r
+5:     dec     r23             ;\r
+       brne    5b              ;/\r
+#endif\r
+       in      r0, _SFR_IO_ADDR(SREG)  ;Save flags\r
+\r
+       com     r24             ;C = start bit\r
+       ldi     r25, 10         ;Bit counter\r
+       cli                     ;Start critical section\r
+\r
+1:     ldi     r23, BPS-1      ;----- Bit transferring loop \r
+2:     dec     r23             ;Wait for a bit time\r
+       brne    2b              ;/\r
+       brcs    3f              ;MISO = bit to be sent\r
+       OUT_1                   ;\r
+3:     brcc    4f              ;\r
+       OUT_0                   ;/\r
+4:     lsr     r24             ;Get next bit into C\r
+       dec     r25             ;All bits sent?\r
+       brne    1b              ;  no, coutinue\r
+\r
+       out     _SFR_IO_ADDR(SREG), r0  ;End of critical section\r
+       ret\r
+.endfunc\r
+\r
+\r
+\r
+;---------------------------------------------------------------------------;\r
+; Receive a byte\r
+;\r
+;Prototype: uint8_t rcvr (void);\r
+;Size: 19 words\r
+\r
+.global rcvr\r
+.func rcvr\r
+rcvr:\r
+       in      r0, _SFR_IO_ADDR(SREG)  ;Save flags\r
+\r
+       ldi     r24, 0x80       ;Receiving shift reg\r
+       cli                     ;Start critical section\r
+\r
+1:     SKIP_IN_1               ;Wait for idle\r
+       rjmp    1b\r
+2:     SKIP_IN_0               ;Wait for start bit\r
+       rjmp    2b\r
+       ldi     r25, BPS/2      ;Wait for half bit time\r
+3:     dec     r25\r
+       brne    3b\r
+\r
+4:     ldi     r25, BPS        ;----- Bit receiving loop\r
+5:     dec     r25             ;Wait for a bit time\r
+       brne    5b              ;/\r
+       lsr     r24             ;Next bit\r
+       SKIP_IN_0               ;Get a data bit into r24.7\r
+       ori     r24, 0x80\r
+       brcc    4b              ;All bits received?  no, continue\r
+\r
+       out     _SFR_IO_ADDR(SREG), r0  ;End of critical section\r
+       ret\r
+.endfunc\r
+\r
+\r
+; Not wait for start bit. This should be called after detecting start bit.\r
+.global recv\r
+.func recv\r
+recv:\r
+       in      r0, _SFR_IO_ADDR(SREG)  ;Save flags\r
+\r
+       ldi     r24, 0x80       ;Receiving shift reg\r
+       cli                     ;Start critical section\r
+\r
+;1:    SKIP_IN_1               ;Wait for idle\r
+;      rjmp    1b\r
+;2:    SKIP_IN_0               ;Wait for start bit\r
+;      rjmp    2b\r
+       ldi     r25, BPS/2      ;Wait for half bit time\r
+3:     dec     r25\r
+       brne    3b\r
+\r
+4:     ldi     r25, BPS        ;----- Bit receiving loop\r
+5:     dec     r25             ;Wait for a bit time\r
+       brne    5b              ;/\r
+       lsr     r24             ;Next bit\r
+       SKIP_IN_0               ;Get a data bit into r24.7\r
+       ori     r24, 0x80\r
+       brcc    4b              ;All bits received?  no, continue\r
+\r
+       ldi     r25, BPS/2      ;Wait for half bit time\r
+6:     dec     r25\r
+       brne    6b\r
+7:     SKIP_IN_1               ;Wait for stop bit\r
+       rjmp    7b\r
+\r
+       out     _SFR_IO_ADDR(SREG), r0  ;End of critical section\r
+       ret\r
+.endfunc\r
diff --git a/keyboard/hhkb_rn42/suart.h b/keyboard/hhkb_rn42/suart.h
new file mode 100644 (file)
index 0000000..72725b9
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef SUART\r
+#define SUART\r
+\r
+void xmit(uint8_t);\r
+uint8_t rcvr(void);\r
+uint8_t recv(void);\r
+\r
+#endif /* SUART */\r