Xmega Application Note | |||||
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 }
Generated on Mon Jan 18 09:26:08 2010 for AVR1907 Xplain USB Gateway by ![]() |