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 | } |