|
MHVLib
20111109
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 00044 _currentTx.data = NULL; 00045 _currentTx.length = 0; 00046 _currentTx.completeFunction = NULL; 00047 _currentTx.progmem = false; 00048 _currentTx.isString = false; 00049 } 00050 00055 bool MHV_Device_TX::moreTX() { 00056 // Call the completeFunction, if one is provided - allows the user to free memory, etc 00057 if (NULL != _currentTx.completeFunction) { 00058 _currentTx.completeFunction(_currentTx.data); 00059 } 00060 00061 if (_txPointers->consume(&_currentTx, sizeof(_currentTx))) { 00062 _tx = NULL; 00063 return false; 00064 } 00065 00066 _tx = _currentTx.data; 00067 00068 return true; 00069 } 00070 00071 /* Can we accept another buffer? 00072 */ 00073 bool MHV_Device_TX::canWrite() { 00074 return !(_txPointers->full(sizeof(MHV_TX_BUFFER))); 00075 } 00076 00081 int MHV_Device_TX::nextCharacter() { 00082 char c = '\0'; 00083 00084 if (NULL != _tx) { 00085 if (_currentTx.progmem) { 00086 c = pgm_read_byte(_tx); 00087 } else { 00088 c = *_tx; 00089 } 00090 } 00091 00092 if ((_currentTx.isString && ('\0' == c)) || 00093 (!_currentTx.isString && (_tx == _currentTx.data + _currentTx.length))) { 00094 if (!moreTX()) { 00095 _tx = NULL; 00096 _currentTx.data = NULL; 00097 _currentTx.length = 0; 00098 _currentTx.completeFunction = NULL; 00099 _currentTx.progmem = false; 00100 _currentTx.isString = false; 00101 return -1; 00102 } 00103 00104 return nextCharacter(); 00105 } 00106 00107 _tx++; 00108 return (int)c; 00109 } 00110 00117 bool MHV_Device_TX::write_P(PGM_P buffer) { 00118 MHV_TX_BUFFER buf; 00119 00120 if (_txPointers->full(sizeof(buf))) { 00121 return true; 00122 } 00123 00124 buf.data = buffer; 00125 buf.length = 0; 00126 buf.completeFunction = NULL; 00127 buf.progmem = true; 00128 buf.isString = true; 00129 00130 _txPointers->append(&buf, sizeof(buf)); 00131 if (!_tx) { 00132 runTxBuffers(); 00133 } 00134 00135 return false; 00136 } 00137 00144 bool MHV_Device_TX::write(const char *buffer) { 00145 MHV_TX_BUFFER buf; 00146 00147 if (_txPointers->full(sizeof(buf))) { 00148 return true; 00149 } 00150 00151 buf.data = buffer; 00152 buf.length = 0; 00153 buf.completeFunction = NULL; 00154 buf.progmem = false; 00155 buf.isString = true; 00156 00157 _txPointers->append(&buf, sizeof(buf)); 00158 if (!_tx) { 00159 runTxBuffers(); 00160 } 00161 00162 return false; 00163 } 00164 00172 bool MHV_Device_TX::write(const char *buffer, void (*completeFunction)(const char *)) { 00173 MHV_TX_BUFFER buf; 00174 00175 if (_txPointers->full(sizeof(buf))) { 00176 return true; 00177 } 00178 00179 buf.data = buffer; 00180 buf.length = 0; 00181 buf.completeFunction = completeFunction; 00182 buf.progmem = false; 00183 buf.isString = true; 00184 00185 _txPointers->append(&buf, sizeof(buf)); 00186 if (!_tx) { 00187 runTxBuffers(); 00188 } 00189 00190 return false; 00191 } 00192 00200 bool MHV_Device_TX::write_P(PGM_P buffer, uint16_t length) { 00201 MHV_TX_BUFFER buf; 00202 00203 if (_txPointers->full(sizeof(buf))) { 00204 return true; 00205 } 00206 00207 buf.data = buffer; 00208 buf.length = length; 00209 buf.completeFunction = NULL; 00210 buf.progmem = true; 00211 buf.isString = false; 00212 00213 _txPointers->append(&buf, sizeof(buf)); 00214 if (!_tx) { 00215 runTxBuffers(); 00216 } 00217 00218 return false; 00219 } 00220 00228 bool MHV_Device_TX::write(const char *buffer, uint16_t length) { 00229 MHV_TX_BUFFER buf; 00230 00231 if (_txPointers->full(sizeof(buf))) { 00232 return true; 00233 } 00234 00235 buf.data = buffer; 00236 buf.length = length; 00237 buf.completeFunction = NULL; 00238 buf.progmem = false; 00239 buf.isString = false; 00240 00241 _txPointers->append(&buf, sizeof(buf)); 00242 if (!_tx) { 00243 runTxBuffers(); 00244 } 00245 00246 return false; 00247 } 00248 00257 bool MHV_Device_TX::write(const char *buffer, uint16_t length, void (*completeFunction)(const char *)) { 00258 MHV_TX_BUFFER buf; 00259 00260 if (_txPointers->full(sizeof(buf))) { 00261 return true; 00262 } 00263 00264 buf.data = buffer; 00265 buf.length = length; 00266 buf.completeFunction = completeFunction; 00267 buf.progmem = false; 00268 buf.isString = false; 00269 00270 _txPointers->append(&buf, sizeof(buf)); 00271 if (!_tx) { 00272 runTxBuffers(); 00273 } 00274 00275 return false; 00276 } 00277 00282 void mhv_device_tx_free(const char *buf) { 00283 free((void *)buf); 00284 } 00285 00296 bool MHV_Device_TX::debug(const char *file, int line, const char *function, 00297 PGM_P format, ...) { 00298 va_list ap; 00299 va_start(ap, format); 00300 00301 int length = snprintf_P(NULL, 0, PSTR("%s:%d\t%s():\t\t"), 00302 file, line, function); 00303 length += vsnprintf_P(NULL, 0, format, ap); 00304 length += 3; // "\r\n\0" 00305 00306 char *buf = (char *)malloc(length); 00307 char *cur = buf; 00308 if (NULL != cur) { 00309 cur += snprintf_P(cur, length, PSTR("%s:%d\t%s():\t\t"), 00310 file, line, function); 00311 length -= cur - buf; 00312 cur += vsnprintf_P(cur, length, format, ap); 00313 *(cur++) = '\r'; 00314 *(cur++) = '\n'; 00315 *cur = '\0'; 00316 00317 if (write(buf, length, &mhv_device_tx_free)) { 00318 mhv_device_tx_free(buf); 00319 va_end(ap); 00320 return true; 00321 } 00322 00323 va_end(ap); 00324 return false; 00325 } 00326 00327 va_end(ap); 00328 return true; 00329 } 00330 00338 bool MHV_Device_TX::printf(PGM_P format, ...) { 00339 va_list ap; 00340 va_start(ap, format); 00341 00342 int length = vsnprintf_P(NULL, 0, format, ap); 00343 length++; // "\0" 00344 00345 char *buf = (char *)malloc(length); 00346 if (NULL != buf) { 00347 vsnprintf_P(buf, length, format, ap); 00348 00349 if (write(buf, length, &mhv_device_tx_free)) { 00350 mhv_device_tx_free(buf); 00351 va_end(ap); 00352 return true; 00353 } 00354 00355 va_end(ap); 00356 return false; 00357 } 00358 00359 va_end(ap); 00360 return true; 00361 00362 } 00363 00370 bool MHV_Device_TX::write(uint8_t value) { 00371 char *buf = (char *)malloc(4); 00372 if (NULL != buf) { 00373 utoa((uint16_t)value, buf, 10); 00374 if (write(buf)) { 00375 mhv_device_tx_free(buf); 00376 return true; 00377 } 00378 return false; 00379 } 00380 return true; 00381 } 00382 00389 bool MHV_Device_TX::write(uint16_t value) { 00390 char *buf = (char *)malloc(6); 00391 if (NULL != buf) { 00392 utoa(value, buf, 10); 00393 if (write(buf)) { 00394 mhv_device_tx_free(buf); 00395 return true; 00396 } 00397 return false; 00398 } 00399 return true; 00400 } 00401 00408 bool MHV_Device_TX::write(uint32_t value) { 00409 char *buf = (char *)malloc(11); 00410 if (NULL != buf) { 00411 ultoa(value, buf, 10); 00412 if (write(buf)) { 00413 mhv_device_tx_free(buf); 00414 return true; 00415 } 00416 return false; 00417 } 00418 return true; 00419 } 00420 00427 bool MHV_Device_TX::write(int8_t value) { 00428 char *buf = (char *)malloc(5); 00429 if (NULL != buf) { 00430 itoa((uint16_t)value, buf, 10); 00431 if (write(buf)) { 00432 mhv_device_tx_free(buf); 00433 return true; 00434 } 00435 return false; 00436 } 00437 return true; 00438 } 00439 00446 bool MHV_Device_TX::write(int16_t value) { 00447 char *buf = (char *)malloc(7); 00448 if (NULL != buf) { 00449 itoa(value, buf, 10); 00450 if (write(buf)) { 00451 mhv_device_tx_free(buf); 00452 return true; 00453 } 00454 return false; 00455 } 00456 return true; 00457 } 00458 00465 bool MHV_Device_TX::write(int32_t value) { 00466 char *buf = (char *)malloc(13); 00467 if (NULL != buf) { 00468 ltoa(value, buf, 10); 00469 if (write(buf)) { 00470 mhv_device_tx_free(buf); 00471 return true; 00472 } 00473 return false; 00474 } 00475 return true; 00476 }