MHVLib
20111011
An efficiency oriented runtime library for AVR microcontrollers
|
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 }