MHVLib  20111227
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 
00051 MHV_Display_Holtek_HT1632::MHV_Display_Holtek_HT1632(
00052                 MHV_DECLARE_PIN(data),
00053                 MHV_DECLARE_PIN(write),
00054                 MHV_HT1632_MODE mode,
00055                 uint8_t arrayX, uint8_t arrayY,
00056                 void (*csCallback)(uint8_t x, uint8_t y, bool active),
00057                 uint8_t *frameBuffer, MHV_RingBuffer &txBuffers) :
00058                         MHV_Display_Monochrome(
00059                                         ((MHV_HT1632_NMOS_32x8 == mode || MHV_HT1632_PMOS_32x8 == mode) ? 32 : 24) * arrayX,
00060                                         ((MHV_HT1632_NMOS_32x8 == mode || MHV_HT1632_PMOS_32x8 == mode) ? 8 : 16) * arrayY,
00061                                         txBuffers) {
00062 
00063         mhv_setOutput(dataDir, dataOut, dataIn, dataPin, dataPinchangeInterrupt);
00064         mhv_setOutput(writeDir, writeOut, writeIn, writePin, writePinchangeInterrupt);
00065 
00066         _port = dataOut;
00067         _data = _BV(dataPin);
00068         _dataPin = dataPin;
00069         _write = _BV(writePin);
00070         _writePin = writePin;
00071         _csCallback = csCallback;
00072         _arrayX = arrayX;
00073         _arrayY = arrayY;
00074         _frameBuffer = frameBuffer;
00075         _mode = mode;
00076 
00077         uint8_t x, y;
00078 
00079         for (y = 0; y < _arrayY; y++) {
00080                 // Set the first module to be the master, rest will be slaves
00081                 for (x = 0; x < _arrayX; x++) {
00082                         _csCallback(x, y, 0);
00083 
00084                         poweron(x, y);
00085                         if (!x && !y) {
00086                                 master(x, y);
00087                         } else {
00088                                 slave(x, y);
00089                         }
00090 
00091                         // Set the display mode
00092                         setMode(x, y, mode);
00093                 }
00094         }
00095 
00096         // Clear the framebuffer
00097         uint16_t bufSize = arrayX * arrayY;
00098         switch (mode) {
00099                 case MHV_HT1632_NMOS_32x8:
00100                 case MHV_HT1632_PMOS_32x8:
00101                         _displayX = 32;
00102                         _displayY = 8;
00103                         _displayBytes = 32 * 8 / 8;
00104                         break;
00105                 case MHV_HT1632_NMOS_24x16:
00106                 case MHV_HT1632_PMOS_24x16:
00107                         _displayX = 24;
00108                         _displayY = 16;
00109                         _displayBytes = 24 * 16 / 8;
00110                         break;
00111         }
00112         bufSize *= _displayBytes;
00113 
00114         for (uint16_t i = 0; i < bufSize; i++) {
00115                 _frameBuffer[i] = 0x0;
00116         }
00117 }
00118 
00125 void MHV_Display_Holtek_HT1632::setPixel(uint16_t col, uint16_t row, uint8_t value) {
00126         if (row < _rowCount && col < _colCount) {
00127 
00128                 // Coordinates of the display module
00129                 uint8_t moduleX, moduleY;
00130 
00131                 moduleX = col / _displayX;
00132                 moduleY = row / _displayY;
00133 
00134                 // offsets within the module
00135                 col -= moduleX * _displayX;
00136                 row -= moduleY * _displayY;
00137 
00138                 uint8_t offset = col;
00139                 uint8_t bit = row;
00140                 switch (_mode) {
00141                 case MHV_HT1632_NMOS_32x8:
00142                 case MHV_HT1632_PMOS_32x8:
00143                         break;
00144                 case MHV_HT1632_NMOS_24x16:
00145                 case MHV_HT1632_PMOS_24x16:
00146                         offset *= 2;
00147                         if (bit > 7) {
00148                                 bit -= 8;
00149                                 offset++;
00150                         }
00151                         break;
00152                 }
00153 
00154                 // Change offset from the start of the display to the start of the framebuffer
00155                 offset += (moduleY * _arrayX + moduleX) * _displayBytes;
00156 
00157                 if (value) {
00158                         _frameBuffer[offset] |= 1 << bit;
00159                 } else {
00160                         _frameBuffer[offset] &= ~(1 << bit);
00161                 }
00162         }
00163 }
00164 
00171 uint8_t MHV_Display_Holtek_HT1632::getPixel(uint16_t col, uint16_t row) {
00172         if (row < _rowCount && col < _colCount) {
00173                 // Coordinates of the display module
00174                 uint8_t moduleX, moduleY;
00175 
00176                 moduleX = row / _displayX;
00177                 moduleY = col / _displayY;
00178 
00179                 // offsets within the module
00180                 row -= moduleX * _displayX;
00181                 col -= moduleY * _displayY;
00182 
00183                 uint8_t offset, bit;
00184                 switch (_mode) {
00185                 case MHV_HT1632_NMOS_32x8:
00186                 case MHV_HT1632_PMOS_32x8:
00187                         offset = col;
00188                         bit = row;
00189                         break;
00190                 case MHV_HT1632_NMOS_24x16:
00191                 case MHV_HT1632_PMOS_24x16:
00192                         offset = col * 2;
00193                         bit = row;
00194                         if (bit > 7) {
00195                                 bit -= 8;
00196                                 offset++;
00197                         }
00198                         break;
00199                 }
00200 
00201                 // Change offset from the start of the display to the start of the framebuffer
00202                 offset += (moduleY * _arrayX + moduleX) * _displayBytes;
00203 
00204                 if (_frameBuffer[offset] & (1 << bit)) {
00205                         return 1;
00206                 }
00207         }
00208 
00209         return 0;
00210 }
00211 
00217 void MHV_Display_Holtek_HT1632::writeData(uint8_t data, uint8_t length) {
00218         while (0 != length) {
00219                 if (data & 1 << (--length)) {
00220                 *_port |= _data;
00221                 } else {
00222                         *_port &= ~_data;
00223                 }
00224 
00225                 *_port &= ~_write;
00226                 *_port |= _write;
00227         }
00228 }
00229 
00236 void MHV_Display_Holtek_HT1632::sendCommand(uint8_t moduleX, uint8_t moduleY, MHV_HT1632_COMMAND command) {
00237         _csCallback(moduleX, moduleY, 1);
00238         writeData(command, 3);
00239 }
00240 
00246 void MHV_Display_Holtek_HT1632::commandComplete(uint8_t moduleX, uint8_t moduleY) {
00247         _csCallback(moduleX, moduleY, 0);
00248 }
00249 
00255 void MHV_Display_Holtek_HT1632::outputStart(uint8_t moduleX, uint8_t moduleY) {
00256         sendCommand(moduleX, moduleY, MHV_HT1632_COMMAND_WRITE);
00257         writeData(0, 7);
00258 }
00259 
00263 void MHV_Display_Holtek_HT1632::flush() {
00264         uint8_t x, y;
00265         uint8_t bytes;
00266         uint8_t bytesCopy;
00267         uint8_t *data;
00268 
00269         bytes = (MHV_HT1632_NMOS_32x8 == _mode || MHV_HT1632_PMOS_32x8 == _mode) ? 32 : 48;
00270 
00271         for (x = 0; x < _arrayX; x++) {
00272                 for (y = 0; y < _arrayY; y++) {
00273                         data = _frameBuffer + (uint16_t)bytes * (y * _arrayY + x);
00274                 }
00275         }
00276 
00277         for (x = 0; x < _arrayX; x++) {
00278                 for (y = 0; y < _arrayY; y++) {
00279                         bytesCopy = bytes;
00280                         data = _frameBuffer + (uint16_t)bytes * (y * _arrayY + x);
00281                         outputStart(x, y);
00282                         MHV_SHIFTOUT_ARRAY_CLOCKED_RISING(data, bytesCopy);
00283                         commandComplete(x, y);
00284                 }
00285         }
00286 }
00287 
00292 void MHV_Display_Holtek_HT1632::master(uint8_t moduleX, uint8_t moduleY) {
00293         sendCommand(moduleX, moduleY, MHV_HT1632_COMMAND_CMD);
00294         writeData(0b00010100, 8);
00295         writeData(0x0, 1);
00296         commandComplete(moduleX, moduleY);
00297 }
00298 
00303 void MHV_Display_Holtek_HT1632::slave(uint8_t moduleX, uint8_t moduleY) {
00304         sendCommand(moduleX, moduleY, MHV_HT1632_COMMAND_CMD);
00305         writeData(0b00010000, 8);
00306         writeData(0x0, 1);
00307         commandComplete(moduleX, moduleY);
00308 }
00309 
00315 void MHV_Display_Holtek_HT1632::brightness(uint8_t moduleX, uint8_t moduleY, uint8_t brightness) {
00316         sendCommand(moduleX, moduleY, MHV_HT1632_COMMAND_CMD);
00317         writeData(0b1010, 4);
00318         writeData(brightness << 1, 5);
00319         commandComplete(moduleX, moduleY);
00320 }
00321 
00326 void MHV_Display_Holtek_HT1632::brightness(uint8_t brightness_in) {
00327         uint8_t x, y;
00328 
00329         for (y = 0; y < _arrayY; y++) {
00330                 for (x = 0; x < _arrayX; x++) {
00331                         brightness(x, y, brightness_in);
00332                 }
00333         }
00334 }
00335 
00341 void MHV_Display_Holtek_HT1632::poweroff(uint8_t moduleX, uint8_t moduleY) {
00342         // Shut down the oscillator & PWM generator
00343         sendCommand(moduleX, moduleY, MHV_HT1632_COMMAND_CMD);
00344         writeData(0b00000000, 8);
00345         writeData(0x0, 1);
00346         commandComplete(moduleX, moduleY);
00347 }
00348 
00354 void MHV_Display_Holtek_HT1632::poweron(uint8_t moduleX, uint8_t moduleY) {
00355 // Turn on the oscillator
00356         sendCommand(moduleX, moduleY, MHV_HT1632_COMMAND_CMD);
00357         writeData(0b00000001, 8);
00358         writeData(0x0, 1);
00359         commandComplete(moduleX, moduleY);
00360 
00361 // Turn on the PWM generator
00362         sendCommand(moduleX, moduleY, MHV_HT1632_COMMAND_CMD);
00363         writeData(0b00000011, 8);
00364         writeData(0x0, 1);
00365         commandComplete(moduleX, moduleY);
00366 }
00367 
00374 void MHV_Display_Holtek_HT1632::setMode(uint8_t moduleX, uint8_t moduleY, MHV_HT1632_MODE mode) {
00375         sendCommand(moduleX, moduleY, MHV_HT1632_COMMAND_CMD);
00376         writeData(0b0010, 4);
00377         writeData(mode, 2);
00378         writeData(0b000, 3);
00379         commandComplete(moduleX, moduleY);
00380 }
00381 
00382 
00386 void MHV_Display_Holtek_HT1632::poweroff() {
00387         uint8_t x, y;
00388 
00389         for (y = 0; y < _arrayY; y++) {
00390                 for (x = 0; x < _arrayX; x++) {
00391                         poweroff(x, y);
00392                 }
00393         }
00394 }
00395 
00399 void MHV_Display_Holtek_HT1632::poweron() {
00400         uint8_t x, y;
00401 
00402         for (y = 0; y < _arrayY; y++) {
00403                 for (x = 0; x < _arrayX; x++) {
00404                         poweron(x, y);
00405                 }
00406         }
00407 }