|
MHVLib
20111227
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 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 }