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.
PT6311.cpp
00001 /* mbed PT6311 Library, for Princeton PT6311 VFD controller 00002 * Copyright (c) 2016, v01: WH, Initial version, for VFDEM2 code 00003 * 00004 * Permission is hereby granted, free of charge, to any person obtaining a copy 00005 * of this software and associated documentation files (the "Software"), to deal 00006 * in the Software without restriction, including without limitation the rights 00007 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00008 * copies of the Software, and to permit persons to whom the Software is 00009 * furnished to do so, subject to the following conditions: 00010 * 00011 * The above copyright notice and this permission notice shall be included in 00012 * all copies or substantial portions of the Software. 00013 * 00014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00015 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00016 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00017 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00018 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00019 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00020 * THE SOFTWARE. 00021 */ 00022 #include "mbed.h" 00023 #include "PT6311.h" 00024 00025 /** Constructor for class for driving Princeton PT6311 VFD controller 00026 * 00027 * @brief Supports 8 Grids of 20 Segments upto 16 Grids of 12 Segments. Also supports a scanned keyboard of upto 48 keys, 4 switches and 5 LEDs. 00028 * SPI bus interface device. 00029 * 00030 * @param PinName mosi, miso, sclk, cs SPI bus pins 00031 * @param Mode selects either number of Digits and Segments 00032 */ 00033 PT6311::PT6311(PinName mosi, PinName miso, PinName sclk, PinName cs, Mode mode) : _spi(mosi,miso,sclk), _cs(cs), _mode(mode) { 00034 00035 _init(); 00036 } 00037 00038 /** Init the SPI interface and the controller 00039 * @param none 00040 * @return none 00041 */ 00042 void PT6311::_init(){ 00043 00044 //init SPI 00045 _cs=1; 00046 _spi.format(8,3); //PT6311 uses mode 3 (Clock High on Idle, Data latched on second (=rising) edge) 00047 // _spi.frequency(100000); 00048 _spi.frequency(500000); 00049 00050 //init controller 00051 _writeCmd(PT6311_MODE_SET_CMD, _mode); // Mode set command 00052 00053 _display = PT6311_DSP_ON; 00054 _bright = PT6311_BRT_DEF; 00055 _writeCmd(PT6311_DSP_CTRL_CMD, _display | _bright ); // Display control cmd, display on/off, brightness 00056 00057 _writeCmd(PT6311_DATA_SET_CMD, PT6311_DATA_WR | PT6311_ADDR_INC | PT6311_MODE_NORM); // Data set cmd, normal mode, auto incr, write data 00058 } 00059 00060 00061 /** Clear the screen and locate to 0 00062 */ 00063 void PT6311::cls() { 00064 00065 _cs=0; 00066 wait_us(1); 00067 _spi.write(_flip(PT6311_ADDR_SET_CMD | 0x00)); // Address set cmd, 0 00068 00069 for (int cnt=0; cnt<PT6311_DISPLAY_MEM; cnt++) { 00070 _spi.write(0x00); // data 00071 } 00072 00073 wait_us(1); 00074 _cs=1; 00075 00076 } 00077 00078 /** Set Brightness 00079 * 00080 * @param char brightness (3 significant bits, valid range 0..7 (1/16 .. 14/14 dutycycle) 00081 * @return none 00082 */ 00083 void PT6311::setBrightness(char brightness){ 00084 00085 _bright = brightness & PT6311_BRT_MSK; // mask invalid bits 00086 00087 _writeCmd(PT6311_DSP_CTRL_CMD, _display | _bright ); // Display control cmd, display on/off, brightness 00088 00089 } 00090 00091 /** Set the Display mode On/off 00092 * 00093 * @param bool display mode 00094 */ 00095 void PT6311::setDisplay(bool on) { 00096 00097 if (on) { 00098 _display = PT6311_DSP_ON; 00099 } 00100 else { 00101 _display = PT6311_DSP_OFF; 00102 } 00103 00104 _writeCmd(PT6311_DSP_CTRL_CMD, _display | _bright ); // Display control cmd, display on/off, brightness 00105 } 00106 00107 /** Write databyte to PT6311 00108 * @param int address display memory location to write byte 00109 * @param char data byte written at given address 00110 * @return none 00111 */ 00112 void PT6311::writeData(int address, char data) { 00113 _cs=0; 00114 wait_us(1); 00115 _spi.write(_flip(PT6311_ADDR_SET_CMD | (address & PT6311_ADDR_MSK))); // Set Address cmd 00116 00117 _spi.write(_flip(data)); // data 00118 00119 wait_us(1); 00120 _cs=1; 00121 00122 } 00123 00124 /** Write Display datablock to PT6311 00125 * @param DisplayData_t data Array of PT6311_DISPLAY_MEM (=48) bytes for displaydata (starting at address 0) 00126 * @param length number bytes to write (valid range 0..PT6311_DISPLAY_MEM (=48), starting at address 0) 00127 * @return none 00128 */ 00129 void PT6311::writeData(DisplayData_t data, int length) { 00130 _cs=0; 00131 wait_us(1); 00132 _spi.write(_flip(PT6311_ADDR_SET_CMD | 0x00)); // Set Address at 0 00133 00134 // sanity check 00135 if (length < 0) {length = 0;} 00136 if (length > PT6311_DISPLAY_MEM) {length = PT6311_DISPLAY_MEM;} 00137 00138 // for (int idx=0; idx<PT6311_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 PT6311 00149 * @param *keydata Ptr to Array of PT6311_KEY_MEM (=6) bytes for keydata 00150 * @return bool keypress True when at least one key was pressed 00151 * 00152 * Note: Due to the hardware configuration the PT6311 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 PT6311::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(PT6311_DATA_SET_CMD | PT6311_KEY_RD | PT6311_ADDR_INC | PT6311_MODE_NORM)); // Data set cmd, normal mode, auto incr, read data 00166 00167 for (int idx=0; idx < PT6311_KEY_MEM; idx++) { 00168 data = _flip(_spi.write(0xFF)); // read keys and correct bitorder 00169 00170 data = data & PT6311_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(PT6311_DATA_SET_CMD, PT6311_DATA_WR | PT6311_ADDR_INC | PT6311_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 /** Read switches from PT6311 00197 * 00198 * @param none 00199 * @return char for switch data (4 least significant bits) 00200 * 00201 */ 00202 char PT6311::getSwitches() { 00203 char data; 00204 00205 // Read switches 00206 _cs=0; 00207 wait_us(1); 00208 00209 // Enable Switch Read mode 00210 _spi.write(_flip(PT6311_DATA_SET_CMD | PT6311_SW_RD | PT6311_ADDR_INC | PT6311_MODE_NORM)); // Data set cmd, normal mode, auto incr, read data 00211 00212 data = _flip(_spi.write(0xFF)) & PT6311_SW_MSK; // read switches and correct bitorder 00213 00214 wait_us(1); 00215 _cs=1; 00216 00217 // Restore Data Write mode 00218 _writeCmd(PT6311_DATA_SET_CMD, PT6311_DATA_WR | PT6311_ADDR_INC | PT6311_MODE_NORM); // Data set cmd, normal mode, auto incr, write data 00219 00220 return data; 00221 } 00222 00223 00224 /** Set LEDs 00225 * 00226 * @param char leds (5 least significant bits) 00227 * @return none 00228 */ 00229 void PT6311::setLED (char leds) { 00230 00231 // Set LEDs 00232 _cs=0; 00233 wait_us(1); 00234 00235 // Enable LED Write mode 00236 _spi.write(_flip(PT6311_DATA_SET_CMD | PT6311_LED_WR | PT6311_ADDR_INC | PT6311_MODE_NORM)); // Data set cmd, normal mode, auto incr, write data 00237 00238 _spi.write(_flip(leds & PT6311_LED_MSK)); // write LEDs in correct bitorder 00239 00240 wait_us(1); 00241 _cs=1; 00242 00243 // Restore Data Write mode 00244 _writeCmd(PT6311_DATA_SET_CMD, PT6311_DATA_WR | PT6311_ADDR_INC | PT6311_MODE_NORM); // Data set cmd, normal mode, auto incr, write data 00245 } 00246 00247 00248 00249 /** Helper to reverse all command or databits. The PT6311 expects LSB first, whereas SPI is MSB first 00250 * @param char data 00251 * @return bitreversed data 00252 */ 00253 char PT6311::_flip(char data) { 00254 char value=0; 00255 00256 if (data & 0x01) {value |= 0x80;} ; 00257 if (data & 0x02) {value |= 0x40;} ; 00258 if (data & 0x04) {value |= 0x20;} ; 00259 if (data & 0x08) {value |= 0x10;} ; 00260 if (data & 0x10) {value |= 0x08;} ; 00261 if (data & 0x20) {value |= 0x04;} ; 00262 if (data & 0x40) {value |= 0x02;} ; 00263 if (data & 0x80) {value |= 0x01;} ; 00264 return value; 00265 } 00266 00267 00268 /** Write command and parameter to PT6311 00269 * @param int cmd Command byte 00270 * &Param int data Parameters for command 00271 * @return none 00272 */ 00273 void PT6311::_writeCmd(int cmd, int data){ 00274 00275 _cs=0; 00276 wait_us(1); 00277 00278 _spi.write(_flip( (cmd & PT6311_CMD_MSK) | (data & ~PT6311_CMD_MSK))); 00279 00280 wait_us(1); 00281 _cs=1; 00282 00283 }; 00284 00285 00286 00287 00288 #if (VFDEM2_TEST == 1) 00289 /** Constructor for class for driving Princeton PT6311 VFD controller as used in VFDEM2 00290 * 00291 * @brief Supports 12 Grids of 16 Segments and Icons (10 digits of 14 Segments plus some icons and another 2 Icon grids). 00292 * Also supports a scanned keyboard of 7 keys and 1 LED. 00293 * 00294 * @param PinName mosi, miso, sclk, cs SPI bus pins 00295 */ 00296 PT6311_VFDEM2::PT6311_VFDEM2(PinName mosi, PinName miso, PinName sclk, PinName cs) : PT6311(mosi, miso, sclk, cs, Grid12_Seg16) { 00297 _column = 0; 00298 _columns = VFDEM2_NR_DIGITS; 00299 } 00300 00301 #if(0) 00302 #if DOXYGEN_ONLY 00303 /** Write a character to the LCD 00304 * 00305 * @param c The character to write to the display 00306 */ 00307 int putc(int c); 00308 00309 /** Write a formatted string to the LCD 00310 * 00311 * @param format A printf-style format string, followed by the 00312 * variables to use in formatting the string. 00313 */ 00314 int printf(const char* format, ...); 00315 #endif 00316 #endif 00317 00318 /** Locate cursor to a screen column 00319 * 00320 * @param column The horizontal position from the left, indexed from 0 00321 */ 00322 void PT6311_VFDEM2::locate(int column) { 00323 //sanity check 00324 if (column < 0) {column = 0;} 00325 if (column > (_columns - 1)) {column = _columns - 1;} 00326 00327 _column = column; 00328 } 00329 00330 00331 /** Number of screen columns 00332 * 00333 * @param none 00334 * @return columns 00335 */ 00336 int PT6311_VFDEM2::columns() { 00337 return _columns; 00338 } 00339 00340 00341 /** Clear the screen and locate to 0 00342 * @param bool clrAll Clear Icons also (default = false) 00343 */ 00344 void PT6311_VFDEM2::cls(bool clrAll) { 00345 int idx; 00346 00347 if (clrAll) { 00348 //clear local buffer (including Icons) 00349 for (idx=0; idx < (VFDEM2_NR_GRIDS * PT6311_BYTES_PER_GRID); idx++) { 00350 _displaybuffer[idx] = 0x00; 00351 } 00352 } 00353 else { 00354 //clear local buffer (preserving Icons) 00355 for (int grd=0; grd < VFDEM2_NR_GRIDS; grd++) { 00356 idx = grd * PT6311_BYTES_PER_GRID; // 3 bytes for every Grid 00357 _displaybuffer[idx ] = _displaybuffer[idx ] & MASK_ICON_GRID[grd][0]; 00358 _displaybuffer[idx + 1] = _displaybuffer[idx + 1] & MASK_ICON_GRID[grd][1]; 00359 _displaybuffer[idx + 2] = _displaybuffer[idx + 2] & MASK_ICON_GRID[grd][2]; 00360 } 00361 } 00362 00363 writeData(_displaybuffer, (VFDEM2_NR_GRIDS * PT6311_BYTES_PER_GRID)); 00364 00365 _column = 0; 00366 } 00367 00368 /** Set Icon 00369 * 00370 * @param Icon icon Enums Icon has Grid position encoded in 8 MSBs, Icon pattern encoded in 16 LSBs 00371 * @return none 00372 */ 00373 void PT6311_VFDEM2::setIcon(Icon icon) { 00374 int addr, icn; 00375 00376 icn = icon & 0xFFFF; 00377 addr = (icon >> 24) & 0xFF; 00378 addr = (addr - 1) * PT6311_BYTES_PER_GRID; // 3 Bytes for every Grid 00379 00380 //Save char...and set bits for icon to write 00381 _displaybuffer[addr ] = _displaybuffer[addr ] | LO(icn); 00382 _displaybuffer[addr + 1] = _displaybuffer[addr + 1] | MD(icn); 00383 _displaybuffer[addr + 2] = _displaybuffer[addr + 2] | HI(icn); 00384 writeData(_displaybuffer, (VFDEM2_NR_GRIDS * PT6311_BYTES_PER_GRID)); 00385 } 00386 00387 /** Clr Icon 00388 * 00389 * @param Icon icon Enums Icon has Grid position encoded in 8 MSBs, Icon pattern encoded in 16 LSBs 00390 * @return none 00391 */ 00392 void PT6311_VFDEM2::clrIcon(Icon icon) { 00393 int addr, icn; 00394 00395 icn = icon & 0xFFFF; 00396 addr = (icon >> 24) & 0xFF; 00397 addr = (addr -1 ) * PT6311_BYTES_PER_GRID; // 3 Bytes for every Grid 00398 00399 //Save char...and clr bits for icon to write 00400 _displaybuffer[addr ] = _displaybuffer[addr ] & ~LO(icn); 00401 _displaybuffer[addr + 1] = _displaybuffer[addr + 1] & ~MD(icn); 00402 _displaybuffer[addr + 2] = _displaybuffer[addr + 2] & ~HI(icn); 00403 writeData(_displaybuffer, (VFDEM2_NR_GRIDS * PT6311_BYTES_PER_GRID)); 00404 } 00405 00406 00407 /** Set User Defined Characters (UDC) 00408 * 00409 * @param unsigned char udc_idx The Index of the UDC (0..7) 00410 * @param int udc_data The bitpattern for the UDC (16 bits) 00411 */ 00412 void PT6311_VFDEM2::setUDC(unsigned char udc_idx, int udc_data) { 00413 00414 //Sanity check 00415 if (udc_idx > (VFDEM2_NR_UDC-1)) { 00416 return; 00417 } 00418 00419 // Mask out Icon bits? 00420 _UDC_16S[udc_idx] = udc_data & 0xFFFF; 00421 } 00422 00423 /** Write a single character (Stream implementation) 00424 */ 00425 int PT6311_VFDEM2::_putc(int value) { 00426 bool validChar = false; 00427 short pattern = 0x0000; 00428 int addr; 00429 00430 if ((value == '\n') || (value == '\r')) { 00431 //No character to write 00432 validChar = false; 00433 00434 //Update Cursor 00435 _column = 0; 00436 } 00437 else if ((value >= 0) && (value < VFDEM2_NR_UDC)) { 00438 //Character to write 00439 validChar = true; 00440 pattern = _UDC_16S[value]; 00441 } 00442 #if (SHOW_ASCII == 1) 00443 //display all ASCII characters 00444 else if ((value >= FONT_16S_START) && (value <= FONT_16S_END)) { 00445 //Character to write 00446 validChar = true; 00447 pattern = FONT_16S[value - FONT_16S_START]; 00448 } // else 00449 #else 00450 //display only digits and hex characters 00451 else if (value == '-') { 00452 //Character to write 00453 validChar = true; 00454 pattern = C16_MIN; 00455 } 00456 else if ((value >= (int)'0') && (value <= (int) '9')) { 00457 //Character to write 00458 validChar = true; 00459 pattern = FONT_16S[value - (int) '0']; 00460 } 00461 else if ((value >= (int) 'A') && (value <= (int) 'F')) { 00462 //Character to write 00463 validChar = true; 00464 pattern = FONT_16S[10 + value - (int) 'A']; 00465 } 00466 else if ((value >= (int) 'a') && (value <= (int) 'f')) { 00467 //Character to write 00468 validChar = true; 00469 pattern = FONT_16S[10 + value - (int) 'a']; 00470 } //else 00471 #endif 00472 if (validChar) { 00473 //Character to write 00474 00475 //Translate between _column and displaybuffer entries 00476 //Note that the VFDEM2 has ten 14 Segment digits/grids. 00477 //Some of these Grids also have icons that need to be preserved 00478 //_column == 0 => Grid11 => addr = 30 00479 //_column == 1 => Grid10 => addr = 27 00480 // .... 00481 //_column == 9 => Grid2 => addr = 3 00482 addr = (10 - _column) * PT6311_BYTES_PER_GRID; // 3 Bytes for every Grid; 00483 00484 //Save icons...and set bits for character to write 00485 _displaybuffer[addr] = (_displaybuffer[addr] & MASK_ICON_GRID[10 - _column][0]) | LO(pattern); 00486 _displaybuffer[addr+1] = (_displaybuffer[addr+1] & MASK_ICON_GRID[10 - _column][1]) | MD(pattern); 00487 // _displaybuffer[addr+2] = (_displaybuffer[addr+2] & MASK_ICON_GRID[10 - _column][2]) | HI(pattern); 00488 00489 writeData(_displaybuffer, (VFDEM2_NR_GRIDS * PT6311_BYTES_PER_GRID)); 00490 00491 //Update Cursor 00492 _column++; 00493 if (_column > (VFDEM2_NR_DIGITS - 1)) { 00494 _column = 0; 00495 } 00496 00497 } // if validChar 00498 00499 return value; 00500 } 00501 00502 // get a single character (Stream implementation) 00503 int PT6311_VFDEM2::_getc() { 00504 return -1; 00505 } 00506 #endif
Generated on Tue Jul 12 2022 17:14:40 by
1.7.2
PT6311 VFD driver (192 segm max), Keyboard scan (48 keys max)