Example circular buffer

Show off your PIC based project.

Example circular buffer

Postby ric » Fri Mar 06, 2015 11:36 pm

I posted this code in answer to a question on the MCHIP forum about how to implement a circular buffer.
This example creates a 16 byte buffer for receiving characters using an interrupt service. I don't show the ISR, just a routine called from it (or embedded in it)

I'm posting it here to save time in future. Feel free to post suggestions, improvements, or bugs!

Code: Select all
volatile char comin_wptr;    //write pointer. Is changed inside an interrupt
char comin_rptr;    //read pointer
char comin_buf[16];  //input data buffer
#define BUFFER_MASK 0x0f    //mask to force pointers to wrap after 16
 
void com_init(void)
{
    comin_wptr=0;
    comin_rptr=0;
    //code here to set baud rate, enable serial port, and enable receive interrupts
}
 
//call from USART RX interrupt (or embed inside the ISR)
void comin_put (char dat)
{
    if (((comin_rptr - comin_wptr) & BUFFER_MASK) != 1)    //test if the write pointer is about to hit the read ppinter
    {    //here if there is room in the buffer
        comin_buf[comin_wptr++]=dat;    //add character to buffer, and bump write pointer
        comin_wptr &= BUFFER_MASK;    //force pointer to wrap
    } else
    {    //buffer is full
        //add code here to drop hardware handshaking, or set a flag saying "buffer overflow"
    }
}
 
//fetch the next character from the buffer. Return zero if buffer empty
char comin_get(void)
{
    char temp;    //temp scratch
    if (comin_wptr == comin_rptr)
        return 0;    //if we are called when there is nothing ready
    temp = comin_buf[comin_rptr++];    //fetch character from buffer, and bump read pointer
    comin_rptr &= BUFFER_MASK;    //force pointer to wrap at 16
    return temp;    //return the value we read from the buffer
}
 
//return 0 (false) if buffer empty, or 1 (true) if there is some data in the buffer
bit comin_ready(void)
{
    if ((comin_wptr == comin_rptr)
        return 0;    //buffer is empty
    return 1;    //buffer contains data
}
Latest test project, an LED matrix display made from one reel of addressable LEDs. here
User avatar
ric
Verified identity
 
Posts: 454
Joined: Sat May 24, 2014 2:35 pm
Location: Melbourne, Australia
PIC experience: Professional 5+ years with MCHP products

Re: Example circular buffer

Postby vloki » Wed Mar 11, 2015 11:59 am

I'm using a simple stack buffer to avoid the more complex pointer handling.
In fact it is rare that the stack really has to be shifted because the incoming
bytes usually get processed fast enough.

Looks like this:
Code: Select all
struct s_rxBuffer{                      // receiver buffer
    unsigned char idx;
    unsigned char bytes[MAX_RX_BUFFER];
};

in interrupt:
Code: Select all
    if (USART_IR) // -------------------------------------------------- USART_IR
    {
        if (RCSTA1bits.OERR) // check overflow error
        {  ...    return; }
        if (RCSTA1bits.FERR) // check framing error
        {  ...    return; }

        if (DataRdy1USART()){ //-------------------- new byte received ###
            if(rxBuffer.idx < MAX_RX_BUFFER){
               rxBuffer.bytes[rxBuffer.idx++] = RCREG;
            }
            else{
                ...
                status.rxOVF = 1;
            }
        }
        return;//IR_USART
    }

in main loop:
Code: Select all
        if(rxBuffer.idx){           //###TODO### ERROR overflow !!!
            mUSART_IR_DIS();
            RXbyteImport(rxBuffer.bytes[0]);  //function to process incoming bytes
            rxBuffer.idx--;
            for(i=0;i<=rxBuffer.idx;i++){
                 rxBuffer.bytes[i] = rxBuffer.bytes[i+1];
            }
            mUSART_IR_EN();
//            status.rxOVF = 0;
        }
vloki
Verified identity
 
Posts: 176
Joined: Wed May 28, 2014 8:42 am
Location: Germany
PIC experience: Professional 5+ years with MCHP products


Return to Project Show Case

Who is online

Users browsing this forum: No registered users and 1 guest