Monday, March 15, 2010

ATTINY2313 Checksum based serial - March Madness Entry 15

In the last entry, I set up a buffer based ATTINY2313 serial file. In this quick tidbit of code, I implement, using that code, a theoretical implementation of a checksum based serial communication.

Here's the idea - the master gives the slave, our ATTINY2313, a random byte between 0 and 255 (exclusive). It inverts that byte and returns it. It then waits for a SUCCESS or FAIL byte (decided by the implementer). This inversion is a checksum - if the master or the slave are not in sync, the slave would not return the correct checksum, telling both that they need to clear their buffer commands and start over and sync back up.

The modified Serial.c after the jump.
volatile char commandBuffer[BUFFERSIZE];
volatile int bufferStepThrough = 0;
volatile int bytesInBuffer = 0;

volatile char inCommand = 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 char enterCommand(void)
 * \brief sets us as "in" a command
 * \param void
 * \return void
 */
void enterCommand(void){
    inCommand = 1;
}

/** \fn char leaveCommand(void)
 * \brief sets us as "out of" a command
 * \param void
 * \return void
 */
void leaveCommand(void){
    inCommand = 0;
}

/** \fn char amIinaCommand(void)
 * \brief returns whether or not we are in a command process.
 * \param void
 * \return char - 0 for false, 1 for true
 */
int amIinaCommand(void){
    return inCommand;
}

/** \fn void checksum(char checksumIn)
 * \brief Inverts the checksum, bitwise, and returns it.
 * \param char checksumIn
 * \return char checksumOut
 */
char checksum(char checksumIn){
    //Return the bitwise inverted value for a checksum.
    char checksumOut = checksumIn ^ 0xFF;
    return checksumOut;
}

/** \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