Axeda demo software for u-blox C027 (GSM)

Dependencies:   mbed

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?

UserRevisionLine numberNew 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 };