]> git.donarmstrong.com Git - tmk_firmware.git/blob - keyboard/hhkb_rn42/rn42/suart.S
Mkdir rn42
[tmk_firmware.git] / keyboard / hhkb_rn42 / rn42 / suart.S
1 ;---------------------------------------------------------------------------;\r
2 ; Software implemented UART module                                          ;\r
3 ; (C)ChaN, 2005 (http://elm-chan.org/)                                      ;\r
4 ;---------------------------------------------------------------------------;\r
5 ; Bit rate settings:\r
6 ;\r
7 ;            1MHz  2MHz  4MHz  6MHz  8MHz  10MHz  12MHz  16MHz  20MHz\r
8 ;   2.4kbps   138     -     -     -     -      -      -      -      -\r
9 ;   4.8kbps    68   138     -     -     -      -      -      -      -\r
10 ;   9.6kbps    33    68   138   208     -      -      -      -      -\r
11 ;  19.2kbps     -    33    68   102   138    173    208      -      -\r
12 ;  38.4kbps     -     -    33    50    68     85    102    138    172\r
13 ;  57.6kbps     -     -    21    33    44     56     68     91    114\r
14 ; 115.2kbps     -     -     -     -    21     27     33     44     56\r
15 \r
16 .nolist\r
17 #include <avr/io.h>\r
18 .list\r
19 \r
20 #define BPS     44      /* Bit delay. (see above table) */\r
21 #define BIDIR   0       /* 0:Separated Tx/Rx, 1:Shared Tx/Rx */\r
22 \r
23 #define OUT_1           sbi _SFR_IO_ADDR(SUART_OUT_PORT), SUART_OUT_BIT /* Output 1 */\r
24 #define OUT_0           cbi _SFR_IO_ADDR(SUART_OUT_PORT), SUART_OUT_BIT /* Output 0 */\r
25 #define SKIP_IN_1       sbis _SFR_IO_ADDR(SUART_IN_PIN), SUART_IN_BIT   /* Skip if 1 */\r
26 #define SKIP_IN_0       sbic _SFR_IO_ADDR(SUART_IN_PIN), SUART_IN_BIT   /* Skip if 0 */\r
27 \r
28 \r
29 \r
30 #ifdef SPM_PAGESIZE\r
31 .macro  _LPMI   reg\r
32         lpm     \reg, Z+\r
33 .endm\r
34 .macro  _MOVW   dh,dl, sh,sl\r
35         movw    \dl, \sl\r
36 .endm\r
37 #else\r
38 .macro  _LPMI   reg\r
39         lpm\r
40         mov     \reg, r0\r
41         adiw    ZL, 1\r
42 .endm\r
43 .macro  _MOVW   dh,dl, sh,sl\r
44         mov     \dl, \sl\r
45         mov     \dh, \sh\r
46 .endm\r
47 #endif\r
48 \r
49 \r
50 \r
51 ;---------------------------------------------------------------------------;\r
52 ; Transmit a byte in serial format of N81\r
53 ;\r
54 ;Prototype: void xmit (uint8_t data);\r
55 ;Size: 16 words\r
56 \r
57 .global xmit\r
58 .func xmit\r
59 xmit:\r
60 #if BIDIR\r
61         ldi     r23, BPS-1      ;Pre-idle time for bidirectional data line\r
62 5:      dec     r23             ;\r
63         brne    5b              ;/\r
64 #endif\r
65         in      r0, _SFR_IO_ADDR(SREG)  ;Save flags\r
66 \r
67         com     r24             ;C = start bit\r
68         ldi     r25, 10         ;Bit counter\r
69         cli                     ;Start critical section\r
70 \r
71 1:      ldi     r23, BPS-1      ;----- Bit transferring loop \r
72 2:      dec     r23             ;Wait for a bit time\r
73         brne    2b              ;/\r
74         brcs    3f              ;MISO = bit to be sent\r
75         OUT_1                   ;\r
76 3:      brcc    4f              ;\r
77         OUT_0                   ;/\r
78 4:      lsr     r24             ;Get next bit into C\r
79         dec     r25             ;All bits sent?\r
80         brne    1b              ;  no, coutinue\r
81 \r
82         out     _SFR_IO_ADDR(SREG), r0  ;End of critical section\r
83         ret\r
84 .endfunc\r
85 \r
86 \r
87 \r
88 ;---------------------------------------------------------------------------;\r
89 ; Receive a byte\r
90 ;\r
91 ;Prototype: uint8_t rcvr (void);\r
92 ;Size: 19 words\r
93 \r
94 .global rcvr\r
95 .func rcvr\r
96 rcvr:\r
97         in      r0, _SFR_IO_ADDR(SREG)  ;Save flags\r
98 \r
99         ldi     r24, 0x80       ;Receiving shift reg\r
100         cli                     ;Start critical section\r
101 \r
102 1:      SKIP_IN_1               ;Wait for idle\r
103         rjmp    1b\r
104 2:      SKIP_IN_0               ;Wait for start bit\r
105         rjmp    2b\r
106         ldi     r25, BPS/2      ;Wait for half bit time\r
107 3:      dec     r25\r
108         brne    3b\r
109 \r
110 4:      ldi     r25, BPS        ;----- Bit receiving loop\r
111 5:      dec     r25             ;Wait for a bit time\r
112         brne    5b              ;/\r
113         lsr     r24             ;Next bit\r
114         SKIP_IN_0               ;Get a data bit into r24.7\r
115         ori     r24, 0x80\r
116         brcc    4b              ;All bits received?  no, continue\r
117 \r
118         out     _SFR_IO_ADDR(SREG), r0  ;End of critical section\r
119         ret\r
120 .endfunc\r
121 \r
122 \r
123 ; Not wait for start bit. This should be called after detecting start bit.\r
124 .global recv\r
125 .func recv\r
126 recv:\r
127         in      r0, _SFR_IO_ADDR(SREG)  ;Save flags\r
128 \r
129         ldi     r24, 0x80       ;Receiving shift reg\r
130         cli                     ;Start critical section\r
131 \r
132 ;1:     SKIP_IN_1               ;Wait for idle\r
133 ;       rjmp    1b\r
134 ;2:     SKIP_IN_0               ;Wait for start bit\r
135 ;       rjmp    2b\r
136         ldi     r25, BPS/2      ;Wait for half bit time\r
137 3:      dec     r25\r
138         brne    3b\r
139 \r
140 4:      ldi     r25, BPS        ;----- Bit receiving loop\r
141 5:      dec     r25             ;Wait for a bit time\r
142         brne    5b              ;/\r
143         lsr     r24             ;Next bit\r
144         SKIP_IN_0               ;Get a data bit into r24.7\r
145         ori     r24, 0x80\r
146         brcc    4b              ;All bits received?  no, continue\r
147 \r
148         ldi     r25, BPS/2      ;Wait for half bit time\r
149 6:      dec     r25\r
150         brne    6b\r
151 7:      SKIP_IN_1               ;Wait for stop bit\r
152         rjmp    7b\r
153 \r
154         out     _SFR_IO_ADDR(SREG), r0  ;End of critical section\r
155         ret\r
156 .endfunc\r