Xmega Application Note


sw_usart.c

Go to the documentation of this file.
00001 /* This file has been prepared for Doxygen automatic documentation generation.*/
00055 #include "sw_usart.h"
00056 
00068 ISR(INT0_vect)
00069 {
00070         SwUsartRXState = RECEIVE;                     /* Change state */
00071         SW_USART_RX_DISABLE_EXTERNAL0_INTERRUPT();    /* Disable interrupt during the data bits. */
00072         
00073         SW_USART_RX_DISABLE_TIMER_INTERRUPT();        /* Disable timer to change its registers. */
00074         SW_USART_RX_DISABLE_PRESCALER();              /* Reset prescaler counter. */
00075         
00076         SW_USART_RX_TIMER = INTERRUPT_EXEC_CYCL;      /* Clear counter register. Include time to run interrupt rutine. */
00077         SW_USART_RX_COMPARE = SwUartTICKS2WAITONE;    /* Count one and a half period into the future. */
00078         SW_USART_RX_ENABLE_PRESCALER();               /* Start prescaler clock. */
00079 
00080         SwUartRXBitCount = 0;                         /* Clear received bit counter. */
00081         SW_USART_RX_CLEAR_TIMER_INTERRUPT();          /* Clear interrupt bits */
00082         SW_USART_RX_ENABLE_TIMER_INTERRUPT();         /* Enable timer0 interrupt on again */
00083         
00084 }
00085 
00086 
00098 ISR(SW_USART_RX_COMP_VECT)
00099 {
00100         /* Get state of RX pin. */
00101         uint8_t rx_pinstate = SW_USART_GET_RX_PIN();
00102         
00103         /* If 8 bit have not been received, capture and add bit to input byte.*/
00104         if( SwUartRXBitCount < 8 ) {
00105 
00106                 /* Rightshift due to receiving LSB first.*/
00107                 SwUartRXData = (SwUartRXData>>1);
00108 
00109                 /* If a logical 1 is read on the pin, add this to the MSB
00110                  * of the input byte.
00111                  */
00112                 if(rx_pinstate != 0 ){
00113                         SwUartRXData |= 0x80;
00114                 }
00115                 
00116                 SwUartRXBitCount++;
00117         }
00118         
00119         /* Complete byte received, send stop byte.
00120          * Store the received byte in the buffer.
00121          * Disable this interrupt for bit receiving and enable
00122          * pin change interrupt for detecting start bit.
00123          */
00124         else{
00125                 /* If STOP bit is detected, add byte to buffer. If STOP was not
00126                  * detected, discard the byte and reset receiver.
00127                  */
00128                 if(rx_pinstate != 0 ){
00129                         SW_USART_RX_Buffer_PutByte(SwUartRXData);
00130                 }
00131                 SwUsartRXState = IDLE;
00132                 SW_USART_RX_DISABLE_TIMER_INTERRUPT();
00133                 SW_USART_RX_DISABLE_PRESCALER();
00134                 SW_USART_EXT_IFR |= (1 << INTF0);
00135                 SW_USART_RX_ENABLE_EXTERNAL0_INTERRUPT();
00136         }
00137 }
00138 
00150 ISR(SW_USART_TX_COMP_VECT)
00151 {
00152         /* Start bit has already been sent, process the byte and stop bit. */
00153         switch (SwUsartTXState) {
00154 
00155             /* Transmit byte in TX buffer. */
00156             case TRANSMIT:
00157                 
00158                 /* If the complete byte is not transmitted, send next bit.*/
00159                 if( SwUartTXBitCount < 8 ) {
00160                         if( SwUartTXData & 0x01 ){
00161                                 SW_USART_SET_TX_PIN();
00162                         }else{
00163                                 SW_USART_CLR_TX_PIN();
00164                         }
00165                         
00166                         /* Rightshift the tx byte to be ready for the next bit transmit. */
00167                         SwUartTXData = SwUartTXData >> 1;
00168                         SwUartTXBitCount++;
00169                 }
00170                 
00171                 /* Send stop bit if complete byte have been sent. */
00172                 else {
00173                         SW_USART_SET_TX_PIN();
00174                         SwUsartTXState = TRANSMIT_STOP_BIT;
00175                 }
00176                 break;
00177                 
00178             /* Stop bit has been sent, go to idle and disable this interrupt. */
00179             case TRANSMIT_STOP_BIT:
00180                 SW_USART_TX_DISABLE_TIMER_INTERRUPT();
00181                 SwUsartTXState = IDLE;
00182                 break;
00183                 
00184             /* Unknown state. This indicates an error, but this should never occur.
00185              * Set state to IDLE to be able to continue operation.
00186              */
00187             default:
00188                 SW_USART_TX_DISABLE_TIMER_INTERRUPT();
00189                 SwUsartTXState = IDLE;
00190         }
00191 }
00192 
00193 
00200 void SW_USART_init( void )
00201 {
00202         /* Setup the TRX PORT for the Soft UART.
00203          * RX_PIN is input, tri-stated.
00204          * TX_PIN is output, set high to IDLE state.
00205          */
00206         SW_USART_TRX_PORT |= ( 1 << SW_USART_RX_PIN );
00207         SW_USART_TRX_DDR |= ( 1 << SW_USART_TX_PIN );
00208         SW_USART_SET_TX_PIN();
00209         
00210         /* Disable all TX and RX interrupts. */
00211         SW_USART_RX_DISABLE_TIMER_INTERRUPT();
00212         SW_USART_TX_DISABLE_TIMER_INTERRUPT();
00213         
00214         /* Initialize the RX Timer to CTC mode.
00215          * This will clear the timer on compare match, and the counter start
00216          * at bottom again. The compare value is equal to on bit length.
00217          */
00218         SW_USART_RX_PRESCALE = 0x00;
00219         SW_USART_RX_CTRL = 0x02;
00220         SW_USART_RX_COMPARE = SwUartTICKS2WAITONE;
00221 
00222         /* Initialize the TX Timer to CTC mode.
00223          * This will clear the timer on compare match, and the counter start
00224          * at bottom again. The compare value is equal to on bit length.
00225          */
00226         SW_USART_TX_PRESCALE = 0x00;
00227         SW_USART_TX_CTRL = 0x02;
00228         SW_USART_TX_COMPARE = SwUartTICKS2WAITONE;
00229         
00230         /* Initialize the RX external interrupt for sensing the start bit.
00231          * This will trigger on the falling edge of the IO pin.
00232          * Clear any pending interrupts and enable the interrupt.
00233          */
00234         SW_USART_EXT_ICR |= ( 1 << ISC01 );
00235         SW_USART_EXT_IFR |= (1 << INTF0 );
00236         SW_USART_RX_ENABLE_EXTERNAL0_INTERRUPT();
00237         
00238         /* Set TRX states initially to IDLE. */
00239         SwUsartRXState = IDLE;
00240         SwUsartTXState = IDLE;
00241 }
00242 
00243 
00255 void SW_USART_PutChar( const uint8_t c )
00256 {
00257         /* Wait until the TX is not busy or the communication will fail */
00258         while( SwUsartTXState != IDLE ){
00259         }
00260         
00261         /* Disable the clock to the timer and set the compare value to one bit length. */
00262         SW_USART_TX_DISABLE_PRESCALER();
00263         SW_USART_TX_COMPARE = SwUartTICKS2WAITONE;
00264 
00265         /* Change state to indicate that the TX is busy. */
00266         SwUsartTXState = TRANSMIT;
00267 
00268         /* Set intial bitcount value and copy byte into the TX buffer. */
00269         SwUartTXData = c;
00270         SwUartTXBitCount = 0;
00271         
00272         /* Clear the timer counter value and clear any pending interrupts. */
00273         SW_USART_TX_TIMER = 0;
00274         SW_USART_TX_CLEAR_TIMER_INTERRUPT();
00275         
00276         /* Start the timer, set pin value to transmit start bit and enable interrupt. */
00277         SW_USART_TX_ENABLE_PRESCALER();
00278         SW_USART_CLR_TX_PIN();
00279         SW_USART_TX_ENABLE_TIMER_INTERRUPT();
00280 }
00281 
00282 
00287 uint8_t SW_USART_Test_Hit(void)
00288 {
00289         return (SW_USART_RX_Num > 0);
00290 }
00291 
00292 
00297 uint8_t SW_USART_Tx_Ready(void)
00298 {
00299         return ( SwUsartTXState == IDLE );
00300 }
00301 
00302 
00310 void SW_USART_RX_Buffer_PutByte(uint8_t rx_byte)
00311 {
00312         /* Check if buffer is full. The byte will be lost if the buffer is full.*/
00313         if(SW_USART_RX_Num < SW_USART_BUFFER_SIZE ){
00314                 SW_USART_RX_Buffer[SW_USART_RX_Head] = rx_byte;
00315                 
00316                 /* Increase the number of bytes in buffer and the pointer. */
00317                 SW_USART_RX_Num++;
00318                 SW_USART_RX_Head++;
00319                 
00320                 /* Check if we should wrap around. */
00321                 if(SW_USART_RX_Head >= SW_USART_BUFFER_SIZE){
00322                         SW_USART_RX_Head = 0;
00323                 }
00324         }       
00325 }
00326 
00327 
00336 uint8_t SW_USART_RX_Buffer_GetByte(void)
00337 {
00338         uint8_t ret_byte = 0;
00339         
00340         /* Check if there is any bytes in the buffer. */
00341         if(SW_USART_RX_Num > 0){
00342                 ret_byte = SW_USART_RX_Buffer[SW_USART_RX_Tail];
00343         
00344                 /* Enter a critical region as the value might be changed in an interrupt. */
00345                 AVR_ENTER_CRITICAL_REGION();
00346                 
00347                 /* Decrease number of bytes left in buffer. */
00348                 SW_USART_RX_Num--;
00349                 
00350                 /* Leave the critical region and restore SREG register. */
00351                 AVR_LEAVE_CRITICAL_REGION();
00352                 
00353                 /* Increase the tail pointer and wrap around if necessary. */
00354                 SW_USART_RX_Tail++;
00355                 if(SW_USART_RX_Tail >= SW_USART_BUFFER_SIZE){
00356                         SW_USART_RX_Tail = 0;
00357                 }
00358         }
00359         return ret_byte;
00360 }
00361 
00362 
00369 void SW_USART_Set_Baudrate(uint32_t new_baud)
00370 {
00371 //      SwUartTICKS2WAITONE = (uint8_t) ((1000000/new_baud)-1);
00372 }
@DOC_TITLE@
Generated on Mon Jan 18 09:26:08 2010 for AVR1907 Xplain USB Gateway by doxygen 1.5.5