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