|
MHVLib
20111227
An efficiency oriented runtime library for AVR microcontrollers
|
00001 /* 00002 * Copyright (c) 2011, Make, Hack, Void Inc 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions are met: 00007 * * Redistributions of source code must retain the above copyright 00008 * notice, this list of conditions and the following disclaimer. 00009 * * Redistributions in binary form must reproduce the above copyright 00010 * notice, this list of conditions and the following disclaimer in the 00011 * documentation and/or other materials provided with the distribution. 00012 * * Neither the name of the Make, Hack, Void nor the 00013 * names of its contributors may be used to endorse or promote products 00014 * derived from this software without specific prior written permission. 00015 * 00016 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 00017 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00018 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00019 * DISCLAIMED. IN NO EVENT SHALL MAKE, HACK, VOID BE LIABLE FOR ANY 00020 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00021 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00022 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00023 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00024 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00025 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00026 */ 00027 00028 00029 #include <stdio.h> 00030 #include <avr/pgmspace.h> 00031 #include <stdlib.h> 00032 #include <string.h> 00033 #include <inttypes.h> 00034 00035 #include "MHV_Device_TX.h" 00036 00041 MHV_Device_TX::MHV_Device_TX(MHV_RingBuffer &txPointers) : 00042 _txPointers(txPointers){ 00043 _currentTx.data = NULL; 00044 _currentTx.length = 0; 00045 _currentTx.completeFunction = NULL; 00046 _currentTx.progmem = false; 00047 _currentTx.isString = false; 00048 } 00049 00054 bool MHV_Device_TX::moreTX() { 00055 // Call the completeFunction, if one is provided - allows the user to free memory, etc 00056 if (NULL != _currentTx.completeFunction) { 00057 _currentTx.completeFunction(_currentTx.data); 00058 } 00059 00060 if (_txPointers.consume(&_currentTx, sizeof(_currentTx))) { 00061 _tx = NULL; 00062 return false; 00063 } 00064 00065 _tx = _currentTx.data; 00066 00067 return true; 00068 } 00069 00070 /* Can we accept another buffer? 00071 */ 00072 bool MHV_Device_TX::canWrite() { 00073 return !(_txPointers.full(sizeof(MHV_TX_BUFFER))); 00074 } 00075 00080 int MHV_Device_TX::nextCharacter() { 00081 char c = '\0'; 00082 00083 if (NULL != _tx) { 00084 if (_currentTx.progmem) { 00085 c = pgm_read_byte(_tx); 00086 } else { 00087 c = *_tx; 00088 } 00089 } 00090 00091 if ((_currentTx.isString && ('\0' == c)) || 00092 (!_currentTx.isString && (_tx == _currentTx.data + _currentTx.length))) { 00093 if (!moreTX()) { 00094 _tx = NULL; 00095 _currentTx.data = NULL; 00096 _currentTx.length = 0; 00097 _currentTx.completeFunction = NULL; 00098 _currentTx.progmem = false; 00099 _currentTx.isString = false; 00100 return -1; 00101 } 00102 00103 return nextCharacter(); 00104 } 00105 00106 _tx++; 00107 return (int)c; 00108 } 00109 00116 bool MHV_Device_TX::write_P(PGM_P buffer) { 00117 MHV_TX_BUFFER buf; 00118 00119 if (_txPointers.full(sizeof(buf))) { 00120 return true; 00121 } 00122 00123 buf.data = buffer; 00124 buf.length = 0; 00125 buf.completeFunction = NULL; 00126 buf.progmem = true; 00127 buf.isString = true; 00128 00129 _txPointers.append(&buf, sizeof(buf)); 00130 if (!_tx) { 00131 runTxBuffers(); 00132 } 00133 00134 return false; 00135 } 00136 00143 bool MHV_Device_TX::write(const char *buffer) { 00144 MHV_TX_BUFFER buf; 00145 00146 if (_txPointers.full(sizeof(buf))) { 00147 return true; 00148 } 00149 00150 buf.data = buffer; 00151 buf.length = 0; 00152 buf.completeFunction = NULL; 00153 buf.progmem = false; 00154 buf.isString = true; 00155 00156 _txPointers.append(&buf, sizeof(buf)); 00157 if (!_tx) { 00158 runTxBuffers(); 00159 } 00160 00161 return false; 00162 } 00163 00171 bool MHV_Device_TX::write(const char *buffer, void (*completeFunction)(const char *)) { 00172 MHV_TX_BUFFER buf; 00173 00174 if (_txPointers.full(sizeof(buf))) { 00175 return true; 00176 } 00177 00178 buf.data = buffer; 00179 buf.length = 0; 00180 buf.completeFunction = completeFunction; 00181 buf.progmem = false; 00182 buf.isString = true; 00183 00184 _txPointers.append(&buf, sizeof(buf)); 00185 if (!_tx) { 00186 runTxBuffers(); 00187 } 00188 00189 return false; 00190 } 00191 00199 bool MHV_Device_TX::write_P(PGM_P buffer, uint16_t length) { 00200 MHV_TX_BUFFER buf; 00201 00202 if (_txPointers.full(sizeof(buf))) { 00203 return true; 00204 } 00205 00206 buf.data = buffer; 00207 buf.length = length; 00208 buf.completeFunction = NULL; 00209 buf.progmem = true; 00210 buf.isString = false; 00211 00212 _txPointers.append(&buf, sizeof(buf)); 00213 if (!_tx) { 00214 runTxBuffers(); 00215 } 00216 00217 return false; 00218 } 00219 00227 bool MHV_Device_TX::write(const char *buffer, uint16_t length) { 00228 MHV_TX_BUFFER buf; 00229 00230 if (_txPointers.full(sizeof(buf))) { 00231 return true; 00232 } 00233 00234 buf.data = buffer; 00235 buf.length = length; 00236 buf.completeFunction = NULL; 00237 buf.progmem = false; 00238 buf.isString = false; 00239 00240 _txPointers.append(&buf, sizeof(buf)); 00241 if (!_tx) { 00242 runTxBuffers(); 00243 } 00244 00245 return false; 00246 } 00247 00256 bool MHV_Device_TX::write(const char *buffer, uint16_t length, void (*completeFunction)(const char *)) { 00257 MHV_TX_BUFFER buf; 00258 00259 if (_txPointers.full(sizeof(buf))) { 00260 return true; 00261 } 00262 00263 buf.data = buffer; 00264 buf.length = length; 00265 buf.completeFunction = completeFunction; 00266 buf.progmem = false; 00267 buf.isString = false; 00268 00269 _txPointers.append(&buf, sizeof(buf)); 00270 if (!_tx) { 00271 runTxBuffers(); 00272 } 00273 00274 return false; 00275 } 00276 00281 void mhv_device_tx_free(const char *buf) { 00282 free((void *)buf); 00283 } 00284 00295 bool MHV_Device_TX::debug(const char *file, int line, const char *function, 00296 PGM_P format, ...) { 00297 va_list ap; 00298 va_start(ap, format); 00299 00300 int length = snprintf_P(NULL, 0, PSTR("%s:%d\t%s():\t\t"), 00301 file, line, function); 00302 length += vsnprintf_P(NULL, 0, format, ap); 00303 length += 3; // "\r\n\0" 00304 00305 char *buf = (char *)malloc(length); 00306 char *cur = buf; 00307 if (NULL != cur) { 00308 cur += snprintf_P(cur, length, PSTR("%s:%d\t%s():\t\t"), 00309 file, line, function); 00310 length -= cur - buf; 00311 cur += vsnprintf_P(cur, length, format, ap); 00312 *(cur++) = '\r'; 00313 *(cur++) = '\n'; 00314 *cur = '\0'; 00315 00316 if (write(buf, length, &mhv_device_tx_free)) { 00317 mhv_device_tx_free(buf); 00318 va_end(ap); 00319 return true; 00320 } 00321 00322 va_end(ap); 00323 return false; 00324 } 00325 00326 va_end(ap); 00327 return true; 00328 } 00329 00337 bool MHV_Device_TX::printf(PGM_P format, ...) { 00338 va_list ap; 00339 va_start(ap, format); 00340 00341 int length = vsnprintf_P(NULL, 0, format, ap); 00342 length++; // "\0" 00343 00344 char *buf = (char *)malloc(length); 00345 if (NULL != buf) { 00346 vsnprintf_P(buf, length, format, ap); 00347 00348 if (write(buf, length, &mhv_device_tx_free)) { 00349 mhv_device_tx_free(buf); 00350 va_end(ap); 00351 return true; 00352 } 00353 00354 va_end(ap); 00355 return false; 00356 } 00357 00358 va_end(ap); 00359 return true; 00360 00361 } 00362 00369 bool MHV_Device_TX::write(uint8_t value) { 00370 char *buf = (char *)malloc(4); 00371 if (NULL != buf) { 00372 utoa((uint16_t)value, buf, 10); 00373 if (write(buf)) { 00374 mhv_device_tx_free(buf); 00375 return true; 00376 } 00377 return false; 00378 } 00379 return true; 00380 } 00381 00388 bool MHV_Device_TX::write(uint16_t value) { 00389 char *buf = (char *)malloc(6); 00390 if (NULL != buf) { 00391 utoa(value, buf, 10); 00392 if (write(buf)) { 00393 mhv_device_tx_free(buf); 00394 return true; 00395 } 00396 return false; 00397 } 00398 return true; 00399 } 00400 00407 bool MHV_Device_TX::write(uint32_t value) { 00408 char *buf = (char *)malloc(11); 00409 if (NULL != buf) { 00410 ultoa(value, buf, 10); 00411 if (write(buf)) { 00412 mhv_device_tx_free(buf); 00413 return true; 00414 } 00415 return false; 00416 } 00417 return true; 00418 } 00419 00426 bool MHV_Device_TX::write(int8_t value) { 00427 char *buf = (char *)malloc(5); 00428 if (NULL != buf) { 00429 itoa((uint16_t)value, buf, 10); 00430 if (write(buf)) { 00431 mhv_device_tx_free(buf); 00432 return true; 00433 } 00434 return false; 00435 } 00436 return true; 00437 } 00438 00445 bool MHV_Device_TX::write(int16_t value) { 00446 char *buf = (char *)malloc(7); 00447 if (NULL != buf) { 00448 itoa(value, buf, 10); 00449 if (write(buf)) { 00450 mhv_device_tx_free(buf); 00451 return true; 00452 } 00453 return false; 00454 } 00455 return true; 00456 } 00457 00464 bool MHV_Device_TX::write(int32_t value) { 00465 char *buf = (char *)malloc(13); 00466 if (NULL != buf) { 00467 ltoa(value, buf, 10); 00468 if (write(buf)) { 00469 mhv_device_tx_free(buf); 00470 return true; 00471 } 00472 return false; 00473 } 00474 return true; 00475 }