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

PT6301.cpp

Committer:
wim
Date:
2021-06-13
Revision:
1:aa0195b0f83c
Parent:
PT6302.cpp@ 0:ecc29c13a997

File content as of revision 1:aa0195b0f83c:

/* mbed PT6301 Library, for Princeton LC7571X VFD controller
 *             The controller is used by Futaba 'Chip In Glass' (CIG) VFD tubes. 
 *
 * Copyright (c) 2021, 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 "PT6301.h"
#include "PT6301_UDC.inc"


 /** Constructor for class for driving Princeton PT6301 VFD controller
  *
  *  @brief Supports upto 20 Grids of 5x7 matrix segments for 2 rows of characters (row A and B).
  *         also supports               2 additional segments for 2 rows of characters (row A and B).
  *         SPI bus interface device. 
  *  @param  PinName mosi, sclk, cs SPI bus pins
  *  @param  Mode selects number of Grids and Rows (default 20 Grids, 2 rows)
  *  @param  bool inverted_rows selects mapping of Data onto Display layout (default false)
  *  @param  Columns selects number of characters per row (default 20, same as Mode Grids)
  *  @param  Rows selects number of rows (default 2, same as Mode Rows)  
  */
PT6301::PT6301(PinName mosi, PinName sclk, PinName cs, PinName rst, Mode mode, bool inverted_rows, int columns, int rows) : _spi(mosi,NC,sclk), _cs(cs), _rst(rst), _mode(mode), _inverted_rows(inverted_rows), _columns(columns), _rows(rows) {
 
  _init();
}


/** Init the PT6301 interface and the controller
  *
  * @param  none
  * @return none
  */ 
void PT6301::_init(){
  
//init SPI
  _cs=1;
  _spi.format(8,3); //PT6301 uses mode 3 (Clock High on Idle, Data latched on second (=rising) edge)
  _spi.frequency(100000);   
//  _spi.frequency(250000);     

//init controller  
#if(0)
  // Reset (3V3 level too low? Add pull-up to 5V)
  _rst=1;
  wait_ms(PT6301_RST_DLY);      
  _rst=0;  
  wait_ms(PT6301_RST_DLY);    
  _rst=1;
  wait_ms(PT6301_RST_DLY); 
#endif

  // Set number of Grids
  _writeCmd((PT6301_GRID_REG | (_mode & PT6301_GRID_MSK)));      // Command register & value
  
  setBrightness(PT6301_BRT_DEF); // Default Brightness

  // Clear the DCRAM and ADRAM (undefined at Reset) and reset (_row, _column)
  cls(true); 
  
  // Clear the UDC RAM (undefined at Reset)
  const char udc_none[] = {0x00,0x00,0x00,0x00,0x00}; 
  for (int idx=0; idx < PT6301_NR_UDC; idx++) {
    setUDC(idx, (char *)udc_none);
  }

  // Update the display
  refresh();
         
  setDisplay(true);  // Display On 
}   


/** Clear the screen and locate to (0,0)
  *
  * @param bool clrAll Clear Icons also (default = false)  
  * @return none  
  */  
void PT6301::cls(bool clrAll) {

  for (_row = 0; _row < _rows; _row++) {
    for (_column = 0; _column < _columns; _column++) {
      _displaybuffer[_row][_column] = ' '; // data 

      if (clrAll) {
        _addbuffer[_row][_column] = 0;     // icons           
      }   
    }  
  }

  _row = 0;
  _column = 0;
}  


/** Locate cursor to a screen row, column
  *
  * @param row     The vertical position from the top, indexed from 0     
  * @param column  The horizontal position from the left, indexed from 0
  * @return none  
  */
void PT6301::locate(int row, int column) {
  //sanity check
  if (row < 0) {row = 0;}
  if (row > (_rows - 1)) {row = _rows - 1;}  

  if (column < 0) {column = 0;}
  if (column > (_columns - 1)) {column = _columns - 1;}  
  
  _row = row;
  _column = column;
}

/** Number of screen columns
  *
  * @param none
  * @return columns
  */
int PT6301::columns(){
  return _columns;    
}      


/** Number of screen rows
  *
  * @param none
  * @return rows
  */
int PT6301::rows() {
  return _rows;
}      


/** Refresh screen and show data in local mirrors on the display
  *
  * @param bool copyAll Copy Icons in Adat local mirror also (default = true)   
  * @return none
  */
void PT6301::refresh(bool copyAll) {
  int row_cnt, col_cnt;
  
//Copy character data mirror to display
  _cs=0; // Send Command for DATA_A_REG
  wait_us(1);  
  _spi.write(_flip(PT6301_DATA_A_REG));  // Command register for DATA_A
  wait_us(PT6301_CMD_DLY);         // Command Delay
  
  row_cnt = _row_flip(0);          // Reorder rows depending on VFD layout
  for (col_cnt = 0; col_cnt < _columns; col_cnt++) {
    _spi.write(_flip(_displaybuffer[row_cnt][col_cnt])); // DATA_A Row
  }
  
  wait_us(PT6301_CS_DLY);          // CS Hold Delay  
  _cs=1; // Latch Command & Params

  wait_us(PT6301_CMD_DLY);         // Command Delay
  
  _cs=0; // Send Command for DATA_B_REG
  wait_us(1);  
  _spi.write(_flip(PT6301_DATA_B_REG));  // Command register for DATA_B
  wait_us(PT6301_CMD_DLY);         // Command Delay
  
  row_cnt = _row_flip(1);          // Reorder rows depending on VFD layout  
  for (col_cnt = 0; col_cnt < _columns; col_cnt++) {
    _spi.write(_flip(_displaybuffer[row_cnt][col_cnt])); // DATA_B Row
  }
  
  wait_us(PT6301_CS_DLY);          // CS Hold Delay  
  _cs=1; // Latch Command & Params

//Copy icon data mirror to display 
  if (copyAll) {
    _cs=0; // Send Command for ADAT_A_REG
    wait_us(1);  
    _spi.write(_flip(PT6301_ADAT_A_REG));  // Command register for ADAT_A
    wait_us(PT6301_CMD_DLY);         // Command Delay
  
    row_cnt = _row_flip(0);          // Reorder rows depending on VFD layout      
    for (col_cnt = 0; col_cnt < _columns; col_cnt++) {
      _spi.write(_flip(_addbuffer[row_cnt][col_cnt])); // ADAT_A Row
    }
  
    wait_us(PT6301_CS_DLY);          // CS Hold Delay  
    _cs=1; // Latch Command & Params

    wait_us(PT6301_CMD_DLY);         // Command Delay
  
    _cs=0; // Send Command for ADAT_B_REG
    wait_us(1);  
    _spi.write(_flip(PT6301_ADAT_B_REG));  // Command register for ADAT_B
    wait_us(PT6301_CMD_DLY);         // Command Delay
  
    row_cnt = _row_flip(1);          // Reorder rows depending on VFD layout      
    for (col_cnt = 0; col_cnt < _columns; col_cnt++) {
      _spi.write(_flip(_addbuffer[row_cnt][col_cnt])); // ADAT_B Row
    }
  
    wait_us(PT6301_CS_DLY);          // CS Hold Delay  
    _cs=1; // Latch Command & Params
  }
} 


/** Set Brightness
  *
  * @param  char brightness (valid range 0..255)  
  * @return none
  */
void PT6301::setBrightness(char brightness){
  
//Sanity check
// 

  _writeCmd(PT6301_BRT_REG, brightness);    // Command register & value
}


/** Set the Display mode On/off
  *
  * @param bool display mode
  * @return none  
  */
void PT6301::setDisplay(bool on) {
  char display;
     
  if (on) {
    display = PT6301_DSPL_NRM; // normal mode, show Display RAM content
  }
  else {
    display = PT6301_DSPL_OFF; // all segments off
  }

  _writeCmd((PT6301_DSPL_REG | display));   // Command register & value
}


/** Set the Display test mode On/off
  *
  * @param bool display test mode
  * @return none  
  */
void PT6301::setDisplayTest(bool on) {
  char display;
     
  if (on) {
    display = PT6301_DSPL_ON;  // test mode, all segments on
  }
  else {
    display = PT6301_DSPL_NRM; // normal mode, show Display RAM content
  }

  _writeCmd((PT6301_DSPL_REG | display));   // Command register & value
}


/** Set User Defined Characters (UDC) for A and B
  *
  * @param unsigned char udc_idx   The Index of the UDC (0..15)
  * @param UDCData_t udc_data      The bitpattern for the UDC (5 bytes)
  * @return none  
  */
void PT6301::setUDC(unsigned char udc_idx, UDCData_t udc_data) {
  
//Sanity check
  udc_idx = udc_idx & PT6301_UADR_MSK; // mask invalid bits

  _cs=0; // Send Command & Params for UDC_A
  wait_us(1);  
  _spi.write(_flip(PT6301_UDC_A_REG | udc_idx));     // Command register & address for UDC_A
  wait_us(PT6301_CMD_DLY);         // Command Delay
    
  _spi.write(_flip(udc_data[0] & PT6301_UDC_MSK)); // CD30 CD25 ......  CD0
  _spi.write(_flip(udc_data[1] & PT6301_UDC_MSK)); // CD31 CD26 ......  CD1
  _spi.write(_flip(udc_data[2] & PT6301_UDC_MSK)); // CD32 CD27 ......  CD2
  _spi.write(_flip(udc_data[3] & PT6301_UDC_MSK)); // CD33 CD28 ......  CD3
  _spi.write(_flip(udc_data[4] & PT6301_UDC_MSK)); // CD34 CD29 ......  CD4

  wait_us(PT6301_CS_DLY);          // CS Hold Delay  
  _cs=1; // Latch Command & Params

  wait_us(PT6301_CMD_DLY);         // Command Delay   
  

  _cs=0; // Send Command & Params for UDC B
  wait_us(1);  
  _spi.write(_flip(PT6301_UDC_B_REG | udc_idx));     // Command register & address for UDC_B
  wait_us(PT6301_CMD_DLY);         // Command Delay
    
  _spi.write(_flip(udc_data[0] & PT6301_UDC_MSK)); // CD30 CD25 ......  CD0
  _spi.write(_flip(udc_data[1] & PT6301_UDC_MSK)); // CD31 CD26 ......  CD1
  _spi.write(_flip(udc_data[2] & PT6301_UDC_MSK)); // CD32 CD27 ......  CD2
  _spi.write(_flip(udc_data[3] & PT6301_UDC_MSK)); // CD33 CD28 ......  CD3
  _spi.write(_flip(udc_data[4] & PT6301_UDC_MSK)); // CD34 CD29 ......  CD4

  wait_us(PT6301_CS_DLY);          // CS Hold Delay  
  _cs=1; // Latch Command & Params

  wait_us(PT6301_CMD_DLY);         // Command Delay   
  
}

/** Set Icon
  *
  * @param int row    The row of the icon (0..(rows-1))
  * @param int column The column of the icon (0..(cols-1))       
  * @return none    
  */
void PT6301::setIcon(int row, int column){
  //sanity check
  if (row < 0) {row = 0;}
  if (row > (_rows - 1)) {row = _rows - 1;}  

  if (column < 0) {column = 0;}
  if (column > (_columns - 1)) {column = _columns - 1;}  
   
  _addbuffer[row][column] = PT6301_ADAT_MSK;    
}

/** Clr Icon
  *
  * @param int row    The row of the icon (0..(rows-1))
  * @param int column The column of the icon (0..(cols-1))       
  * @return none    
  */
void PT6301::clrIcon(int row, int column){
  //sanity check
  if (row < 0) {row = 0;}
  if (row > (_rows - 1)) {row = _rows - 1;}  

  if (column < 0) {column = 0;}
  if (column > (_columns - 1)) {column = _columns - 1;}  
    
  _addbuffer[row][column] = 0x00;
}    


/** Write command to PT6301
  *
  *  @param char cmd Command byte
  *  @return none
  */  
void PT6301::_writeCmd(char cmd){

  _cs=0; // Prepare to send Command
  wait_us(1);

  _spi.write(_flip(cmd));          // Command register & value

  wait_us(PT6301_CS_DLY);          // CS Hold Delay  
  _cs=1; // Latch Command

  wait_us(PT6301_CMD_DLY);         // Command Delay
}  


/** Write command and data to PT6301
  *
  *  @param char cmd Command byte
  *  @param char data Parameter for command  
  *  @return none
  */  
void PT6301::_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(PT6301_CMD_DLY);         // Command Delay
  
  _spi.write(_flip(data));         // data

  wait_us(PT6301_CS_DLY);          // CS Hold Delay
  _cs=1; // Latch Command and data 

  wait_us(PT6301_CMD_DLY);         // Command Delay
}  

/** Write Data to local mirror
  *
  * @param char data The databyte        
  * @param row       The vertical position from the top, indexed from 0     
  * @param column    The horizontal position from the left, indexed from 0
  * @return none     
  */
void PT6301::setData(char data, int row, int column){
  
  //Sanity check, allow access to all of local mirror
  if (row < 0) {row = 0;}
  if (row > (PT6301_MAX_NR_ROWS - 1)) {row = PT6301_MAX_NR_ROWS - 1;}  

  if (column < 0) {column = 0;}
  if (column > (PT6301_MAX_NR_GRIDS - 1)) {column = PT6301_MAX_NR_GRIDS - 1;}  
   
  _displaybuffer[row][column] = data;  
}    

/** Read Data from local mirror
  *
  * @param row       The vertical position from the top, indexed from 0     
  * @param column    The horizontal position from the left, indexed from 0
  * @return char     The databyte        
  */
char PT6301::getData(int row, int column){
  
  //Sanity check, allow access to all of local mirror
  if (row < 0) {row = 0;}
  if (row > (PT6301_MAX_NR_ROWS - 1)) {row = PT6301_MAX_NR_ROWS - 1;}  

  if (column < 0) {column = 0;}
  if (column > (PT6301_MAX_NR_GRIDS - 1)) {column = PT6301_MAX_NR_GRIDS - 1;}  
   
  return _displaybuffer[row][column];  
}    

/** Write AData to local mirror
  *
  * @param char data The symbol databyte        
  * @param row       The vertical position from the top, indexed from 0     
  * @param column    The horizontal position from the left, indexed from 0
  * @return none     
  */
void PT6301::setAData(char data, int row, int column){
  
  //Sanity check, allow access to all of local mirror
  if (row < 0) {row = 0;}
  if (row > (PT6301_MAX_NR_ROWS - 1)) {row = PT6301_MAX_NR_ROWS - 1;}  

  if (column < 0) {column = 0;}
  if (column > (PT6301_MAX_NR_GRIDS - 1)) {column = PT6301_MAX_NR_GRIDS - 1;}  
   
  _addbuffer[row][column] = data & PT6301_ADAT_MSK;  
}    

/** Read AData from local mirror
  *
  * @param row       The vertical position from the top, indexed from 0     
  * @param column    The horizontal position from the left, indexed from 0
  * @return char     The symbol databyte        
  */
char PT6301::getAData(int row, int column){
  
  //Sanity check, allow access to all of local mirror
  if (row < 0) {row = 0;}
  if (row > (PT6301_MAX_NR_ROWS - 1)) {row = PT6301_MAX_NR_ROWS - 1;}  

  if (column < 0) {column = 0;}
  if (column > (PT6301_MAX_NR_GRIDS - 1)) {column = PT6301_MAX_NR_GRIDS - 1;}  
   
  return _addbuffer[row][column];  
}    




/** Helper to reverse all command or databits. The PT6301 expects LSB first, whereas SPI is MSB first
  *
  *  @param  char data
  *  @return bitreversed data
  */ 
char PT6301::_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;  
}


/** Helper to reverse row idx depending on VFD layout
  *
  *  @param  int row_idx
  *  @return adjusted row_idx
  */ 
int PT6301::_row_flip(int row_idx) {
  if (_inverted_rows) {
    return (1 - row_idx);    // Reorder row mapping to match VFD layout
                             //   Top line is DATA_B_REG, ADAT_B_REG 
                             //   Bottom line is DATA_A_REG, ADAT_A_REG 
  }  
  else {
    return row_idx;          // Maintain row mapping to match VFD layout      
                             //   Top line is DATA_A_REG, ADAT_A_REG 
                             //   Bottom line is DATA_B_REG, ADAT_B_REG     
  }        
}
 

/** Write a single character (Stream implementation)
  * 
  * @param value char to print
  * @return value;
  */
int PT6301::_putc(int value) {

    if (value == '\r') {
      //No character to write
     
      //Update Cursor      
      _column = 0;
    }
    else if (value == '\n') {
      //No character to write
     
      //Update Cursor      
      _row++;
      if (_row > (_rows - 1)) {        
        _row = 0;
      }     
    }    
    else if ((value >= 0) && (value < 256)) {
      //Valid character to write

      //Write displaybuffer entry
      _displaybuffer[_row][_column] = value;
      
      //Update Cursor
      _column++;
      if (_column > (_columns - 1)) {        
        _column = 0;
        _row++;
      }
      if (_row > (_rows - 1)) {        
        _row = 0;
      }
    } // if validChar

    return value;
}

/** Get a single character (Stream implementation)
  *
  * @param none  
  * @return -1
  */
int PT6301::_getc() {
    return -1;
} 
      


#if (SMTG7400_TEST == 1) 

/** Constructor for class for Princeton PT6301 VFD controller as used in SMTG7400
  *
  *  @brief Supports 16 Grids of 5x7 Segments with 4 additional Segments in use.
  *  
  *  @param  PinName mosi, miso, sclk, cs SPI bus pins
  *  @param  PinName rst Reset pin  
  */
PT6301_SMTG7400::PT6301_SMTG7400(PinName mosi, PinName sclk, PinName cs, PinName rst) : PT6301(mosi, sclk, cs, rst, Grid16, true, SMTG7400_NR_COLS, SMTG7400_NR_ROWS) {

}

/** Set Icon
  *
  * @param int icon   The icon ID
  * @return none    
  */
void PT6301_SMTG7400::setIcon(int icon) {
  PT6301::setIcon((icon >> SMTG7400_ICON_ROW_SHFT), (icon & SMTG7400_ICON_COL_MSK));
}      
      
/** Clr Icon
  *
  * @param int icon   The icon ID
  * @return none    
  */
void PT6301_SMTG7400::clrIcon(int icon) {
  PT6301::clrIcon((icon >> SMTG7400_ICON_ROW_SHFT), (icon & SMTG7400_ICON_COL_MSK));
}      

#endif


#if (SMTC7140_TEST == 1) 

/** Constructor for class for Princeton PT6301 VFD controller as used in SMTC7140
  *
  *  @brief Supports 12 Grids of 5x7 Segments without additional Icon Segments, for 2 Rows.
  *                  Grid13 is used for icons displayed by a UDC symbol. 
  *  
  *  @param  PinName mosi, miso, sclk, cs SPI bus pins
  *  @param  PinName rst Reset pin  
  */
PT6301_SMTC7140::PT6301_SMTC7140(PinName mosi, PinName sclk, PinName cs, PinName rst) : PT6301(mosi, sclk, cs, rst, Grid13, true, SMTC7140_NR_COLS, SMTC7140_NR_ROWS) {
 
  //Enable VGen for VFD Power Supply
  //Note this is wrong because we should send the init commands to the PT6301 before the 5V powersupply is enabled !
//  setVGen(true);   
 
}

/** Set VFD VGen
  *
  * @param  bool on
  * @return none
  */
void PT6301_SMTC7140::setVGen (bool on) {

}     


/** Set IconGrid13
  * Icons are shown on Grid13 using the UDC at index=0. The UDC char=0 is stored in _displaybuffer[0][12] at reset.
  * This method will set the correct segment in the UDC for each icon.
  *
  * @param int icon   The icon ID
  * @return none    
  */
void PT6301_SMTC7140::setIconGrid13(int icon) {

#if(0)  
  //Test version to check all bits
  // clear icon
  for (int udc_col=0; udc_col<5; udc_col++) {        
    _icon_data[udc_col] = 0x00;
  };

  _icon_data[icon >> 8] = (icon & 0x7F);
  setUDC(0, (char *) _icon_data); // Store mirror for UDC_idx=0  

#else
  //Normal version
  for (int udc_col=0; udc_col<5; udc_col++) {    
    _icon_data[udc_col] = _icon_data[udc_col] | SMTC7140_ICONS[icon][udc_col]; // OR icon bitpattern with UDC mirror for UDC_idx=0
  }    

  setUDC(0, (char *) _icon_data); // Store mirror for UDC_idx=0
#endif  
  
}      
      
/** Clr IconGrid13
  * Icons are shown on Grid13 using the UDC at index=0. The UDC char=0 is stored in _displaybuffer[0][12] at reset.
  * This method will clr the correct segment in the UDC for each icon.
  *
  * @param int icon   The icon ID
  * @return none    
  */
void PT6301_SMTC7140::clrIconGrid13(int icon) {

  for (int udc_col=0; udc_col<5; udc_col++) {    
    _icon_data[udc_col] = _icon_data[udc_col] & ~(SMTC7140_ICONS[icon][udc_col]); // AND inverted icon bitpattern with UDC mirror for UDC_idx=0
  }    

  setUDC(0, (char *) _icon_data); // Store mirror for UDC_idx=0
}      

#endif