* add C027_Support fork

Fork of C027_Support by u-blox

Committer:
simonpfeifhofer
Date:
Sat Sep 10 10:12:25 2016 +0000
Revision:
139:b9a7b3f44734
Parent:
101:edfeb8af206e
* fix parameter name

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mazgch 0:cb2d45baaca3 1 #pragma once
mazgch 0:cb2d45baaca3 2
mazgch 40:295099ff5338 3 /** pipe, this class implements a buffered pipe that can be savely
mazgch 40:295099ff5338 4 written and read between two context. E.g. Written from a task
mazgch 40:295099ff5338 5 and read from a interrupt.
mazgch 40:295099ff5338 6 */
mazgch 0:cb2d45baaca3 7 template <class T>
mazgch 0:cb2d45baaca3 8 class Pipe
mazgch 0:cb2d45baaca3 9 {
mazgch 0:cb2d45baaca3 10 public:
mazgch 40:295099ff5338 11 /* Constructor
mazgch 40:295099ff5338 12 \param n size of the pipe/buffer
mazgch 40:295099ff5338 13 \param b optional buffer that should be used.
mazgch 40:295099ff5338 14 if NULL the constructor will allocate a buffer of size n.
mazgch 40:295099ff5338 15 */
mazgch 9:e7a5959ffae1 16 Pipe(int n, T* b = NULL)
mazgch 0:cb2d45baaca3 17 {
mazgch 74:208e3e32d263 18 _a = b ? NULL : n ? new T[n] : NULL;
mazgch 9:e7a5959ffae1 19 _r = 0;
mazgch 9:e7a5959ffae1 20 _w = 0;
mazgch 9:e7a5959ffae1 21 _b = b ? b : _a;
mazgch 9:e7a5959ffae1 22 _s = n;
mazgch 0:cb2d45baaca3 23 }
mazgch 40:295099ff5338 24 /** Destructor
mazgch 40:295099ff5338 25 frees a allocated buffer.
mazgch 40:295099ff5338 26 */
mazgch 41:b94a1f410e71 27 ~Pipe(void)
mazgch 0:cb2d45baaca3 28 {
mazgch 9:e7a5959ffae1 29 if (_a)
mazgch 9:e7a5959ffae1 30 delete [] _a;
mazgch 0:cb2d45baaca3 31 }
mazgch 40:295099ff5338 32
mazgch 40:295099ff5338 33 /* This function can be used during debugging to hexdump the
mazgch 40:295099ff5338 34 content of a buffer to the stdout.
mazgch 40:295099ff5338 35 */
mazgch 21:c4d64830bf02 36 void dump(void)
mazgch 21:c4d64830bf02 37 {
mazgch 21:c4d64830bf02 38 int o = _r;
mazgch 21:c4d64830bf02 39 printf("pipe: %d/%d ", size(), _s);
mazgch 21:c4d64830bf02 40 while (o != _w) {
mazgch 21:c4d64830bf02 41 T t = _b[o];
mazgch 21:c4d64830bf02 42 printf("%0*X", sizeof(T)*2, t);
mazgch 21:c4d64830bf02 43 o = _inc(o);
mazgch 21:c4d64830bf02 44 }
mazgch 21:c4d64830bf02 45 printf("\n");
mazgch 21:c4d64830bf02 46 }
mazgch 40:295099ff5338 47
mazgch 40:295099ff5338 48 // writing thread/context API
mazgch 40:295099ff5338 49 //-------------------------------------------------------------
mazgch 40:295099ff5338 50
mazgch 40:295099ff5338 51 /** Check if buffer is writeable (=not full)
mazgch 40:295099ff5338 52 \return true if writeable
mazgch 40:295099ff5338 53 */
mazgch 40:295099ff5338 54 bool writeable(void)
mazgch 0:cb2d45baaca3 55 {
mazgch 9:e7a5959ffae1 56 return free() > 0;
mazgch 0:cb2d45baaca3 57 }
mazgch 40:295099ff5338 58
mazgch 40:295099ff5338 59 /** Return the number of free elements in the buffer
mazgch 40:295099ff5338 60 \return the number of free elements
mazgch 40:295099ff5338 61 */
mazgch 40:295099ff5338 62 int free(void)
mazgch 0:cb2d45baaca3 63 {
mazgch 9:e7a5959ffae1 64 int s = _r - _w;
mazgch 9:e7a5959ffae1 65 if (s <= 0)
mazgch 9:e7a5959ffae1 66 s += _s;
mazgch 9:e7a5959ffae1 67 return s - 1;
mazgch 0:cb2d45baaca3 68 }
mazgch 40:295099ff5338 69
mazgch 40:295099ff5338 70 /* Add a single element to the buffer. (blocking)
mazgch 40:295099ff5338 71 \param c the element to add.
mazgch 40:295099ff5338 72 \return c
mazgch 40:295099ff5338 73 */
mazgch 13:e2446fcdc246 74 T putc(T c)
mazgch 0:cb2d45baaca3 75 {
mazgch 9:e7a5959ffae1 76 int i = _w;
mazgch 0:cb2d45baaca3 77 int j = i;
mazgch 0:cb2d45baaca3 78 i = _inc(i);
mazgch 9:e7a5959ffae1 79 while (i == _r) // = !writeable()
mazgch 95:8282dbbe1492 80 /* nothing / just wait */;
mazgch 9:e7a5959ffae1 81 _b[j] = c;
mazgch 13:e2446fcdc246 82 _w = i;
mazgch 13:e2446fcdc246 83 return c;
mazgch 0:cb2d45baaca3 84 }
mazgch 40:295099ff5338 85
mazgch 40:295099ff5338 86 /* Add a buffer of elements to the buffer.
mazgch 40:295099ff5338 87 \param p the elements to add
mazgch 40:295099ff5338 88 \param n the number elements to add from p
mazgch 40:295099ff5338 89 \param t set to true if blocking, false otherwise
mazgch 40:295099ff5338 90 \return number elements added
mazgch 40:295099ff5338 91 */
mazgch 9:e7a5959ffae1 92 int put(const T* p, int n, bool t = false)
mazgch 0:cb2d45baaca3 93 {
mazgch 9:e7a5959ffae1 94 int c = n;
mazgch 9:e7a5959ffae1 95 while (c)
mazgch 0:cb2d45baaca3 96 {
mazgch 9:e7a5959ffae1 97 int f;
mazgch 9:e7a5959ffae1 98 for (;;) // wait for space
mazgch 0:cb2d45baaca3 99 {
mazgch 9:e7a5959ffae1 100 f = free();
mazgch 74:208e3e32d263 101 if (f > 0) break; // data avail
mazgch 9:e7a5959ffae1 102 if (!t) return n - c; // no more space and not blocking
mazgch 95:8282dbbe1492 103 /* nothing / just wait */;
mazgch 0:cb2d45baaca3 104 }
mazgch 9:e7a5959ffae1 105 // check free space
mazgch 9:e7a5959ffae1 106 if (c < f) f = c;
mazgch 9:e7a5959ffae1 107 int w = _w;
mazgch 9:e7a5959ffae1 108 int m = _s - w;
mazgch 9:e7a5959ffae1 109 // check wrap
mazgch 9:e7a5959ffae1 110 if (f > m) f = m;
mazgch 9:e7a5959ffae1 111 memcpy(&_b[w], p, f);
mazgch 9:e7a5959ffae1 112 _w = _inc(w, f);
mazgch 9:e7a5959ffae1 113 c -= f;
mazgch 9:e7a5959ffae1 114 p += f;
mazgch 8:2435cdff8015 115 }
mazgch 9:e7a5959ffae1 116 return n - c;
mazgch 0:cb2d45baaca3 117 }
mazgch 40:295099ff5338 118
mazgch 40:295099ff5338 119 // reading thread/context API
mazgch 0:cb2d45baaca3 120 // --------------------------------------------------------
mazgch 40:295099ff5338 121
mazgch 40:295099ff5338 122 /** Check if there are any emelemnt available (readble / not empty)
mazgch 40:295099ff5338 123 \return true if readable/not empty
mazgch 40:295099ff5338 124 */
mazgch 40:295099ff5338 125 bool readable(void)
mazgch 0:cb2d45baaca3 126 {
mazgch 9:e7a5959ffae1 127 return (_r != _w);
mazgch 0:cb2d45baaca3 128 }
mazgch 40:295099ff5338 129
mazgch 40:295099ff5338 130 /** Get the number of values available in the buffer
mazgch 40:295099ff5338 131 return the number of element available
mazgch 40:295099ff5338 132 */
mazgch 41:b94a1f410e71 133 int size(void)
mazgch 0:cb2d45baaca3 134 {
mazgch 9:e7a5959ffae1 135 int s = _w - _r;
mazgch 9:e7a5959ffae1 136 if (s < 0)
mazgch 9:e7a5959ffae1 137 s += _s;
mazgch 9:e7a5959ffae1 138 return s;
mazgch 0:cb2d45baaca3 139 }
mazgch 40:295099ff5338 140
mazgch 40:295099ff5338 141 /** get a single value from buffered pipe (this function will block if no values available)
mazgch 40:295099ff5338 142 \return the element extracted
mazgch 40:295099ff5338 143 */
mazgch 0:cb2d45baaca3 144 T getc(void)
mazgch 0:cb2d45baaca3 145 {
mazgch 9:e7a5959ffae1 146 int r = _r;
mazgch 9:e7a5959ffae1 147 while (r == _w) // = !readable()
mazgch 95:8282dbbe1492 148 /* nothing / just wait */;
mazgch 9:e7a5959ffae1 149 T t = _b[r];
mazgch 9:e7a5959ffae1 150 _r = _inc(r);
mazgch 0:cb2d45baaca3 151 return t;
mazgch 0:cb2d45baaca3 152 }
mazgch 40:295099ff5338 153
mazgch 40:295099ff5338 154 /*! get elements from the buffered pipe
mazgch 40:295099ff5338 155 \param p the elements extracted
mazgch 40:295099ff5338 156 \param n the maximum number elements to extract
mazgch 40:295099ff5338 157 \param t set to true if blocking, false otherwise
mazgch 40:295099ff5338 158 \return number elements extracted
mazgch 40:295099ff5338 159 */
mazgch 41:b94a1f410e71 160 int get(T* p, int n, bool t = false)
mazgch 0:cb2d45baaca3 161 {
mazgch 9:e7a5959ffae1 162 int c = n;
mazgch 9:e7a5959ffae1 163 while (c)
mazgch 0:cb2d45baaca3 164 {
mazgch 9:e7a5959ffae1 165 int f;
mazgch 9:e7a5959ffae1 166 for (;;) // wait for data
mazgch 0:cb2d45baaca3 167 {
mazgch 9:e7a5959ffae1 168 f = size();
mazgch 9:e7a5959ffae1 169 if (f) break; // free space
mazgch 9:e7a5959ffae1 170 if (!t) return n - c; // no space and not blocking
mazgch 95:8282dbbe1492 171 /* nothing / just wait */;
mazgch 0:cb2d45baaca3 172 }
mazgch 9:e7a5959ffae1 173 // check available data
mazgch 9:e7a5959ffae1 174 if (c < f) f = c;
mazgch 9:e7a5959ffae1 175 int r = _r;
mazgch 9:e7a5959ffae1 176 int m = _s - r;
mazgch 9:e7a5959ffae1 177 // check wrap
mazgch 9:e7a5959ffae1 178 if (f > m) f = m;
mazgch 9:e7a5959ffae1 179 memcpy(p, &_b[r], f);
mazgch 9:e7a5959ffae1 180 _r = _inc(r, f);
mazgch 9:e7a5959ffae1 181 c -= f;
mazgch 9:e7a5959ffae1 182 p += f;
mazgch 0:cb2d45baaca3 183 }
mazgch 9:e7a5959ffae1 184 return n - c;
mazgch 0:cb2d45baaca3 185 }
mazgch 9:e7a5959ffae1 186
mazgch 40:295099ff5338 187 // the following functions are useful if you like to inspect
mazgch 40:295099ff5338 188 // or parse the buffer in the reading thread/context
mazgch 40:295099ff5338 189 // --------------------------------------------------------
mazgch 9:e7a5959ffae1 190
mazgch 40:295099ff5338 191 /** set the parsing index and return the number of available
mazgch 40:295099ff5338 192 elments starting this position.
mazgch 40:295099ff5338 193 \param ix the index to set.
mazgch 40:295099ff5338 194 \return the number of elements starting at this position
mazgch 40:295099ff5338 195 */
mazgch 41:b94a1f410e71 196 int set(int ix)
mazgch 9:e7a5959ffae1 197 {
mazgch 21:c4d64830bf02 198 int sz = size();
mazgch 21:c4d64830bf02 199 ix = (ix > sz) ? sz : ix;
mazgch 21:c4d64830bf02 200 _o = _inc(_r, ix);
mazgch 21:c4d64830bf02 201 return sz - ix;
mazgch 9:e7a5959ffae1 202 }
mazgch 40:295099ff5338 203
mazgch 40:295099ff5338 204 /** get the next element from parsing position and increment parsing index
mazgch 40:295099ff5338 205 \return the extracted element.
mazgch 40:295099ff5338 206 */
mazgch 41:b94a1f410e71 207 T next(void)
mazgch 9:e7a5959ffae1 208 {
mazgch 9:e7a5959ffae1 209 int o = _o;
mazgch 9:e7a5959ffae1 210 T t = _b[o];
mazgch 9:e7a5959ffae1 211 _o = _inc(o);
mazgch 9:e7a5959ffae1 212 return t;
mazgch 9:e7a5959ffae1 213 }
mazgch 40:295099ff5338 214
mazgch 101:edfeb8af206e 215 /** commit the index, mark the current parsing index as consumed data.
mazgch 40:295099ff5338 216 */
mazgch 41:b94a1f410e71 217 void done(void)
mazgch 9:e7a5959ffae1 218 {
mazgch 9:e7a5959ffae1 219 _r = _o;
mazgch 9:e7a5959ffae1 220 }
mazgch 101:edfeb8af206e 221
mazgch 0:cb2d45baaca3 222 private:
mazgch 40:295099ff5338 223 /** increment the index
mazgch 40:295099ff5338 224 \param i index to increment
mazgch 40:295099ff5338 225 \param n the step to increment
mazgch 40:295099ff5338 226 \return the incremented index.
mazgch 40:295099ff5338 227 */
mazgch 40:295099ff5338 228 inline int _inc(int i, int n = 1)
mazgch 40:295099ff5338 229 {
mazgch 40:295099ff5338 230 i += n;
mazgch 40:295099ff5338 231 if (i >= _s)
mazgch 40:295099ff5338 232 i -= _s;
mazgch 40:295099ff5338 233 return i;
mazgch 40:295099ff5338 234 }
mazgch 40:295099ff5338 235
mazgch 9:e7a5959ffae1 236 T* _b; //!< buffer
mazgch 9:e7a5959ffae1 237 T* _a; //!< allocated buffer
mazgch 9:e7a5959ffae1 238 int _s; //!< size of buffer (s - 1) elements can be stored
mazgch 9:e7a5959ffae1 239 volatile int _w; //!< write index
mazgch 9:e7a5959ffae1 240 volatile int _r; //!< read index
mazgch 9:e7a5959ffae1 241 int _o; //!< offest index used by parsing functions
mazgch 0:cb2d45baaca3 242 };