[ create a new paste ] login | about

Link: http://codepad.org/jz43HMRE    [ raw code | fork ]

C, pasted on Jan 25:
#include <stdint.h>                                                             
                                                                                
#include <avr/io.h>                                                             
#include <avr/interrupt.h>                                                      
#include <avr/cpufunc.h>                                                        
#include <util/delay.h>                                                         
                                                                                
#define UART_RXBUF_SZ 32 //receive and transmit buffer sizes                    
#define UART_TXBUF_SZ 32                                                        
#define UART_RXBUF_MASK (UART_RXBUF_SZ - 1) //buffer index bitmasks for         
#define UART_TXBUF_MASK (UART_TXBUF_SZ - 1) //  cheap modulo operation          
                                                                                
static uint8_t rxbuf[UART_RXBUF_SZ]; //receive ring buffer                      
static uint8_t txbuf[UART_TXBUF_SZ]; //transmit ring buffer                     
                                                                                
static uint8_t rx_prod_ind; //receiver ISR stores next byte at this index       
static uint8_t tx_prod_ind; //uart_send() queues next  byte(s) at this index    
                                                                                
static uint8_t rx_cons_ind; //uart_recv() gets next byte(s) from this index     
static uint8_t tx_cons_ind; //transmitter ISR transmits byte at this index next 
                                                                                
volatile uint8_t rx_count = 0; //number of bytes in receive buffer              
volatile uint8_t tx_count = 0; //number of bytes in transmit buffer             
                                                                                
ISR(USART_UDRE_vect) //data register empty - can add next char to be transmitted
{                                                                               
        if (tx_count) { //more data to be transmitted                           
                UDR = txbuf[tx_cons_ind++ & UART_TXBUF_MASK];                   
                tx_count--;                                                     
        } else                                                                  
                UCSRB &= ~(1<<UDRIE); //no more data - disable this interrupt   
}                                                                               
                                                                                
ISR(USART_RXC_vect) //incoming data, put into receive buffer                    
{                                                                               
        rxbuf[rx_prod_ind++ & UART_RXBUF_MASK] = UDR;                           
                                                                                
        if (++rx_count > UART_RXBUF_SZ)                                         
                rx_count = UART_RXBUF_SZ; //overflow, data has been overwritten 
}                                                                               
                                                                                
uint8_t //read at most `num` bytes from recv buffer into `data`, return num read
uart_recv(uint8_t *data, uint8_t num)                                           
{                                                                               
        uint8_t numgot = 0; //count how many bytes we got so far                
        uint8_t rxcnt = rx_count; //cache volatile                              
                                                                                
        while(rxcnt > 0 && numgot < num) {                                      
                data[numgot++] = rxbuf[rx_cons_ind++ & UART_RXBUF_MASK];        
                rxcnt--;                                                        
        }                                                                       
                                                                                
        cli();                                                                  
        rx_count -= numgot;//rx_count = rxcnt would be wrong                    
        sei();                                                                  
                                                                                
        return numgot;                                                          
}                                                                               
                                                                                
uint8_t //buffer up to `num` bytes for transmit, return num. actually buffered  
uart_send(uint8_t *data, uint8_t num)                                           
{                                                                               
        uint8_t numput = 0; //count how many bytes we processed so far          
        uint8_t txcnt = tx_count; //cache volatile                              
        while(num-- && txcnt < UART_TXBUF_SZ) {                                 
                txbuf[tx_prod_ind++ & UART_TXBUF_MASK] = *data++;               
                numput++;                                                       
                txcnt++;                                                        
         }                                                                       
                                                                                
        cli();                                                                  
        tx_count += numput;                                                     
        sei();                                                                  
                                                                                
        UCSRB |= (1<<UDRIE); //enable interrupt so that transmission starts     
        return numput;                                                          
}                                                                               
                                                                                
int                                                                             
main(void)                                                                      
{                                                                               
        uint16_t ubrr = 25; //38400 baud @ 16MHz clock                          
        UBRRH = (uint8_t)(ubrr>>8); //initialize uart                           
        UBRRL = (uint8_t)ubrr;                                                  
        UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); // frame format: 8N1          
                                                                                
        DDRC = (1<<DDC7); // a debug led                                        
                                                                                
        for(int x = 0; x < 3; x++) { //flash the led to indicate startup        
                PORTC ^= (1<<PORTC7); _delay_ms(500);                           
                PORTC ^= (1<<PORTC7); _delay_ms(100);                           
        }                                                                       
                                                                                
        UCSRB = (1<<TXEN)|(1<<UDRIE)|(1<<RXEN)|(1<<RXCIE); // usart enable      
        sei();                                                                  
                                                                                
        uint8_t buf[32];                                                        
        for(;;) { //now just read...                                            
                uint8_t n = uart_recv(buf, sizeof buf);                         
                if (n) //...and echo back                                       
                        uart_send(buf, n);                                      
        }                                                                       
}                                                                               
                                                                                


Create a new paste based on this one


Comments: