Subversion Repositories pentevo

Rev

Rev 910 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed | ?url?

  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. }
  81. UBYTE rs232_receive( void )
  82. {
  83.         if(UCSR1A & (1<<RXC)) return UDR1;
  84.         else return 0x00;
  85. }
  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. }
  426.