]> cloudbase.mooo.com Git - avrcpm.git/blob - avrcpm/avr/hw-uart.asm
Tag for Version 2.0
[avrcpm.git] / avrcpm / avr / hw-uart.asm
1 ; Serial interface using the ATmega8/88 USART.
2 ; This is part of the Z80-CP/M emulator written by Sprite_tm.
3 ;
4 ; Copyright (C) 2010 Leo C.
5 ;
6 ; This file is part of avrcpm.
7 ;
8 ; avrcpm is free software: you can redistribute it and/or modify it
9 ; under the terms of the GNU General Public License as published by
10 ; the Free Software Foundation, either version 3 of the License, or
11 ; (at your option) any later version.
12 ;
13 ; avrcpm is distributed in the hope that it will be useful,
14 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ; GNU General Public License for more details.
17 ;
18 ; You should have received a copy of the GNU General Public License
19 ; along with avrcpm. If not, see <http://www.gnu.org/licenses/>.
20 ;
21 ; $Id$
22 ;
23
24 #define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) /* clever rounding */
25
26 #define RXBUFMASK RXBUFSIZE-1
27 #define TXBUFMASK TXBUFSIZE-1
28
29 .dseg
30
31 rxcount:
32 .byte 1
33 rxidx_w:
34 .byte 1
35 rxidx_r:
36 .byte 1
37 txcount:
38 .byte 1
39 txidx_w:
40 .byte 1
41 txidx_r:
42 .byte 1
43 rxfifo:
44 .byte RXBUFSIZE
45 txfifo:
46 .byte TXBUFSIZE
47
48
49 .cseg
50 ; Init
51 uart_init:
52
53 ldi temp, (1<<TXEN0) | (1<<RXEN0) | (1<<RXCIE0)
54 outm8 UCSR0B,temp
55 .ifdef URSEL
56 ldi temp, (1<<URSEL) | (1<<UCSZ01) | (1<<UCSZ00)
57 .else
58 ldi temp, (1<<UCSZ01) | (1<<UCSZ00)
59 .endif
60 outm8 UCSR0C,temp
61 ldi temp, HIGH(UBRR_VAL)
62 outm8 UBRR0H,temp
63 ldi temp, LOW(UBRR_VAL)
64 outm8 UBRR0L,temp
65 ret
66
67 ; Save received character in a circular buffer. Do nothing if buffer overflows.
68
69 rxint:
70 .org URXCaddr
71 rjmp rxint ; USART receive int.
72
73 .org rxint
74 push temp
75 in temp,sreg
76 push temp
77 push zh
78 push zl
79 inm8 temp,RXTXDR0
80 lds zh,rxcount ;if rxcount < RXBUFSIZE
81 cpi zh,RXBUFSIZE ; (room for at least 1 char?)
82 brsh rxi_ov ;
83 inc zh ;
84 sts rxcount,zh ; rxcount++
85
86 ldi zl,low(rxfifo) ;
87 lds zh,rxidx_w ;
88 add zl,zh ;
89 inc zh ;
90 andi zh,RXBUFMASK ;
91 sts rxidx_w,zh ; rxidx_w = ++rxidx_w % RXBUFSIZE
92 ldi zh,high(rxfifo) ;
93 brcc PC+2 ;
94 inc zh ;
95 st z,temp ; rxfifo[rxidx_w] = char
96 rxi_ov: ;endif
97 pop zl
98 pop zh
99 pop temp
100 out sreg,temp
101 pop temp
102 reti
103
104
105 ;Fetches a char from the buffer to temp. If none available, waits till one is.
106
107 uartgetc:
108 lds temp,rxcount ; Number of characters in buffer
109 tst temp
110 breq uartgetc ;Wait for char
111
112 push zh
113 push zl
114 ldi zl,low(rxfifo)
115 ldi zh,high(rxfifo)
116 lds temp,rxidx_r
117 add zl,temp
118 brcc PC+2
119 inc zh
120 inc temp
121 andi temp,RXBUFMASK
122 sts rxidx_r,temp
123 cli
124 lds temp,rxcount
125 dec temp
126 sts rxcount,temp
127 sei
128 ld temp,z ;don't forget to get the char
129 pop zl
130 pop zh
131 ret
132
133 txint:
134 .org UDREaddr
135 rjmp txint ; USART transmit int.
136
137 .org txint
138 push temp
139 in temp,sreg
140 push temp
141 lds temp,txcount ;if txcount != 0
142 tst temp ;
143 breq txi_e ;
144
145 dec temp ;
146 sts txcount,temp ; --txcount
147 push zh ;
148 push zl ;
149 ldi zl,low(txfifo) ;
150 ldi zh,high(txfifo) ;
151 lds temp,txidx_r ;
152 add zl,temp ;
153 brcc PC+2 ;
154 inc zh ;
155 inc temp ;
156 andi temp,TXBUFMASK ;
157 sts txidx_r,temp ;
158 ld temp,z
159 outm8 RXTXDR0,temp
160 pop zl
161 pop zh
162 txi_e: ;endif
163 lds temp,txcount
164 tst temp
165 brne txi_x
166 ldi temp, (1<<TXEN0) | (1<<RXEN0) | (1<<RXCIE0)
167 outm8 UCSR0B,temp
168 txi_x:
169 pop temp
170 out sreg,temp
171 pop temp
172 reti
173
174
175 ;Sends a char from temp to the uart.
176 uartputc:
177 push zh
178 push zl
179 push temp
180 putc_l:
181 lds temp,txcount ;do {
182 cpi temp,TXBUFSIZE ;
183 brsh putc_l ;} while (txcount >= TXBUFSIZE)
184
185 ldi zl,low(txfifo) ;
186 ldi zh,high(txfifo) ;
187 lds temp,txidx_w ;
188 add zl,temp ;
189 brcc PC+2 ;
190 inc zh ;
191 inc temp ;
192 andi temp,TXBUFMASK ;
193 sts txidx_w,temp ; txidx_w = ++txidx_w % TXBUFSIZE
194 pop temp ;
195 st z,temp ; txfifo[txidx_w] = char
196 cli
197 lds zl,txcount
198 inc zl
199 sts txcount,zl
200 ldi zl, (1<<UDRIE0) | (1<<TXEN0) | (1<<RXEN0) | (1<<RXCIE0)
201 outm8 UCSR0B,zl
202 sei
203 pop zl
204 pop zh
205 ret
206
207 ; vim:set ts=8 noet nowrap
208