Wim Huiskamp / PT6315

Dependents:   mbed_PT6315

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers PT6315.cpp Source File

PT6315.cpp

00001 /* mbed PT6315 Library, for Princeton PT6315 VFD controller
00002  * Copyright (c) 2016, v01: WH, Initial version, for DVDR3510 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 "PT6315.h"
00024 
00025 /** Constructor for class for driving Princeton PT6315 VFD controller
00026  *
00027  *  @brief Supports 4 Grids of 24 Segments upto 12 Grids of 16 Segments. Also supports a scanned keyboard of upto 32 keys and 4 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 PT6315::PT6315(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 PT6315::_init(){
00043   
00044 //init SPI
00045   _cs=1;
00046   _spi.format(8,3); //PT6315 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(PT6315_MODE_SET_CMD, _mode);                                               // Mode set command
00052 
00053   _display = PT6315_DSP_ON;
00054   _bright  = PT6315_BRT_DEF; 
00055   _writeCmd(PT6315_DSP_CTRL_CMD, _display | _bright );                                 // Display control cmd, display on/off, brightness   
00056   
00057   _writeCmd(PT6315_DATA_SET_CMD, PT6315_DATA_WR | PT6315_ADDR_INC | PT6315_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 PT6315::cls() {
00064   
00065   _cs=0;
00066   wait_us(1);    
00067   _spi.write(_flip(PT6315_ADDR_SET_CMD | 0x00)); // Address set cmd, 0
00068       
00069   for (int cnt=0; cnt<PT6315_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 PT6315::setBrightness(char brightness){
00084 
00085   _bright = brightness & PT6315_BRT_MSK; // mask invalid bits
00086   
00087   _writeCmd(PT6315_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 PT6315::setDisplay(bool on) {
00096   
00097   if (on) {
00098     _display = PT6315_DSP_ON;
00099   }
00100   else {
00101    _display = PT6315_DSP_OFF;
00102   }
00103   
00104   _writeCmd(PT6315_DSP_CTRL_CMD, _display | _bright );  // Display control cmd, display on/off, brightness   
00105 }
00106 
00107 /** Write databyte to PT6315
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 PT6315::writeData(int address, char data) {
00113   _cs=0;
00114   wait_us(1);    
00115   _spi.write(_flip(PT6315_ADDR_SET_CMD | (address & PT6315_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 PT6315
00125   *  @param  DisplayData_t data Array of PT6315_DISPLAY_MEM (=48) bytes for displaydata (starting at address 0)
00126   *  @param  length number bytes to write (valid range 0..PT6315_DISPLAY_MEM (=48), starting at address 0)   
00127   *  @return none
00128   */    
00129 void PT6315::writeData(DisplayData_t data, int length) {
00130   _cs=0;
00131   wait_us(1);    
00132   _spi.write(_flip(PT6315_ADDR_SET_CMD | 0x00)); // Set Address at 0
00133       
00134 // sanity check
00135   if (length < 0) {length = 0;}
00136   if (length > PT6315_DISPLAY_MEM) {length = PT6315_DISPLAY_MEM;}
00137 
00138 //  for (int idx=0; idx<PT6315_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 PT6315
00149   *  @param  *keydata Ptr to Array of PT6315_KEY_MEM (=4) bytes for keydata
00150   *  @return bool keypress True when at least one key was pressed
00151   *
00152   * Note: Due to the hardware configuration the PT6315 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 PT6315::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(PT6315_DATA_SET_CMD | PT6315_KEY_RD | PT6315_ADDR_INC | PT6315_MODE_NORM)); // Data set cmd, normal mode, auto incr, read data
00166 
00167   for (int idx=0; idx < PT6315_KEY_MEM; idx++) {
00168     data = _flip(_spi.write(0xFF));    // read keys and correct bitorder
00169     
00170     data = data & PT6315_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(PT6315_DATA_SET_CMD, PT6315_DATA_WR | PT6315_ADDR_INC | PT6315_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 /** Set LEDs
00196   *
00197   * @param  char leds (4 least significant bits)  
00198   * @return none
00199   */
00200 void  PT6315::setLED (char leds) {
00201 
00202   // Set LEDs
00203   _cs=0;
00204   wait_us(1);    
00205   
00206   // Enable LED Write mode
00207   _spi.write(_flip(PT6315_DATA_SET_CMD | PT6315_LED_WR | PT6315_ADDR_INC | PT6315_MODE_NORM)); // Data set cmd, normal mode, auto incr, write data
00208 
00209   _spi.write(_flip(leds & PT6315_LED_MSK));    // write LEDs in correct bitorder
00210 
00211   wait_us(1);
00212   _cs=1;    
00213 
00214   // Restore Data Write mode
00215   _writeCmd(PT6315_DATA_SET_CMD, PT6315_DATA_WR | PT6315_ADDR_INC | PT6315_MODE_NORM); // Data set cmd, normal mode, auto incr, write data  
00216 }
00217 
00218 
00219 
00220 /** Helper to reverse all command or databits. The PT6315 expects LSB first, whereas SPI is MSB first
00221   *  @param  char data
00222   *  @return bitreversed data
00223   */ 
00224 char PT6315::_flip(char data) {
00225  char value=0;
00226   
00227  if (data & 0x01) {value |= 0x80;} ;  
00228  if (data & 0x02) {value |= 0x40;} ;
00229  if (data & 0x04) {value |= 0x20;} ;
00230  if (data & 0x08) {value |= 0x10;} ;
00231  if (data & 0x10) {value |= 0x08;} ;
00232  if (data & 0x20) {value |= 0x04;} ;
00233  if (data & 0x40) {value |= 0x02;} ;
00234  if (data & 0x80) {value |= 0x01;} ;
00235  return value;       
00236 }
00237 
00238 
00239 /** Write command and parameter to PT6315
00240   *  @param  int cmd Command byte
00241   *  &Param  int data Parameters for command
00242   *  @return none
00243   */  
00244 void PT6315::_writeCmd(int cmd, int data){
00245     
00246   _cs=0;
00247   wait_us(1);    
00248  
00249   _spi.write(_flip( (cmd & PT6315_CMD_MSK) | (data & ~PT6315_CMD_MSK)));   
00250  
00251   wait_us(1);
00252   _cs=1;      
00253     
00254 };  
00255 
00256 
00257 
00258 #if (DVDR3510_TEST == 1)
00259 /** Constructor for class for driving Princeton PT6315 VFD controller as used in DVDR3510
00260   *
00261   *  @brief Supports 11 Grids of 17 Segments and Icons (8 digits of 14 Segments plus some icons).  
00262   *         Also supports a scanned keyboard of 11 keys and 1 LED.
00263   *  
00264   *  @param  PinName mosi, miso, sclk, cs SPI bus pins
00265   */  
00266 PT6315_DVDR3510::PT6315_DVDR3510(PinName mosi, PinName miso, PinName sclk, PinName cs) : PT6315(mosi, miso, sclk, cs, Grid11_Seg17) {
00267   _column  = 0;
00268   _columns = DVDR3510_NR_DIGITS;    
00269 }  
00270 
00271 #if(0)
00272 #if DOXYGEN_ONLY
00273     /** Write a character to the LCD
00274      *
00275      * @param c The character to write to the display
00276      */
00277     int putc(int c);
00278 
00279     /** Write a formatted string to the LCD
00280      *
00281      * @param format A printf-style format string, followed by the
00282      *               variables to use in formatting the string.
00283      */
00284     int printf(const char* format, ...);   
00285 #endif
00286 #endif
00287 
00288 /** Locate cursor to a screen column
00289   *
00290   * @param column  The horizontal position from the left, indexed from 0
00291   */
00292 void PT6315_DVDR3510::locate(int column) {
00293   //sanity check
00294   if (column < 0) {column = 0;}
00295   if (column > (_columns - 1)) {column = _columns - 1;}  
00296   
00297   _column = column;       
00298 }
00299 
00300 
00301 /** Number of screen columns
00302   *
00303   * @param none
00304   * @return columns
00305   */
00306 int PT6315_DVDR3510::columns() {
00307     return _columns;
00308 }
00309 
00310     
00311 /** Clear the screen and locate to 0
00312   * @param bool clrAll Clear Icons also (default = false)
00313   */ 
00314 void PT6315_DVDR3510::cls(bool clrAll) {  
00315   int idx;
00316   
00317   if (clrAll) {
00318     //clear local buffer (including Icons)
00319     for (idx=0; idx < (DVDR3510_NR_GRIDS * PT6315_BYTES_PER_GRID); idx++) {
00320       _displaybuffer[idx] = 0x00;  
00321     }
00322   }  
00323   else {
00324     //clear local buffer (preserving Icons)
00325     for (int grd=0; grd < DVDR3510_NR_GRIDS; grd++) {
00326       idx = grd * PT6315_BYTES_PER_GRID; // 3 bytes for every Grid
00327       _displaybuffer[idx    ] = _displaybuffer[idx    ] & MASK_ICON_GRID[grd][0];  
00328       _displaybuffer[idx + 1] = _displaybuffer[idx + 1] & MASK_ICON_GRID[grd][1];
00329       _displaybuffer[idx + 2] = _displaybuffer[idx + 2] & MASK_ICON_GRID[grd][2];      
00330     }  
00331   }
00332 
00333   writeData(_displaybuffer, (DVDR3510_NR_GRIDS * PT6315_BYTES_PER_GRID));
00334 
00335   _column = 0;   
00336 }    
00337 
00338 /** Set Icon
00339   *
00340   * @param Icon icon Enums Icon has Grid position encoded in 8 MSBs, Icon pattern encoded in 24 LSBs
00341   * @return none
00342   */
00343 void PT6315_DVDR3510::setIcon(Icon icon) {
00344   int addr, icn;
00345 
00346    icn =        icon  & 0xFFFFFF;
00347   addr = (icon >> 24) & 0xFF; 
00348   addr = (addr - 1) * PT6315_BYTES_PER_GRID;  // 3 Bytes for every Grid
00349     
00350   //Save char...and set bits for icon to write
00351   _displaybuffer[addr    ] = _displaybuffer[addr    ] | LO(icn);      
00352   _displaybuffer[addr + 1] = _displaybuffer[addr + 1] | MD(icn);      
00353   _displaybuffer[addr + 2] = _displaybuffer[addr + 2] | HI(icn);        
00354   writeData(_displaybuffer, (DVDR3510_NR_GRIDS * PT6315_BYTES_PER_GRID));
00355 }
00356 
00357 /** Clr Icon
00358   *
00359   * @param Icon icon Enums Icon has Grid position encoded in 8 MSBs, Icon pattern encoded in 24 LSBs
00360   * @return none
00361   */
00362 void PT6315_DVDR3510::clrIcon(Icon icon) {
00363   int addr, icn;
00364 
00365    icn =        icon  & 0xFFFFFF;
00366   addr = (icon >> 24) & 0xFF; 
00367   addr = (addr - 1) * PT6315_BYTES_PER_GRID;   // 3 Bytes for every Grid
00368     
00369   //Save char...and clr bits for icon to write
00370   _displaybuffer[addr    ] = _displaybuffer[addr    ] & ~LO(icn);      
00371   _displaybuffer[addr + 1] = _displaybuffer[addr + 1] & ~MD(icn);      
00372   _displaybuffer[addr + 2] = _displaybuffer[addr + 2] & ~HI(icn);        
00373   writeData(_displaybuffer, (DVDR3510_NR_GRIDS * PT6315_BYTES_PER_GRID));
00374 }
00375 
00376 
00377 /** Set User Defined Characters (UDC)
00378   *
00379   * @param unsigned char udc_idx  The Index of the UDC (0..7)
00380   * @param int udc_data           The bitpattern for the UDC (16 bits)       
00381   */
00382 void PT6315_DVDR3510::setUDC(unsigned char udc_idx, int udc_data) {
00383 
00384   //Sanity check
00385   if (udc_idx > (DVDR3510_NR_UDC-1)) {
00386     return;
00387   }
00388 
00389   // Mask out Icon bits?
00390   _UDC_16S[udc_idx] = udc_data & 0xFFFF;
00391 }
00392 
00393 /** Write a single character (Stream implementation)
00394   */
00395 int PT6315_DVDR3510::_putc(int value) {
00396     bool validChar = false;
00397     short pattern  = 0x0000;
00398     int addr;
00399     
00400     if ((value == '\n') || (value == '\r')) {
00401       //No character to write
00402       validChar = false;
00403       
00404       //Update Cursor      
00405       _column = 0;
00406     }
00407     else if ((value >= 0) && (value < DVDR3510_NR_UDC)) {
00408       //Character to write
00409       validChar = true;
00410       pattern = _UDC_16S[value];
00411     }  
00412 #if (SHOW_ASCII == 1)
00413     //display all ASCII characters
00414     else if ((value >= FONT_16S_START) && (value <= FONT_16S_END)) {   
00415       //Character to write
00416       validChar = true;
00417       pattern = FONT_16S[value - FONT_16S_START];
00418     } // else
00419 #else
00420     //display only digits and hex characters
00421     else if (value == '-') {
00422       //Character to write
00423       validChar = true;
00424       pattern = C16_MIN;         
00425     }
00426     else if ((value >= (int)'0') && (value <= (int) '9')) {   
00427       //Character to write
00428       validChar = true;
00429       pattern = FONT_16S[value - (int) '0'];
00430     }
00431     else if ((value >= (int) 'A') && (value <= (int) 'F')) {   
00432       //Character to write
00433       validChar = true;
00434       pattern = FONT_16S[10 + value - (int) 'A'];
00435     }
00436     else if ((value >= (int) 'a') && (value <= (int) 'f')) {   
00437       //Character to write
00438       validChar = true;
00439       pattern = FONT_16S[10 + value - (int) 'a'];
00440     } //else
00441 #endif
00442     if (validChar) {
00443       //Character to write
00444  
00445       //Translate between _column and displaybuffer entries
00446       //Note that the DVDR3510 has eight 14 Segment digits/grids. 
00447       //Some of these Grids also have icons that need to be preserved
00448       //_column ==  0 => Grid1 => addr = 0
00449       //_column ==  1 => Grid2 => addr = 3
00450       // ....
00451       //_column ==  7 => Grid8 => addr = 21            
00452       addr = (_column * PT6315_BYTES_PER_GRID); // 3 Bytes for every Grid;
00453       
00454       //Save icons...and set bits for character to write
00455       _displaybuffer[addr]   = (_displaybuffer[addr]   & MASK_ICON_GRID[_column][0]) | LO(pattern);
00456       _displaybuffer[addr+1] = (_displaybuffer[addr+1] & MASK_ICON_GRID[_column][1]) | MD(pattern);
00457       _displaybuffer[addr+2] = (_displaybuffer[addr+2] & MASK_ICON_GRID[_column][2]) | HI(pattern);
00458 
00459       writeData(_displaybuffer, (DVDR3510_NR_GRIDS * PT6315_BYTES_PER_GRID));
00460                                 
00461       //Update Cursor
00462       _column++;
00463       if (_column > (DVDR3510_NR_DIGITS - 1)) {
00464         _column = 0;
00465       }
00466 
00467     } // if validChar           
00468 
00469     return value;
00470 }
00471 
00472 // get a single character (Stream implementation)
00473 int PT6315_DVDR3510::_getc() {
00474     return -1;
00475 }
00476 #endif