This class provides an API to communicate with a u-blox GNSS chip. The files here were originally part of the C027_Support library (https://developer.mbed.org/teams/ublox/code/C027_Support/ at revision 138:dafbbf31bf76) but have been separated out, primarily for use on the u-blox C030 board where the cellular interace portion of the C027_Support library will instead be provided through the new mbed Cellular API.

Dependents:   example-ublox-at-cellular-interface-ext example-low-power-sleep example-C030-out-of-box-demo example-C030-out-of-box-demo ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pipe.h Source File

pipe.h

00001 /* Copyright (c) 2017 Michael Ammann
00002  *
00003  * Licensed under the Apache License, Version 2.0 (the "License");
00004  * you may not use this file except in compliance with the License.
00005  * You may obtain a copy of the License at
00006  *
00007  *     http://www.apache.org/licenses/LICENSE-2.0
00008  *
00009  * Unless required by applicable law or agreed to in writing, software
00010  * distributed under the License is distributed on an "AS IS" BASIS,
00011  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012  * See the License for the specific language governing permissions and
00013  * limitations under the License.
00014  */
00015 
00016 #ifndef PIPE_H
00017 #define PIPE_H
00018 
00019 /** pipe, this class implements a buffered pipe that can be savely 
00020     written and read between two context. E.g. Written from a task 
00021     and read from a interrupt.
00022 */
00023 template <class T>
00024 class Pipe
00025 {
00026 public:
00027     /* Constructor
00028         \param n size of the pipe/buffer
00029         \param b optional buffer that should be used. 
00030                  if NULL the constructor will allocate a buffer of size n. 
00031     */
00032     Pipe(int n, T* b = NULL)
00033     {
00034         _a = b ? NULL : n ? new T[n] : NULL;
00035         _r = 0;
00036         _w = 0;
00037         _b = b ? b : _a;
00038         _s = n;
00039     }    
00040     /** Destructor 
00041         frees a allocated buffer.
00042     */
00043     ~Pipe(void)
00044     {
00045         if (_a) 
00046             delete [] _a;
00047     }
00048     
00049     /* This function can be used during debugging to hexdump the 
00050        content of a buffer to the stdout. 
00051     */
00052     void dump(void)
00053     {
00054         int o = _r;
00055         printf("pipe: %d/%d ", size(), _s);
00056         while (o != _w) {
00057             T t = _b[o]; 
00058             printf("%0*X", sizeof(T)*2, t);
00059             o = _inc(o); 
00060         }
00061         printf("\n");
00062     }
00063     
00064     // writing thread/context API
00065     //------------------------------------------------------------- 
00066     
00067     /** Check if buffer is writeable (=not full)
00068         \return true if writeable
00069     */
00070     bool writeable(void)
00071     {
00072         return free() > 0;
00073     }
00074     
00075     /** Return the number of free elements in the buffer 
00076         \return the number of free elements
00077     */
00078     int free(void)
00079     {
00080         int s = _r - _w;
00081         if (s <= 0)
00082             s += _s;
00083         return s - 1;
00084     }
00085     
00086     /* Add a single element to the buffer. (blocking)
00087         \param c the element to add.
00088         \return c
00089     */
00090     T putc(T c)
00091     {
00092         int i = _w;
00093         int j = i;
00094         i = _inc(i);
00095         while (i == _r) // = !writeable() 
00096             /* nothing / just wait */;
00097         _b[j] = c;
00098         _w = i; 
00099         return c;
00100     }
00101     
00102     /* Add a buffer of elements to the buffer.
00103         \param p the elements to add
00104         \param n the number elements to add from p
00105         \param t set to true if blocking, false otherwise
00106         \return number elements added 
00107     */
00108     int put(const T* p, int n, bool t = false)
00109     {
00110         int c = n;
00111         while (c)
00112         {
00113             int f;
00114             for (;;) // wait for space
00115             {
00116                 f = free();
00117                 if (f > 0) break;     // data avail
00118                 if (!t) return n - c; // no more space and not blocking
00119                 /* nothing / just wait */;
00120             }
00121             // check free space
00122             if (c < f) f = c;
00123             int w = _w;
00124             int m = _s - w; 
00125             // check wrap
00126             if (f > m) f = m;
00127             memcpy(&_b[w], p, f);
00128             _w = _inc(w, f);
00129             c -= f;
00130             p += f;
00131         }
00132         return n - c;
00133     }
00134     
00135     // reading thread/context API
00136     // --------------------------------------------------------
00137     
00138     /** Check if there are any emelemnt available (readble / not empty)
00139         \return true if readable/not empty
00140     */
00141     bool readable(void)
00142     {
00143         return (_r != _w);
00144     }
00145     
00146     /** Get the number of values available in the buffer
00147         return the number of element available
00148     */
00149     int size(void)
00150     {
00151         int s = _w - _r;
00152         if (s < 0)
00153             s += _s;
00154         return s;
00155     }
00156     
00157     /** get a single value from buffered pipe (this function will block if no values available)
00158         \return the element extracted
00159     */
00160     T getc(void)
00161     {
00162         int r = _r;
00163         while (r == _w) // = !readable()
00164             /* nothing / just wait */;
00165         T t = _b[r];
00166         _r = _inc(r);
00167         return t;
00168     }
00169     
00170     /*! get elements from the buffered pipe
00171         \param p the elements extracted
00172         \param n the maximum number elements to extract
00173         \param t set to true if blocking, false otherwise
00174         \return number elements extracted
00175     */
00176     int get(T* p, int n, bool t = false)
00177     {
00178         int c = n;
00179         while (c)
00180         {
00181             int f;
00182             for (;;) // wait for data
00183             {
00184                 f = size();
00185                 if (f)  break;        // free space
00186                 if (!t) return n - c; // no space and not blocking
00187                 /* nothing / just wait */;
00188             }
00189             // check available data
00190             if (c < f) f = c;
00191             int r = _r;
00192             int m = _s - r; 
00193             // check wrap
00194             if (f > m) f = m;
00195             memcpy(p, &_b[r], f);
00196             _r = _inc(r, f);
00197             c -= f;
00198             p += f;
00199         }
00200         return n - c;
00201     }
00202     
00203     // the following functions are useful if you like to inspect 
00204     // or parse the buffer in the reading thread/context
00205     // --------------------------------------------------------
00206     
00207     /** set the parsing index and return the number of available 
00208         elments starting this position.
00209         \param ix the index to set.
00210         \return the number of elements starting at this position 
00211     */
00212     int set(int ix) 
00213     {
00214         int sz = size();
00215         ix = (ix > sz) ? sz : ix;
00216         _o = _inc(_r, ix); 
00217         return sz - ix;
00218     }
00219     
00220     /** get the next element from parsing position and increment parsing index
00221         \return the extracted element.
00222     */
00223     T next(void)
00224     {
00225         int o = _o;
00226         T t = _b[o]; 
00227         _o = _inc(o); 
00228         return t; 
00229     }
00230     
00231     /** commit the index, mark the current parsing index as consumed data.
00232     */
00233     void done(void) 
00234     {
00235         _r = _o; 
00236     } 
00237 
00238 private:
00239     /** increment the index
00240         \param i index to increment
00241         \param n the step to increment
00242         \return the incremented index.
00243     */
00244     inline int _inc(int i, int n = 1)
00245     {
00246         i += n;
00247         if (i >= _s)
00248             i -= _s;
00249         return i;
00250     }
00251 
00252     T*            _b; //!< buffer
00253     T*            _a; //!< allocated buffer
00254     int           _s; //!< size of buffer (s - 1) elements can be stored
00255     volatile int  _w; //!< write index 
00256     volatile int  _r; //!< read index 
00257     int           _o; //!< offest index used by parsing functions  
00258 };
00259 
00260 #endif
00261 
00262 // End Of File