MHVLib  20111011
An efficiency oriented runtime library for AVR microcontrollers
A:/eclipse/mhvlib/MHV_Display_Character.cpp
Go to the documentation of this file.
00001 /* Copyright (c) 2011, Make, Hack, Void Inc
00002  * All rights reserved.
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions are met:
00006  *  * Redistributions of source code must retain the above copyright
00007  *    notice, this list of conditions and the following disclaimer.
00008  *  * Redistributions in binary form must reproduce the above copyright
00009  *    notice, this list of conditions and the following disclaimer in the
00010  *    documentation and/or other materials provided with the distribution.
00011  *  * Neither the name of the Make, Hack, Void nor the
00012  *    names of its contributors may be used to endorse or promote products
00013  *    derived from this software without specific prior written permission.
00014  *
00015  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00016  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00017  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00018  * DISCLAIMED. IN NO EVENT SHALL MAKE, HACK, VOID BE LIABLE FOR ANY
00019  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00020  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00021  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00022  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00023  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00024  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00025  */
00026 
00027 #include <MHV_Display_Character.h>
00028 
00040 MHV_Display_Character::MHV_Display_Character(uint16_t colCount, uint16_t rowCount,
00041                 MHV_RingBuffer *txBuffers) :
00042                         MHV_Device_TX(txBuffers){
00043         _colCount = colCount;
00044         _rowCount = rowCount;
00045         _wrap = true;
00046         _scroll = true;
00047         _currentRow = 0;
00048         _currentCol = 0;
00049 }
00050 
00054 uint8_t MHV_Display_Character::getWidth() {
00055         return _colCount;
00056 }
00057 
00061 uint8_t MHV_Display_Character::getHeight() {
00062         return _rowCount;
00063 }
00064 
00072 bool MHV_Display_Character::writeString(int16_t *offsetX, uint16_t offsetY, const char *string) {
00073         const char *p = string;
00074 
00075         while (*offsetX < 0) {
00076                 (*offsetX)++;
00077                 p++;
00078                 if ('\0' == *p) {
00079                         return false;
00080                 }
00081         }
00082 
00083         setCursor((uint16_t)*offsetX, offsetY);
00084 
00085         bool ret = false;
00086         if (offsetY >= 0 && offsetY < _rowCount) {
00087                 while (*p != '\0' && (*offsetX)++ < (int16_t)_colCount) {
00088                         ret = true;
00089                         writeChar(*p++);
00090                 }
00091         }
00092 
00093         return ret;
00094 }
00095 
00104 bool MHV_Display_Character::writeBuffer(int16_t *offsetX, uint16_t offsetY,
00105                 const char *buffer, uint16_t length) {
00106         bool ret = false;
00107         uint16_t i = 0;
00108 
00109         if (*offsetX < 0) {
00110                 i -= *offsetX;
00111                 *offsetX = 0;
00112         }
00113 
00114         setCursor((uint16_t)*offsetX, offsetY);
00115 
00116         while (i < length && (*offsetX)++ < (int16_t)_colCount) {
00117                 ret = true;
00118                 writeChar(buffer[i++]);
00119         }
00120 
00121         return ret;
00122 }
00123 
00124 
00132 bool MHV_Display_Character::writeString_P(int16_t *offsetX, uint16_t offsetY, PGM_P string) {
00133         const char *p = string;
00134         char c;
00135 
00136         while (*offsetX < 0) {
00137                 (*offsetX)++;
00138                 p++;
00139                 if ('\0' == pgm_read_byte(p)) {
00140                         return false;
00141                 }
00142         }
00143         setCursor((uint16_t)*offsetX, offsetY);
00144 
00145         bool ret = false;
00146         if (offsetY >= 0 && offsetY < _rowCount) {
00147                 while ('\0' != (c = pgm_read_byte(p++)) && (*offsetX)++ < (int16_t)_colCount) {
00148                         ret = true;
00149                         writeChar(c);
00150                 }
00151         }
00152 
00153         return ret;
00154 }
00155 
00164 bool MHV_Display_Character::writeBuffer_P(int16_t *offsetX, uint16_t offsetY,
00165                 PGM_P buffer, uint16_t length) {
00166         bool ret = false;
00167         uint16_t i = 0;
00168 
00169         while (*offsetX < 0) {
00170                 (*offsetX)++;
00171                 i++;
00172         }
00173         setCursor((uint16_t)*offsetX, offsetY);
00174 
00175         while (i < length && (*offsetX)++ < (int16_t)_colCount) {
00176                 ret = true;
00177                 writeChar(pgm_read_byte(buffer + i++));
00178         }
00179 
00180         return ret;
00181 }
00182 
00186 void MHV_Display_Character::runTxBuffers() {
00187         _txOffset = _colCount - 1;
00188         moreTX();
00189 }
00190 
00196 bool MHV_Display_Character::txAnimation(uint16_t row) {
00197         if (!_tx) {
00198                 return false;
00199         }
00200 
00201         int16_t offsetX = _txOffset--;
00202 
00203         setCursor(0, row);
00204 
00205         bool ret;
00206         if (_currentTx.progmem) {
00207                 if (_currentTx.isString) {
00208                         ret = writeString_P(&offsetX, row, _tx);
00209                 } else {
00210                         ret = writeBuffer_P(&offsetX, row, _tx, _currentTx.length);
00211                 }
00212         } else {
00213                 if (_currentTx.isString) {
00214                         ret = writeString(&offsetX, row, _tx);
00215                 } else {
00216                         ret = writeBuffer(&offsetX, row, _tx, _currentTx.length);
00217                 }
00218         }
00219 
00220         while (offsetX++ < (int16_t)_colCount) {
00221                 writeChar(' ');
00222         }
00223 
00224         if (!ret) {
00225                 _txOffset = _colCount - 1;
00226                 return moreTX();
00227         }
00228 
00229         return true;
00230 }
00231 
00236 void MHV_Display_Character::setWrap(bool shouldWrap) {
00237         _wrap = shouldWrap;
00238 }
00239 
00244 void MHV_Display_Character::setScroll(bool shouldScroll) {
00245         _scroll = shouldScroll;
00246 }
00247 
00253 void MHV_Display_Character::setCursor(uint16_t col, uint16_t row) {
00254         _currentRow = row;
00255         _currentCol = col;
00256         _setCursor(col, row);
00257 }
00258 
00268 void MHV_Display_Character::writeChar(char character) {
00269         switch (character) {
00270         case '\b':
00271                 if (_wrap && 0 == _currentCol) {
00272 // Go to the previous line
00273                         if (_currentRow + 1 < _rowCount) {
00274                                 _currentRow++;
00275                         }
00276                         setCursor(_colCount - 1, _currentRow);
00277                 } else {
00278                         setCursor(_currentCol - 1, _currentRow);
00279                 }
00280                 break;
00281         case '\t':
00282                 _currentCol = (_currentCol + 4) & ~(4 - 1);
00283                 if (_currentCol >= _colCount) {
00284                         if (_wrap) {
00285                                 if (_currentRow > 0) {
00286                                         _currentRow--;
00287                                 } else if (_scroll) {
00288                                         scrollVertically();
00289                                         break;
00290                                 }
00291                                 _currentCol = 0;
00292                         } else {
00293                                 _currentCol = _colCount - 1;
00294                         }
00295                 }
00296                 setCursor(_currentCol, _currentRow);
00297                 break;
00298         case '\n':
00299                 if (_currentRow > 0) {
00300                         _currentRow--;
00301                 } else if (_scroll) {
00302                         scrollVertically();
00303                 }
00304                 _currentCol = 0;
00305                 setCursor(_currentCol, _currentRow);
00306                 break;
00307         default:
00308                 if (_currentCol++ >= _colCount - 1 && _wrap) {
00309                         _currentCol = 0;
00310                         if (_currentRow > 0) {
00311                                 _currentRow--;
00312                         } else if (_scroll) {
00313                                 scrollVertically();
00314                         } else {
00315                                 setCursor(_currentCol, _currentRow);
00316                         }
00317                 }
00318                 _writeChar(character);
00319         }
00320 }
00321 
00325 void MHV_Display_Character::scrollVertically() {
00326         uint16_t x, y;
00327         char    c;
00328 
00329         for (y = _rowCount - 2; y > 0; y--) {
00330 // Copy each character in this row to the row above
00331                 for (x = 0; x < _colCount; ++x) {
00332                         _setCursor(x, y + 1);
00333                         c = _readChar();
00334                         _setCursor(x, y);
00335                         _writeChar(c);
00336                 }
00337         }
00338 
00339 // Blank the last row
00340         _setCursor(0, 0);
00341         for (x = 0; x < _colCount; ++x) {
00342                 _writeChar(' ');
00343         }
00344 
00345 // Set the cursor ready to write another line
00346         setCursor(0, 0);
00347 }