Mirror with some correction
Dependencies: mbed FastIO FastPWM USBDevice
circbuf.h@116:7a67265d7c19, 2021-10-01 (annotated)
- Committer:
- arnoz
- Date:
- Fri Oct 01 08:19:46 2021 +0000
- Revision:
- 116:7a67265d7c19
- Parent:
- 77:0b96f6867312
- Correct information regarding your last merge
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
mjr | 77:0b96f6867312 | 1 | // Circular buffer for incoming reports. We write reports in the IRQ |
mjr | 77:0b96f6867312 | 2 | // handler, and we read reports in the main loop in normal application |
mjr | 77:0b96f6867312 | 3 | // (non-IRQ) context. |
mjr | 77:0b96f6867312 | 4 | // |
mjr | 77:0b96f6867312 | 5 | // The design is organically safe for IRQ threading; there are no critical |
mjr | 77:0b96f6867312 | 6 | // sections. The IRQ context has exclusive access to the write pointer, |
mjr | 77:0b96f6867312 | 7 | // and the application context has exclusive access to the read pointer, |
mjr | 77:0b96f6867312 | 8 | // so there are no test-and-set or read-and-modify race conditions. |
mjr | 77:0b96f6867312 | 9 | |
mjr | 77:0b96f6867312 | 10 | #ifndef _CIRCBUF_H_ |
mjr | 77:0b96f6867312 | 11 | #define _CIRCBUF_H_ |
mjr | 77:0b96f6867312 | 12 | |
mjr | 77:0b96f6867312 | 13 | // Circular buffer with a fixed buffer size |
mjr | 77:0b96f6867312 | 14 | template<class T, int cnt> class CircBuf |
mjr | 77:0b96f6867312 | 15 | { |
mjr | 77:0b96f6867312 | 16 | public: |
mjr | 77:0b96f6867312 | 17 | CircBuf() |
mjr | 77:0b96f6867312 | 18 | { |
mjr | 77:0b96f6867312 | 19 | iRead = iWrite = 0; |
mjr | 77:0b96f6867312 | 20 | } |
mjr | 77:0b96f6867312 | 21 | |
mjr | 77:0b96f6867312 | 22 | // Read an item from the buffer. Returns true if an item was available, |
mjr | 77:0b96f6867312 | 23 | // false if the buffer was empty. (Called in the main loop, in application |
mjr | 77:0b96f6867312 | 24 | // context.) |
mjr | 77:0b96f6867312 | 25 | bool read(T &result) |
mjr | 77:0b96f6867312 | 26 | { |
mjr | 77:0b96f6867312 | 27 | if (iRead != iWrite) |
mjr | 77:0b96f6867312 | 28 | { |
mjr | 77:0b96f6867312 | 29 | //{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]);} |
mjr | 77:0b96f6867312 | 30 | memcpy(&result, &buf[iRead], sizeof(T)); |
mjr | 77:0b96f6867312 | 31 | iRead = advance(iRead); |
mjr | 77:0b96f6867312 | 32 | return true; |
mjr | 77:0b96f6867312 | 33 | } |
mjr | 77:0b96f6867312 | 34 | else |
mjr | 77:0b96f6867312 | 35 | return false; |
mjr | 77:0b96f6867312 | 36 | } |
mjr | 77:0b96f6867312 | 37 | |
mjr | 77:0b96f6867312 | 38 | // is an item ready to read? |
mjr | 77:0b96f6867312 | 39 | bool readReady() const { return iRead != iWrite; } |
mjr | 77:0b96f6867312 | 40 | |
mjr | 77:0b96f6867312 | 41 | // Write an item to the buffer. (Called in the IRQ handler, in interrupt |
mjr | 77:0b96f6867312 | 42 | // context.) |
mjr | 77:0b96f6867312 | 43 | bool write(const T &item) |
mjr | 77:0b96f6867312 | 44 | { |
mjr | 77:0b96f6867312 | 45 | int nxt = advance(iWrite); |
mjr | 77:0b96f6867312 | 46 | if (nxt != iRead) |
mjr | 77:0b96f6867312 | 47 | { |
mjr | 77:0b96f6867312 | 48 | memcpy(&buf[iWrite], &item, sizeof(T)); |
mjr | 77:0b96f6867312 | 49 | iWrite = nxt; |
mjr | 77:0b96f6867312 | 50 | return true; |
mjr | 77:0b96f6867312 | 51 | } |
mjr | 77:0b96f6867312 | 52 | else |
mjr | 77:0b96f6867312 | 53 | return false; |
mjr | 77:0b96f6867312 | 54 | } |
mjr | 77:0b96f6867312 | 55 | |
mjr | 77:0b96f6867312 | 56 | private: |
mjr | 77:0b96f6867312 | 57 | int advance(int i) |
mjr | 77:0b96f6867312 | 58 | { |
mjr | 77:0b96f6867312 | 59 | ++i; |
mjr | 77:0b96f6867312 | 60 | return i < cnt ? i : 0; |
mjr | 77:0b96f6867312 | 61 | } |
mjr | 77:0b96f6867312 | 62 | |
mjr | 77:0b96f6867312 | 63 | int iRead; |
mjr | 77:0b96f6867312 | 64 | int iWrite; |
mjr | 77:0b96f6867312 | 65 | T buf[cnt]; |
mjr | 77:0b96f6867312 | 66 | }; |
mjr | 77:0b96f6867312 | 67 | |
mjr | 77:0b96f6867312 | 68 | // Circular buffer with a variable buffer size |
mjr | 77:0b96f6867312 | 69 | template<class T> class CircBufV |
mjr | 77:0b96f6867312 | 70 | { |
mjr | 77:0b96f6867312 | 71 | public: |
mjr | 77:0b96f6867312 | 72 | CircBufV(int cnt) |
mjr | 77:0b96f6867312 | 73 | { |
mjr | 77:0b96f6867312 | 74 | buf = new T[cnt]; |
mjr | 77:0b96f6867312 | 75 | this->cnt = cnt; |
mjr | 77:0b96f6867312 | 76 | iRead = iWrite = 0; |
mjr | 77:0b96f6867312 | 77 | } |
mjr | 77:0b96f6867312 | 78 | |
mjr | 77:0b96f6867312 | 79 | ~CircBufV() |
mjr | 77:0b96f6867312 | 80 | { |
mjr | 77:0b96f6867312 | 81 | delete[] buf; |
mjr | 77:0b96f6867312 | 82 | } |
mjr | 77:0b96f6867312 | 83 | |
mjr | 77:0b96f6867312 | 84 | // Read an item from the buffer. Returns true if an item was available, |
mjr | 77:0b96f6867312 | 85 | // false if the buffer was empty. (Called in the main loop, in application |
mjr | 77:0b96f6867312 | 86 | // context.) |
mjr | 77:0b96f6867312 | 87 | bool read(T &result) |
mjr | 77:0b96f6867312 | 88 | { |
mjr | 77:0b96f6867312 | 89 | if (iRead != iWrite) |
mjr | 77:0b96f6867312 | 90 | { |
mjr | 77:0b96f6867312 | 91 | //{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]);} |
mjr | 77:0b96f6867312 | 92 | memcpy(&result, &buf[iRead], sizeof(T)); |
mjr | 77:0b96f6867312 | 93 | iRead = advance(iRead); |
mjr | 77:0b96f6867312 | 94 | return true; |
mjr | 77:0b96f6867312 | 95 | } |
mjr | 77:0b96f6867312 | 96 | else |
mjr | 77:0b96f6867312 | 97 | return false; |
mjr | 77:0b96f6867312 | 98 | } |
mjr | 77:0b96f6867312 | 99 | |
mjr | 77:0b96f6867312 | 100 | // is an item ready to read? |
mjr | 77:0b96f6867312 | 101 | bool readReady() const { return iRead != iWrite; } |
mjr | 77:0b96f6867312 | 102 | |
mjr | 77:0b96f6867312 | 103 | // Write an item to the buffer. (Called in the IRQ handler, in interrupt |
mjr | 77:0b96f6867312 | 104 | // context.) |
mjr | 77:0b96f6867312 | 105 | bool write(const T &item) |
mjr | 77:0b96f6867312 | 106 | { |
mjr | 77:0b96f6867312 | 107 | int nxt = advance(iWrite); |
mjr | 77:0b96f6867312 | 108 | if (nxt != iRead) |
mjr | 77:0b96f6867312 | 109 | { |
mjr | 77:0b96f6867312 | 110 | memcpy(&buf[iWrite], &item, sizeof(T)); |
mjr | 77:0b96f6867312 | 111 | iWrite = nxt; |
mjr | 77:0b96f6867312 | 112 | return true; |
mjr | 77:0b96f6867312 | 113 | } |
mjr | 77:0b96f6867312 | 114 | else |
mjr | 77:0b96f6867312 | 115 | return false; |
mjr | 77:0b96f6867312 | 116 | } |
mjr | 77:0b96f6867312 | 117 | |
mjr | 77:0b96f6867312 | 118 | private: |
mjr | 77:0b96f6867312 | 119 | int advance(int i) |
mjr | 77:0b96f6867312 | 120 | { |
mjr | 77:0b96f6867312 | 121 | ++i; |
mjr | 77:0b96f6867312 | 122 | return i < cnt ? i : 0; |
mjr | 77:0b96f6867312 | 123 | } |
mjr | 77:0b96f6867312 | 124 | |
mjr | 77:0b96f6867312 | 125 | int iRead; |
mjr | 77:0b96f6867312 | 126 | int iWrite; |
mjr | 77:0b96f6867312 | 127 | int cnt; |
mjr | 77:0b96f6867312 | 128 | T *buf; |
mjr | 77:0b96f6867312 | 129 | }; |
mjr | 77:0b96f6867312 | 130 | |
mjr | 77:0b96f6867312 | 131 | #endif |