Sunday, March 14, 2010

AVR Serial Buffer - March Madness Entry 14

A little while back, I finally got the USART working on the ATTINY2313. Tonight I managed to adapt buffer code to the device.

The point of the buffer is to allow a host to send a series of commands and let them back up, so that the slave (the ATTINY2313) can deal with the commands as it can. This works best in a one directional setup, where the majority of the information being processed is the master talking to the slave. I will confirm that this works fine for some robotic applications, however. In retrospect I should have used a different system, as that was a robot that mapped an area and returned a heavy amount of data - but it still worked.

In my example, it would wait for 3 bytesCode after the jump.
These files are without headers, etc. FunctionHeaders.h is just a collection of function prototypes.

main.c:

int main(){
    InitializeSerial();
    sei();
    DDRB = 0xFF;

    while(1){

        //Don't do anything until we receive 3 items in our buffer.
        while(getBufferSize() < 3){};

        //Release whatever built up in the buffer.
        while(isBufferEmpty() != 1) serialTx(readFromBuffer());
    }


}

Serial.c:

volatile char commandBuffer[BUFFERSIZE];
volatile int bufferStepThrough = 0;
volatile int bytesInBuffer = 0;


/** \fn void InitializeSerial()
 * \brief Initializes the USART0.
 * \param void
 * \return void
 */
void InitializeSerial(void)
{
                UBRRH = (unsigned char)(BAUD_CALC>>8);//Set baud rate
                UBRRL = (unsigned char)BAUD_CALC;//Set baud rate
                UCSRB = _BV(TXEN) | _BV(RXEN) | _BV(RXCIE);
                UCSRC = (1<<USBS)|(3<<UCSZ0);//Set frame format
}


/** \fn void serialTx( unsigned char output )
 * \brief Transmits an individual byte over serial.
 * \param unsigned char output
 * \return void
 */
void serialTx( unsigned char output )
{
                while ( !( UCSRA & (1<<UDRE)) ){}
                UDR = output;//Sends data through buffer
}

/** \fn unsigned char serialRx()
 * \brief Receives an individual byte for serial and echoes it back.
 * \param void
 * \return unsigned char received
 */
unsigned char serialRx( void )
{
                char received = UDR;
                return received;//Get and return received data
}

/** \fn void serialTxString( char * str)
 * \brief Transmits a string, byte by byte, until it sees a null terminator.
 * \param char * str
 * \return void
 */
void serialTxString(char * str) {
                int i=0;
                while(str[i] != '\0') {
                    serialTx(str[i++]);
                }
                PORTB ^= 0xFF;
}

/** \fn void addToBuffer(char newInput)
 * \brief Given a new element, add it to the end of the buffer
 *  given we have not already filled it. If the buffer is full,
 *  it will OVERWRITE THE RECENT COMMANDS, so BEWARE.
 * \param newInput - a new character byte to add.
 * \return void
 */
void addToBuffer(char newInput){
    bufferStepThrough++;
    bytesInBuffer++;
    if(bufferStepThrough >= BUFFERSIZE) bufferStepThrough = 0;
    commandBuffer[bufferStepThrough] = newInput;
}

/** \fn char readFromBuffer(void)
 * \brief returns the most recent command in the buffer.
 * \param void
 * \return void
 */
char readFromBuffer(void){
    while(bytesInBuffer == 0){}; //How can I get around needing this?
    char tmp = commandBuffer[bufferStepThrough];
    if(bufferStepThrough == 0) bufferStepThrough = BUFFERSIZE - 1;
    else bufferStepThrough--;
    bytesInBuffer--;
    return tmp;
}

/** \fn char isBufferEmpty(void)
 * \brief returns 1 if the buffer is empty, 0 if not.
 * \param void
 * \return char
 */
char isBufferEmpty(void){
    if(bytesInBuffer > 0) return 0;
    else return 1;
}

/** \fn char getBufferSize(void)
 * \brief returns the number of bytes in the buffer.
 * \param void
 * \return int
 */
int getBufferSize(void){
    return bytesInBuffer;
}

/** \fn ISR(USART0_RX_vect)
 * \brief Handles serial receive interrupts.
 * \param void
 * \return void
 */
ISR(USART_RX_vect){
    addToBuffer(UDR); //Add to buffer
}

No comments:

Post a Comment