Library for Modtronix NZ32 STM32 boards, like the NZ32-SC151, NZ32-SB072, NZ32-SE411 and others

Committer:
modtronix-com
Date:
Thu Sep 10 20:09:01 2015 +1000
Revision:
7:709130701ac7
Parent:
4:43abdd8eda40
Child:
9:5000feb4b46f
Added MxTick class, circular and command buffer bug fixes

Who changed what in which revision?

UserRevisionLine numberNew contents of line
modtronix 4:43abdd8eda40 1 /**
modtronix 4:43abdd8eda40 2 * File: mx_ascii_cmd_buffer.h
modtronix 4:43abdd8eda40 3 *
modtronix 4:43abdd8eda40 4 * Author: Modtronix Engineering - www.modtronix.com
modtronix 4:43abdd8eda40 5 *
modtronix 4:43abdd8eda40 6 * Description:
modtronix 4:43abdd8eda40 7 *
modtronix 4:43abdd8eda40 8 * Software License Agreement:
modtronix 4:43abdd8eda40 9 * This software has been written or modified by Modtronix Engineering. The code
modtronix 4:43abdd8eda40 10 * may be modified and can be used free of charge for commercial and non commercial
modtronix 4:43abdd8eda40 11 * applications. If this is modified software, any license conditions from original
modtronix 4:43abdd8eda40 12 * software also apply. Any redistribution must include reference to 'Modtronix
modtronix 4:43abdd8eda40 13 * Engineering' and web link(www.modtronix.com) in the file header.
modtronix 4:43abdd8eda40 14 *
modtronix 4:43abdd8eda40 15 * THIS SOFTWARE IS PROVIDED IN AN 'AS IS' CONDITION. NO WARRANTIES, WHETHER EXPRESS,
modtronix 4:43abdd8eda40 16 * IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
modtronix 4:43abdd8eda40 17 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE
modtronix 4:43abdd8eda40 18 * COMPANY SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
modtronix 4:43abdd8eda40 19 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
modtronix 4:43abdd8eda40 20 */
modtronix 4:43abdd8eda40 21 #ifndef SRC_MX_CMD_BUFFER_H_
modtronix 4:43abdd8eda40 22 #define SRC_MX_CMD_BUFFER_H_
modtronix 4:43abdd8eda40 23
modtronix 4:43abdd8eda40 24 // This file contains an ASCII command buffer. It is used to store ASCII commands.
modtronix 4:43abdd8eda40 25 // Each command ends with a ';' character. CR(0x0a='\r') and LF(0x0d='\n') are converted to ';' characters.
modtronix 4:43abdd8eda40 26 // A ASCII command is an ASCII Formatted String, with Escape Sequences (Control Characters).
modtronix 4:43abdd8eda40 27 // It uses 2 upper case characters to represent a single hex character.
modtronix 4:43abdd8eda40 28 // Strings must be enclosed within single quotation marks(').
modtronix 4:43abdd8eda40 29 // Lower case characters 'a' to 'z' are used to represent "Control characters". It has the following format:
modtronix 4:43abdd8eda40 30 // HH = Two upper case characters representing a single byte (hex value).
modtronix 4:43abdd8eda40 31 // XHH = Same as HH
modtronix 4:43abdd8eda40 32 // NDD = Decimal number. For example "N100" = decimal 100 t0='500'
modtronix 4:43abdd8eda40 33 // c = Lower case character 'a' to 'z' represents a "control character".
modtronix 4:43abdd8eda40 34 // s, p = 's' an 'p' control characters represent the start and stop of a message.
modtronix 4:43abdd8eda40 35 // ^^ = Two "escape characters" represents a single '^' character.
modtronix 4:43abdd8eda40 36 // ^x = Use this format to represent a "control character" that is not lower. Lower case characters do not have
modtronix 4:43abdd8eda40 37 // to be escaped. Currently not used, but reserved for future use!
modtronix 4:43abdd8eda40 38 // ' = Enclose string with single quotes. A double ' character will not end the string, but represents a
modtronix 4:43abdd8eda40 39 // single ' character.
modtronix 4:43abdd8eda40 40 //
modtronix 4:43abdd8eda40 41 // Some Examples:
modtronix 4:43abdd8eda40 42 // 30A8'abc' = 2 bytes (0x30, 0xA8), and 3 characters = 'abc'
modtronix 4:43abdd8eda40 43 // 50800C'Hello'0A'World' = 3 bytes, 5 characters('Hello'), 1 byte, 5 characters('World')
modtronix 4:43abdd8eda40 44 // 5588;
modtronix 4:43abdd8eda40 45
modtronix 4:43abdd8eda40 46 #include "mx_buffer_base.h"
modtronix 4:43abdd8eda40 47 #include "mx_circular_buffer.h"
modtronix 4:43abdd8eda40 48
modtronix 4:43abdd8eda40 49 //Defines for MXH_DEBUG - debugging for include file
modtronix 4:43abdd8eda40 50 #define DEBUG_ENABLE_MX_CMD_BUFFER 1
modtronix 4:43abdd8eda40 51 #define DEBUG_ENABLE_INFO_MX_CMD_BUFFER 0
modtronix 4:43abdd8eda40 52
modtronix 4:43abdd8eda40 53 #if !defined(MXH_DEBUG)
modtronix 4:43abdd8eda40 54 #if (DEBUG_ENABLE_MX_CMD_BUFFER == 1)
modtronix 4:43abdd8eda40 55 #define MXH_DEBUG MX_DEBUG
modtronix 4:43abdd8eda40 56 #if (DEBUG_ENABLE_INFO_MX_CMD_BUFFER == 1)
modtronix 4:43abdd8eda40 57 #define MXH_DEBUG_INFO MX_DEBUG
modtronix 4:43abdd8eda40 58 #else
modtronix 4:43abdd8eda40 59 #define MXH_DEBUG_INFO(format, args...) ((void)0)
modtronix 4:43abdd8eda40 60 #endif
modtronix 4:43abdd8eda40 61 #else
modtronix 4:43abdd8eda40 62 #define MXH_DEBUG(format, args...) ((void)0)
modtronix 4:43abdd8eda40 63 #define MXH_DEBUG_INFO(format, args...) ((void)0)
modtronix 4:43abdd8eda40 64 #endif // #if (DEBUG_ENABLE_MX_CMD_BUFFER == 1)
modtronix 4:43abdd8eda40 65 #endif // #if !defined(MXH_DEBUG)
modtronix 4:43abdd8eda40 66
modtronix 4:43abdd8eda40 67
modtronix 4:43abdd8eda40 68 /** Templated Circular buffer class
modtronix 4:43abdd8eda40 69 */
modtronix 4:43abdd8eda40 70 template<uint32_t BufferSize, uint8_t Commands = 16, typename CounterType = uint32_t>
modtronix 4:43abdd8eda40 71 class MxCmdBuffer : public MxBuffer {
modtronix 4:43abdd8eda40 72 public:
modtronix-com 7:709130701ac7 73 MxCmdBuffer() : _head(0), _tail(0), _full(false),
modtronix-com 7:709130701ac7 74 _errBufFull(0), _dontSaveCurrentCommand(0), _lastCharWasEOF(0), flags(0)
modtronix 4:43abdd8eda40 75 {
modtronix 4:43abdd8eda40 76 //flags.Val = 0;
modtronix 4:43abdd8eda40 77 }
modtronix 4:43abdd8eda40 78
modtronix 4:43abdd8eda40 79 ~MxCmdBuffer() {
modtronix 4:43abdd8eda40 80 }
modtronix 4:43abdd8eda40 81
modtronix 4:43abdd8eda40 82 /** Adds a byte to the current command in the buffer. This function checks for the "End of Command" character,
modtronix 4:43abdd8eda40 83 * and if found, increments the "command count" register indicating how many commands this buffer has.
modtronix 4:43abdd8eda40 84 *
modtronix 4:43abdd8eda40 85 * If the buffer becomes full before the "End of Command" character is reached, all bytes added for current
modtronix 4:43abdd8eda40 86 * command are removed. And, all following bytes added until the next "End of Command" character will be ignored.
modtronix 4:43abdd8eda40 87 *
modtronix 4:43abdd8eda40 88 * The checkBufferFullError() function can be used to check if this function caused an error, and command was
modtronix 4:43abdd8eda40 89 * not added to buffer.
modtronix 4:43abdd8eda40 90 *
modtronix 4:43abdd8eda40 91 * @param data Data to be pushed to the buffer
modtronix 4:43abdd8eda40 92 *
modtronix 4:43abdd8eda40 93 * @return true if character added to buffer, else false. Important to note that all characters added to
modtronix 4:43abdd8eda40 94 * current command CAN BE REMOVED if buffer gets full before "End of Command" added to buffer!
modtronix 4:43abdd8eda40 95 */
modtronix 4:43abdd8eda40 96 bool put(const uint8_t& data) {
modtronix 4:43abdd8eda40 97 uint8_t c = data;
modtronix 4:43abdd8eda40 98
modtronix 4:43abdd8eda40 99 //Check if buffer full! If so:
modtronix 4:43abdd8eda40 100 // - All data for this command added till now is lost
modtronix 4:43abdd8eda40 101 // - All future data added for this command is ignored, until next "End of command" character is received
modtronix 4:43abdd8eda40 102 if (isFull() && (_dontSaveCurrentCommand==false)) {
modtronix 4:43abdd8eda40 103 _dontSaveCurrentCommand = true;
modtronix 4:43abdd8eda40 104 _errBufFull = true;
modtronix 4:43abdd8eda40 105 MXH_DEBUG("\r\nBuffer full, cmd LOST!");
modtronix 4:43abdd8eda40 106
modtronix 4:43abdd8eda40 107 //Remove all character added for this command. Restore head to last "End of Command" pointer
modtronix 4:43abdd8eda40 108 if (cmdEndsBuf.isEmpty() == false) {
modtronix-com 7:709130701ac7 109 //Restore head to byte following last "End of Command" pointer
modtronix-com 7:709130701ac7 110 CounterType oldHead;
modtronix-com 7:709130701ac7 111 oldHead = ((cmdEndsBuf.peekLastAdded()+1) % BufferSize);
modtronix-com 7:709130701ac7 112 //Ensure buffer not still full
modtronix-com 7:709130701ac7 113 if (oldHead != _head) {
modtronix-com 7:709130701ac7 114 _head = oldHead;
modtronix-com 7:709130701ac7 115 _full = false;
modtronix-com 7:709130701ac7 116 }
modtronix 4:43abdd8eda40 117 }
modtronix 4:43abdd8eda40 118 //If no commands in buffer, set head=tail
modtronix 4:43abdd8eda40 119 else {
modtronix 4:43abdd8eda40 120 _head = _tail;
modtronix 4:43abdd8eda40 121 _full = false;
modtronix 4:43abdd8eda40 122 }
modtronix 4:43abdd8eda40 123 }
modtronix 4:43abdd8eda40 124
modtronix 4:43abdd8eda40 125 //Check if "End of Command" byte. A command string is terminated with a ';', CR(0x0a='\r') or LF(0x0d='\n') character
modtronix 4:43abdd8eda40 126 if ((c == ';') || (c == 0x0d) || (c == 0x0a)) {
modtronix 4:43abdd8eda40 127 if (flags.bits.replaceCrLfWithEoc) {
modtronix 4:43abdd8eda40 128 c = ';'; //Change to "end of command" character
modtronix 4:43abdd8eda40 129 }
modtronix 4:43abdd8eda40 130
modtronix-com 7:709130701ac7 131 //If last character was also an "End of Command" character, ignore this one
modtronix-com 7:709130701ac7 132 if (_lastCharWasEOF == true) {
modtronix-com 7:709130701ac7 133 MXH_DEBUG_INFO("\r\nMultiple EOC");
modtronix 4:43abdd8eda40 134 return false; //Nothing added
modtronix 4:43abdd8eda40 135 }
modtronix-com 7:709130701ac7 136
modtronix-com 7:709130701ac7 137 _lastCharWasEOF = true; //Remember this was an "End of Command" character
modtronix 4:43abdd8eda40 138
modtronix-com 7:709130701ac7 139 //Current command is now finished, so reset _dontSaveCurrentCommand
modtronix-com 7:709130701ac7 140 if (_dontSaveCurrentCommand == true) {
modtronix-com 7:709130701ac7 141 _dontSaveCurrentCommand = false;
modtronix-com 7:709130701ac7 142 return false; //Nothing added
modtronix-com 7:709130701ac7 143 }
modtronix 4:43abdd8eda40 144
modtronix-com 7:709130701ac7 145 //Add pointer to "end of command" character
modtronix-com 7:709130701ac7 146 cmdEndsBuf.put(_head);
modtronix-com 7:709130701ac7 147 //End of command character will be added to buffer below at current _head pointer
modtronix-com 7:709130701ac7 148 MXH_DEBUG_INFO("\r\nAdded Cmd, EOC=%d", _head);
modtronix-com 7:709130701ac7 149 }
modtronix-com 7:709130701ac7 150 else {
modtronix-com 7:709130701ac7 151 _lastCharWasEOF = false;
modtronix 4:43abdd8eda40 152 }
modtronix 4:43abdd8eda40 153
modtronix 4:43abdd8eda40 154 if (_dontSaveCurrentCommand) {
modtronix 4:43abdd8eda40 155 return false;
modtronix 4:43abdd8eda40 156 }
modtronix 4:43abdd8eda40 157
modtronix 4:43abdd8eda40 158 //Add byte to buffer
modtronix 4:43abdd8eda40 159 _pool[_head++] = c;
modtronix 4:43abdd8eda40 160 _head %= BufferSize;
modtronix 4:43abdd8eda40 161 if (_head == _tail) {
modtronix 4:43abdd8eda40 162 _full = true;
modtronix 4:43abdd8eda40 163 }
modtronix 4:43abdd8eda40 164
modtronix 4:43abdd8eda40 165 return true;
modtronix 4:43abdd8eda40 166 }
modtronix 4:43abdd8eda40 167
modtronix 4:43abdd8eda40 168 /** Adds given NULL terminated string to the buffer. This function checks for the "End of Command" character,
modtronix 4:43abdd8eda40 169 * and if found, increments the "command count" register indicating how many commands this buffer has.
modtronix 4:43abdd8eda40 170 *
modtronix 4:43abdd8eda40 171 * If the buffer becomes full before the "End of Command" character is reached, all bytes added for current
modtronix 4:43abdd8eda40 172 * command are removed. And, all following bytes added until the next "End of Command" character will be ignored.
modtronix 4:43abdd8eda40 173 *
modtronix 4:43abdd8eda40 174 * The checkBufferFullError() function can be used to check if this function caused an error, and command was
modtronix 4:43abdd8eda40 175 * not added to buffer.
modtronix 4:43abdd8eda40 176 *
modtronix 4:43abdd8eda40 177 * @param buf Source buffer containing array to add to buffer
modtronix 4:43abdd8eda40 178 * @param bufSize Size of array to add to buffer
modtronix 4:43abdd8eda40 179 *
modtronix 4:43abdd8eda40 180 * @return Returns true if something added to buffer, else false. Important to note that all characters added to
modtronix 4:43abdd8eda40 181 * current command CAN BE REMOVED if buffer gets full before "End of Command" added to buffer!
modtronix 4:43abdd8eda40 182 */
modtronix 4:43abdd8eda40 183 bool put(const char* str) {
modtronix 4:43abdd8eda40 184 bool retVal = 0;
modtronix 4:43abdd8eda40 185
modtronix 4:43abdd8eda40 186 //DO NOT DO this check here! This check MUST be done by put() function, because if buffer becomes full before
modtronix 4:43abdd8eda40 187 //"End of Command" character received, the put() function will remove all current command characters added!
modtronix 4:43abdd8eda40 188 //if (isFull() == true) {
modtronix 4:43abdd8eda40 189 // return false;
modtronix 4:43abdd8eda40 190 //}
modtronix 4:43abdd8eda40 191
modtronix 4:43abdd8eda40 192 //Add whole string to buffer. DO NOT check isFull() in next line, MUST be checked in put() below!!!!
modtronix 4:43abdd8eda40 193 while((*str != 0) /*&& (isFull()==false)*/) {
modtronix 4:43abdd8eda40 194 retVal = retVal | put((uint8_t)(*str++));
modtronix 4:43abdd8eda40 195 }
modtronix 4:43abdd8eda40 196 return retVal;
modtronix 4:43abdd8eda40 197 }
modtronix 4:43abdd8eda40 198
modtronix 4:43abdd8eda40 199
modtronix 4:43abdd8eda40 200 /** Adds given array to the buffer. This function checks for the "End of Command" character,
modtronix 4:43abdd8eda40 201 * and if found, increments the "command count" register indicating how many commands this buffer has.
modtronix 4:43abdd8eda40 202 *
modtronix 4:43abdd8eda40 203 * If the buffer becomes full before the "End of Command" character is reached, all bytes added for current
modtronix 4:43abdd8eda40 204 * command are removed. And, all following bytes added until the next "End of Command" character will be ignored.
modtronix 4:43abdd8eda40 205 *
modtronix 4:43abdd8eda40 206 * The checkBufferFullError() function can be used to check if this function caused an error, and command was
modtronix 4:43abdd8eda40 207 * not added to buffer.
modtronix 4:43abdd8eda40 208
modtronix 4:43abdd8eda40 209 * @param buf Source buffer containing array to add to buffer
modtronix 4:43abdd8eda40 210 * @param bufSize Size of array to add to buffer
modtronix 4:43abdd8eda40 211 *
modtronix 4:43abdd8eda40 212 * @return Returns true if something added to buffer, else false. Important to note that all characters added to
modtronix 4:43abdd8eda40 213 * current command CAN BE REMOVED if buffer gets full before "End of Command" added to buffer!
modtronix 4:43abdd8eda40 214 */
modtronix 4:43abdd8eda40 215 bool putArray(uint8_t* buf, uint16_t bufSize) {
modtronix 4:43abdd8eda40 216 bool retVal = 0;
modtronix 4:43abdd8eda40 217 int i;
modtronix 4:43abdd8eda40 218
modtronix 4:43abdd8eda40 219 //DO NOT DO this check here! This check MUST be done by put() function, because if buffer becomes full before
modtronix 4:43abdd8eda40 220 //"End of Command" character received, the put() function will remove all current command characters added!
modtronix 4:43abdd8eda40 221 //if (getFree() < bufSize) {
modtronix 4:43abdd8eda40 222 // return 0;
modtronix 4:43abdd8eda40 223 //}
modtronix 4:43abdd8eda40 224
modtronix 4:43abdd8eda40 225 for(i=0; i<bufSize; i++) {
modtronix 4:43abdd8eda40 226 retVal = retVal | put(buf[i]);
modtronix 4:43abdd8eda40 227 }
modtronix 4:43abdd8eda40 228 return retVal;
modtronix 4:43abdd8eda40 229 }
modtronix 4:43abdd8eda40 230
modtronix 4:43abdd8eda40 231 /** Gets and object from the buffer. Ensure buffer is NOT empty before calling this function!
modtronix 4:43abdd8eda40 232 *
modtronix 4:43abdd8eda40 233 * @return Read data
modtronix 4:43abdd8eda40 234 */
modtronix 4:43abdd8eda40 235 uint8_t get() {
modtronix 4:43abdd8eda40 236 if (!isEmpty()) {
modtronix 4:43abdd8eda40 237 uint8_t retData;
modtronix 4:43abdd8eda40 238 retData = _pool[_tail++];
modtronix 4:43abdd8eda40 239 _tail %= BufferSize;
modtronix 4:43abdd8eda40 240 _full = false;
modtronix 4:43abdd8eda40 241 return retData;
modtronix 4:43abdd8eda40 242 }
modtronix 4:43abdd8eda40 243 return 0;
modtronix 4:43abdd8eda40 244 }
modtronix 4:43abdd8eda40 245
modtronix 4:43abdd8eda40 246 /** Gets and object from the buffer. Returns true if OK, else false
modtronix 4:43abdd8eda40 247 *
modtronix 4:43abdd8eda40 248 * @param data Variable to put read data into
modtronix 4:43abdd8eda40 249 * @return True if the buffer is not empty and data contains a transaction, false otherwise
modtronix 4:43abdd8eda40 250 */
modtronix 4:43abdd8eda40 251 bool getAndCheck(uint8_t& data) {
modtronix 4:43abdd8eda40 252 if (!isEmpty()) {
modtronix 4:43abdd8eda40 253 data = _pool[_tail++];
modtronix 4:43abdd8eda40 254 _tail %= BufferSize;
modtronix 4:43abdd8eda40 255 _full = false;
modtronix 4:43abdd8eda40 256 return true;
modtronix 4:43abdd8eda40 257 }
modtronix 4:43abdd8eda40 258 return false;
modtronix 4:43abdd8eda40 259 }
modtronix 4:43abdd8eda40 260
modtronix 4:43abdd8eda40 261
modtronix 4:43abdd8eda40 262 /** Gets and object from the buffer, but do NOT remove it. Ensure buffer is NOT empty before calling
modtronix 4:43abdd8eda40 263 * this function! If buffer is empty, will return an undefined value.
modtronix 4:43abdd8eda40 264 *
modtronix 4:43abdd8eda40 265 * @return Read data
modtronix 4:43abdd8eda40 266 */
modtronix 4:43abdd8eda40 267 uint8_t peek() {
modtronix 4:43abdd8eda40 268 return _pool[_tail];
modtronix 4:43abdd8eda40 269 }
modtronix 4:43abdd8eda40 270
modtronix 4:43abdd8eda40 271 /** Gets an object from the buffer at given offset, but do NOT remove it. Given offset is a value from
modtronix 4:43abdd8eda40 272 * 0 to n. Ensure buffer has as many objects as the offset requested! For example, if buffer has 5 objects
modtronix 4:43abdd8eda40 273 * available, given offset can be a value from 0 to 4.
modtronix 4:43abdd8eda40 274 *
modtronix 4:43abdd8eda40 275 * @param offset Offset of requested object. A value from 0-n, where (n+1) = available objects = getAvailable()
modtronix 4:43abdd8eda40 276 * @return Object at given offset
modtronix 4:43abdd8eda40 277 */
modtronix 4:43abdd8eda40 278 uint8_t peekAt(CounterType offset) {
modtronix 4:43abdd8eda40 279 return _pool[(offset+_tail)%BufferSize];
modtronix 4:43abdd8eda40 280 }
modtronix 4:43abdd8eda40 281
modtronix 4:43abdd8eda40 282 /** Gets the last object added to the buffer, but do NOT remove it.
modtronix 4:43abdd8eda40 283 *
modtronix 4:43abdd8eda40 284 * @return Object at given offset
modtronix 4:43abdd8eda40 285 */
modtronix 4:43abdd8eda40 286 uint8_t peekLastAdded() {
modtronix 4:43abdd8eda40 287 return _pool[(_head-1)%BufferSize];
modtronix 4:43abdd8eda40 288 }
modtronix 4:43abdd8eda40 289
modtronix 4:43abdd8eda40 290 /** Gets and array of given size, and write it to given buffer.
modtronix 4:43abdd8eda40 291 * Nothing is removed from buffer
modtronix 4:43abdd8eda40 292 *
modtronix 4:43abdd8eda40 293 * @param buf Destination buffer to array to
modtronix 4:43abdd8eda40 294 * @param bufSize Maximum size to write to destination buffer
modtronix 4:43abdd8eda40 295 * @param lenReq Requested length
modtronix 4:43abdd8eda40 296 *
modtronix 4:43abdd8eda40 297 *
modtronix 4:43abdd8eda40 298 * @return Number of bytes written to given buffer
modtronix 4:43abdd8eda40 299 */
modtronix 4:43abdd8eda40 300 uint16_t peekArray(uint8_t* buf, uint16_t bufSize, CounterType lenReq) {
modtronix 4:43abdd8eda40 301 uint16_t lenWritten=0;
modtronix 4:43abdd8eda40 302 CounterType currTail;
modtronix 4:43abdd8eda40 303 currTail = _tail;
modtronix 4:43abdd8eda40 304
modtronix 4:43abdd8eda40 305 //Some checks
modtronix 4:43abdd8eda40 306 if (isEmpty() || (bufSize==0) || (lenReq==0)) {
modtronix 4:43abdd8eda40 307 return 0;
modtronix 4:43abdd8eda40 308 }
modtronix 4:43abdd8eda40 309
modtronix 4:43abdd8eda40 310 do {
modtronix 4:43abdd8eda40 311 buf[lenWritten++] = _pool[currTail];
modtronix 4:43abdd8eda40 312 currTail = ((currTail+1)%BufferSize);
modtronix 4:43abdd8eda40 313 } while((lenWritten<bufSize) && (lenWritten<lenReq));
modtronix 4:43abdd8eda40 314
modtronix 4:43abdd8eda40 315
modtronix 4:43abdd8eda40 316 return lenWritten;
modtronix 4:43abdd8eda40 317 }
modtronix 4:43abdd8eda40 318
modtronix 4:43abdd8eda40 319 /** Check if the buffer has a complete command
modtronix 4:43abdd8eda40 320 *
modtronix 4:43abdd8eda40 321 * @return True if the buffer has a command, false if not
modtronix 4:43abdd8eda40 322 */
modtronix 4:43abdd8eda40 323 bool hasCommand() {
modtronix 4:43abdd8eda40 324 return !cmdEndsBuf.isEmpty();
modtronix 4:43abdd8eda40 325 }
modtronix 4:43abdd8eda40 326
modtronix 4:43abdd8eda40 327 /** Get length of next command in buffer, excluding "end of command" character! For example,
modtronix 4:43abdd8eda40 328 * the command "r=100;" will return 5.
modtronix 4:43abdd8eda40 329 * @return Length of next command in buffer
modtronix 4:43abdd8eda40 330 */
modtronix 4:43abdd8eda40 331 uint8_t getCommandLength() {
modtronix 4:43abdd8eda40 332 CounterType offsetEOC;
modtronix 4:43abdd8eda40 333
modtronix 4:43abdd8eda40 334 if (cmdEndsBuf.isEmpty()) {
modtronix 4:43abdd8eda40 335 return 0;
modtronix 4:43abdd8eda40 336 }
modtronix 4:43abdd8eda40 337
modtronix 4:43abdd8eda40 338 //Get offset of "end of command" character of current command in buffer
modtronix 4:43abdd8eda40 339 offsetEOC = cmdEndsBuf.peek();
modtronix 4:43abdd8eda40 340
modtronix 4:43abdd8eda40 341 return ((offsetEOC-_tail) % BufferSize);
modtronix 4:43abdd8eda40 342 }
modtronix 4:43abdd8eda40 343
modtronix 4:43abdd8eda40 344 /** Get number of commands waiting in buffer
modtronix 4:43abdd8eda40 345 * @return Number of commands waiting in buffer
modtronix 4:43abdd8eda40 346 */
modtronix 4:43abdd8eda40 347 uint8_t getCommandsAvailable() {
modtronix 4:43abdd8eda40 348 return cmdEndsBuf.getAvailable();
modtronix 4:43abdd8eda40 349 }
modtronix 4:43abdd8eda40 350
modtronix 4:43abdd8eda40 351 /** If current command has "name=value" format, the 'name' part is returned.
modtronix 4:43abdd8eda40 352 * Else, the whole command is returned(excluding a possible trailing '=' character).
modtronix 4:43abdd8eda40 353 * Returned string is NULL terminated by default.
modtronix 4:43abdd8eda40 354 * Nothing is removed from the buffer!
modtronix 4:43abdd8eda40 355 *
modtronix 4:43abdd8eda40 356 * If true is returned in the "isNameValue" parameter, this is a "name=value" command, with a name part of at
modtronix 4:43abdd8eda40 357 * lease 1 character long. The offset of the 'value' part will be the returned
modtronix 4:43abdd8eda40 358 *
modtronix 4:43abdd8eda40 359 * If false is returned in the "isNameValue" parameter, there is no 'value' part of at least 1 character. There could however
modtronix 4:43abdd8eda40 360 * still be a '=' character with no 'value' following it. Any possible trailing '=' character is removed string returned in 'buf'.
modtronix 4:43abdd8eda40 361 *
modtronix 4:43abdd8eda40 362 * @param buf Destination buffer to write string to
modtronix 4:43abdd8eda40 363 *
modtronix 4:43abdd8eda40 364 * @param bufSize Maximum size to write to destination buffer
modtronix 4:43abdd8eda40 365 *
modtronix 4:43abdd8eda40 366 * @param isNameValue Returns true if a '=' character was found -AND- at least 1 char following it. This indicates
modtronix 4:43abdd8eda40 367 * this is a "name=value" command, and has a value part(of at least 1 character) following the '='.
modtronix 4:43abdd8eda40 368 * First character of 'value' is value returned by this function + 1!
modtronix 4:43abdd8eda40 369 *
modtronix 4:43abdd8eda40 370 * @return Size in bytes of string returned in 'buf' parameter(is 'name' if isNameValue=true).
modtronix 4:43abdd8eda40 371 * If true is returned in 'isNameValue', 'buf' contains the 'name' part of a 'name=value' command. This returned offset points to '='.
modtronix 4:43abdd8eda40 372 * If false is returned in 'isNameValue', 'buf' contains the whole command string(excluding possible trailing '=' character).
modtronix 4:43abdd8eda40 373 */
modtronix 4:43abdd8eda40 374 uint16_t getCommandName(uint8_t* buf, uint16_t bufSize, bool& isNameValue, bool nullTerminate = true) {
modtronix 4:43abdd8eda40 375 CounterType offsetEOC;
modtronix 4:43abdd8eda40 376 CounterType currTail;
modtronix 4:43abdd8eda40 377 uint16_t nameLen = 0;
modtronix 4:43abdd8eda40 378 isNameValue=false;
modtronix 4:43abdd8eda40 379
modtronix 4:43abdd8eda40 380 //Some checks
modtronix 4:43abdd8eda40 381 if (cmdEndsBuf.isEmpty() || (bufSize==0) || (_pool[_tail]=='=')) {
modtronix 4:43abdd8eda40 382 return 0;
modtronix 4:43abdd8eda40 383 }
modtronix 4:43abdd8eda40 384 offsetEOC = cmdEndsBuf.peek();
modtronix 4:43abdd8eda40 385 currTail = _tail;
modtronix 4:43abdd8eda40 386
modtronix 4:43abdd8eda40 387 //Copy current command string to given buffer, until '=' reached
modtronix 4:43abdd8eda40 388 do {
modtronix 4:43abdd8eda40 389 buf[nameLen++] = _pool[currTail];
modtronix 4:43abdd8eda40 390 currTail = ((currTail+1)%BufferSize);
modtronix 4:43abdd8eda40 391 //If next character is '='
modtronix 4:43abdd8eda40 392 if(_pool[currTail] == '=') {
modtronix 4:43abdd8eda40 393 //Check at least 1 character following '='
modtronix 4:43abdd8eda40 394 //Get pointer of character following '=', and ensure it is not "end of command"(offsetEOC). Meaning there is
modtronix 4:43abdd8eda40 395 //still at least 1 more character following '='
modtronix 4:43abdd8eda40 396 if(((currTail+1)%BufferSize) != offsetEOC) {
modtronix 4:43abdd8eda40 397 isNameValue = true;
modtronix 4:43abdd8eda40 398 }
modtronix 4:43abdd8eda40 399 break;
modtronix 4:43abdd8eda40 400 }
modtronix 4:43abdd8eda40 401 } while((currTail!=offsetEOC) && (nameLen<bufSize));
modtronix 4:43abdd8eda40 402
modtronix 4:43abdd8eda40 403
modtronix 4:43abdd8eda40 404 if (nullTerminate) {
modtronix 4:43abdd8eda40 405 if(nameLen<bufSize) {
modtronix 4:43abdd8eda40 406 buf[nameLen] = 0;
modtronix 4:43abdd8eda40 407 }
modtronix 4:43abdd8eda40 408 buf[bufSize-1] = 0; //Null terminate last position of buffer in case it filled up
modtronix 4:43abdd8eda40 409 }
modtronix 4:43abdd8eda40 410
modtronix 4:43abdd8eda40 411 return nameLen;
modtronix 4:43abdd8eda40 412 }
modtronix 4:43abdd8eda40 413
modtronix 4:43abdd8eda40 414 /** For commands with "name=value" format, returns the 'value' part.
modtronix 4:43abdd8eda40 415 * Returned string is NULL terminated by default.
modtronix 4:43abdd8eda40 416 * Nothing is removed from the buffer!
modtronix 4:43abdd8eda40 417 *
modtronix 4:43abdd8eda40 418 * To optimize this function, call getCommandName() before calling this function. The getCommandName() return value(+1)
modtronix 4:43abdd8eda40 419 * can be used as 'offset' parameter to this function. This will save this function from searching for '=' character.
modtronix 4:43abdd8eda40 420 *
modtronix 4:43abdd8eda40 421 *
modtronix 4:43abdd8eda40 422 * @param buf Destination buffer to write string to
modtronix 4:43abdd8eda40 423 * @param bufSize Maximum size to write to destination buffer
modtronix 4:43abdd8eda40 424 * @param offset Gives offset of value string if known. This can be value(+1) returned by
modtronix 4:43abdd8eda40 425 * getCommandName() function. Use -1 if unknown.
modtronix 4:43abdd8eda40 426 *
modtronix 4:43abdd8eda40 427 * @return Size in bytes of returned string
modtronix 4:43abdd8eda40 428 */
modtronix 4:43abdd8eda40 429 uint16_t getCommandValue(uint8_t* buf, uint16_t bufSize, uint16_t offset = -1, bool nullTerminate = true) {
modtronix 4:43abdd8eda40 430 CounterType offsetEOC;
modtronix 4:43abdd8eda40 431 CounterType currTail;
modtronix 4:43abdd8eda40 432 uint16_t valueLen = 0;
modtronix 4:43abdd8eda40 433 bool foundEq=false; //'=' character found
modtronix 4:43abdd8eda40 434
modtronix 4:43abdd8eda40 435 //Some checks
modtronix 4:43abdd8eda40 436 if (cmdEndsBuf.isEmpty() || (bufSize==0)) {
modtronix 4:43abdd8eda40 437 return 0;
modtronix 4:43abdd8eda40 438 }
modtronix 4:43abdd8eda40 439 offsetEOC = cmdEndsBuf.peek(); //offset of "end of command" character
modtronix 4:43abdd8eda40 440
modtronix 4:43abdd8eda40 441 currTail = _tail;
modtronix 4:43abdd8eda40 442
modtronix 4:43abdd8eda40 443 //If offset was given, it will point to first character of value string
modtronix 4:43abdd8eda40 444 if (offset != -1) {
modtronix 4:43abdd8eda40 445 //Check offset point somewhere inside current command! Where ((offsetEOC-_tail) % BufferSize) = command length
modtronix 4:43abdd8eda40 446 if (offset < ((offsetEOC-_tail)%BufferSize)) {
modtronix 4:43abdd8eda40 447 currTail = ((currTail + offset)%BufferSize); //Add offset to tail
modtronix 4:43abdd8eda40 448
modtronix 4:43abdd8eda40 449 //If given offset was for first character of 'value', it will NOT point to '='. It will be next character.
modtronix 4:43abdd8eda40 450 if(_pool[currTail] != '=') {
modtronix 4:43abdd8eda40 451 //Points to character after '=', indicate '=' has already been found.
modtronix 4:43abdd8eda40 452 foundEq=true;
modtronix 4:43abdd8eda40 453 }
modtronix 4:43abdd8eda40 454 //ELSE, assume offset for for '=' character. It will be found in step below
modtronix 4:43abdd8eda40 455 }
modtronix 4:43abdd8eda40 456 else {
modtronix 4:43abdd8eda40 457 //currTail = _tail; //Ignore given offset, and search whole command for '='
modtronix 4:43abdd8eda40 458 MXH_DEBUG("\r\ngetCommandValue() Offset error!");
modtronix 4:43abdd8eda40 459 }
modtronix 4:43abdd8eda40 460 }
modtronix 4:43abdd8eda40 461
modtronix 4:43abdd8eda40 462 do {
modtronix 4:43abdd8eda40 463 if (foundEq) {
modtronix 4:43abdd8eda40 464 buf[valueLen++] = _pool[currTail];
modtronix 4:43abdd8eda40 465 }
modtronix 4:43abdd8eda40 466 else {
modtronix 4:43abdd8eda40 467 if(_pool[currTail] == '=') {
modtronix 4:43abdd8eda40 468 foundEq=true;
modtronix 4:43abdd8eda40 469 }
modtronix 4:43abdd8eda40 470 }
modtronix 4:43abdd8eda40 471 currTail = ((currTail+1)%BufferSize);
modtronix 4:43abdd8eda40 472 } while((currTail != offsetEOC) && (valueLen<bufSize));
modtronix 4:43abdd8eda40 473
modtronix 4:43abdd8eda40 474 if (nullTerminate) {
modtronix 4:43abdd8eda40 475 if(valueLen<bufSize) {
modtronix 4:43abdd8eda40 476 buf[valueLen] = 0;
modtronix 4:43abdd8eda40 477 }
modtronix 4:43abdd8eda40 478 buf[bufSize-1] = 0; //Null terminate last position of buffer in case it filled up
modtronix 4:43abdd8eda40 479 }
modtronix 4:43abdd8eda40 480
modtronix 4:43abdd8eda40 481 return valueLen;
modtronix 4:43abdd8eda40 482 }
modtronix 4:43abdd8eda40 483
modtronix 4:43abdd8eda40 484 /** Search current command for given character
modtronix 4:43abdd8eda40 485 *
modtronix 4:43abdd8eda40 486 * @param offset Returns offset of found character. If NULL, this parameter is not used.
modtronix 4:43abdd8eda40 487 *
modtronix 4:43abdd8eda40 488 * @return Returns true if found, else false
modtronix 4:43abdd8eda40 489 */
modtronix 4:43abdd8eda40 490 bool search(uint8_t c, uint16_t* offsetFound) {
modtronix 4:43abdd8eda40 491 CounterType offsetEOF;
modtronix 4:43abdd8eda40 492 CounterType currTail;
modtronix 4:43abdd8eda40 493
modtronix 4:43abdd8eda40 494 //Get command length
modtronix 4:43abdd8eda40 495 if (cmdEndsBuf.isEmpty()) {
modtronix 4:43abdd8eda40 496 return false;
modtronix 4:43abdd8eda40 497 }
modtronix 4:43abdd8eda40 498 offsetEOF = cmdEndsBuf.peek();
modtronix 4:43abdd8eda40 499 currTail = _tail;
modtronix 4:43abdd8eda40 500 do {
modtronix 4:43abdd8eda40 501 if(_pool[currTail] == c) {
modtronix 4:43abdd8eda40 502 if (offsetFound!=NULL) {
modtronix 4:43abdd8eda40 503 *offsetFound = (uint16_t)currTail;
modtronix 4:43abdd8eda40 504 }
modtronix 4:43abdd8eda40 505 return true;
modtronix 4:43abdd8eda40 506 }
modtronix 4:43abdd8eda40 507 currTail = ((currTail+1)%BufferSize);
modtronix 4:43abdd8eda40 508 } while(currTail != offsetEOF);
modtronix 4:43abdd8eda40 509
modtronix 4:43abdd8eda40 510 // CounterType i;
modtronix 4:43abdd8eda40 511 // CounterType cmdLen;
modtronix 4:43abdd8eda40 512 // cmdLen = (offsetEOF-_tail) % BufferSize;
modtronix 4:43abdd8eda40 513 // for (i=0; i<cmdLen; i++) {
modtronix 4:43abdd8eda40 514 // if(_pool[(i+_tail)%BufferSize] == c) {
modtronix 4:43abdd8eda40 515 // //if(peekAt(i)==c) {
modtronix 4:43abdd8eda40 516 // offsetFound = (uint16_t)i;
modtronix 4:43abdd8eda40 517 // return true;
modtronix 4:43abdd8eda40 518 // }
modtronix 4:43abdd8eda40 519 // }
modtronix 4:43abdd8eda40 520 return false;
modtronix 4:43abdd8eda40 521 }
modtronix 4:43abdd8eda40 522
modtronix 4:43abdd8eda40 523 /** Check if the buffer is empty
modtronix 4:43abdd8eda40 524 *
modtronix 4:43abdd8eda40 525 * @return True if the buffer is empty, false if not
modtronix 4:43abdd8eda40 526 */
modtronix 4:43abdd8eda40 527 bool isEmpty() {
modtronix 4:43abdd8eda40 528 return (_head == _tail) && !_full;
modtronix 4:43abdd8eda40 529 }
modtronix 4:43abdd8eda40 530
modtronix 4:43abdd8eda40 531 /** Check if the buffer is full
modtronix 4:43abdd8eda40 532 *
modtronix 4:43abdd8eda40 533 * @return True if the buffer is full, false if not
modtronix 4:43abdd8eda40 534 */
modtronix 4:43abdd8eda40 535 bool isFull() {
modtronix 4:43abdd8eda40 536 return _full;
modtronix 4:43abdd8eda40 537 }
modtronix 4:43abdd8eda40 538
modtronix 4:43abdd8eda40 539 /** Get number of available bytes in buffer
modtronix 4:43abdd8eda40 540 * @return Number of available bytes in buffer
modtronix 4:43abdd8eda40 541 */
modtronix 4:43abdd8eda40 542 CounterType getAvailable() {
modtronix-com 7:709130701ac7 543 if (_head != _tail) {
modtronix-com 7:709130701ac7 544 CounterType avail;
modtronix-com 7:709130701ac7 545 avail = _head - _tail;
modtronix-com 7:709130701ac7 546 avail %= BufferSize;
modtronix-com 7:709130701ac7 547 return avail;
modtronix-com 7:709130701ac7 548 }
modtronix-com 7:709130701ac7 549
modtronix-com 7:709130701ac7 550 //Head=Tail. Can be full or empty
modtronix-com 7:709130701ac7 551 if (_full==false) {
modtronix 4:43abdd8eda40 552 return 0;
modtronix 4:43abdd8eda40 553 }
modtronix-com 7:709130701ac7 554 else {
modtronix-com 7:709130701ac7 555 return BufferSize;
modtronix-com 7:709130701ac7 556 }
modtronix 4:43abdd8eda40 557 }
modtronix 4:43abdd8eda40 558
modtronix 4:43abdd8eda40 559
modtronix 4:43abdd8eda40 560 /** Get number of free bytes in buffer available for writing data to.
modtronix 4:43abdd8eda40 561 * @return Number of free bytes in buffer available for writing data to.
modtronix 4:43abdd8eda40 562 */
modtronix 4:43abdd8eda40 563 CounterType getFree() {
modtronix 4:43abdd8eda40 564 CounterType free;
modtronix 4:43abdd8eda40 565 //Full
modtronix 4:43abdd8eda40 566 if (_full==true) {
modtronix 4:43abdd8eda40 567 return 0;
modtronix 4:43abdd8eda40 568 }
modtronix 4:43abdd8eda40 569 //Empty
modtronix 4:43abdd8eda40 570 if(_head == _tail) {
modtronix 4:43abdd8eda40 571 return BufferSize;
modtronix 4:43abdd8eda40 572 }
modtronix 4:43abdd8eda40 573 free = _tail - _head;
modtronix 4:43abdd8eda40 574 free %= BufferSize;
modtronix 4:43abdd8eda40 575 return free;
modtronix 4:43abdd8eda40 576 }
modtronix 4:43abdd8eda40 577
modtronix 4:43abdd8eda40 578 /** Replaces any LF or CR characters with an "End of Command" character = ';'
modtronix 4:43abdd8eda40 579 */
modtronix 4:43abdd8eda40 580 void enableReplaceCrLfWithEoc() {
modtronix 4:43abdd8eda40 581 flags.bits.replaceCrLfWithEoc = true;
modtronix 4:43abdd8eda40 582 }
modtronix 4:43abdd8eda40 583
modtronix 4:43abdd8eda40 584 /** Do NOT replaces LF and CR characters with an "End of Command" character = ';'
modtronix 4:43abdd8eda40 585 */
modtronix 4:43abdd8eda40 586 void disableReplaceCrLfWithEoc() {
modtronix 4:43abdd8eda40 587 flags.bits.replaceCrLfWithEoc = false;
modtronix 4:43abdd8eda40 588 }
modtronix 4:43abdd8eda40 589
modtronix 4:43abdd8eda40 590 /** Check if an overwrite error occurred. It resets the error flag if it was set
modtronix 4:43abdd8eda40 591 * @return True if overwrite error occurred since last time this function was called, else false
modtronix 4:43abdd8eda40 592 */
modtronix 4:43abdd8eda40 593 bool checkBufferFullError() {
modtronix 4:43abdd8eda40 594 bool retVal = _errBufFull;
modtronix 4:43abdd8eda40 595 _errBufFull = false;
modtronix 4:43abdd8eda40 596 return retVal;
modtronix 4:43abdd8eda40 597 }
modtronix 4:43abdd8eda40 598
modtronix 4:43abdd8eda40 599 /** Reset the buffer
modtronix 4:43abdd8eda40 600 */
modtronix 4:43abdd8eda40 601 void reset() {
modtronix 4:43abdd8eda40 602 _head = 0;
modtronix 4:43abdd8eda40 603 _tail = 0;
modtronix 4:43abdd8eda40 604 _full = false;
modtronix 4:43abdd8eda40 605 _errBufFull = false;
modtronix 4:43abdd8eda40 606 _dontSaveCurrentCommand = false;
modtronix 4:43abdd8eda40 607 }
modtronix 4:43abdd8eda40 608
modtronix 4:43abdd8eda40 609 /** Remove a command from buffer
modtronix 4:43abdd8eda40 610 */
modtronix 4:43abdd8eda40 611 void removeCommand() {
modtronix 4:43abdd8eda40 612 if (cmdEndsBuf.isEmpty()) {
modtronix 4:43abdd8eda40 613 return;
modtronix 4:43abdd8eda40 614 }
modtronix 4:43abdd8eda40 615
modtronix 4:43abdd8eda40 616 //MXH_DEBUG("\r\nRemoving Cmd");
modtronix 4:43abdd8eda40 617
modtronix 4:43abdd8eda40 618 //Set tail = "end of command" character + 1. This is first character of next command
modtronix 4:43abdd8eda40 619 _tail = (cmdEndsBuf.get()+1) % BufferSize;
modtronix 4:43abdd8eda40 620 _full = false;
modtronix 4:43abdd8eda40 621 }
modtronix 4:43abdd8eda40 622
modtronix 4:43abdd8eda40 623 private:
modtronix 4:43abdd8eda40 624 uint8_t _pool[BufferSize];
modtronix 4:43abdd8eda40 625 volatile CounterType _head;
modtronix 4:43abdd8eda40 626 volatile CounterType _tail;
modtronix 4:43abdd8eda40 627 volatile bool _full;
modtronix 4:43abdd8eda40 628 volatile bool _errBufFull;
modtronix 4:43abdd8eda40 629 volatile bool _dontSaveCurrentCommand;
modtronix-com 7:709130701ac7 630 volatile bool _lastCharWasEOF;
modtronix 4:43abdd8eda40 631
modtronix 4:43abdd8eda40 632 union Flags {
modtronix 4:43abdd8eda40 633 struct {
modtronix 4:43abdd8eda40 634 uint8_t replaceCrLfWithEoc : 1; //Replace CR and LF with "End of Command" character = ';'
modtronix 4:43abdd8eda40 635 } bits;
modtronix 4:43abdd8eda40 636 uint8_t Val;
modtronix 4:43abdd8eda40 637 //Union constructor. Used in initialization list of this class.
modtronix 4:43abdd8eda40 638 Flags(uint8_t v) : Val(v) {}
modtronix 4:43abdd8eda40 639 } flags;
modtronix 4:43abdd8eda40 640
modtronix 4:43abdd8eda40 641 public:
modtronix 4:43abdd8eda40 642 //Buffer for storing "end of command" locations
modtronix 4:43abdd8eda40 643 MxCircularBuffer <uint16_t, Commands, CounterType> cmdEndsBuf;
modtronix 4:43abdd8eda40 644 //MxCircularBuffer <uint16_t, Commands, uint16_t> cmdEndsBuf; //Creates larger code
modtronix 4:43abdd8eda40 645 };
modtronix 4:43abdd8eda40 646
modtronix 4:43abdd8eda40 647
modtronix 4:43abdd8eda40 648
modtronix 4:43abdd8eda40 649
modtronix 4:43abdd8eda40 650 #endif /* SRC_MX_CMD_BUFFER_H_ */