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

Committer:
modtronix
Date:
Sun Aug 30 09:29:08 2015 +1000
Revision:
4:43abdd8eda40
Child:
7:709130701ac7
Added buffer and debug files

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 4:43abdd8eda40 73 MxCmdBuffer() : _head(0), _tail(0), _headStartOfNxtCmd(0), _full(false),
modtronix 4:43abdd8eda40 74 _errBufFull(0), _dontSaveCurrentCommand(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 4:43abdd8eda40 109 //Restore head to byte following loast "End of Command" pointer
modtronix 4:43abdd8eda40 110 _head = ((cmdEndsBuf.peekLastAdded()+1)%BufferSize);
modtronix 4:43abdd8eda40 111 }
modtronix 4:43abdd8eda40 112 //If no commands in buffer, set head=tail
modtronix 4:43abdd8eda40 113 else {
modtronix 4:43abdd8eda40 114 _head = _tail;
modtronix 4:43abdd8eda40 115 _full = false;
modtronix 4:43abdd8eda40 116 }
modtronix 4:43abdd8eda40 117 }
modtronix 4:43abdd8eda40 118
modtronix 4:43abdd8eda40 119 //Check if "End of Command" byte. A command string is terminated with a ';', CR(0x0a='\r') or LF(0x0d='\n') character
modtronix 4:43abdd8eda40 120 if ((c == ';') || (c == 0x0d) || (c == 0x0a)) {
modtronix 4:43abdd8eda40 121 if (flags.bits.replaceCrLfWithEoc) {
modtronix 4:43abdd8eda40 122 c = ';'; //Change to "end of command" character
modtronix 4:43abdd8eda40 123 }
modtronix 4:43abdd8eda40 124
modtronix 4:43abdd8eda40 125 if (_dontSaveCurrentCommand == true) {
modtronix 4:43abdd8eda40 126 _dontSaveCurrentCommand = false;
modtronix 4:43abdd8eda40 127 _headStartOfNxtCmd = _head;
modtronix 4:43abdd8eda40 128 return false; //Nothing added
modtronix 4:43abdd8eda40 129 }
modtronix 4:43abdd8eda40 130 else {
modtronix 4:43abdd8eda40 131 //If multiple "end of command" characters received, ignore them.
modtronix 4:43abdd8eda40 132 if (_headStartOfNxtCmd == _head) {
modtronix 4:43abdd8eda40 133 //Nothing to do, exit
modtronix 4:43abdd8eda40 134 MXH_DEBUG_INFO("\r\nMultiple EOC");
modtronix 4:43abdd8eda40 135 return false; //Nothing added
modtronix 4:43abdd8eda40 136 }
modtronix 4:43abdd8eda40 137
modtronix 4:43abdd8eda40 138 cmdEndsBuf.put(_head); //Add pointer to "end of command" character
modtronix 4:43abdd8eda40 139 //End of command character will be added to buffer below at current _head pointer
modtronix 4:43abdd8eda40 140 MXH_DEBUG_INFO("\r\nAdded Cmd, EOC=%d", _head);
modtronix 4:43abdd8eda40 141
modtronix 4:43abdd8eda40 142 //Save start of next command = byte following current _head
modtronix 4:43abdd8eda40 143 _headStartOfNxtCmd = ((_head+1)%BufferSize);
modtronix 4:43abdd8eda40 144 MXH_DEBUG_INFO(" Nxt=%d", _headStartOfNxtCmd);
modtronix 4:43abdd8eda40 145 }
modtronix 4:43abdd8eda40 146 }
modtronix 4:43abdd8eda40 147
modtronix 4:43abdd8eda40 148 if (_dontSaveCurrentCommand) {
modtronix 4:43abdd8eda40 149 return false;
modtronix 4:43abdd8eda40 150 }
modtronix 4:43abdd8eda40 151
modtronix 4:43abdd8eda40 152 //Add byte to buffer
modtronix 4:43abdd8eda40 153 _pool[_head++] = c;
modtronix 4:43abdd8eda40 154 _head %= BufferSize;
modtronix 4:43abdd8eda40 155 if (_head == _tail) {
modtronix 4:43abdd8eda40 156 _full = true;
modtronix 4:43abdd8eda40 157 }
modtronix 4:43abdd8eda40 158
modtronix 4:43abdd8eda40 159 return true;
modtronix 4:43abdd8eda40 160 }
modtronix 4:43abdd8eda40 161
modtronix 4:43abdd8eda40 162 /** Adds given NULL terminated string to the buffer. This function checks for the "End of Command" character,
modtronix 4:43abdd8eda40 163 * and if found, increments the "command count" register indicating how many commands this buffer has.
modtronix 4:43abdd8eda40 164 *
modtronix 4:43abdd8eda40 165 * If the buffer becomes full before the "End of Command" character is reached, all bytes added for current
modtronix 4:43abdd8eda40 166 * command are removed. And, all following bytes added until the next "End of Command" character will be ignored.
modtronix 4:43abdd8eda40 167 *
modtronix 4:43abdd8eda40 168 * The checkBufferFullError() function can be used to check if this function caused an error, and command was
modtronix 4:43abdd8eda40 169 * not added to buffer.
modtronix 4:43abdd8eda40 170 *
modtronix 4:43abdd8eda40 171 * @param buf Source buffer containing array to add to buffer
modtronix 4:43abdd8eda40 172 * @param bufSize Size of array to add to buffer
modtronix 4:43abdd8eda40 173 *
modtronix 4:43abdd8eda40 174 * @return Returns true if something added to buffer, else false. Important to note that all characters added to
modtronix 4:43abdd8eda40 175 * current command CAN BE REMOVED if buffer gets full before "End of Command" added to buffer!
modtronix 4:43abdd8eda40 176 */
modtronix 4:43abdd8eda40 177 bool put(const char* str) {
modtronix 4:43abdd8eda40 178 bool retVal = 0;
modtronix 4:43abdd8eda40 179
modtronix 4:43abdd8eda40 180 //DO NOT DO this check here! This check MUST be done by put() function, because if buffer becomes full before
modtronix 4:43abdd8eda40 181 //"End of Command" character received, the put() function will remove all current command characters added!
modtronix 4:43abdd8eda40 182 //if (isFull() == true) {
modtronix 4:43abdd8eda40 183 // return false;
modtronix 4:43abdd8eda40 184 //}
modtronix 4:43abdd8eda40 185
modtronix 4:43abdd8eda40 186 //Add whole string to buffer. DO NOT check isFull() in next line, MUST be checked in put() below!!!!
modtronix 4:43abdd8eda40 187 while((*str != 0) /*&& (isFull()==false)*/) {
modtronix 4:43abdd8eda40 188 retVal = retVal | put((uint8_t)(*str++));
modtronix 4:43abdd8eda40 189 }
modtronix 4:43abdd8eda40 190 return retVal;
modtronix 4:43abdd8eda40 191 }
modtronix 4:43abdd8eda40 192
modtronix 4:43abdd8eda40 193
modtronix 4:43abdd8eda40 194 /** Adds given array to the buffer. This function checks for the "End of Command" character,
modtronix 4:43abdd8eda40 195 * and if found, increments the "command count" register indicating how many commands this buffer has.
modtronix 4:43abdd8eda40 196 *
modtronix 4:43abdd8eda40 197 * If the buffer becomes full before the "End of Command" character is reached, all bytes added for current
modtronix 4:43abdd8eda40 198 * command are removed. And, all following bytes added until the next "End of Command" character will be ignored.
modtronix 4:43abdd8eda40 199 *
modtronix 4:43abdd8eda40 200 * The checkBufferFullError() function can be used to check if this function caused an error, and command was
modtronix 4:43abdd8eda40 201 * not added to buffer.
modtronix 4:43abdd8eda40 202
modtronix 4:43abdd8eda40 203 * @param buf Source buffer containing array to add to buffer
modtronix 4:43abdd8eda40 204 * @param bufSize Size of array to add to buffer
modtronix 4:43abdd8eda40 205 *
modtronix 4:43abdd8eda40 206 * @return Returns true if something added to buffer, else false. Important to note that all characters added to
modtronix 4:43abdd8eda40 207 * current command CAN BE REMOVED if buffer gets full before "End of Command" added to buffer!
modtronix 4:43abdd8eda40 208 */
modtronix 4:43abdd8eda40 209 bool putArray(uint8_t* buf, uint16_t bufSize) {
modtronix 4:43abdd8eda40 210 bool retVal = 0;
modtronix 4:43abdd8eda40 211 int i;
modtronix 4:43abdd8eda40 212
modtronix 4:43abdd8eda40 213 //DO NOT DO this check here! This check MUST be done by put() function, because if buffer becomes full before
modtronix 4:43abdd8eda40 214 //"End of Command" character received, the put() function will remove all current command characters added!
modtronix 4:43abdd8eda40 215 //if (getFree() < bufSize) {
modtronix 4:43abdd8eda40 216 // return 0;
modtronix 4:43abdd8eda40 217 //}
modtronix 4:43abdd8eda40 218
modtronix 4:43abdd8eda40 219 for(i=0; i<bufSize; i++) {
modtronix 4:43abdd8eda40 220 retVal = retVal | put(buf[i]);
modtronix 4:43abdd8eda40 221 }
modtronix 4:43abdd8eda40 222 return retVal;
modtronix 4:43abdd8eda40 223 }
modtronix 4:43abdd8eda40 224
modtronix 4:43abdd8eda40 225 /** Gets and object from the buffer. Ensure buffer is NOT empty before calling this function!
modtronix 4:43abdd8eda40 226 *
modtronix 4:43abdd8eda40 227 * @return Read data
modtronix 4:43abdd8eda40 228 */
modtronix 4:43abdd8eda40 229 uint8_t get() {
modtronix 4:43abdd8eda40 230 if (!isEmpty()) {
modtronix 4:43abdd8eda40 231 uint8_t retData;
modtronix 4:43abdd8eda40 232 retData = _pool[_tail++];
modtronix 4:43abdd8eda40 233 _tail %= BufferSize;
modtronix 4:43abdd8eda40 234 _full = false;
modtronix 4:43abdd8eda40 235 return retData;
modtronix 4:43abdd8eda40 236 }
modtronix 4:43abdd8eda40 237 return 0;
modtronix 4:43abdd8eda40 238 }
modtronix 4:43abdd8eda40 239
modtronix 4:43abdd8eda40 240 /** Gets and object from the buffer. Returns true if OK, else false
modtronix 4:43abdd8eda40 241 *
modtronix 4:43abdd8eda40 242 * @param data Variable to put read data into
modtronix 4:43abdd8eda40 243 * @return True if the buffer is not empty and data contains a transaction, false otherwise
modtronix 4:43abdd8eda40 244 */
modtronix 4:43abdd8eda40 245 bool getAndCheck(uint8_t& data) {
modtronix 4:43abdd8eda40 246 if (!isEmpty()) {
modtronix 4:43abdd8eda40 247 data = _pool[_tail++];
modtronix 4:43abdd8eda40 248 _tail %= BufferSize;
modtronix 4:43abdd8eda40 249 _full = false;
modtronix 4:43abdd8eda40 250 return true;
modtronix 4:43abdd8eda40 251 }
modtronix 4:43abdd8eda40 252 return false;
modtronix 4:43abdd8eda40 253 }
modtronix 4:43abdd8eda40 254
modtronix 4:43abdd8eda40 255
modtronix 4:43abdd8eda40 256 /** Gets and object from the buffer, but do NOT remove it. Ensure buffer is NOT empty before calling
modtronix 4:43abdd8eda40 257 * this function! If buffer is empty, will return an undefined value.
modtronix 4:43abdd8eda40 258 *
modtronix 4:43abdd8eda40 259 * @return Read data
modtronix 4:43abdd8eda40 260 */
modtronix 4:43abdd8eda40 261 uint8_t peek() {
modtronix 4:43abdd8eda40 262 return _pool[_tail];
modtronix 4:43abdd8eda40 263 }
modtronix 4:43abdd8eda40 264
modtronix 4:43abdd8eda40 265 /** Gets an object from the buffer at given offset, but do NOT remove it. Given offset is a value from
modtronix 4:43abdd8eda40 266 * 0 to n. Ensure buffer has as many objects as the offset requested! For example, if buffer has 5 objects
modtronix 4:43abdd8eda40 267 * available, given offset can be a value from 0 to 4.
modtronix 4:43abdd8eda40 268 *
modtronix 4:43abdd8eda40 269 * @param offset Offset of requested object. A value from 0-n, where (n+1) = available objects = getAvailable()
modtronix 4:43abdd8eda40 270 * @return Object at given offset
modtronix 4:43abdd8eda40 271 */
modtronix 4:43abdd8eda40 272 uint8_t peekAt(CounterType offset) {
modtronix 4:43abdd8eda40 273 return _pool[(offset+_tail)%BufferSize];
modtronix 4:43abdd8eda40 274 }
modtronix 4:43abdd8eda40 275
modtronix 4:43abdd8eda40 276 /** Gets the last object added to the buffer, but do NOT remove it.
modtronix 4:43abdd8eda40 277 *
modtronix 4:43abdd8eda40 278 * @return Object at given offset
modtronix 4:43abdd8eda40 279 */
modtronix 4:43abdd8eda40 280 uint8_t peekLastAdded() {
modtronix 4:43abdd8eda40 281 return _pool[(_head-1)%BufferSize];
modtronix 4:43abdd8eda40 282 }
modtronix 4:43abdd8eda40 283
modtronix 4:43abdd8eda40 284 /** Gets and array of given size, and write it to given buffer.
modtronix 4:43abdd8eda40 285 * Nothing is removed from buffer
modtronix 4:43abdd8eda40 286 *
modtronix 4:43abdd8eda40 287 * @param buf Destination buffer to array to
modtronix 4:43abdd8eda40 288 * @param bufSize Maximum size to write to destination buffer
modtronix 4:43abdd8eda40 289 * @param lenReq Requested length
modtronix 4:43abdd8eda40 290 *
modtronix 4:43abdd8eda40 291 *
modtronix 4:43abdd8eda40 292 * @return Number of bytes written to given buffer
modtronix 4:43abdd8eda40 293 */
modtronix 4:43abdd8eda40 294 uint16_t peekArray(uint8_t* buf, uint16_t bufSize, CounterType lenReq) {
modtronix 4:43abdd8eda40 295 uint16_t lenWritten=0;
modtronix 4:43abdd8eda40 296 CounterType currTail;
modtronix 4:43abdd8eda40 297 currTail = _tail;
modtronix 4:43abdd8eda40 298
modtronix 4:43abdd8eda40 299 //Some checks
modtronix 4:43abdd8eda40 300 if (isEmpty() || (bufSize==0) || (lenReq==0)) {
modtronix 4:43abdd8eda40 301 return 0;
modtronix 4:43abdd8eda40 302 }
modtronix 4:43abdd8eda40 303
modtronix 4:43abdd8eda40 304 do {
modtronix 4:43abdd8eda40 305 buf[lenWritten++] = _pool[currTail];
modtronix 4:43abdd8eda40 306 currTail = ((currTail+1)%BufferSize);
modtronix 4:43abdd8eda40 307 } while((lenWritten<bufSize) && (lenWritten<lenReq));
modtronix 4:43abdd8eda40 308
modtronix 4:43abdd8eda40 309
modtronix 4:43abdd8eda40 310 return lenWritten;
modtronix 4:43abdd8eda40 311 }
modtronix 4:43abdd8eda40 312
modtronix 4:43abdd8eda40 313 /** Check if the buffer has a complete command
modtronix 4:43abdd8eda40 314 *
modtronix 4:43abdd8eda40 315 * @return True if the buffer has a command, false if not
modtronix 4:43abdd8eda40 316 */
modtronix 4:43abdd8eda40 317 bool hasCommand() {
modtronix 4:43abdd8eda40 318 return !cmdEndsBuf.isEmpty();
modtronix 4:43abdd8eda40 319 }
modtronix 4:43abdd8eda40 320
modtronix 4:43abdd8eda40 321 /** Get length of next command in buffer, excluding "end of command" character! For example,
modtronix 4:43abdd8eda40 322 * the command "r=100;" will return 5.
modtronix 4:43abdd8eda40 323 * @return Length of next command in buffer
modtronix 4:43abdd8eda40 324 */
modtronix 4:43abdd8eda40 325 uint8_t getCommandLength() {
modtronix 4:43abdd8eda40 326 CounterType offsetEOC;
modtronix 4:43abdd8eda40 327
modtronix 4:43abdd8eda40 328 if (cmdEndsBuf.isEmpty()) {
modtronix 4:43abdd8eda40 329 return 0;
modtronix 4:43abdd8eda40 330 }
modtronix 4:43abdd8eda40 331
modtronix 4:43abdd8eda40 332 //Get offset of "end of command" character of current command in buffer
modtronix 4:43abdd8eda40 333 offsetEOC = cmdEndsBuf.peek();
modtronix 4:43abdd8eda40 334
modtronix 4:43abdd8eda40 335 return ((offsetEOC-_tail) % BufferSize);
modtronix 4:43abdd8eda40 336 }
modtronix 4:43abdd8eda40 337
modtronix 4:43abdd8eda40 338 /** Get number of commands waiting in buffer
modtronix 4:43abdd8eda40 339 * @return Number of commands waiting in buffer
modtronix 4:43abdd8eda40 340 */
modtronix 4:43abdd8eda40 341 uint8_t getCommandsAvailable() {
modtronix 4:43abdd8eda40 342 return cmdEndsBuf.getAvailable();
modtronix 4:43abdd8eda40 343 }
modtronix 4:43abdd8eda40 344
modtronix 4:43abdd8eda40 345 /** If current command has "name=value" format, the 'name' part is returned.
modtronix 4:43abdd8eda40 346 * Else, the whole command is returned(excluding a possible trailing '=' character).
modtronix 4:43abdd8eda40 347 * Returned string is NULL terminated by default.
modtronix 4:43abdd8eda40 348 * Nothing is removed from the buffer!
modtronix 4:43abdd8eda40 349 *
modtronix 4:43abdd8eda40 350 * If true is returned in the "isNameValue" parameter, this is a "name=value" command, with a name part of at
modtronix 4:43abdd8eda40 351 * lease 1 character long. The offset of the 'value' part will be the returned
modtronix 4:43abdd8eda40 352 *
modtronix 4:43abdd8eda40 353 * If false is returned in the "isNameValue" parameter, there is no 'value' part of at least 1 character. There could however
modtronix 4:43abdd8eda40 354 * still be a '=' character with no 'value' following it. Any possible trailing '=' character is removed string returned in 'buf'.
modtronix 4:43abdd8eda40 355 *
modtronix 4:43abdd8eda40 356 * @param buf Destination buffer to write string to
modtronix 4:43abdd8eda40 357 *
modtronix 4:43abdd8eda40 358 * @param bufSize Maximum size to write to destination buffer
modtronix 4:43abdd8eda40 359 *
modtronix 4:43abdd8eda40 360 * @param isNameValue Returns true if a '=' character was found -AND- at least 1 char following it. This indicates
modtronix 4:43abdd8eda40 361 * this is a "name=value" command, and has a value part(of at least 1 character) following the '='.
modtronix 4:43abdd8eda40 362 * First character of 'value' is value returned by this function + 1!
modtronix 4:43abdd8eda40 363 *
modtronix 4:43abdd8eda40 364 * @return Size in bytes of string returned in 'buf' parameter(is 'name' if isNameValue=true).
modtronix 4:43abdd8eda40 365 * If true is returned in 'isNameValue', 'buf' contains the 'name' part of a 'name=value' command. This returned offset points to '='.
modtronix 4:43abdd8eda40 366 * If false is returned in 'isNameValue', 'buf' contains the whole command string(excluding possible trailing '=' character).
modtronix 4:43abdd8eda40 367 */
modtronix 4:43abdd8eda40 368 uint16_t getCommandName(uint8_t* buf, uint16_t bufSize, bool& isNameValue, bool nullTerminate = true) {
modtronix 4:43abdd8eda40 369 CounterType offsetEOC;
modtronix 4:43abdd8eda40 370 CounterType currTail;
modtronix 4:43abdd8eda40 371 uint16_t nameLen = 0;
modtronix 4:43abdd8eda40 372 isNameValue=false;
modtronix 4:43abdd8eda40 373
modtronix 4:43abdd8eda40 374 //Some checks
modtronix 4:43abdd8eda40 375 if (cmdEndsBuf.isEmpty() || (bufSize==0) || (_pool[_tail]=='=')) {
modtronix 4:43abdd8eda40 376 return 0;
modtronix 4:43abdd8eda40 377 }
modtronix 4:43abdd8eda40 378 offsetEOC = cmdEndsBuf.peek();
modtronix 4:43abdd8eda40 379 currTail = _tail;
modtronix 4:43abdd8eda40 380
modtronix 4:43abdd8eda40 381 //Copy current command string to given buffer, until '=' reached
modtronix 4:43abdd8eda40 382 do {
modtronix 4:43abdd8eda40 383 buf[nameLen++] = _pool[currTail];
modtronix 4:43abdd8eda40 384 currTail = ((currTail+1)%BufferSize);
modtronix 4:43abdd8eda40 385 //If next character is '='
modtronix 4:43abdd8eda40 386 if(_pool[currTail] == '=') {
modtronix 4:43abdd8eda40 387 //Check at least 1 character following '='
modtronix 4:43abdd8eda40 388 //Get pointer of character following '=', and ensure it is not "end of command"(offsetEOC). Meaning there is
modtronix 4:43abdd8eda40 389 //still at least 1 more character following '='
modtronix 4:43abdd8eda40 390 if(((currTail+1)%BufferSize) != offsetEOC) {
modtronix 4:43abdd8eda40 391 isNameValue = true;
modtronix 4:43abdd8eda40 392 }
modtronix 4:43abdd8eda40 393 break;
modtronix 4:43abdd8eda40 394 }
modtronix 4:43abdd8eda40 395 } while((currTail!=offsetEOC) && (nameLen<bufSize));
modtronix 4:43abdd8eda40 396
modtronix 4:43abdd8eda40 397
modtronix 4:43abdd8eda40 398 if (nullTerminate) {
modtronix 4:43abdd8eda40 399 if(nameLen<bufSize) {
modtronix 4:43abdd8eda40 400 buf[nameLen] = 0;
modtronix 4:43abdd8eda40 401 }
modtronix 4:43abdd8eda40 402 buf[bufSize-1] = 0; //Null terminate last position of buffer in case it filled up
modtronix 4:43abdd8eda40 403 }
modtronix 4:43abdd8eda40 404
modtronix 4:43abdd8eda40 405 return nameLen;
modtronix 4:43abdd8eda40 406 }
modtronix 4:43abdd8eda40 407
modtronix 4:43abdd8eda40 408 /** For commands with "name=value" format, returns the 'value' part.
modtronix 4:43abdd8eda40 409 * Returned string is NULL terminated by default.
modtronix 4:43abdd8eda40 410 * Nothing is removed from the buffer!
modtronix 4:43abdd8eda40 411 *
modtronix 4:43abdd8eda40 412 * To optimize this function, call getCommandName() before calling this function. The getCommandName() return value(+1)
modtronix 4:43abdd8eda40 413 * can be used as 'offset' parameter to this function. This will save this function from searching for '=' character.
modtronix 4:43abdd8eda40 414 *
modtronix 4:43abdd8eda40 415 *
modtronix 4:43abdd8eda40 416 * @param buf Destination buffer to write string to
modtronix 4:43abdd8eda40 417 * @param bufSize Maximum size to write to destination buffer
modtronix 4:43abdd8eda40 418 * @param offset Gives offset of value string if known. This can be value(+1) returned by
modtronix 4:43abdd8eda40 419 * getCommandName() function. Use -1 if unknown.
modtronix 4:43abdd8eda40 420 *
modtronix 4:43abdd8eda40 421 * @return Size in bytes of returned string
modtronix 4:43abdd8eda40 422 */
modtronix 4:43abdd8eda40 423 uint16_t getCommandValue(uint8_t* buf, uint16_t bufSize, uint16_t offset = -1, bool nullTerminate = true) {
modtronix 4:43abdd8eda40 424 CounterType offsetEOC;
modtronix 4:43abdd8eda40 425 CounterType currTail;
modtronix 4:43abdd8eda40 426 uint16_t valueLen = 0;
modtronix 4:43abdd8eda40 427 bool foundEq=false; //'=' character found
modtronix 4:43abdd8eda40 428
modtronix 4:43abdd8eda40 429 //Some checks
modtronix 4:43abdd8eda40 430 if (cmdEndsBuf.isEmpty() || (bufSize==0)) {
modtronix 4:43abdd8eda40 431 return 0;
modtronix 4:43abdd8eda40 432 }
modtronix 4:43abdd8eda40 433 offsetEOC = cmdEndsBuf.peek(); //offset of "end of command" character
modtronix 4:43abdd8eda40 434
modtronix 4:43abdd8eda40 435 currTail = _tail;
modtronix 4:43abdd8eda40 436
modtronix 4:43abdd8eda40 437 //If offset was given, it will point to first character of value string
modtronix 4:43abdd8eda40 438 if (offset != -1) {
modtronix 4:43abdd8eda40 439 //Check offset point somewhere inside current command! Where ((offsetEOC-_tail) % BufferSize) = command length
modtronix 4:43abdd8eda40 440 if (offset < ((offsetEOC-_tail)%BufferSize)) {
modtronix 4:43abdd8eda40 441 currTail = ((currTail + offset)%BufferSize); //Add offset to tail
modtronix 4:43abdd8eda40 442
modtronix 4:43abdd8eda40 443 //If given offset was for first character of 'value', it will NOT point to '='. It will be next character.
modtronix 4:43abdd8eda40 444 if(_pool[currTail] != '=') {
modtronix 4:43abdd8eda40 445 //Points to character after '=', indicate '=' has already been found.
modtronix 4:43abdd8eda40 446 foundEq=true;
modtronix 4:43abdd8eda40 447 }
modtronix 4:43abdd8eda40 448 //ELSE, assume offset for for '=' character. It will be found in step below
modtronix 4:43abdd8eda40 449 }
modtronix 4:43abdd8eda40 450 else {
modtronix 4:43abdd8eda40 451 //currTail = _tail; //Ignore given offset, and search whole command for '='
modtronix 4:43abdd8eda40 452 MXH_DEBUG("\r\ngetCommandValue() Offset error!");
modtronix 4:43abdd8eda40 453 }
modtronix 4:43abdd8eda40 454 }
modtronix 4:43abdd8eda40 455
modtronix 4:43abdd8eda40 456 do {
modtronix 4:43abdd8eda40 457 if (foundEq) {
modtronix 4:43abdd8eda40 458 buf[valueLen++] = _pool[currTail];
modtronix 4:43abdd8eda40 459 }
modtronix 4:43abdd8eda40 460 else {
modtronix 4:43abdd8eda40 461 if(_pool[currTail] == '=') {
modtronix 4:43abdd8eda40 462 foundEq=true;
modtronix 4:43abdd8eda40 463 }
modtronix 4:43abdd8eda40 464 }
modtronix 4:43abdd8eda40 465 currTail = ((currTail+1)%BufferSize);
modtronix 4:43abdd8eda40 466 } while((currTail != offsetEOC) && (valueLen<bufSize));
modtronix 4:43abdd8eda40 467
modtronix 4:43abdd8eda40 468 if (nullTerminate) {
modtronix 4:43abdd8eda40 469 if(valueLen<bufSize) {
modtronix 4:43abdd8eda40 470 buf[valueLen] = 0;
modtronix 4:43abdd8eda40 471 }
modtronix 4:43abdd8eda40 472 buf[bufSize-1] = 0; //Null terminate last position of buffer in case it filled up
modtronix 4:43abdd8eda40 473 }
modtronix 4:43abdd8eda40 474
modtronix 4:43abdd8eda40 475 return valueLen;
modtronix 4:43abdd8eda40 476 }
modtronix 4:43abdd8eda40 477
modtronix 4:43abdd8eda40 478 /** Search current command for given character
modtronix 4:43abdd8eda40 479 *
modtronix 4:43abdd8eda40 480 * @param offset Returns offset of found character. If NULL, this parameter is not used.
modtronix 4:43abdd8eda40 481 *
modtronix 4:43abdd8eda40 482 * @return Returns true if found, else false
modtronix 4:43abdd8eda40 483 */
modtronix 4:43abdd8eda40 484 bool search(uint8_t c, uint16_t* offsetFound) {
modtronix 4:43abdd8eda40 485 CounterType offsetEOF;
modtronix 4:43abdd8eda40 486 CounterType currTail;
modtronix 4:43abdd8eda40 487
modtronix 4:43abdd8eda40 488 //Get command length
modtronix 4:43abdd8eda40 489 if (cmdEndsBuf.isEmpty()) {
modtronix 4:43abdd8eda40 490 return false;
modtronix 4:43abdd8eda40 491 }
modtronix 4:43abdd8eda40 492 offsetEOF = cmdEndsBuf.peek();
modtronix 4:43abdd8eda40 493 currTail = _tail;
modtronix 4:43abdd8eda40 494 do {
modtronix 4:43abdd8eda40 495 if(_pool[currTail] == c) {
modtronix 4:43abdd8eda40 496 if (offsetFound!=NULL) {
modtronix 4:43abdd8eda40 497 *offsetFound = (uint16_t)currTail;
modtronix 4:43abdd8eda40 498 }
modtronix 4:43abdd8eda40 499 return true;
modtronix 4:43abdd8eda40 500 }
modtronix 4:43abdd8eda40 501 currTail = ((currTail+1)%BufferSize);
modtronix 4:43abdd8eda40 502 } while(currTail != offsetEOF);
modtronix 4:43abdd8eda40 503
modtronix 4:43abdd8eda40 504 // CounterType i;
modtronix 4:43abdd8eda40 505 // CounterType cmdLen;
modtronix 4:43abdd8eda40 506 // cmdLen = (offsetEOF-_tail) % BufferSize;
modtronix 4:43abdd8eda40 507 // for (i=0; i<cmdLen; i++) {
modtronix 4:43abdd8eda40 508 // if(_pool[(i+_tail)%BufferSize] == c) {
modtronix 4:43abdd8eda40 509 // //if(peekAt(i)==c) {
modtronix 4:43abdd8eda40 510 // offsetFound = (uint16_t)i;
modtronix 4:43abdd8eda40 511 // return true;
modtronix 4:43abdd8eda40 512 // }
modtronix 4:43abdd8eda40 513 // }
modtronix 4:43abdd8eda40 514 return false;
modtronix 4:43abdd8eda40 515 }
modtronix 4:43abdd8eda40 516
modtronix 4:43abdd8eda40 517 /** Check if the buffer is empty
modtronix 4:43abdd8eda40 518 *
modtronix 4:43abdd8eda40 519 * @return True if the buffer is empty, false if not
modtronix 4:43abdd8eda40 520 */
modtronix 4:43abdd8eda40 521 bool isEmpty() {
modtronix 4:43abdd8eda40 522 return (_head == _tail) && !_full;
modtronix 4:43abdd8eda40 523 }
modtronix 4:43abdd8eda40 524
modtronix 4:43abdd8eda40 525 /** Check if the buffer is full
modtronix 4:43abdd8eda40 526 *
modtronix 4:43abdd8eda40 527 * @return True if the buffer is full, false if not
modtronix 4:43abdd8eda40 528 */
modtronix 4:43abdd8eda40 529 bool isFull() {
modtronix 4:43abdd8eda40 530 return _full;
modtronix 4:43abdd8eda40 531 }
modtronix 4:43abdd8eda40 532
modtronix 4:43abdd8eda40 533 /** Get number of available bytes in buffer
modtronix 4:43abdd8eda40 534 * @return Number of available bytes in buffer
modtronix 4:43abdd8eda40 535 */
modtronix 4:43abdd8eda40 536 CounterType getAvailable() {
modtronix 4:43abdd8eda40 537 CounterType avail;
modtronix 4:43abdd8eda40 538 if (isEmpty()) {
modtronix 4:43abdd8eda40 539 return 0;
modtronix 4:43abdd8eda40 540 }
modtronix 4:43abdd8eda40 541 avail = _head - _tail;
modtronix 4:43abdd8eda40 542 avail %= BufferSize;
modtronix 4:43abdd8eda40 543 return avail;
modtronix 4:43abdd8eda40 544 }
modtronix 4:43abdd8eda40 545
modtronix 4:43abdd8eda40 546
modtronix 4:43abdd8eda40 547 /** Get number of free bytes in buffer available for writing data to.
modtronix 4:43abdd8eda40 548 * @return Number of free bytes in buffer available for writing data to.
modtronix 4:43abdd8eda40 549 */
modtronix 4:43abdd8eda40 550 CounterType getFree() {
modtronix 4:43abdd8eda40 551 CounterType free;
modtronix 4:43abdd8eda40 552 //Full
modtronix 4:43abdd8eda40 553 if (_full==true) {
modtronix 4:43abdd8eda40 554 return 0;
modtronix 4:43abdd8eda40 555 }
modtronix 4:43abdd8eda40 556 //Empty
modtronix 4:43abdd8eda40 557 if(_head == _tail) {
modtronix 4:43abdd8eda40 558 return BufferSize;
modtronix 4:43abdd8eda40 559 }
modtronix 4:43abdd8eda40 560 free = _tail - _head;
modtronix 4:43abdd8eda40 561 free %= BufferSize;
modtronix 4:43abdd8eda40 562 return free;
modtronix 4:43abdd8eda40 563 }
modtronix 4:43abdd8eda40 564
modtronix 4:43abdd8eda40 565 /** Replaces any LF or CR characters with an "End of Command" character = ';'
modtronix 4:43abdd8eda40 566 */
modtronix 4:43abdd8eda40 567 void enableReplaceCrLfWithEoc() {
modtronix 4:43abdd8eda40 568 flags.bits.replaceCrLfWithEoc = true;
modtronix 4:43abdd8eda40 569 }
modtronix 4:43abdd8eda40 570
modtronix 4:43abdd8eda40 571 /** Do NOT replaces LF and CR characters with an "End of Command" character = ';'
modtronix 4:43abdd8eda40 572 */
modtronix 4:43abdd8eda40 573 void disableReplaceCrLfWithEoc() {
modtronix 4:43abdd8eda40 574 flags.bits.replaceCrLfWithEoc = false;
modtronix 4:43abdd8eda40 575 }
modtronix 4:43abdd8eda40 576
modtronix 4:43abdd8eda40 577 /** Check if an overwrite error occurred. It resets the error flag if it was set
modtronix 4:43abdd8eda40 578 * @return True if overwrite error occurred since last time this function was called, else false
modtronix 4:43abdd8eda40 579 */
modtronix 4:43abdd8eda40 580 bool checkBufferFullError() {
modtronix 4:43abdd8eda40 581 bool retVal = _errBufFull;
modtronix 4:43abdd8eda40 582 _errBufFull = false;
modtronix 4:43abdd8eda40 583 return retVal;
modtronix 4:43abdd8eda40 584 }
modtronix 4:43abdd8eda40 585
modtronix 4:43abdd8eda40 586 /** Reset the buffer
modtronix 4:43abdd8eda40 587 */
modtronix 4:43abdd8eda40 588 void reset() {
modtronix 4:43abdd8eda40 589 _head = 0;
modtronix 4:43abdd8eda40 590 _headStartOfNxtCmd = 0;
modtronix 4:43abdd8eda40 591 _tail = 0;
modtronix 4:43abdd8eda40 592 _full = false;
modtronix 4:43abdd8eda40 593 _errBufFull = false;
modtronix 4:43abdd8eda40 594 _dontSaveCurrentCommand = false;
modtronix 4:43abdd8eda40 595 }
modtronix 4:43abdd8eda40 596
modtronix 4:43abdd8eda40 597 /** Remove a command from buffer
modtronix 4:43abdd8eda40 598 */
modtronix 4:43abdd8eda40 599 void removeCommand() {
modtronix 4:43abdd8eda40 600 if (cmdEndsBuf.isEmpty()) {
modtronix 4:43abdd8eda40 601 return;
modtronix 4:43abdd8eda40 602 }
modtronix 4:43abdd8eda40 603
modtronix 4:43abdd8eda40 604 //MXH_DEBUG("\r\nRemoving Cmd");
modtronix 4:43abdd8eda40 605
modtronix 4:43abdd8eda40 606 //Set tail = "end of command" character + 1. This is first character of next command
modtronix 4:43abdd8eda40 607 _tail = (cmdEndsBuf.get()+1) % BufferSize;
modtronix 4:43abdd8eda40 608 _full = false;
modtronix 4:43abdd8eda40 609 }
modtronix 4:43abdd8eda40 610
modtronix 4:43abdd8eda40 611 private:
modtronix 4:43abdd8eda40 612 uint8_t _pool[BufferSize];
modtronix 4:43abdd8eda40 613 volatile CounterType _head;
modtronix 4:43abdd8eda40 614 volatile CounterType _tail;
modtronix 4:43abdd8eda40 615 //_head position of first character of next command = position of first byte after last "end of command" character was added
modtronix 4:43abdd8eda40 616 volatile CounterType _headStartOfNxtCmd;
modtronix 4:43abdd8eda40 617 volatile bool _full;
modtronix 4:43abdd8eda40 618 volatile bool _errBufFull;
modtronix 4:43abdd8eda40 619 volatile bool _dontSaveCurrentCommand;
modtronix 4:43abdd8eda40 620
modtronix 4:43abdd8eda40 621 union Flags {
modtronix 4:43abdd8eda40 622 struct {
modtronix 4:43abdd8eda40 623 uint8_t replaceCrLfWithEoc : 1; //Replace CR and LF with "End of Command" character = ';'
modtronix 4:43abdd8eda40 624 } bits;
modtronix 4:43abdd8eda40 625 uint8_t Val;
modtronix 4:43abdd8eda40 626 //Union constructor. Used in initialization list of this class.
modtronix 4:43abdd8eda40 627 Flags(uint8_t v) : Val(v) {}
modtronix 4:43abdd8eda40 628 } flags;
modtronix 4:43abdd8eda40 629
modtronix 4:43abdd8eda40 630 public:
modtronix 4:43abdd8eda40 631 //Buffer for storing "end of command" locations
modtronix 4:43abdd8eda40 632 MxCircularBuffer <uint16_t, Commands, CounterType> cmdEndsBuf;
modtronix 4:43abdd8eda40 633 //MxCircularBuffer <uint16_t, Commands, uint16_t> cmdEndsBuf; //Creates larger code
modtronix 4:43abdd8eda40 634 };
modtronix 4:43abdd8eda40 635
modtronix 4:43abdd8eda40 636
modtronix 4:43abdd8eda40 637
modtronix 4:43abdd8eda40 638
modtronix 4:43abdd8eda40 639 #endif /* SRC_MX_CMD_BUFFER_H_ */