Library for Princeton PT6301 VFD controller. Used in Futaba CIG VFD tubes.

This is a library for the Princeton PT6301 VFD controller. The controller is used by Futaba 'Chip In Glass' (CIG) VFD tubes. The device supports upto 20 Grids of 5x7 matrix segments for 2 rows of characters (A and B). It also supports 1 additional segment for 2 rows (A and B). In addition to the internal ROM character set, the PT6301 also supports 16 User Defined Characters.

The PT6301 has an SPI Serial interface. Control data consists of an 8-bit command and one or more data bytes. Command and data are sent LSB first and latched on rising edge of CLK. Idle CLK is high. Data address is auto incremented. Same for Icon and UDC addresses. The commands and data are transmitted during CE low and latched on rising CE edge.

The PT6301 has internal memory for all characters and icons. The content is automatically displayed on the tube. The memory consists of two banks (row A and row B) for character memory and two banks (row A and row B) for icon memory. Each of those banks is accessed by separate commands. However, these command do not support addressing individual locations in the memory. Memory updates always start at address 0 in the selected row A or B. Consequently, the whole displaymemory needs to be rewritten when any location (except for 0) is to be updated. The library therefor uses a local mirror memory to store the display content, update one or more characters in the mirror-memory as needed, and rewrite the whole display memory from the mirror-content. The write-back is performed by calling the 'refresh' method. Additional advantage of the mirror-memory is that we can also implement wrap-around and scrolling from row A to B for multi-line displays.

The lib was tested on displays salvaged from two Samsung cable TV receivers (e.g. Samsung SMT-C7140 and Samsung SMT-G7400). The examples don't use all features as this depends on how the controller has been applied inside the tube. The SMT-C7140 for example does not use the icon segments, but uses a separate grid to display a User Defined Character. The segments in the UDC light up specific icons (eg mail, clock). See picture below.

https://os.mbed.com/media/uploads/wim/img_4409.jpg

The example code is

Import programmbed_PT6301

Test for PT6301 VFD. First release.

I stumbled on the SMT-C7140 display and found some useful reverse engineering info by Codebeat here that helped to identify the controller. The pinout for the VFD tube connector (starting from the left side in the picture above) is: GND1, GND2, +35V DC (switched), 5V DC supply (switched), OSC pin (RC network between 5V and GND), /RST, /CS, CLK, DAT, NC, NC

The 35V DC is generated on the PCB by a DC/DC converter. The 35V generator, the 5V supply and the filament supply are all enabled by a pin on the connector at the bottom of the PCB.

The SMT-G7400 had a similar schematic for the tube connection as the SMT-C7140, but used a dedicated processor on the display PCB. The processor was removed and replaced by flying wires to an mbed LPC1768 for testing with the lib.

General explanation of VFD is here

Revision:
1:aa0195b0f83c
Parent:
0:ecc29c13a997
--- a/PT6302.cpp	Sun Dec 03 18:02:15 2017 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,406 +0,0 @@
-/* mbed PT6302 Library, for Princeton LC7571X VFD controller
- * Note the PT6302 is identical to the OKI ML9208 
- *
- * Copyright (c) 2017, v01: WH, Initial version
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "mbed.h" 
-#include "PT6302.h"
-#include "PT6302_UDC.inc"
-
-
- /** Constructor for class for driving Princeton PT6302 VFD controller
-  *
-  *  @brief Supports upto 16 Grids of 35 matrix segments.
-  *         Also supports 2 additional segments and 2 port pins.
-  *         SPI bus interface device. 
-  *  @param  PinName mosi, sclk, cs SPI bus pins
-  *  @param  Mode selects number of Grids and Segments (default 16 Grids, 2 additional segments)
-  */
-PT6302::PT6302(PinName mosi, PinName sclk, PinName cs, Mode mode) : _spi(mosi,NC,sclk), _cs(cs), _mode(mode) {
-
-  _init();
-}
-
-/** Init the PT6302 interface and the controller
-  *
-  * @param  none
-  * @return none
-  */ 
-void PT6302::_init(){
-  
-//init SPI
-  _cs=1;
-  _spi.format(8,3); //PT6302 uses mode 3 (Clock High on Idle, Data latched on second (=rising) edge)
-  _spi.frequency(100000);   
-//  _spi.frequency(250000);     
-
-//init controller  
-  //setPort(0x0);  // Port Off (default at Reset)
-
-  // Set number of Grids
-  _writeCmd((PT6302_GRID_REG | _mode));      // Command register & value
-
-  setBrightness(PT6302_BRT_DEF); // Default Brightness
-
-  // Clear the DCRAM and ADRAM (undefined at Reset)
-  cls(); 
-
-  // Clear the UDC RAM (undefined at Reset)
-  const char udc_none[] = {0x00,0x00,0x00,0x00,0x00}; 
-  for (int idx=0; idx < PT6302_NR_UDC; idx++) {
-    setUDC(idx, (char *)udc_none);
-  }
-       
-  setDisplay(true);  // Display On
-}   
-
-
-/** Clear the screen
-  *
-  * @param none
-  * @return none  
-  */  
-void PT6302::cls() {
-
-  for (int cnt=0; cnt<PT6302_DSP_MEM; cnt++) {
-    writeData(char (' '), cnt); // data 
-//    writeData(0x00, cnt);       // data     
-  }
-
-  for (int cnt=0; cnt<PT6302_ADD_MEM; cnt++) {
-    writeAData(0x00, cnt);      // adata 
-  }  
-}  
-
-
-/** Set Brightness
-  *
-  * @param  char brightness (3 significant bits, valid range 0..7)  
-  * @return none
-  */
-void PT6302::setBrightness(char brightness){
-  
-//Sanity check
-  brightness = brightness & PT6302_BRT_MSK; // mask invalid bits
- 
-  _writeCmd((PT6302_BRT_REG | brightness));  // Command register & value
-}
-
-/** Set the Display mode On/off
-  *
-  * @param bool display mode
-  * @return none  
-  */
-void PT6302::setDisplay(bool on) {
-  char display;
-     
-  if (on) {
-    display = PT6302_DSPL_NRM; // normal mode, show Display RAM content
-  }
-  else {
-    display = PT6302_DSPL_OFF; // all segments off
-  }
-
-  _writeCmd((PT6302_DSPL_REG | display));   // Command register & value
-}
-
-/** Set Port
-  *
-  * @param  char port (2 least significant bits)  
-  * @return none
-  */
-void PT6302::setPort (char port){
-
-//Sanity check
-  _port = port & PT6302_PDAT_MSK;          // Mask invalid bits
- 
-  _writeCmd((PT6302_PDAT_REG | _port));    // Command register & value
-  _writeCmd((PT6302_PDAT_REG | _port));    // Command register & value (Dummy cmd to show on Latched LEDs)
-}
-
-
-/** Set User Defined Characters (UDC)
-  *
-  * @param unsigned char udc_idx   The Index of the UDC (0..7)
-  * @param UDCData_t udc_data      The bitpattern for the UDC (5 bytes)
-  * @return none  
-  */
-void PT6302::setUDC(unsigned char udc_idx, UDCData_t udc_data) {
-  
-//Sanity check
-  udc_idx = udc_idx & PT6302_UADR_MSK; // mask invalid bits
-
-  _cs=0; // Send Command & Params 
-  wait_us(1);  
-  _spi.write(_flip(PT6302_UDC_REG | udc_idx));     // Command register & address
-  wait_us(PT6302_CMD_DLY);         // Command Delay
-    
-  _spi.write(_flip(udc_data[0] & PT6302_UDC_MSK)); // CD30 CD25 ......  CD0
-  _spi.write(_flip(udc_data[1] & PT6302_UDC_MSK)); // CD31 CD26 ......  CD1
-  _spi.write(_flip(udc_data[2] & PT6302_UDC_MSK)); // CD32 CD27 ......  CD2
-  _spi.write(_flip(udc_data[3] & PT6302_UDC_MSK)); // CD33 CD28 ......  CD3
-  _spi.write(_flip(udc_data[4] & PT6302_UDC_MSK)); // CD34 CD29 ......  CD4
-
-  wait_us(PT6302_CS_DLY);          // CS Hold Delay  
-  _cs=1; // Latch Command & Params
-
-  wait_us(PT6302_CMD_DLY);         // Command Delay   
-}
-
-
-/** Write Data to PT6302
-  *
-  *  @param char data Character code
-  *  @param char address Parameter for data
-  *  @return none
-  */  
-void PT6302::writeData(char data, char address){
-
-//Sanity check
-  address = address & PT6302_DADR_MSK; // mask invalid bits
-
-  _writeCmd((PT6302_DATA_REG | address), // Command register & address
-             data);                      // Character code
-}  
-
-/** Write Additional Data to PT6302
-  *
-  *  @param char adata Additional code (annunciator)
-  *  @param char address Parameter for data
-  *  @return none
-  */  
-void PT6302::writeAData(char adata, char address){
-
-//Sanity check
-  address = address & PT6302_AADR_MSK; // mask invalid bits
- 
-  _writeCmd((PT6302_ADAT_REG | address), // Command register & ADRAM address
-             adata);                     // ADATA
-}  
-
-/** Write command and data to PT6302
-  *
-  *  @param char cmd Command byte
-  *  @param char data Parameter for command  
-  *  @return none
-  */  
-void PT6302::_writeCmd(char cmd, char data){
-
-  _cs=0; // Prepare to send Command and data
-  wait_us(1);    
-
-  _spi.write(_flip(cmd));          // Command register & value
-
-  wait_us(PT6302_CMD_DLY);         // Command Delay
-  
-  _spi.write(_flip(data));         // data
-
-  wait_us(PT6302_CS_DLY);          // CS Hold Delay
-  _cs=1; // Latch Command and data 
-
-  wait_us(PT6302_CMD_DLY);         // Command Delay
-}  
-
-/** Write command to PT6302
-  *
-  *  @param char cmd Command byte
-  *  @return none
-  */  
-void PT6302::_writeCmd(char cmd){
-
-  _cs=0; // Prepare to send Command
-  wait_us(1);
-
-  _spi.write(_flip(cmd));          // Command register & value
-
-  wait_us(PT6302_CS_DLY);          // CS Hold Delay  
-  _cs=1; // Latch Command
-
-  wait_us(PT6302_CMD_DLY);         // Command Delay
-}  
-
-
-
-/** Helper to reverse all command or databits. The PT6302 expects LSB first, whereas SPI is MSB first
-  *
-  *  @param  char data
-  *  @return bitreversed data
-  */ 
-char PT6302::_flip(char data) {
- char value=0;
-  
- if (data & 0x01) {value |= 0x80;} ;  
- if (data & 0x02) {value |= 0x40;} ;
- if (data & 0x04) {value |= 0x20;} ;
- if (data & 0x08) {value |= 0x10;} ;
- if (data & 0x10) {value |= 0x08;} ;
- if (data & 0x20) {value |= 0x04;} ;
- if (data & 0x40) {value |= 0x02;} ;
- if (data & 0x80) {value |= 0x01;} ;
- return value;       
-}
-
-
-#if (HANNSTAR_TEST == 1) 
-
-/** Constructor for class for Princeton PT6302 VFD controller as used in HANNSTAR
-  *
-  *  @brief Supports 16 Grids of 35 Segments without additional Segments.
-  *  
-  *  @param  PinName mosi, miso, sclk, cs SPI bus pins
-  */
-PT6302_HANNSTAR::PT6302_HANNSTAR(PinName mosi, PinName sclk, PinName cs) : PT6302(mosi, sclk, cs, Grid16_Add2) {
-  _column   = 0;
-  _columns  = HANNSTAR_NR_DIGITS;
-  
-  //Enable VGen for VFD Power Supply
-  setVGen(true);   
-}
-
-/** Locate cursor to a screen column
-  *
-  * @param column  The horizontal position from the left, indexed from 0
-  * @return none  
-  */
-void PT6302_HANNSTAR::locate(int column) {
-  //sanity check
-  if (column < 0) {column = 0;}
-  if (column > (_columns - 1)) {column = _columns - 1;}  
-  
-  _column = column;       
-}
-
-
-/** Number of screen columns
-  *
-  * @param none
-  * @return columns
-  */
-int PT6302_HANNSTAR::columns() {
-    return _columns;
-}
-
-
-/** Clear the screen and locate to 0
-  *
-  * @param bool clrAll Clear Icons also (default = false)
-  * @return none  
-  */ 
-void PT6302_HANNSTAR::cls(bool clrAll) {  
-
-  for (int cnt=0; cnt<HANNSTAR_NR_DIGITS; cnt++) {
-    writeData(char (' '), cnt); // data 
-  }
-
-  if (clrAll) {
-    //Clear Icons    
-    for (int cnt=0; cnt<HANNSTAR_NR_DIGITS; cnt++) {
-      writeAData(0x00, cnt);      // adata 
-    }   
-  }  
-
-  _column = 0;   
-}    
-
-
-/** Set Port
-  *
-  * @param  char port (Only Bit 1 is used)  
-  * @return none
-  */
-void PT6302_HANNSTAR::setPort (char port){
-
-//Sanity check
-  _port &= ~PT6302_HANN_PDAT_MSK;         // Clear valid bits
-  _port |= (port & PT6302_HANN_PDAT_MSK); // Mask invalid bits
- 
-  _writeCmd((PT6302_PDAT_REG | _port));   // Command register & value
-  _writeCmd((PT6302_PDAT_REG | _port));   // Command register & value (Dummy cmd to show on Latched LEDs)  
-}
-
-
-/** Set VFD VGen
-  *
-  * @param  bool on
-  * @return none
-  */
-void PT6302_HANNSTAR::setVGen(bool on){     
-
-  if (on) {
-    _port = _port | PT6302_HANN_VGEN;  // VGen On
-  }
-  else {
-    _port = _port & ~PT6302_HANN_VGEN; // VGen Off
-  }
-
-  _writeCmd((PT6302_PDAT_REG | _port));   // Command register & value
-  _writeCmd((PT6302_PDAT_REG | _port));   // Command register & value (Dummy cmd to show on Latched LEDs)  
-}
-
-
-/** Write a single character (Stream implementation)
-  * 
-  * @param value char to print
-  * @return value;
-  */
-int PT6302_HANNSTAR::_putc(int value) {
-    int addr;
-    
-    if ((value == '\n') || (value == '\r')) {
-      //No character to write
-     
-      //Update Cursor      
-      _column = 0;
-    }
-    else if ((value >= 0) && (value < 256)) {
-      //Character to write
-
-      //Translate between _column and displaybuffer entries
-      //Note that the HANNSTAR has 1 digit/grid. 
-      //_column ==  0 => Grid15  => addr = 15
-      //_column ==  1 => Grid14  => addr = 14
-      // ....
-      //_column == 15 => Grid1   => addr = 0            
-      addr = (15 - _column); // 1 Byte for every Grid;
-      
-      writeData(value, addr);
-                                
-      //Update Cursor
-      _column++;
-      if (_column > (HANNSTAR_NR_DIGITS - 1)) {        
-        _column = 0;
-      }
-
-    } // if validChar           
-
-    return value;
-}
-
-/** Get a single character (Stream implementation)
-  *
-  * @param none  
-  * @return -1
-  */
-int PT6302_HANNSTAR::_getc() {
-    return -1;
-}
-#endif