Michael Spencer / Smoothie

Dependencies:   mbed

Fork of Smoothie by Stéphane Cachat

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers RingBuffer.h Source File

RingBuffer.h

00001 /*
00002       This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
00003       Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
00004       Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
00005       You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>.
00006 
00007       With chucks taken from http://en.wikipedia.org/wiki/Circular_buffer, see licence there also
00008 */
00009 
00010 #ifndef RINGBUFFER_H
00011 #define RINGBUFFER_H
00012 
00013 
00014 template<class kind, int length> class RingBuffer {
00015     public:
00016         RingBuffer();
00017         int          size();
00018         int          capacity();
00019         int          next_block_index(int index);
00020         int          prev_block_index(int index);
00021         void         push_back(kind object);
00022         void         pop_front(kind &object);
00023         kind*        get_head_ref();
00024         kind*        get_tail_ref();
00025         void         get( int index, kind &object);
00026         kind*        get_ref( int index);
00027         void         delete_tail();
00028 
00029         kind         buffer[length];
00030         volatile int          tail;
00031         volatile int          head;
00032 };
00033 
00034 template<class kind, int length> RingBuffer<kind, length>::RingBuffer(){
00035     this->tail = this->head = 0;
00036 }
00037 
00038 template<class kind, int length>  int RingBuffer<kind, length>::capacity(){
00039     return length-1;
00040 }
00041 
00042 template<class kind, int length>  int RingBuffer<kind, length>::size(){
00043     //return((this->tail>this->head)?length:0)+this->head-tail;
00044     __disable_irq();
00045     int i = head - tail + ((tail > head)?length:0);
00046     __enable_irq();
00047     return i;
00048 }
00049 
00050 template<class kind, int length> int RingBuffer<kind, length>::next_block_index(int index){
00051     index++;
00052     if (index == length) { index = 0; }
00053     return(index);
00054 }
00055 
00056 template<class kind, int length> int RingBuffer<kind, length>::prev_block_index(int index){
00057     if (index == 0) { index = length; }
00058     index--;
00059     return(index);
00060 }
00061 
00062 template<class kind, int length> void RingBuffer<kind, length>::push_back(kind object){
00063     this->buffer[this->head] = object;
00064     this->head = (head+1)&(length-1);
00065 }
00066 
00067 template<class kind, int length> kind* RingBuffer<kind, length>::get_head_ref(){
00068     return &(buffer[head]);
00069 }
00070 
00071 template<class kind, int length> kind* RingBuffer<kind, length>::get_tail_ref(){
00072     return &(buffer[tail]);
00073 }
00074 
00075 template<class kind, int length> void RingBuffer<kind, length>::get(int index, kind &object){
00076     int j= 0;
00077     int k= this->tail;
00078     while (k != this->head){
00079         if (j == index) break;
00080         j++;
00081         k= (k + 1) & (length - 1);
00082     }
00083     // TODO : this checks wether we are asked a value out of range
00084     //if (k == this->head){
00085     //    return NULL;
00086     //}
00087     object = this->buffer[k];
00088 }
00089 
00090 
00091 template<class kind, int length> kind* RingBuffer<kind, length>::get_ref(int index){
00092     int j= 0;
00093     int k= this->tail;
00094     while (k != this->head){
00095         if (j == index) break;
00096         j++;
00097         k= (k + 1) & (length - 1);
00098     }
00099     // TODO : this checks wether we are asked a value out of range
00100     if (k == this->head){
00101         return NULL;
00102     }
00103     return &(this->buffer[k]);
00104 }
00105 
00106 template<class kind, int length> void RingBuffer<kind, length>::pop_front(kind &object){
00107     object = this->buffer[this->tail];
00108     this->tail = (this->tail+1)&(length-1);
00109 }
00110 
00111 template<class kind, int length> void RingBuffer<kind, length>::delete_tail(){
00112     //kind dummy;
00113     //this->pop_front(dummy);
00114     this->tail = (this->tail+1)&(length-1);
00115 }
00116 
00117 
00118 #endif