]> cloudbase.mooo.com Git - avrcpm.git/blame - avrcpm/avr/hw-uart.asm
Merged branch modules back into trunk.
[avrcpm.git] / avrcpm / avr / hw-uart.asm
CommitLineData
9c15f366
L
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
31rxcount:
32 .byte 1
33rxidx_w:
34 .byte 1
35rxidx_r:
36 .byte 1
37txcount:
38 .byte 1
39txidx_w:
40 .byte 1
41txidx_r:
42 .byte 1
43rxfifo:
44 .byte RXBUFSIZE
45txfifo:
46 .byte TXBUFSIZE
47
48
49 .cseg
50; Init
51uart_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
69rxint:
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
96rxi_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
107uartgetc:
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
133txint:
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
162txi_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
168txi_x:
169 pop temp
170 out sreg,temp
171 pop temp
172 reti
173
174
175;Sends a char from temp to the uart.
176uartputc:
177 push zh
178 push zl
179 push temp
180putc_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