Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
PT6964.cpp
00001 /* mbed PT6964 Library, for PT6964 LED controller 00002 * Copyright (c) 2015, v01: WH, Initial version 00003 * 2015, v02: WH, rename Digit/Grid 00004 * 2016, v03: WH, updated Icon handling, UDCs and _putc() 00005 * 2016, v04: WH, Refactored display and keyboard defines 00006 * 00007 * Permission is hereby granted, free of charge, to any person obtaining a copy 00008 * of this software and associated documentation files (the "Software"), to deal 00009 * in the Software without restriction, including without limitation the rights 00010 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00011 * copies of the Software, and to permit persons to whom the Software is 00012 * furnished to do so, subject to the following conditions: 00013 * 00014 * The above copyright notice and this permission notice shall be included in 00015 * all copies or substantial portions of the Software. 00016 * 00017 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00018 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00019 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00020 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00021 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00022 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00023 * THE SOFTWARE. 00024 */ 00025 #include "mbed.h" 00026 #include "PT6964.h" 00027 #include "Font_7Seg.h" 00028 00029 /** Constructor for class for driving PT6964 LED controller with SPI bus interface device. 00030 * Note: the PT6964 is also available from other chipvendors eg AIP1628, HT1628, CM1628, SM1628 00031 * @brief Supports 4 digits @ 13 segments or 5 digits @ 12 segments or 6 Digits @ 11 Segments or 7 Digits @ 10 Segments. 00032 * Also supports a scanned keyboard of upto 20 keys. 00033 * 00034 * @param PinName mosi, miso, sclk, cs SPI bus pins 00035 * @param Mode selects either 6 Digits of 12 Segments or 7 Digits of 10 Segments (default) 00036 */ 00037 PT6964::PT6964(PinName mosi, PinName miso, PinName sclk, PinName cs, Mode mode) : _spi(mosi,miso,sclk), _cs(cs), _mode(mode) { 00038 00039 _init(); 00040 } 00041 00042 /** Init the SPI interface and the controller 00043 * @param none 00044 * @return none 00045 */ 00046 void PT6964::_init(){ 00047 00048 //init SPI 00049 _cs=1; 00050 _spi.format(8,3); //PT6964 uses mode 3 (Clock High on Idle, Data latched on second (=rising) edge) 00051 _spi.frequency(500000); 00052 00053 //init controller 00054 _writeCmd(PT6964_MODE_SET_CMD, _mode); // Mode set command 00055 00056 _display = PT6964_DSP_ON; 00057 _bright = PT6964_BRT_DEF; 00058 _writeCmd(PT6964_DSP_CTRL_CMD, _display | _bright ); // Display control cmd, display on/off, brightness 00059 00060 _writeCmd(PT6964_DATA_SET_CMD, PT6964_DATA_WR | PT6964_ADDR_INC | PT6964_MODE_NORM); // Data set cmd, normal mode, auto incr, write data 00061 } 00062 00063 00064 /** Clear the screen and locate to 0 00065 */ 00066 void PT6964::cls() { 00067 00068 _cs=0; 00069 wait_us(1); 00070 _spi.write(_flip(PT6964_ADDR_SET_CMD | 0x00)); // Address set cmd, 0 00071 00072 for (int cnt=0; cnt<PT6964_DISPLAY_MEM; cnt++) { 00073 _spi.write(0x00); // data 00074 } 00075 00076 wait_us(1); 00077 _cs=1; 00078 } 00079 00080 /** Set Brightness 00081 * 00082 * @param char brightness (3 significant bits, valid range 0..7 (1/16 .. 14/14 dutycycle) 00083 * @return none 00084 */ 00085 void PT6964::setBrightness(char brightness){ 00086 00087 _bright = brightness & PT6964_BRT_MSK; // mask invalid bits 00088 00089 _writeCmd(PT6964_DSP_CTRL_CMD, _display | _bright ); // Display control cmd, display on/off, brightness 00090 } 00091 00092 /** Set the Display mode On/off 00093 * 00094 * @param bool display mode 00095 */ 00096 void PT6964::setDisplay(bool on) { 00097 00098 if (on) { 00099 _display = PT6964_DSP_ON; 00100 } 00101 else { 00102 _display = PT6964_DSP_OFF; 00103 } 00104 00105 _writeCmd(PT6964_DSP_CTRL_CMD, _display | _bright ); // Display control cmd, display on/off, brightness 00106 } 00107 00108 /** Write databyte to PT6964 00109 * @param int address display memory location to write byte 00110 * @param char data byte written at given address 00111 * @return none 00112 */ 00113 void PT6964::writeData(int address, char data) { 00114 _cs=0; 00115 wait_us(1); 00116 _spi.write(_flip(PT6964_ADDR_SET_CMD | (address & PT6964_ADDR_MSK))); // Set Address cmd 00117 00118 _spi.write(_flip(data)); // data 00119 00120 wait_us(1); 00121 _cs=1; 00122 } 00123 00124 /** Write Display datablock to PT6964 00125 * @param DisplayData_t data Array of PT6964_DISPLAY_MEM (=14) bytes for displaydata (starting at address 0) 00126 * @param length number bytes to write (valide range 0..PT6964_DISPLAY_MEM (=14), starting at address 0) 00127 * @return none 00128 */ 00129 void PT6964::writeData(DisplayData_t data, int length) { 00130 _cs=0; 00131 wait_us(1); 00132 _spi.write(_flip(PT6964_ADDR_SET_CMD | 0x00)); // Set Address at 0 00133 00134 // sanity check 00135 if (length < 0) {length = 0;} 00136 if (length > PT6964_DISPLAY_MEM) {length = PT6964_DISPLAY_MEM;} 00137 00138 // for (int idx=0; idx<PT6964_DISPLAY_MEM; idx++) { 00139 for (int idx=0; idx<length; idx++) { 00140 _spi.write(_flip(data[idx])); // data 00141 } 00142 00143 wait_us(1); 00144 _cs=1; 00145 } 00146 00147 00148 /** Read keydata block from PT6964 00149 * @param *keydata Ptr to Array of PT6964_KEY_MEM (=5) bytes for keydata 00150 * @return bool keypress True when at least one key was pressed 00151 * 00152 * Note: Due to the hardware configuration the PT6964 key matrix scanner will detect multiple keys pressed at same time, 00153 * but this may also result in some spurious keys being set in keypress data array. 00154 * It may be best to ignore all keys in those situations. That option is implemented in this method depending on #define setting. 00155 */ 00156 bool PT6964::getKeys(KeyData_t *keydata) { 00157 int keypress = 0; 00158 char data; 00159 00160 // Read keys 00161 _cs=0; 00162 wait_us(1); 00163 00164 // Enable Key Read mode 00165 _spi.write(_flip(PT6964_DATA_SET_CMD | PT6964_KEY_RD | PT6964_ADDR_INC | PT6964_MODE_NORM)); // Data set cmd, normal mode, auto incr, read data 00166 00167 for (int idx=0; idx < PT6964_KEY_MEM; idx++) { 00168 data = _flip(_spi.write(0xFF)); // read keys and correct bitorder 00169 00170 data = data & PT6964_KEY_MSK; // Mask valid bits 00171 if (data != 0) { // Check for any pressed key 00172 for (int bit=0; bit < 8; bit++) { 00173 if (data & (1 << bit)) {keypress++;} // Test all significant bits 00174 } 00175 } 00176 00177 (*keydata)[idx] = data; // Store keydata after correcting bitorder 00178 } 00179 00180 wait_us(1); 00181 _cs=1; 00182 00183 // Restore Data Write mode 00184 _writeCmd(PT6964_DATA_SET_CMD, PT6964_DATA_WR | PT6964_ADDR_INC | PT6964_MODE_NORM); // Data set cmd, normal mode, auto incr, write data 00185 00186 #if(1) 00187 // Dismiss multiple keypresses at same time 00188 return (keypress == 1); 00189 #else 00190 // Allow multiple keypress and accept possible spurious keys 00191 return (keypress > 0); 00192 #endif 00193 } 00194 00195 00196 /** Helper to reverse all command or databits. The PT6964 expects LSB first, whereas SPI is MSB first 00197 * @param char data 00198 * @return bitreversed data 00199 */ 00200 char PT6964::_flip(char data) { 00201 char value=0; 00202 00203 if (data & 0x01) {value |= 0x80;} ; 00204 if (data & 0x02) {value |= 0x40;} ; 00205 if (data & 0x04) {value |= 0x20;} ; 00206 if (data & 0x08) {value |= 0x10;} ; 00207 if (data & 0x10) {value |= 0x08;} ; 00208 if (data & 0x20) {value |= 0x04;} ; 00209 if (data & 0x40) {value |= 0x02;} ; 00210 if (data & 0x80) {value |= 0x01;} ; 00211 return value; 00212 } 00213 00214 00215 /** Write command and parameter to PT6964 00216 * @param int cmd Command byte 00217 * &Param int data Parameters for command 00218 * @return none 00219 */ 00220 void PT6964::_writeCmd(int cmd, int data){ 00221 00222 _cs=0; 00223 wait_us(1); 00224 // _spi.write(_flip( (cmd & 0xF0) | (data & 0x0F))); 00225 _spi.write(_flip( (cmd & PT6964_CMD_MSK) | (data & ~PT6964_CMD_MSK))); 00226 00227 wait_us(1); 00228 _cs=1; 00229 } 00230 00231 00232 00233 00234 /** Constructor for class for driving Princeton PT6964 controller as used in DVD538A 00235 * 00236 * @brief Supports 4 Digits of 7 Segments, 1 Grid of 9 Icons. Also supports a scanned keyboard of 4. 00237 * 00238 * @param PinName mosi, miso, sclk, cs SPI bus pins 00239 */ 00240 PT6964_DVD538A::PT6964_DVD538A(PinName mosi, PinName miso, PinName sclk, PinName cs) : PT6964(mosi, miso, sclk, cs, Grid7_Seg10) { 00241 _column = 0; 00242 _columns = DVD538A_NR_DIGITS; 00243 } 00244 00245 #if(0) 00246 #if DOXYGEN_ONLY 00247 /** Write a character to the Display 00248 * 00249 * @param c The character to write to the display 00250 */ 00251 int putc(int c); 00252 00253 /** Write a formatted string to the Display 00254 * 00255 * @param format A printf-style format string, followed by the 00256 * variables to use in formatting the string. 00257 */ 00258 int printf(const char* format, ...); 00259 #endif 00260 #endif 00261 00262 /** Locate cursor to a screen column 00263 * 00264 * @param column The horizontal position from the left, indexed from 0 00265 */ 00266 void PT6964_DVD538A::locate(int column) { 00267 //sanity check 00268 if (column < 0) {column = 0;} 00269 if (column > (_columns - 1)) {column = _columns - 1;} 00270 00271 _column = column; 00272 } 00273 00274 00275 /** Number of screen columns 00276 * 00277 * @param none 00278 * @return columns 00279 */ 00280 int PT6964_DVD538A::columns() { 00281 return _columns; 00282 } 00283 00284 00285 /** Clear the screen and locate to 0 00286 * @param bool clrAll Clear Icons also (default = false) 00287 */ 00288 void PT6964_DVD538A::cls(bool clrAll) { 00289 00290 if (clrAll) { 00291 //clear local buffer (including Icons) 00292 for (int idx=0; idx < (DVD538A_NR_GRIDS << 1); idx++) { // * PT6964_BYTES_PER_GRID 00293 _displaybuffer[idx] = 0x00; 00294 } 00295 } 00296 else { 00297 //clear local buffer (preserving Icons) 00298 for (int idx=0; idx < DVD538A_NR_GRIDS; idx++) { 00299 _displaybuffer[(idx<<1)] = _displaybuffer[(idx<<1)] & MASK_ICON_GRID[idx][0]; 00300 _displaybuffer[(idx<<1) + 1] = _displaybuffer[(idx<<1) + 1] & MASK_ICON_GRID[idx][1]; 00301 } 00302 } 00303 00304 writeData(_displaybuffer, (DVD538A_NR_GRIDS * PT6964_BYTES_PER_GRID)); 00305 00306 _column = 0; 00307 } 00308 00309 00310 /** Set Icon 00311 * 00312 * @param Icon icon Enums Icon has Grid position encoded in 8 MSBs, Icon pattern encoded in 16 LSBs 00313 * @return none 00314 */ 00315 void PT6964_DVD538A::setIcon(Icon icon) { 00316 int addr, icn; 00317 00318 icn = icon & 0xFFFF; 00319 addr = (icon >> 24) & 0xFF; 00320 addr = (addr - 1) << 1; // * PT6964_BYTES_PER_GRID 00321 00322 //Save char...and set bits for icon to write 00323 _displaybuffer[addr] = _displaybuffer[addr] | LO(icn); 00324 _displaybuffer[addr+1] = _displaybuffer[addr+1] | HI(icn); 00325 writeData(_displaybuffer, (DVD538A_NR_GRIDS * PT6964_BYTES_PER_GRID)); 00326 } 00327 00328 /** Clr Icon 00329 * 00330 * @param Icon icon Enums Icon has Grid position encoded in 8 MSBs, Icon pattern encoded in 16 LSBs 00331 * @return none 00332 */ 00333 void PT6964_DVD538A::clrIcon(Icon icon) { 00334 int addr, icn; 00335 00336 icn = icon & 0xFFFF; 00337 addr = (icon >> 24) & 0xFF; 00338 addr = (addr - 1) << 1; // * PT6964_BYTES_PER_GRID 00339 00340 //Save char...and clr bits for icon to write 00341 _displaybuffer[addr] = _displaybuffer[addr] & ~LO(icn); 00342 _displaybuffer[addr+1] = _displaybuffer[addr+1] & ~HI(icn); 00343 writeData(_displaybuffer, (DVD538A_NR_GRIDS * PT6964_BYTES_PER_GRID)); 00344 } 00345 00346 00347 /** Set User Defined Characters (UDC) 00348 * 00349 * @param unsigned char udc_idx The Index of the UDC (0..7) 00350 * @param int udc_data The bitpattern for the UDC (16 bits) 00351 */ 00352 void PT6964_DVD538A::setUDC(unsigned char udc_idx, int udc_data) { 00353 00354 //Sanity check 00355 if (udc_idx > (DVD538A_NR_UDC-1)) { 00356 return; 00357 } 00358 // Mask out Icon bits? 00359 00360 _UDC_7S[udc_idx] = udc_data; 00361 } 00362 00363 00364 /** Write a single character (Stream implementation) 00365 */ 00366 int PT6964_DVD538A::_putc(int value) { 00367 int addr; 00368 bool validChar = false; 00369 short pattern = 0x0000; 00370 00371 if ((value == '\n') || (value == '\r')) { 00372 //No character to write 00373 validChar = false; 00374 00375 //Update Cursor 00376 _column = 0; 00377 } 00378 else if (value == '-') { 00379 //No character to write 00380 validChar = true; 00381 pattern = C7_MIN; 00382 } 00383 else if ((value >= 0) && (value < DVD538A_NR_UDC)) { 00384 //Character to write 00385 validChar = true; 00386 pattern = _UDC_7S[value]; 00387 } 00388 else if ((value >= (int)'0') && (value <= (int) '9')) { 00389 //Character to write 00390 validChar = true; 00391 pattern = FONT_7S[value - (int) '0']; 00392 } 00393 else if ((value >= (int) 'A') && (value <= (int) 'F')) { 00394 //Character to write 00395 validChar = true; 00396 pattern = FONT_7S[10 + value - (int) 'A']; 00397 } 00398 else if ((value >= (int) 'a') && (value <= (int) 'f')) { 00399 //Character to write 00400 validChar = true; 00401 pattern = FONT_7S[10 + value - (int) 'a']; 00402 } //else 00403 00404 if (validChar) { 00405 //Character to write 00406 00407 //Translate between _column and displaybuffer entries 00408 //_column == 0 => Grid5 => addr = 8 00409 //_column == 1 => Grid4 => addr = 6 00410 //_column == 2 => Grid3 => addr = 4 00411 //_column == 3 => Grid4 => addr = 2 00412 addr = (4 - _column) << 1; // * PT6964_BYTES_PER_GRID 00413 00414 //Save icons...and set bits for character to write 00415 _displaybuffer[addr] = (_displaybuffer[addr] & MASK_ICON_GRID[4 - _column][0]) | LO(pattern); 00416 _displaybuffer[addr+1] = (_displaybuffer[addr+1] & MASK_ICON_GRID[4 - _column][1]) | HI(pattern); 00417 00418 writeData(_displaybuffer, (DVD538A_NR_GRIDS * PT6964_BYTES_PER_GRID)); 00419 00420 //Update Cursor 00421 _column++; 00422 if (_column > (DVD538A_NR_DIGITS - 1)) { 00423 _column = 0; 00424 } 00425 00426 } // if validChar 00427 00428 return value; 00429 } 00430 00431 // get a single character (Stream implementation) 00432 int PT6964_DVD538A::_getc() { 00433 return -1; 00434 }
Generated on Tue Jul 12 2022 17:56:28 by
1.7.2
PT6964 LED controller (70 LEDs max), Keyboard scan (20 keys max)