MHVLib  20111011
An efficiency oriented runtime library for AVR microcontrollers
A:/eclipse/mhvlib/MHV_Display_Holtek_HT1632.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 
00032 #include <stdio.h>
00033 #include <MHV_Display_Holtek_HT1632.h>
00034 
00035 #define MHV_SHIFT_WRITECLOCK NULL, _port, NULL, _writePin, -1
00036 #define MHV_SHIFT_WRITEDATA NULL, _port, NULL, _dataPin, -1
00037 #define MHV_SHIFT_ORDER_MSB
00038 #include <MHV_Shifter.h>
00039 
00059 MHV_Display_Holtek_HT1632::MHV_Display_Holtek_HT1632(
00060                 volatile uint8_t *dataDir, volatile uint8_t *dataOut, volatile uint8_t *dataIn,
00061                         uint8_t dataPin, int8_t dataPinchangeInterrupt,
00062                 volatile uint8_t *writeDir, volatile uint8_t *writeOut, volatile uint8_t *writeIn,
00063                                         uint8_t writePin, int8_t writePinchangeInterrupt,
00064                 MHV_HT1632_MODE mode,
00065                 uint8_t arrayX, uint8_t arrayY,
00066                 void (*csCallback)(uint8_t x, uint8_t y, bool active),
00067                 uint8_t *frameBuffer, MHV_RingBuffer *txBuffers) :
00068                         MHV_Display_Monochrome(
00069                                         ((MHV_HT1632_NMOS_32x8 == mode || MHV_HT1632_PMOS_32x8 == mode) ? 32 : 24) * arrayX,
00070                                         ((MHV_HT1632_NMOS_32x8 == mode || MHV_HT1632_PMOS_32x8 == mode) ? 8 : 16) * arrayY,
00071                                         txBuffers) {
00072 
00073         mhv_setOutput(dataDir, dataOut, dataIn, dataPin, dataPinchangeInterrupt);
00074         mhv_setOutput(writeDir, writeOut, writeIn, writePin, writePinchangeInterrupt);
00075 
00076         _port = dataOut;
00077         _data = _BV(dataPin);
00078         _dataPin = dataPin;
00079         _write = _BV(writePin);
00080         _writePin = writePin;
00081         _csCallback = csCallback;
00082         _arrayX = arrayX;
00083         _arrayY = arrayY;
00084         _frameBuffer = frameBuffer;
00085         _mode = mode;
00086 
00087         uint8_t x, y;
00088 
00089         for (y = 0; y < _arrayY; y++) {
00090                 // Set the first module to be the master, rest will be slaves
00091                 for (x = 0; x < _arrayX; x++) {
00092                         _csCallback(x, y, 0);
00093 
00094                         poweron(x, y);
00095                         if (!x && !y) {
00096                                 master(x, y);
00097                         } else {
00098                                 slave(x, y);
00099                         }
00100 
00101                         // Set the display mode
00102                         setMode(x, y, mode);
00103                 }
00104         }
00105 
00106         // Clear the framebuffer
00107         uint16_t bufSize = arrayX * arrayY;
00108         switch (mode) {
00109                 case MHV_HT1632_NMOS_32x8:
00110                 case MHV_HT1632_PMOS_32x8:
00111                         _displayX = 32;
00112                         _displayY = 8;
00113                         _displayBytes = 32 * 8 / 8;
00114                         break;
00115                 case MHV_HT1632_NMOS_24x16:
00116                 case MHV_HT1632_PMOS_24x16:
00117                         _displayX = 24;
00118                         _displayY = 16;
00119                         _displayBytes = 24 * 16 / 8;
00120                         break;
00121         }
00122         bufSize *= _displayBytes;
00123 
00124         for (uint16_t i = 0; i < bufSize; i++) {
00125                 _frameBuffer[i] = 0x0;
00126         }
00127 }
00128 
00135 void MHV_Display_Holtek_HT1632::setPixel(uint16_t col, uint16_t row, uint8_t value) {
00136         if (row < _rowCount && col < _colCount) {
00137 
00138                 // Coordinates of the display module
00139                 uint8_t moduleX, moduleY;
00140 
00141                 moduleX = col / _displayX;
00142                 moduleY = row / _displayY;
00143 
00144                 // offsets within the module
00145                 col -= moduleX * _displayX;
00146                 row -= moduleY * _displayY;
00147 
00148                 uint8_t offset = col;
00149                 uint8_t bit = row;
00150                 switch (_mode) {
00151                 case MHV_HT1632_NMOS_32x8:
00152                 case MHV_HT1632_PMOS_32x8:
00153                         break;
00154                 case MHV_HT1632_NMOS_24x16:
00155                 case MHV_HT1632_PMOS_24x16:
00156                         offset *= 2;
00157                         if (bit > 7) {
00158                                 bit -= 8;
00159                                 offset++;
00160                         }
00161                         break;
00162                 }
00163 
00164                 // Change offset from the start of the display to the start of the framebuffer
00165                 offset += (moduleY * _arrayX + moduleX) * _displayBytes;
00166 
00167                 if (value) {
00168                         _frameBuffer[offset] |= 1 << bit;
00169                 } else {
00170                         _frameBuffer[offset] &= ~(1 << bit);
00171                 }
00172         }
00173 }
00174 
00181 uint8_t MHV_Display_Holtek_HT1632::getPixel(uint16_t col, uint16_t row) {
00182         if (row < _rowCount && col < _colCount) {
00183                 // Coordinates of the display module
00184                 uint8_t moduleX, moduleY;
00185 
00186                 moduleX = row / _displayX;
00187                 moduleY = col / _displayY;
00188 
00189                 // offsets within the module
00190                 row -= moduleX * _displayX;
00191                 col -= moduleY * _displayY;
00192 
00193                 uint8_t offset, bit;
00194                 switch (_mode) {
00195                 case MHV_HT1632_NMOS_32x8:
00196                 case MHV_HT1632_PMOS_32x8:
00197                         offset = col;
00198                         bit = row;
00199                         break;
00200                 case MHV_HT1632_NMOS_24x16:
00201                 case MHV_HT1632_PMOS_24x16:
00202                         offset = col * 2;
00203                         bit = row;
00204                         if (bit > 7) {
00205                                 bit -= 8;
00206                                 offset++;
00207                         }
00208                         break;
00209                 }
00210 
00211                 // Change offset from the start of the display to the start of the framebuffer
00212                 offset += (moduleY * _arrayX + moduleX) * _displayBytes;
00213 
00214                 if (_frameBuffer[offset] & (1 << bit)) {
00215                         return 1;
00216                 }
00217         }
00218 
00219         return 0;
00220 }
00221 
00227 void MHV_Display_Holtek_HT1632::writeData(uint8_t data, uint8_t length) {
00228         while (0 != length) {
00229                 if (data & 1 << (--length)) {
00230                 *_port |= _data;
00231                 } else {
00232                         *_port &= ~_data;
00233                 }
00234 
00235                 *_port &= ~_write;
00236                 *_port |= _write;
00237         }
00238 }
00239 
00246 void MHV_Display_Holtek_HT1632::sendCommand(uint8_t moduleX, uint8_t moduleY, MHV_HT1632_COMMAND command) {
00247         _csCallback(moduleX, moduleY, 1);
00248         writeData(command, 3);
00249 }
00250 
00256 void MHV_Display_Holtek_HT1632::commandComplete(uint8_t moduleX, uint8_t moduleY) {
00257         _csCallback(moduleX, moduleY, 0);
00258 }
00259 
00265 void MHV_Display_Holtek_HT1632::outputStart(uint8_t moduleX, uint8_t moduleY) {
00266         sendCommand(moduleX, moduleY, MHV_HT1632_COMMAND_WRITE);
00267         writeData(0, 7);
00268 }
00269 
00273 void MHV_Display_Holtek_HT1632::flush() {
00274         uint8_t x, y;
00275         uint8_t bytes;
00276         uint8_t bytesCopy;
00277         uint8_t *data;
00278 
00279         bytes = (MHV_HT1632_NMOS_32x8 == _mode || MHV_HT1632_PMOS_32x8 == _mode) ? 32 : 48;
00280 
00281         for (x = 0; x < _arrayX; x++) {
00282                 for (y = 0; y < _arrayY; y++) {
00283                         data = _frameBuffer + (uint16_t)bytes * (y * _arrayY + x);
00284                 }
00285         }
00286 
00287         for (x = 0; x < _arrayX; x++) {
00288                 for (y = 0; y < _arrayY; y++) {
00289                         bytesCopy = bytes;
00290                         data = _frameBuffer + (uint16_t)bytes * (y * _arrayY + x);
00291                         outputStart(x, y);
00292                         MHV_SHIFTOUT_ARRAY_CLOCKED_RISING(data, bytesCopy);
00293                         commandComplete(x, y);
00294                 }
00295         }
00296 }
00297 
00302 void MHV_Display_Holtek_HT1632::master(uint8_t moduleX, uint8_t moduleY) {
00303         sendCommand(moduleX, moduleY, MHV_HT1632_COMMAND_CMD);
00304         writeData(0b00010100, 8);
00305         writeData(0x0, 1);
00306         commandComplete(moduleX, moduleY);
00307 }
00308 
00313 void MHV_Display_Holtek_HT1632::slave(uint8_t moduleX, uint8_t moduleY) {
00314         sendCommand(moduleX, moduleY, MHV_HT1632_COMMAND_CMD);
00315         writeData(0b00010000, 8);
00316         writeData(0x0, 1);
00317         commandComplete(moduleX, moduleY);
00318 }
00319 
00325 void MHV_Display_Holtek_HT1632::brightness(uint8_t moduleX, uint8_t moduleY, uint8_t brightness) {
00326         sendCommand(moduleX, moduleY, MHV_HT1632_COMMAND_CMD);
00327         writeData(0b1010, 4);
00328         writeData(brightness << 1, 5);
00329         commandComplete(moduleX, moduleY);
00330 }
00331 
00336 void MHV_Display_Holtek_HT1632::brightness(uint8_t brightness_in) {
00337         uint8_t x, y;
00338 
00339         for (y = 0; y < _arrayY; y++) {
00340                 for (x = 0; x < _arrayX; x++) {
00341                         brightness(x, y, brightness_in);
00342                 }
00343         }
00344 }
00345 
00351 void MHV_Display_Holtek_HT1632::poweroff(uint8_t moduleX, uint8_t moduleY) {
00352         // Shut down the oscillator & PWM generator
00353         sendCommand(moduleX, moduleY, MHV_HT1632_COMMAND_CMD);
00354         writeData(0b00000000, 8);
00355         writeData(0x0, 1);
00356         commandComplete(moduleX, moduleY);
00357 }
00358 
00364 void MHV_Display_Holtek_HT1632::poweron(uint8_t moduleX, uint8_t moduleY) {
00365 // Turn on the oscillator
00366         sendCommand(moduleX, moduleY, MHV_HT1632_COMMAND_CMD);
00367         writeData(0b00000001, 8);
00368         writeData(0x0, 1);
00369         commandComplete(moduleX, moduleY);
00370 
00371 // Turn on the PWM generator
00372         sendCommand(moduleX, moduleY, MHV_HT1632_COMMAND_CMD);
00373         writeData(0b00000011, 8);
00374         writeData(0x0, 1);
00375         commandComplete(moduleX, moduleY);
00376 }
00377 
00384 void MHV_Display_Holtek_HT1632::setMode(uint8_t moduleX, uint8_t moduleY, MHV_HT1632_MODE mode) {
00385         sendCommand(moduleX, moduleY, MHV_HT1632_COMMAND_CMD);
00386         writeData(0b0010, 4);
00387         writeData(mode, 2);
00388         writeData(0b000, 3);
00389         commandComplete(moduleX, moduleY);
00390 }
00391 
00392 
00396 void MHV_Display_Holtek_HT1632::poweroff() {
00397         uint8_t x, y;
00398 
00399         for (y = 0; y < _arrayY; y++) {
00400                 for (x = 0; x < _arrayX; x++) {
00401                         poweroff(x, y);
00402                 }
00403         }
00404 }
00405 
00409 void MHV_Display_Holtek_HT1632::poweron() {
00410         uint8_t x, y;
00411 
00412         for (y = 0; y < _arrayY; y++) {
00413                 for (x = 0; x < _arrayX; x++) {
00414                         poweron(x, y);
00415                 }
00416         }
00417 }