]> git.donarmstrong.com Git - tmk_firmware.git/blobdiff - keyboard/hhkb_rn42/rn42/suart.S
Merge remote-tracking branch 'tmk/master' into cub_layout
[tmk_firmware.git] / keyboard / hhkb_rn42 / rn42 / suart.S
diff --git a/keyboard/hhkb_rn42/rn42/suart.S b/keyboard/hhkb_rn42/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