Mirror with some correction

Dependencies:   mbed FastIO FastPWM USBDevice

Revision:
77:0b96f6867312
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/circbuf.h	Fri Mar 17 22:02:08 2017 +0000
@@ -0,0 +1,131 @@
+// Circular buffer for incoming reports.  We write reports in the IRQ
+// handler, and we read reports in the main loop in normal application
+// (non-IRQ) context.  
+// 
+// The design is organically safe for IRQ threading; there are no critical 
+// sections.  The IRQ context has exclusive access to the write pointer, 
+// and the application context has exclusive access to the read pointer, 
+// so there are no test-and-set or read-and-modify race conditions.
+
+#ifndef _CIRCBUF_H_
+#define _CIRCBUF_H_
+
+// Circular buffer with a fixed buffer size
+template<class T, int cnt> class CircBuf
+{
+public:
+    CircBuf() 
+    {
+        iRead = iWrite = 0;
+    }
+
+    // Read an item from the buffer.  Returns true if an item was available,
+    // false if the buffer was empty.  (Called in the main loop, in application
+    // context.)
+    bool read(T &result) 
+    {
+        if (iRead != iWrite)
+        {
+            //{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]);}
+            memcpy(&result, &buf[iRead], sizeof(T));
+            iRead = advance(iRead);
+            return true;
+        }
+        else
+            return false;
+    }
+    
+    // is an item ready to read?
+    bool readReady() const { return iRead != iWrite; }
+    
+    // Write an item to the buffer.  (Called in the IRQ handler, in interrupt
+    // context.)
+    bool write(const T &item)
+    {
+        int nxt = advance(iWrite);
+        if (nxt != iRead)
+        {
+            memcpy(&buf[iWrite], &item, sizeof(T));
+            iWrite = nxt;
+            return true;
+        }
+        else
+            return false;
+    }
+    
+private:
+    int advance(int i)
+    {
+        ++i;
+        return i < cnt ? i : 0;
+    } 
+    
+    int iRead;
+    int iWrite;
+    T buf[cnt];
+};
+
+// Circular buffer with a variable buffer size
+template<class T> class CircBufV
+{
+public:
+    CircBufV(int cnt)
+    {
+        buf = new T[cnt];
+        this->cnt = cnt;
+        iRead = iWrite = 0;
+    }
+    
+    ~CircBufV()
+    {
+        delete[] buf;
+    }
+
+    // Read an item from the buffer.  Returns true if an item was available,
+    // false if the buffer was empty.  (Called in the main loop, in application
+    // context.)
+    bool read(T &result) 
+    {
+        if (iRead != iWrite)
+        {
+            //{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]);}
+            memcpy(&result, &buf[iRead], sizeof(T));
+            iRead = advance(iRead);
+            return true;
+        }
+        else
+            return false;
+    }
+    
+    // is an item ready to read?
+    bool readReady() const { return iRead != iWrite; }
+    
+    // Write an item to the buffer.  (Called in the IRQ handler, in interrupt
+    // context.)
+    bool write(const T &item)
+    {
+        int nxt = advance(iWrite);
+        if (nxt != iRead)
+        {
+            memcpy(&buf[iWrite], &item, sizeof(T));
+            iWrite = nxt;
+            return true;
+        }
+        else
+            return false;
+    }
+
+private:
+    int advance(int i)
+    {
+        ++i;
+        return i < cnt ? i : 0;
+    } 
+    
+    int iRead;
+    int iWrite;
+    int cnt;
+    T *buf;
+};
+
+#endif