/****************************************************************************** * The MIT License * * Copyright (c) 2015 Frank-Michael Krause * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, copy, * modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * 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 "ringbuffer.h" #ifdef WIN32 int tmcnt=10; unsigned long millis() { return tmcnt++; } #define NULL 0 #else #include #endif RingBuffer::RingBuffer(int _size, int *_values, unsigned long *_timeStamps) { size = _size; // muss ZweierPotenz sein values = _values; // Pointer auf Speicher für Werte timeStamps = _timeStamps; // optional Pointer auf Speicher für ms timestamps mask = 0; int t = size/2; while (t) { mask = (mask<<1)|1; t = t/2; } reset(); } void RingBuffer::addValue(int value) { values[wrIdx] = value; if (timeStamps != NULL) timeStamps[wrIdx] = millis(); if (anz < size) anz++; wrIdx++; wrIdx &= mask; } void RingBuffer::reset() { anz = 0; wrIdx = 0; rdIdx = 0; for (int i=0; i anz) return 0; rdIdx = (wrIdx - distance) & mask; lastRead = 0; return 1; } /* * Setzt rdIdx auf den ersten Wert, für den der zugehörige timeStamp mindestens zurückliegt, * Es wird das Alter des betreffenden Wertes in ms zurückgegeben * = wird zurückgegeben, wenn kein Wert mindestens so alt wie gefordert ist oder keine timestamps vorhanden sind */ int RingBuffer::setReadIdxDt(int ms) { if (timeStamps == NULL) // keine timeStamps vorhanden return 0; unsigned long aktTime = millis(); unsigned long dt=0; int count = 0; rdIdx = (wrIdx - 1)&mask; // auf letzten eingetragenen Wert setzen lastRead = 0; while (count ms) return dt; count++; rdIdx = (rdIdx-1)&mask; } return 0; } /* * gibt Wert für rdIdx zurück und incrementiert rdIdx, solange rdIdx < (wrIdx-1) * ACHTUNG: wird wrPtr erreicht, so wird immer wieder der letzte Wert zurückgegeben! */ int RingBuffer::getValue() { int ret = values[rdIdx]; if (((rdIdx+1)&mask) == wrIdx) lastRead = 1; else rdIdx = (rdIdx+1)&mask; return ret; } /* * gibt Wert für rdIdx zurück, trägt den zugehörigen timestamp * in time ein und incrementiert rdIdx, solange rdIdx < wrIdx * ACHTUNG: wird wrPtr erreicht, so wird immer wieder der letzte Wert zurückgegeben! */ int RingBuffer::getValue(unsigned long *time) { int ret = values[rdIdx]; if ((time != NULL) && (timeStamps!=NULL)) *time = timeStamps[rdIdx]; if (((rdIdx+1)&mask) == wrIdx) lastRead = 1; else rdIdx = (rdIdx+1)&mask; return ret; } /* * gibt den Wert von rdIdx-1 zurück und decrementiert rdIdx wenn rdIdx-1 != wrIdx * */ int RingBuffer::getPreviousValue() { int idx = (rdIdx-1)&mask; int ret = values[idx]; if (idx != wrIdx) // rdIdx darf nicht kleiner als wrIdx werden rdIdx = idx; else lastRead = 1; return ret; } /* `* decrementiert rdPtr und gibt den zugehörigen Wert zurück */ int RingBuffer::getPreviousValue(unsigned long *time) { int idx = (rdIdx-1)&mask; int ret = values[idx]; rdIdx = (rdIdx-1)&mask; if ((time != NULL) && (timeStamps!=NULL)) *time = timeStamps[idx]; if (idx != wrIdx) // rdIdx darf nicht kleiner als wrIdx werden rdIdx = idx; else lastRead = 1; return ret; } int RingBuffer::getPreviousValueDt(unsigned long *dt) { int idx = (rdIdx-1)&mask; int ret = values[idx]; if ((dt != NULL) && (timeStamps!=NULL)) { unsigned long aktTime = millis(); *dt = aktTime - timeStamps[idx]; } if (idx != wrIdx) // rdIdx darf nicht kleiner als wrIdx werden rdIdx = idx; else lastRead = 1; return ret; } /* * gibt eins zurück, sobald der älteste Wert mit einer PreviousValue-Funktion * gelesen wurde * wird durch jeden Aufruf einer SetReadIdx-Funktion zurückgesetzt */ int RingBuffer::lastValueRead() { return lastRead; } /* * gibt 1 zurück, wenn rdPtr != wrPtr * gibt 0 zurück, wenn rdPtr == wrPtr * * --> funktioniert nur, wenn zuvor SetReadIdx() aufgerufen wurde */ int RingBuffer::valueAvailable() { return !lastRead; } int RingBuffer::getValueAt(int idx) { return values[(wrIdx+idx)&mask]; } int RingBuffer::getValueAt(int idx, unsigned long *time) { int valueIdx = (wrIdx+idx)&mask; if ((time != NULL) && (timeStamps!=NULL)) *time = timeStamps[valueIdx]; return values[valueIdx]; } int RingBuffer::getPreviousValueAt(int idx) { return values[(wrIdx-1-idx)&mask]; } int RingBuffer::getPreviousValueAt(int idx, unsigned long *time) { int valueIdx = (wrIdx-1-idx)&mask; if ((time != NULL) && (timeStamps!=NULL)) *time = timeStamps[valueIdx]; return values[valueIdx]; } //***************************************************************** RingBufferAverage::RingBufferAverage(int _size, int *_values, unsigned long *_timeStamps, int _averageSize):RingBuffer(_size, _values, _timeStamps) { averageSize = _averageSize; averageSum = 0; } void RingBufferAverage::addValue(int val) { RingBuffer::addValue(val); averageSum += val; if (anz > averageSize) averageSum -= getPreviousValueAt(averageSize); } void RingBufferAverage::reset() { RingBuffer::reset(); averageSum = 0; } void RingBufferAverage::setAverageLen(int len) { averageSize = len; reset(); } int RingBufferAverage::getAverage() { if (anz>averageSize) return averageSum/averageSize; return averageSum/anz; } int RingBufferAverage::getAverageSum() { return averageSum; }