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