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