This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Ring buffer or queue for different datatype

Hi,

I want to sample ADC signals and send data when requested via BLE or UART. I set a timer that triggers every 100 ms and gets ADC data.

To store the data, I would like to use some large buffer that will store incoming data. If the buffer reaches end limit and previous data isn't pulled out, it should overwrite the first data and while reading it should start reading from first data (of course not overwritten one) simple: FIFO with first in data replaceable if size full.

I think Ring buffer should solve my issue but the problem is with its data type. The datatype of ADC values is uint16_t while ring buffer has uint8_t so I have to break values in two 8 bytes and store them.

Ring Buffer

Queue library

I read a post about the difference between ring and queue here but it is a general discussion and states both are the same.

Could you please suggest what mechanism shall I use and do I need to modify nrf ring buffer library to support the required data type?

  • From the queue buffer docs: "The queue library provides interrupt secure implementation of the circular buffer to store predefined objects". 

    Whether your data is accessed as uint8 or int16 does not really matter as long as you read and write to the ring buffer in multiples of two bytes, the data is still there. 


  • Thank you for your response.

    I am little confused;

    data is accessed as uint8 or int16 does not really matter

    The nrf_ringbuf_cpy_put API accepts data as uint8_t, so I can't put any other datatype like uint16_t or something so how will it work for my application?

    ret_code_t nrf_ringbuf_cpy_put(nrf_ringbuf_t const * p_ringbuf,
                                   uint8_t const * p_data,
                                   size_t * p_length);

    read and write to the ring buffer in multiples of two bytes

    Let's say I want to store 5 bytes data so do I deliberately need to store 0 or some other value so that data becomes 6 which is multiple of 2 and ignore while retrieving it?


    Regards

  • Ali Rumane said:
    The nrf_ringbuf_cpy_put API accepts data as uint8_t, so I can't put any other datatype like uint16_t or something so how will it work for my application?

     You store an array of data no matter what type it is. Whether you access the data as uint8 or int16 won't change the data itself. 

    I suggest you read up on Type Casting and Pointer Type Casting in C as it is fundamental in understanding your problem and its solution. 

    see f.ex. https://stackoverflow.com/questions/17260527/what-are-the-rules-for-casting-pointers-in-c/17260931

    Ali Rumane said:
    Let's say I want to store 5 bytes data so do I deliberately need to store 0 or some other value so that data becomes 6 which is multiple of 2 and ignore while retrieving it?

     Int16's are exactly two bytes of data. If you want to store 5 uint8's then you will need 5x1 bytes, but if you want to store 5 int16's as uint8's it will require 5x2 bytes. 

  • Hi,
    Thank you for your help.


    I suggest you read up on Type Casting and Pointer Type Casting in C as it is fundamental in understanding your problem and its solution.

    Sure, I will be doing the same.

  • HI ,

    Thank you for your help, I managed to implement it correctly.

    NRF_RINGBUF_DEF(m_ringbuf, 8);
    
    int main(void)
    {
    	ret_code_t err_code;
    	
    	nrf_ringbuf_init(&m_ringbuf);
    	
    	uint16_t data_in[] = {1024, 1025, 1026, 1027};
    	size_t  len_in = sizeof(data_in);
    
    	err_code = nrf_ringbuf_cpy_put(&m_ringbuf, (uint8_t*)data_in, &len_in);
    	APP_ERROR_CHECK(err_code);
    		
        uint16_t data_out[4];
        size_t  len_out = sizeof(data_out);
    
        err_code = nrf_ringbuf_cpy_get(&m_ringbuf, (uint8_t*)data_out, &len_out);
    	APP_ERROR_CHECK(err_code);
    }

    I am facing another issue.

    Let's say I have got 2 bytes of memory left and would like to copy 4 bytes of data. If I use

    nrf_ringbuf_cpy_put, I will get available length or copied length after copying the data.

    Is there a way I can get available length before copying so that I don't have to remove half written data or copy half data so that I can free (nrf_ringbuf_free) some data and then copy the data.

    e.g.

    NRF_RINGBUF_DEF(m_ringbuf, 8);

    ring_bufer(1,2,3,4,5,6)   // Data already present in buffer

    {7,8,9,10}  // New data to write

    Since only two bytes are left, ring buffer will write 7&8 and return available length.

    Regards

Related