Rev 910 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
910 | dimkam | 1 | #include <avr/io.h> |
2 | #include <avr/interrupt.h> |
||
3 | |||
4 | #include "mytypes.h" |
||
5 | #include "rs232.h" |
||
6 | #include "pins.h" |
||
7 | |||
8 | //if want Log than comment next string |
||
9 | #undef LOGENABLE |
||
10 | |||
11 | #define BAUD115200 115200 |
||
12 | #define BAUD256000 256000 |
||
13 | #define UBRR115200 (((F_CPU/16)/BAUD115200)-1) |
||
14 | #define UBRR256000 (((F_CPU/16)/BAUD256000)-1) |
||
15 | |||
16 | //Registers for 16550 emulation: |
||
17 | |||
18 | //Divisor Latch LSB |
||
19 | static UBYTE rs232_DLL; |
||
20 | //Divisor Latch MSB |
||
21 | static UBYTE rs232_DLM; |
||
22 | //Interrupt Enable |
||
23 | static UBYTE rs232_IER; |
||
24 | //Interrupt Identification |
||
25 | static UBYTE rs232_ISR; |
||
26 | //FIFO Control |
||
27 | static UBYTE rs232_FCR; |
||
28 | //Line Control |
||
29 | static UBYTE rs232_LCR; |
||
30 | //Modem Control |
||
31 | static UBYTE rs232_MCR; |
||
32 | //Line Status |
||
33 | static UBYTE rs232_LSR; |
||
34 | //Modem Status |
||
35 | static UBYTE rs232_MSR; |
||
36 | //Scratch Pad |
||
37 | static UBYTE rs232_SCR; |
||
38 | //Fifo In |
||
39 | static UBYTE rs232_FI[16]; |
||
40 | static UBYTE rs232_FI_start; |
||
41 | static UBYTE rs232_FI_end; |
||
42 | //Fifo Out |
||
43 | static UBYTE rs232_FO[16]; |
||
44 | static UBYTE rs232_FO_start; |
||
45 | static UBYTE rs232_FO_end; |
||
46 | |||
47 | void rs232_init(void) |
||
48 | { |
||
49 | // Set baud rate |
||
50 | UBRR1H = (UBYTE)(UBRR115200>>8); |
||
51 | UBRR1L = (UBYTE)UBRR115200; |
||
52 | // Clear reg |
||
53 | UCSR1A = 0; |
||
54 | // Enable receiver and transmitter |
||
55 | UCSR1B = _BV(RXEN)|_BV(TXEN); |
||
56 | // Set frame format: 8data, 1stop bit |
||
57 | UCSR1C = _BV(USBS)|_BV(UCSZ0)|_BV(UCSZ1); |
||
58 | |||
59 | //Set default values: |
||
60 | rs232_DLM = 0; |
||
61 | rs232_DLL = 0x01; |
||
62 | rs232_IER = 0; |
||
63 | rs232_FCR = 0x01; //FIFO always enable |
||
64 | rs232_ISR = 0x01; |
||
65 | rs232_LCR = 0; |
||
66 | rs232_MCR = 0; |
||
67 | rs232_LSR = 0x60; |
||
68 | rs232_MSR = 0xA0; //DSR=CD=1, RI=0 |
||
69 | rs232_SCR = 0xFF; |
||
70 | rs232_FI_start = rs232_FI_end = 0; |
||
71 | rs232_FO_start = rs232_FO_end = 0; |
||
72 | } |
||
73 | |||
74 | void rs232_transmit( UBYTE data ) |
||
75 | { |
||
76 | // Wait for empty transmit buffer |
||
77 | while ( !( UCSR1A & (1<<UDRE)) ); |
||
78 | // Put data into buffer, sends the data |
||
79 | UDR1 = data; |
||
80 | } |
||
920 | dimkam | 81 | UBYTE rs232_receive( void ) |
82 | { |
||
83 | if(UCSR1A & (1<<RXC)) return UDR1; |
||
84 | else return 0x00; |
||
85 | } |
||
910 | dimkam | 86 | |
87 | //#ifdef LOGENABLE |
||
88 | void to_log(char* ptr) |
||
89 | { |
||
90 | while( (*ptr)!=0 ) |
||
91 | { |
||
92 | rs232_transmit(*ptr); |
||
93 | ptr++; |
||
94 | } |
||
95 | } |
||
96 | //#endif |
||
97 | |||
98 | |||
99 | //after DLL or DLM changing |
||
100 | void rs232_set_baud(void) |
||
101 | { |
||
102 | if ( rs232_DLM | rs232_DLL ) |
||
103 | { |
||
104 | if( (rs232_DLM&0x80)!=0 ) |
||
105 | { |
||
106 | //AVR mode - direct load UBRR |
||
107 | UBRR1H = 0x7F&rs232_DLM; |
||
108 | UBRR1L = rs232_DLL; |
||
109 | } |
||
110 | else |
||
111 | { |
||
112 | //default mode - like 16550 |
||
113 | ULONG i = BAUD115200/ ((((UWORD)rs232_DLM)<<8) + rs232_DLL); |
||
114 | UWORD rate = ((F_CPU/16)/i)-1; |
||
115 | // Set baud rate |
||
116 | UBRR1H = (UBYTE)(rate>>8); |
||
117 | UBRR1L = (UBYTE)rate; |
||
118 | } |
||
119 | } |
||
120 | else |
||
121 | { |
||
122 | // If( ( rs232_DLM==0 ) && ( rs232_DLL==0 ) ) |
||
123 | // set rate to 256000 baud |
||
124 | UBRR1H = (UBYTE)(UBRR256000>>8); |
||
125 | UBRR1L = (UBYTE)UBRR256000; |
||
126 | } |
||
127 | } |
||
128 | |||
129 | //after LCR changing |
||
130 | void rs232_set_format(void) |
||
131 | { |
||
132 | //set word length and stopbits |
||
133 | UBYTE format = ((rs232_LCR&0x07)<<1); |
||
134 | |||
135 | //set parity (only "No parity","Odd","Even" supported) |
||
136 | switch( rs232_LCR&0x38 ) |
||
137 | { |
||
138 | case 0x08: |
||
139 | //odd parity |
||
140 | format |= _BV(UPM0)|_BV(UPM1); |
||
141 | break; |
||
142 | case 0x18: |
||
143 | //even parity |
||
144 | format |= _BV(UPM1); |
||
145 | break; |
||
146 | //default - parity not used |
||
147 | } |
||
148 | |||
149 | UCSR1C = format; |
||
150 | } |
||
151 | |||
152 | void rs232_zx_write(UBYTE index, UBYTE data) |
||
153 | { |
||
154 | #ifdef LOGENABLE |
||
155 | char log_write[] = "A..D..W\r\n"; |
||
156 | log_write[1] = ((index >> 4) <= 9 )?'0'+(index >> 4):'A'+((index >> 4)-10); |
||
157 | log_write[2] = ((index & 0x0F) <= 9 )?'0'+(index & 0x0F):'A'+(index & 0x0F)-10; |
||
158 | log_write[4] = ((data >> 4) <= 9 )?'0'+(data >> 4):'A'+((data >> 4)-10); |
||
159 | log_write[5] = ((data & 0x0F) <= 9 )?'0'+(data & 0x0F):'A'+((data & 0x0F)-10); |
||
160 | to_log(log_write); |
||
161 | #endif |
||
162 | switch( index ) |
||
163 | { |
||
164 | case 0: |
||
165 | if ( rs232_LCR & 0x80 ) |
||
166 | { |
||
167 | rs232_DLL = data; |
||
168 | rs232_set_baud(); |
||
169 | } |
||
170 | else |
||
171 | { |
||
172 | //place byte to fifo out |
||
173 | if ( ( rs232_FO_end != rs232_FO_start ) || |
||
174 | ( rs232_LSR&0x20 ) ) |
||
175 | { |
||
176 | rs232_FO[rs232_FO_end] = data; |
||
177 | rs232_FO_end = (rs232_FO_end + 1) & 0x0F; |
||
178 | |||
179 | //clear fifo empty flag |
||
180 | rs232_LSR &= ~(0x60); |
||
181 | } |
||
182 | else |
||
183 | { |
||
184 | //fifo overload |
||
185 | } |
||
186 | } |
||
187 | break; |
||
188 | |||
189 | case 1: |
||
190 | if ( rs232_LCR & 0x80 ) |
||
191 | { |
||
192 | //write to DLM |
||
193 | rs232_DLM = data; |
||
194 | rs232_set_baud(); |
||
195 | } |
||
196 | else |
||
197 | { |
||
198 | //bit 7-4 not used and set to '0' |
||
199 | rs232_IER = data & 0x0F; |
||
200 | } |
||
201 | break; |
||
202 | |||
203 | case 2: |
||
204 | if( data&1 ) |
||
205 | { |
||
206 | //FIFO always enable |
||
207 | if( data&(1<<1) ) |
||
208 | { |
||
209 | //receive FIFO reset |
||
210 | rs232_FI_start = rs232_FI_end = 0; |
||
211 | //set empty FIFO flag and clear overrun flag |
||
212 | rs232_LSR &= ~(0x03); |
||
213 | } |
||
214 | if( data&(1<<2) ) |
||
215 | { |
||
216 | //tramsmit FIFO reset |
||
217 | rs232_FO_start = rs232_FO_end = 0; |
||
218 | //set fifo is empty flag |
||
219 | rs232_LSR |= 0x60; |
||
220 | } |
||
221 | rs232_FCR = data&0xC9; |
||
222 | } |
||
223 | break; |
||
224 | |||
225 | case 3: |
||
226 | rs232_LCR = data; |
||
227 | rs232_set_format(); |
||
228 | break; |
||
229 | |||
230 | case 4: |
||
231 | //bit 7-5 not used and set to '0' |
||
232 | rs232_MCR = data & 0x1F; |
||
233 | if ( data&(1<<1) ) |
||
234 | { |
||
235 | //clear RTS |
||
236 | RS232RTS_PORT &= ~(_BV(RS232RTS)); |
||
237 | } |
||
238 | else |
||
239 | { |
||
240 | //set RTS |
||
241 | RS232RTS_PORT |= _BV(RS232RTS); |
||
242 | } |
||
243 | break; |
||
244 | |||
245 | case 5: |
||
246 | //rs232_LSR = data; |
||
247 | break; |
||
248 | |||
249 | case 6: |
||
250 | //rs232_MSR = data; |
||
251 | break; |
||
252 | |||
253 | case 7: |
||
254 | rs232_SCR = data; |
||
255 | break; |
||
256 | } |
||
257 | } |
||
258 | |||
259 | UBYTE rs232_zx_read(UBYTE index) |
||
260 | { |
||
261 | UBYTE data = 0; |
||
262 | switch( index ) |
||
263 | { |
||
264 | case 0: |
||
265 | if ( rs232_LCR & 0x80 ) |
||
266 | { |
||
267 | data = rs232_DLL; |
||
268 | } |
||
269 | else |
||
270 | { |
||
271 | //get byte from fifo in |
||
272 | if ( rs232_LSR&0x01 ) |
||
273 | { |
||
274 | data = rs232_FI[rs232_FI_start]; |
||
275 | rs232_FI_start = ( rs232_FI_start + 1 ) & 0x0F; |
||
276 | |||
277 | if( rs232_FI_start == rs232_FI_end ) |
||
278 | { |
||
279 | //set empty FIFO flag |
||
280 | rs232_LSR &= ~(0x01); |
||
281 | } |
||
282 | } |
||
283 | } |
||
284 | break; |
||
285 | |||
286 | case 1: |
||
287 | if ( rs232_LCR & 0x80 ) |
||
288 | { |
||
289 | data = rs232_DLM; |
||
290 | } |
||
291 | else |
||
292 | { |
||
293 | data = rs232_IER; |
||
294 | } |
||
295 | break; |
||
296 | |||
297 | case 2: |
||
298 | data = rs232_ISR; |
||
299 | break; |
||
300 | |||
301 | case 3: |
||
302 | data = rs232_LCR; |
||
303 | break; |
||
304 | |||
305 | case 4: |
||
306 | data = rs232_MCR; |
||
307 | break; |
||
308 | |||
309 | case 5: |
||
310 | data = rs232_LSR; |
||
311 | break; |
||
312 | |||
313 | case 6: |
||
314 | //DSR=CD=1 |
||
315 | data = rs232_MSR; |
||
316 | //clear flags |
||
317 | rs232_MSR &= 0xF0; |
||
318 | break; |
||
319 | |||
320 | case 7: |
||
321 | data = rs232_SCR; |
||
322 | break; |
||
323 | } |
||
324 | #ifdef LOGENABLE |
||
325 | static UBYTE last = 0; |
||
326 | if ( last!=index ) |
||
327 | { |
||
328 | char log_read[] = "A..D..R\r\n"; |
||
329 | log_read[1] = ((index >> 4) <= 9 )?'0'+(index >> 4):'A'+((index >> 4)-10); |
||
330 | log_read[2] = ((index & 0x0F) <= 9 )?'0'+(index & 0x0F):'A'+(index & 0x0F)-10; |
||
331 | log_read[4] = ((data >> 4) <= 9 )?'0'+(data >> 4):'A'+((data >> 4)-10); |
||
332 | log_read[5] = ((data & 0x0F) <= 9 )?'0'+(data & 0x0F):'A'+((data & 0x0F)-10); |
||
333 | to_log(log_read); |
||
334 | last = index; |
||
335 | } |
||
336 | #endif |
||
337 | return data; |
||
338 | } |
||
339 | |||
340 | void rs232_task(void) |
||
341 | { |
||
342 | //send data |
||
343 | if( (rs232_LSR&0x20)==0 ) |
||
344 | { |
||
345 | if ( UCSR1A&_BV(UDRE) ) |
||
346 | { |
||
347 | UDR1 = rs232_FO[rs232_FO_start]; |
||
348 | rs232_FO_start = (rs232_FO_start+1)&0x0F; |
||
349 | |||
350 | if( rs232_FO_start == rs232_FO_end ) |
||
351 | { |
||
352 | //set fifo is empty flag |
||
353 | rs232_LSR |= 0x60; |
||
354 | } |
||
355 | } |
||
356 | } |
||
357 | |||
358 | //receive data |
||
359 | if( UCSR1A&_BV(RXC) ) |
||
360 | { |
||
361 | BYTE b = UDR1; |
||
362 | if( (rs232_FI_end == rs232_FI_start) && |
||
363 | (rs232_LSR&0x01) ) |
||
364 | { |
||
365 | //set overrun flag |
||
366 | rs232_LSR|=0x02; |
||
367 | } |
||
368 | else |
||
369 | { |
||
370 | //receive data |
||
371 | rs232_FI[rs232_FI_end] = b; |
||
372 | rs232_FI_end = (rs232_FI_end+1)&0x0F; |
||
373 | //set data received flag |
||
374 | rs232_LSR |= 0x01; |
||
375 | } |
||
376 | } |
||
377 | |||
378 | //statuses |
||
379 | if( UCSR1A&_BV(FE) ) |
||
380 | { |
||
381 | //frame error |
||
382 | rs232_LSR |= 0x08; |
||
383 | } |
||
384 | else |
||
385 | { |
||
386 | rs232_LSR &= ~(0x08); |
||
387 | } |
||
388 | |||
389 | if( UCSR1A&_BV(UPE) ) |
||
390 | { |
||
391 | //parity error |
||
392 | rs232_LSR |= 0x04; |
||
393 | } |
||
394 | else |
||
395 | { |
||
396 | rs232_LSR &= ~(0x04); |
||
397 | } |
||
398 | |||
399 | if( RS232CTS_PIN&_BV(RS232CTS) ) |
||
400 | { |
||
401 | //CTS clear |
||
402 | if( (rs232_MSR&0x10)!=0 ) |
||
403 | { |
||
404 | #ifdef LOGENABLE |
||
405 | to_log("CTS\r\n"); |
||
406 | #endif |
||
407 | //CTS changed - set flag |
||
408 | rs232_MSR |= 0x01; |
||
409 | } |
||
410 | rs232_MSR &= ~(0x10); |
||
411 | } |
||
412 | else |
||
413 | { |
||
414 | //CTS set |
||
415 | if( (rs232_MSR&0x10)==0 ) |
||
416 | { |
||
417 | #ifdef LOGENABLE |
||
418 | to_log("CTS\r\n"); |
||
419 | #endif |
||
420 | //CTS changed - set flag |
||
421 | rs232_MSR |= 0x01; |
||
422 | } |
||
423 | rs232_MSR |= 0x10; |
||
424 | } |
||
425 | } |