Sanyo LC75711 VFD controller/driver for upto 16 Dot Matrix Characters

Dependents:   mbed_LC75711

The component page is here.

Revision:
0:5eb5fee234e8
Child:
1:bcf010fcacae
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LC75711.cpp	Tue Sep 12 18:36:56 2017 +0000
@@ -0,0 +1,441 @@
+/* mbed LC75710 Library, for Sanyo LC7571X VFD controller
+ * Note: The LC75710, LC75711 and LC75712 differ only in the built-in character ROM
+ *
+ * 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 "LC75711.h"
+#include "LC75711_UDC.inc"
+
+
+ /** Constructor for class for driving Sanyo LC75711 VFD controller
+  *
+  * @brief Supports upto 16 Grids of 35 matrix segments. Also supports 3-8 additional segments (depending on number of grids).
+  *        SPI bus interface device. 
+  *  @param  PinName mosi, sclk, cs SPI bus pins
+  *  @param  Mode selects number of Grids and Segments (default 11 Grids, 35 matrix segments, 8 additional segments)
+  */
+LC75711::LC75711(PinName mosi, PinName sclk, PinName cs, Mode mode) : _spi(mosi,NC,sclk), _cs(cs), _mode(mode) {
+
+  _init();
+}
+
+/** Init the LC75711 interface and the controller
+  * @param  none
+  * @return none
+  */ 
+void LC75711::_init(){
+  
+//init SPI
+  _cs=0;
+  _spi.format(8,0); //LC75711 uses mode 0 (Clock Low on Idle, Data latched on first (=rising) edge)
+//  _spi.frequency(100000);   
+  _spi.frequency(250000);     
+
+//init controller  
+
+  // Set number of Grids
+  _writeCmd((LC75711_GRID_REG | _mode),      // B16..B23, Command register & value
+             0x00,                           // B8..B15, Dummy
+             0x00,                           // B0..B7, Dummy
+             LC75711_GRID_DLY);              // Command Delay    
+
+  _setAddress(0, 0); // No shift
+
+  setBlink(false);   // No Blink
+  setBrightness(LC75711_BRT_DEF); // Default Brightness
+
+  // Clear the DCRAM (undefined at Reset)
+  cls(); 
+
+  // Clear the UDC RAM (undefined at Reset)
+  const char udc_none[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
+  for (int idx=0; idx < LC75711_NR_UDC; idx++) {
+    setUDC(idx, (char *)udc_none);
+  }
+       
+  setDisplay(true);  // Display On
+}   
+
+
+/** Clear the screen and locate to 0
+ */  
+void LC75711::cls() {
+
+  for (int cnt=0; cnt<LC75711_DISPLAY_MEM; cnt++) {
+    writeData(char (' '), cnt); // data 
+//    writeData(0x00, cnt);       // data     
+  }
+
+  for (int cnt=0; cnt<LC75711_ADD_MEM; cnt++) {
+    writeData(0x00, cnt);       // adata 
+  }  
+}  
+
+/** Set the Blink mode
+  *
+  * @param bool Blink mode
+  * @param int  grids selected grids for Blinking enable/disable (default = all)  
+  */
+void LC75711::setBlink(bool on, int grids) {
+  
+  // Sanity check and update of local shadow
+  if (on) {
+    _blink = _blink | (grids & LC75711_GR_MSK);    // Set grid bits
+  }
+  else {
+    _blink = _blink & ~(grids & LC75711_GR_MSK);   // Clr grid bits   
+  }
+
+  _writeCmd((LC75711_BLNK_REG | LC75711_BLNK_ON),  // B16..B23, Command register & value
+             ((_blink >> 8) & 0xFF),               // B8..B15, GR8..GR16  
+             ( _blink       & 0xFF),               // B0..B7, GR1..GR7            
+             LC75711_BLNK_DLY);                    // Command Delay    
+}
+
+
+/** Set Brightness
+  *
+  * @param  char brightness (8 significant bits, valid range 0..239 (dutycycle linked to number of grids)  
+  * @return none
+  */
+void LC75711::setBrightness(char brightness){
+  
+//Sanity check
+  brightness = brightness & LC75711_BRT_MSK; // mask invalid bits
+  if (brightness > 239) {brightness = 239;} 
+ 
+  _writeCmd((LC75711_BRT_REG),               // B16..B23, Command register
+             brightness,                     // B8..B15, Brightness
+             0x00,                           // B0..B7, Dummy
+             LC75711_BRT_DLY);               // Command Delay      
+}
+
+/** Set the Display mode On/off
+  *
+  * @param bool display mode
+  */
+void LC75711::setDisplay(bool on) {
+  char display;
+     
+  if (on) {
+    display = LC75711_DSPL_ON;
+  }
+  else {
+    display = LC75711_DSPL_OFF;
+  }
+
+  _writeCmd((LC75711_DSPL_REG | display),    // B16..B23, Command register & value
+             0xFF,                           // B8..B15, GR8..GR16  
+             0xFF,                           // B0..B7, GR1..GR7
+             LC75711_DSPL_DLY);              // Command Delay    
+}
+
+
+/** 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 (7 bytes)       
+  */
+void LC75711::setUDC(unsigned char udc_idx, UDCData_t udc_data) {
+  char data;
+  
+//Sanity check
+  udc_idx = udc_idx & LC75711_UDC_MSK; // mask invalid bits
+
+  _cs=0; // Prepare to send Address
+  wait_us(1);    
+
+  _spi.write(_flip(LC75711_ADDRESS)); // Address 
+
+  _cs=1; // Latch Address, Prepare to send Command & Params 
+  wait_us(1);
+  
+  data = ((udc_data[1] & 0x07) << 5) | ((udc_data[0] & 0x1F) << 0); 
+  _spi.write(_flip(data));            // B0..B7, AM1-AM8
+
+  data = ((udc_data[3] & 0x01) << 7) | ((udc_data[2] & 0x1F) << 2) | ((udc_data[1] & 0x18) >> 3);
+  _spi.write(_flip(data));            // B8..B15, AM9-AM16  
+    
+  data = ((udc_data[4] & 0x0F) << 4) | ((udc_data[3] & 0x1E) >> 1);
+  _spi.write(_flip(data));            // B16..B23, AM17-AM24  
+
+  data = ((udc_data[6] & 0x03) << 6) | ((udc_data[5] & 0x1F) << 1) | ((udc_data[4] & 0x10) >> 4);
+  _spi.write(_flip(data));            // B24..B31, AM25-AM32  
+
+  data = ((udc_data[6] & 0x1C) >> 2);
+  _spi.write(_flip(data));            // B32..B39, AM32-AM35  
+
+  _spi.write(_flip(udc_idx));         // B40..B47, CA0-CA7  
+  
+  _spi.write(_flip(LC75711_UDC_REG)); // B48..B55, Command register
+
+  wait_us(1);
+  _cs=0; // Latch Command & Params
+
+  wait_us(LC75711_UDC_DLY);           // Command Delay  
+}
+
+
+/** Write Data to LC75711
+  *  @Param char data Character code
+  *  @Param char address Parameter for data
+  *  @return none
+  */  
+void LC75711::writeData(char data, char address){
+
+//Sanity check
+  address = address & LC75711_DADR_MSK; // mask invalid bits
+
+  _writeCmd((LC75711_DATA_REG),         // B16..B23, Command register
+             address,                   // B8..B15, DCRAM address
+             data,                      // B0..B7, Character code
+             LC75711_DATA_DLY);         // Command Delay    
+}  
+
+/** Write Additional Data to LC75711
+  *  @Param char adata Additional code (annunciator)
+  *  @Param char address Parameter for data
+  *  @return none
+  */  
+void LC75711::writeAData(char adata, char address){
+
+//Sanity check
+  address = address & LC75711_AADR_MSK; // mask invalid bits
+ 
+  _writeCmd((LC75711_ADAT_REG | address), // B16..B23, Command register & ADRAM address
+             adata,                       // B8..B15, ADATA
+             0x00,                        // B0..B7, Dummy
+             LC75711_ADAT_DLY);           // Command Delay
+}  
+
+
+/** Set Address
+  *  @Param char RAM address for data displayed at Grid1 (0..63)
+  *  @Param char RAM address for adata displayed at Grid1 (0..15) 
+  *  @return none
+  *
+  * Note that a Shift (L/R) command will change the Address of data displayed at Grid1
+  */  
+void LC75711::_setAddress(char data_addr, char adata_addr){
+
+//Sanity check
+  data_addr  =  data_addr & LC75711_DADR_MSK; // mask invalid bits
+  adata_addr = adata_addr & LC75711_AADR_MSK; // mask invalid bits
+
+  _writeCmd((LC75711_AC_REG | adata_addr),   // B16..B23, Command register & ADRAM address
+             data_addr,                      // B8..B15, DCRAM address
+             0x00,                           // B0..B7, Dummy
+             LC75711_AC_DLY);                // Command Delay    
+}  
+
+
+/** Write command and parameters to LC75711
+  *  @Param char cmd Command byte
+  *  @Param char data1 Parameters for command
+  *  @Param char data0 Parameters for command  
+  *  @Param char delay Delay for command execution
+  *  @return none
+  */  
+void LC75711::_writeCmd(char cmd, char data1, char data0, char delay){
+
+  _cs=0; // Prepare to send Address
+  wait_us(1);    
+
+  _spi.write(_flip(LC75711_ADDRESS)); // Address 
+
+  _cs=1; // Latch Address, Prepare to send Command & Params 
+  wait_us(1);
+
+  _spi.write(_flip(data0));        // B0..B7
+
+  _spi.write(_flip(data1));        // B8..B15  
+    
+  _spi.write(_flip(cmd));          // B16..B23, Command register & value
+
+  wait_us(1);
+  _cs=0; // Latch Command & Params
+
+  wait_us(delay);                  // Command Delay        
+}  
+
+
+/** Helper to reverse all command or databits. The LC75711 expects LSB first, whereas SPI is MSB first
+  *  @param  char data
+  *  @return bitreversed data
+  */ 
+char LC75711::_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 (ASTON_TEST == 1) 
+
+/** Constructor for class for Sanyo LC75711 VFD controller as used in ASTON
+  *
+  *  @brief Supports 10 Grids of 35 Segments without additional Segments and uses Grid 11 for Icon segments.
+  *  
+  *  @param  PinName mosi, miso, sclk, cs SPI bus pins
+  */
+LC75711_ASTON::LC75711_ASTON(PinName mosi, PinName sclk, PinName cs) : LC75711(mosi, sclk, cs, Grid11_Add8) {
+  _column   = 0;
+  _columns  = ASTON_NR_DIGITS;
+  
+  // Clear the _udc_icon (should be cleared at Reset)
+//  for (int idx=0; idx < 7; idx++) {
+//    _udc_icon = 0x00;
+//  }
+}
+
+/** Locate cursor to a screen column
+  *
+  * @param column  The horizontal position from the left, indexed from 0
+  */
+void LC75711_ASTON::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 LC75711_ASTON::columns() {
+    return _columns;
+}
+
+
+/** Clear the screen and locate to 0
+  * @param bool clrAll Clear Icons also (default = false)
+  */ 
+void LC75711_ASTON::cls(bool clrAll) {  
+
+  for (int cnt=0; cnt<ASTON_NR_DIGITS; cnt++) {
+    writeData(char (' '), cnt); // data 
+  }
+
+  if (clrAll) {
+    for (int cnt=0; cnt<ASTON_NR_DIGITS; cnt++) {
+      writeAData(0x00, cnt);      // adata 
+    }
+    
+    //Clear Icons
+    //
+  }  
+
+  _column = 0;   
+}    
+
+
+/** Set Icon
+  *
+  * @param Icon Enums Icon Encodes UDC_0 byte index in 8 MSBs and encodes Icon bit/segment in 8 LSBs
+  * @return none
+  */
+void LC75711_ASTON::setIcon(Icon icon){
+  int byte_idx, bits;
+  
+  byte_idx = (icon >> 8) & 0x07;          // Decode byte index and sanity mask
+  bits     = (1 << (icon & 0x07)) & 0x1F; // Decode bits and sanity mask  
+    
+  //Set the segment bit for the Icon
+  _udc_icon[byte_idx] |= bits;
+  
+  //Update UDC_0 used to display the Icons at Grid 11
+  setUDC(0, _udc_icon);
+}
+
+/** Clr Icon
+  *
+  * @param Icon Enums Icon Encodes UDC_0 byte index in 8 MSBs and encodes Icon bit/segment in 8 LSBs     
+  * @return none
+  */
+void LC75711_ASTON::clrIcon(Icon icon) {
+  int byte_idx, bits;
+  
+  byte_idx = (icon >> 8) & 0x07;          // Decode byte index and sanity mask
+  bits     = (1 << (icon & 0x07)) & 0x1F; // Decode bits and sanity mask
+    
+  //Clear the segment bit for the Icon
+  _udc_icon[byte_idx] &= ~bits;
+  
+  //Update UDC_0 used to display the Icons at Grid 11
+  setUDC(0, _udc_icon);
+}
+
+/** Write a single character (Stream implementation)
+  */
+int LC75711_ASTON::_putc(int value) {
+    int addr;
+    
+    if ((value == '\n') || (value == '\r')) {
+      //No character to write
+     
+      //Update Cursor      
+      _column = 0;
+    }
+    else if ((value >= 0) && (value < 192)) {
+      //Character to write
+
+      //Translate between _column and displaybuffer entries
+      //Note that the ASTON has 1 digit/grids. 
+      //_column ==  0 => Grid10 => addr = 9
+      //_column ==  1 => Grid9  => addr = 8
+      // ....
+      //_column ==  9 => Grid1  => addr = 0            
+      addr = (9 - _column); // 1 Byte for every Grid;
+      
+      writeData(value, addr);
+                                
+      //Update Cursor
+      _column++;
+      if (_column > (ASTON_NR_DIGITS - 1)) {        
+        _column = 0;
+      }
+
+    } // if validChar           
+
+    return value;
+}
+
+// get a single character (Stream implementation)
+int LC75711_ASTON::_getc() {
+    return -1;
+}
+#endif