An I/O controller for virtual pinball machines: accelerometer nudge sensing, analog plunger input, button input encoding, LedWiz compatible output controls, and more.

Dependencies:   mbed FastIO FastPWM USBDevice

Fork of Pinscape_Controller by Mike R

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers circbuf.h Source File

circbuf.h

00001 // Circular buffer for incoming reports.  We write reports in the IRQ
00002 // handler, and we read reports in the main loop in normal application
00003 // (non-IRQ) context.  
00004 // 
00005 // The design is organically safe for IRQ threading; there are no critical 
00006 // sections.  The IRQ context has exclusive access to the write pointer, 
00007 // and the application context has exclusive access to the read pointer, 
00008 // so there are no test-and-set or read-and-modify race conditions.
00009 
00010 #ifndef _CIRCBUF_H_
00011 #define _CIRCBUF_H_
00012 
00013 // Circular buffer with a fixed buffer size
00014 template<class T, int cnt> class CircBuf
00015 {
00016 public:
00017     CircBuf() 
00018     {
00019         iRead = iWrite = 0;
00020     }
00021 
00022     // Read an item from the buffer.  Returns true if an item was available,
00023     // false if the buffer was empty.  (Called in the main loop, in application
00024     // context.)
00025     bool read(T &result) 
00026     {
00027         if (iRead != iWrite)
00028         {
00029             //{uint8_t *d = buf[iRead].data; printf("circ read [%02x %02x %02x %02x %02x %02x %02x %02x]\r\n", d[0],d[1],d[2],d[3],d[4],d[5],d[6],d[7]);}
00030             memcpy(&result, &buf[iRead], sizeof(T));
00031             iRead = advance(iRead);
00032             return true;
00033         }
00034         else
00035             return false;
00036     }
00037     
00038     // is an item ready to read?
00039     bool readReady() const { return iRead != iWrite; }
00040     
00041     // Write an item to the buffer.  (Called in the IRQ handler, in interrupt
00042     // context.)
00043     bool write(const T &item)
00044     {
00045         int nxt = advance(iWrite);
00046         if (nxt != iRead)
00047         {
00048             memcpy(&buf[iWrite], &item, sizeof(T));
00049             iWrite = nxt;
00050             return true;
00051         }
00052         else
00053             return false;
00054     }
00055     
00056 private:
00057     int advance(int i)
00058     {
00059         ++i;
00060         return i < cnt ? i : 0;
00061     } 
00062     
00063     int iRead;
00064     int iWrite;
00065     T buf[cnt];
00066 };
00067 
00068 // Circular buffer with a variable buffer size
00069 template<class T> class CircBufV
00070 {
00071 public:
00072     CircBufV(int cnt)
00073     {
00074         buf = new T[cnt];
00075         this->cnt = cnt;
00076         iRead = iWrite = 0;
00077     }
00078     
00079     ~CircBufV()
00080     {
00081         delete[] buf;
00082     }
00083 
00084     // Read an item from the buffer.  Returns true if an item was available,
00085     // false if the buffer was empty.  (Called in the main loop, in application
00086     // context.)
00087     bool read(T &result) 
00088     {
00089         if (iRead != iWrite)
00090         {
00091             //{uint8_t *d = buf[iRead].data; printf("circ read [%02x %02x %02x %02x %02x %02x %02x %02x]\r\n", d[0],d[1],d[2],d[3],d[4],d[5],d[6],d[7]);}
00092             memcpy(&result, &buf[iRead], sizeof(T));
00093             iRead = advance(iRead);
00094             return true;
00095         }
00096         else
00097             return false;
00098     }
00099     
00100     // is an item ready to read?
00101     bool readReady() const { return iRead != iWrite; }
00102     
00103     // Write an item to the buffer.  (Called in the IRQ handler, in interrupt
00104     // context.)
00105     bool write(const T &item)
00106     {
00107         int nxt = advance(iWrite);
00108         if (nxt != iRead)
00109         {
00110             memcpy(&buf[iWrite], &item, sizeof(T));
00111             iWrite = nxt;
00112             return true;
00113         }
00114         else
00115             return false;
00116     }
00117 
00118 private:
00119     int advance(int i)
00120     {
00121         ++i;
00122         return i < cnt ? i : 0;
00123     } 
00124     
00125     int iRead;
00126     int iWrite;
00127     int cnt;
00128     T *buf;
00129 };
00130 
00131 #endif