very special ring buffer. This is only for fc_GPS1PPS_F746_F4xx library

Dependents:   fc_GPS1PPS_f746_f4xx Frq_cuntr_Nucleo-F746ZG

RingBuff.cpp

Committer:
kenjiArai
Date:
2016-11-16
Revision:
0:e206b41f0032

File content as of revision 0:e206b41f0032:

/*
 * mbed Library program / Ring Buffer
 *  CAUTION!!
 *  This is very special ring buffer which save newest data and remember
 *   some amount of old data. 
 *  If write newest data into the buffer, lose oldest data.
 *  Don't use this library as normal type of a FIFO ring buffer!!
 *
 * Copyright (c) 2016 Kenji Arai / JH1PJL
 *  http://www.page.sannet.ne.jp/kenjia/index.html
 *  http://mbed.org/users/kenjiArai/
 *      Created:    September 18th, 2016
 *      Revised:    November   8th, 2016
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include <stdint.h>
#include <stdlib.h>
#include "mbed.h"
#include "RingBuff.h"

template <typename T>
RingBuff<T>::RingBuff(const int16_t size)
    :buffer_size(size)
{
    head = tail = 0;
    buff = (T *)malloc(buffer_size * sizeof(T));
}

template <typename T>
RingBuff<T>::~RingBuff()
{
    free(buff);
}

//------------------------------------------------------------------------------
// Ring Buffer Control
//------------------------------------------------------------------------------
template <typename T>
int16_t RingBuff<T>::ring_is_buf_full (void){
    if (tail == head + 1 ||
        (head == buffer_size - 1 && tail == 0)){
        return 1;
    }else {
        return 0;
    }
}

template <typename T>
void RingBuff<T>::ring_put_dt (T dt){
    if (ring_is_buf_full()){
        buff[head++] = dt;
        tail++;
        if (head == buffer_size){
            head = 0;
        }
        if (tail == buffer_size){
            tail = 0;
        }
    } else {    // Not full yet
        buff[head++] = dt;
        if (head == buffer_size){
            head = 0;
            tail = 1;
        }
    }
}

template <typename T>
T RingBuff<T>::ring_get_newest_dt (void){
    T dt;

    if (ring_is_buf_empty()){
        return 0;
    }
    do{ // check interrupt
        head_temp = head;
        if (head == 0){
            dt = buff[buffer_size - 1];
        } else {
            dt = buff[head - 1];
        }
    } while(head != head_temp);
    return dt;
}

template <typename T>
T RingBuff<T>::ring_get_pointed_dt (int16_t offset){
    int16_t hd;
    T dt;

    if (ring_is_buf_empty()){
        return 0;
    }
    do {
        head_temp = head;
        int16_t sz = ring_get_buf_size();
        if (head == 0){
            hd = buffer_size - 1;
        } else {
            hd = head - 1;
        }
        if (sz == buffer_size){ // Buffer is full
            if (sz < offset){   // error
                dt = 0;
            } else {            // data is in buffer
                if (hd >= offset){
                    dt = buff[hd - offset];
                } else {
                    dt = buff[buffer_size - (offset - hd)];
                }
            }
        } else {                // Buffer is not full
            if (sz <= offset){  // error
                dt = 0;
            } else {
                dt = buff[hd - offset];
            }
        }
    } while(head != head_temp);
    return dt;
}


template <typename T>
int16_t RingBuff<T>::ring_get_buf_size (void){
    if (head == tail){      // empty
        return 0;
    }
    if (head > tail){       // Not full yet
        return head;
    } else {                // full
        return buffer_size;
    }
}

template <typename T>
void RingBuff<T>::ring_clear_buf (void){
    head = tail = 0;
}

template <typename T>
int16_t RingBuff<T>::ring_is_buf_empty (void){
    if (head == tail){
        return 1;           // Empty
    } else {
        return 0;
    }
}

template <typename T>
void RingBuff<T>::debug_print_all_buffer (void){
    printf("\r\nhead = %d, tail = %d, size =%d \r\n", head, tail, ring_get_buf_size());
#if 1
    printf("%d, %.0f\r\n", head,   (double)buff[head]);
    printf("%d, %.0f\r\n", head-1, (double)buff[head-1]);
    printf("%d, %.0f\r\n", head-2, (double)buff[head-2]);
    printf("%d, %.0f\r\n", head-3, (double)buff[head-3]);
    printf("%d, %.0f\r\n", head-4, (double)buff[head-4]);
    printf("%d, %.0f\r\n", head-5, (double)buff[head-5]);
    printf("%d, %.0f\r\n", head-6, (double)buff[head-6]); 
#else
    printf("print all buffer contents\r\n");
    for (uint16_t n = 0;n < buffer_size; n++){
        printf("%d, %.0f\r\n", (double)buff[n]);
    }
#endif
}

//------------------------------------------------------------------------------
// force compiler to create code for template
//------------------------------------------------------------------------------
template class RingBuff<uint64_t>;
template class RingBuff<uint32_t>;
template class RingBuff<uint16_t>;