first commit
This commit is contained in:
447
libraries/hd44780/hd44780ioClass/hd44780_NTCU165ECPB.h
Normal file
447
libraries/hd44780/hd44780ioClass/hd44780_NTCU165ECPB.h
Normal file
@@ -0,0 +1,447 @@
|
||||
// vi:ts=4
|
||||
// ---------------------------------------------------------------------------
|
||||
// hd44780_NTCU165ECPB.h - hd44780_NTCU165ECPB i/o subclass for hd44780 library
|
||||
// Copyright (c) 2016-2020 Bill Perry
|
||||
//
|
||||
// The API functionality provided by this library class is compatible
|
||||
// with the API functionality of the Arduino LiquidCrystal library.
|
||||
//
|
||||
// ---------------------------------------------------------------------------
|
||||
//
|
||||
// This file is part of the hd44780 library
|
||||
//
|
||||
// hd44780_NTCU165ECPB is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation version 3 of the License.
|
||||
//
|
||||
// hd44780_NTCU165ECPB is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with hd44780_NTCU165ECPB. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// ---------------------------------------------------------------------------
|
||||
//
|
||||
// It implements hd44780 library subclass i/o methods to control a
|
||||
// Noritake CU165ECBP-T2J display.
|
||||
// The Noritake CU165ECBP-T2J display is a 16x1 line VFD display.
|
||||
// It is not a hd44780 display. So while this device is supported by hd44780,
|
||||
// it will not be capable of supporting all the hd44780 capabilities.
|
||||
// The subclass will do its best to emulatate hd44780 functions and map
|
||||
// them to equivalent functionality when possible but certain capabilities
|
||||
// will not be possible.
|
||||
//
|
||||
// Datasheet can be found here:
|
||||
// http://www.blog.zapro.dk/wp-content/CU165.pdf
|
||||
// Full datasheet/release notes:
|
||||
// http://www.blog.zapro.dk/wp-content/CU165ECPB_T2J_specification.pdf
|
||||
//
|
||||
// The device uses SPI for communication.
|
||||
// Pinout:
|
||||
// 1 Vcc
|
||||
// 2 GND
|
||||
// 3 /CS (SS)
|
||||
// 4 CLK (SCK)
|
||||
// 5 DATA (MOSI)
|
||||
//
|
||||
// ---------------------------------------------------------------------------
|
||||
// history
|
||||
//
|
||||
// 2017.12.23 bperrybap - added support LCD API 1.0 init()
|
||||
// 2016.08.22 bperrybap - initial creation
|
||||
//
|
||||
// @author Bill Perry - bperrybap@opensource.billsworld.billandterrie.com
|
||||
//
|
||||
// ---------------------------------------------------------------------------
|
||||
#ifndef hd44780_NTCU165ECPB_h
|
||||
#define hd44780_NTCU165ECPB_h
|
||||
|
||||
class hd44780_NTCU165ECPB : public hd44780
|
||||
{
|
||||
public:
|
||||
// ====================
|
||||
// === constructors ===
|
||||
// ====================
|
||||
|
||||
// no parameters: use h/w spi signals
|
||||
// Note: This doesn't work for Leonardo since SS is not available and only drives an LED
|
||||
hd44780_NTCU165ECPB() : hd44780(16,1), _cs(SS), _clk(SCK), _data(MOSI) { }
|
||||
|
||||
// supply alternate chip/slave select
|
||||
// will use h/w spi with alternate chip select
|
||||
hd44780_NTCU165ECPB(int cs) : hd44780(16,1), _cs(cs), _clk(SCK), _data(MOSI) { }
|
||||
|
||||
// supply pins for chip select, clock, and data
|
||||
hd44780_NTCU165ECPB(int cs, int clock, int data) : hd44780(16,1), _cs(cs), _clk(clock), _data(data) { }
|
||||
|
||||
|
||||
private:
|
||||
// ====================
|
||||
// === private data ===
|
||||
// ====================
|
||||
|
||||
// Arduino Pin information
|
||||
|
||||
const uint8_t _cs; // arduino pint for slave select (chip select)
|
||||
const uint8_t _clk; // arduino pin for clock
|
||||
const uint8_t _data; // arduino pin for master out slave in (data)
|
||||
|
||||
// other internal variables
|
||||
uint8_t _cgmode; // set when in cgramaddr mode
|
||||
uint8_t _udf[5]; // udf buffer area
|
||||
uint8_t _cgindx; // index into cgdata (will be 0 to 7)
|
||||
uint8_t _cgchar; // custom character (0 to 7, this board goes to f)
|
||||
|
||||
|
||||
// device commands
|
||||
|
||||
static const uint8_t CMD_SETDISPLAYLEN = 0x00; // lower 3 bits sets total digits/cols
|
||||
// to display
|
||||
// 0 is 9 and 7 means all 16 digits/cols
|
||||
|
||||
static const uint8_t CMD_SETBRIGHTNESS = 0x08; // lower 3 bits sets brigtness
|
||||
// 0 is 1/16 and 7 is 14/16 max
|
||||
static const uint8_t CMD_SETDIGSCAN160 = 0xF6; // set digit scan time to 160us
|
||||
static const uint8_t CMD_SETDIGSCAN320 = 0xF7; // set digit scan time to 320us
|
||||
static const uint8_t CMD_SETDIGPOINTER = 0xE0; // set column, lower 4 bits sets column
|
||||
static const uint8_t CMD_NOAUTOINCREMENT = 0xF0; // no auto advance to next column
|
||||
static const uint8_t CMD_AUTOINCREMENT = 0xF1; // auto advance to next column
|
||||
|
||||
static const uint8_t CMD_DISPLAYOFF = 0xF0; // all digits/dots off
|
||||
static const uint8_t CMD_DISPLAYON = 0xF1; // normal display mode
|
||||
static const uint8_t CMD_DISPLAYALLON = 0xF3; // all digits, all dots on
|
||||
|
||||
static const uint8_t CMD_STOREUDF = 0xFC; // begin user defined font (custom char)
|
||||
// There are 16 custom chars, they are
|
||||
// accessed/printed using 0x90-0x9F
|
||||
// they are programmed using locations 0-F
|
||||
// Each character glyph is 5 bytes.
|
||||
// Each byte is vertical 7 pixels with the
|
||||
// MSB at the top and the LSB dropped.
|
||||
// The first byte is the left most column of
|
||||
// the glyph.
|
||||
// full command data is 7 bytes:
|
||||
// 0xFC,<location (0-f)> 5 bytes of data
|
||||
|
||||
// start of custom user defined font (UDF) characters
|
||||
// There are 16 UDF characters that start here
|
||||
static const uint8_t UDF_BASE = 0x90;
|
||||
|
||||
|
||||
// ==================================================
|
||||
// === hd44780 i/o subclass virtual i/o functions ===
|
||||
// ==================================================
|
||||
//
|
||||
// Note:
|
||||
// It is not possible to read from the device.
|
||||
// so ioread(), and & iostatus()
|
||||
// will not be defined and will use the defaults in
|
||||
// hd44780 which will return an apropriate error status
|
||||
|
||||
// ioinit() - Returns non zero if initialization failed.
|
||||
int ioinit()
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
// setup SPI signals
|
||||
digitalWrite(_cs, HIGH);
|
||||
pinMode(_cs, OUTPUT);
|
||||
|
||||
pinMode(_clk, OUTPUT);
|
||||
digitalWrite(_clk, LOW);
|
||||
pinMode(_data, OUTPUT);
|
||||
|
||||
// check to see if SPI has beginTransaction() and endTransaction()
|
||||
// this was added in IDE 1.06 and so if using an IDE older than that,
|
||||
// H/W spi will not be used
|
||||
// This requires that <SPI.h> be included prior to this header
|
||||
#if (defined(SPI_HAS_TRANSACTION) && !defined(ARDUINO_ARCH_ESP32)) || \
|
||||
(defined(ARDUINO_ARCH_ESP32) && defined(_SPI_H_INCLUDED) && defined(SPI_HAS_TRANSACTION))
|
||||
// check to see if h/w spi can be used
|
||||
if((_data == MOSI) && (_clk == SCK))
|
||||
SPI.begin();
|
||||
#endif
|
||||
|
||||
// maybe look at cols to see how many should be turned on?
|
||||
devicewrite(CMD_SETDISPLAYLEN|0x7); // show all 16 characters
|
||||
|
||||
devicewrite(CMD_SETDIGSCAN320); // set digit scan time to 320us
|
||||
devicewrite(CMD_AUTOINCREMENT); // set auto advance to next column on writes
|
||||
|
||||
// for now turn on display and "backlight"
|
||||
// clear and set to "home" address position
|
||||
devicewrite(CMD_DISPLAYON);
|
||||
devicewrite(CMD_SETBRIGHTNESS | 0x7); // max brightness
|
||||
device_clear();
|
||||
|
||||
return ( status );
|
||||
}
|
||||
|
||||
//
|
||||
// iowrite() - send either a command or data byte to lcd
|
||||
// returns zero on success, non zero on failure
|
||||
//
|
||||
// Things are a bit tricky here since this is not a hd44780 device.
|
||||
// The code must look at the commands and emulate them or drop them
|
||||
//
|
||||
int iowrite(hd44780::iotype type, uint8_t value)
|
||||
{
|
||||
|
||||
/*
|
||||
* waitReady() is not called as this module does not need any execution time
|
||||
* delays even when using a 4mHz h/w clock.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 4 bit commands are part of low level hd44780 initalization.
|
||||
* since this is not a hd44780 display, just throw them away
|
||||
* and say they "worked"
|
||||
*/
|
||||
|
||||
if(type == hd44780::HD44780_IOcmd4bit)
|
||||
return(0);
|
||||
|
||||
if(type == hd44780::HD44780_IOcmd)
|
||||
{
|
||||
return(hd44780cmd(value));
|
||||
}
|
||||
|
||||
if(_cgmode)
|
||||
{
|
||||
// in cgram mode so have to process custom character data.
|
||||
// hd44780 font data is stored horizontally in 8 bytes
|
||||
// with each byte being 1 row of dots
|
||||
// with upper 3 bits of each byte ignored.
|
||||
// first byte of the 8 bytes is upper row of dots.
|
||||
// Noritake UDF format is vertical columns of 5 bytes with
|
||||
// the LSB of each byte ignored as it only has 5x7 dots.
|
||||
// the first byte is the right most column of 7 dots of the font.
|
||||
//
|
||||
// Because of this mismatch, the bits & bytes have to be flipped
|
||||
// around and stored in the 5 UDF bytes until the full 8 hd44780 font
|
||||
// bytes come in. Once all 8 hd44780 font bytes are in,
|
||||
// the 5 byte UDF font definition can be pushed to the device.
|
||||
|
||||
for(int i = 0; i < 5; i++)
|
||||
{
|
||||
if( (value & (1<< i)))
|
||||
{
|
||||
_udf[4-i] |= (1 << (7- _cgindx));
|
||||
}
|
||||
else
|
||||
{
|
||||
_udf[4-i] &= ~(1 << (7-_cgindx));
|
||||
}
|
||||
}
|
||||
_cgindx++;
|
||||
if(_cgindx > 7) // is this the last of the 8 bytes?
|
||||
{
|
||||
// 0xFC,<location (0-f)> 5 bytes of data
|
||||
devicewrite(CMD_STOREUDF);
|
||||
devicewrite(_cgchar);
|
||||
for(int i = 0; i < 5; i++)
|
||||
{
|
||||
devicewrite(_udf[i]);
|
||||
}
|
||||
|
||||
// now send it again for the 8-f version
|
||||
// to emulate the hd44780 custom chars
|
||||
// that duplicate 0-7 at 8-f
|
||||
devicewrite(CMD_STOREUDF);
|
||||
devicewrite(_cgchar+8);
|
||||
for(int i = 0; i < 5; i++)
|
||||
{
|
||||
devicewrite(_udf[i]);
|
||||
}
|
||||
|
||||
// note, cgmode is still in effect.
|
||||
// the UDF/font byte index is reset back to 0,
|
||||
// and the cgchar location is bumped.
|
||||
// this is to allow for the case when the code may
|
||||
// be attempting to program more than a single character at once.
|
||||
_cgindx = 0;
|
||||
_cgchar++;
|
||||
_cgchar &= 0xf;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
// upper 32 bytes are for commands so drop chars that are in the 0xE0 to 0xFF range
|
||||
if(value >= 0xE0)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
// check for hd44780 custom font characters,
|
||||
// The hd44780 character code must be mapped to the UDF characters
|
||||
// which start at a different location.
|
||||
if(value < 16)
|
||||
{
|
||||
value += UDF_BASE;
|
||||
}
|
||||
|
||||
devicewrite(value);
|
||||
return(0);
|
||||
}
|
||||
|
||||
// iosetBacklight() - set backlight brightness
|
||||
// Since this display does not use a backlight but can control pixel intensity
|
||||
// use the backlight brightness to set the pixel intensity.
|
||||
//
|
||||
// Note:
|
||||
// The dimmer value on the CU165 is 3 bit value
|
||||
// other than the 000 value it looks like the value is mapped to a 4 bit
|
||||
// value by adding a 0 msb.
|
||||
// 000 is 1/16
|
||||
// 001 is 2/16
|
||||
// 010 is 4/16
|
||||
// 011 is 6/16
|
||||
// 100 is 8/16
|
||||
// 101 is 10/16
|
||||
// 110 is 12/16
|
||||
// 111 is 14/16
|
||||
//
|
||||
// Becauswe of this, an API dimvalue of 0 does not turn off the display pixels
|
||||
// so the code must check for that and explicitly turn off the display if the
|
||||
// API dimvalue is zero.
|
||||
int iosetBacklight(uint8_t dimvalue)
|
||||
{
|
||||
if(dimvalue)
|
||||
{
|
||||
// the dim value is 0-255 so devide by 32 to get a value 0-7
|
||||
devicewrite(CMD_SETBRIGHTNESS | (dimvalue/32));
|
||||
devicewrite(CMD_DISPLAYON);
|
||||
}
|
||||
else
|
||||
{
|
||||
devicewrite(CMD_DISPLAYOFF);
|
||||
}
|
||||
return(RV_ENOERR);
|
||||
}
|
||||
|
||||
// ================================
|
||||
// === internal class functions ===
|
||||
// ================================
|
||||
|
||||
// devicwrite() - send a byte to the device
|
||||
void devicewrite(uint8_t value)
|
||||
{
|
||||
|
||||
// use h/w spi if we can
|
||||
// note: checking for SPI support (SPI.h included) is messy since
|
||||
// ESP32 core always defines SPI_HAS_TRANSACTION even when SPI.h is not included
|
||||
|
||||
#if (defined(SPI_HAS_TRANSACTION) && !defined(ARDUINO_ARCH_ESP32)) || \
|
||||
(defined(ARDUINO_ARCH_ESP32) && defined(_SPI_H_INCLUDED) && defined(SPI_HAS_TRANSACTION))
|
||||
if((_data == MOSI) && (_clk == SCK))
|
||||
{
|
||||
// NOTE: spec says 2Mhz is max, 4Mhz seems to work.
|
||||
SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0));
|
||||
digitalWrite(_cs,LOW); // select device
|
||||
SPI.transfer(value);
|
||||
delayMicroseconds(1); // must delay at least 130ns before de-selecting
|
||||
digitalWrite(_cs,HIGH); // deselect device
|
||||
SPI.endTransaction();
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
digitalWrite(_cs,LOW); // select device
|
||||
myshiftOut(_data, _clk, MSBFIRST, value);
|
||||
delayMicroseconds(1); // must delay at least 130ns before de-selecting
|
||||
digitalWrite(_cs,HIGH); // deselect device
|
||||
}
|
||||
}
|
||||
|
||||
// can't use standard shiftOut() on esp32 because it is too fast for display
|
||||
//
|
||||
void myshiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (bitOrder == LSBFIRST) {
|
||||
digitalWrite(dataPin, val & 1);
|
||||
val >>= 1;
|
||||
} else {
|
||||
digitalWrite(dataPin, (val & 128) != 0);
|
||||
val <<= 1;
|
||||
}
|
||||
|
||||
// insert delay on super fast processors to slow down clock
|
||||
// and allow a bit of time for slew rate rise when using 3v processor with 5v logic
|
||||
#if (F_CPU > 40000000)
|
||||
delayMicroseconds(1); // min pulse width is 230ns
|
||||
#endif
|
||||
digitalWrite(clockPin, HIGH);
|
||||
|
||||
#if (F_CPU > 40000000) // insert delay on super fast processors to slow down clock
|
||||
delayMicroseconds(1); // min pulse width is 230ns
|
||||
#endif
|
||||
digitalWrite(clockPin, LOW);
|
||||
}
|
||||
}
|
||||
|
||||
// hd44780cmd() - emulate hd44780 commands best we can
|
||||
// for now, silently drop unsupported commands
|
||||
int hd44780cmd(uint8_t value)
|
||||
{
|
||||
// detect the hd44780 command
|
||||
if(value & HD44780_SETDDRAMADDR)
|
||||
{
|
||||
_cgmode = 0; // back to ddram mode
|
||||
devicewrite(CMD_SETDIGPOINTER | (value & 0xf));
|
||||
}
|
||||
else if(value & HD44780_SETCGRAMADDR)
|
||||
{
|
||||
_cgmode = 1; // enter cgram mode
|
||||
_cgindx = 0;
|
||||
_cgchar = (value >> 3) & 0x7; // for now limmit to 8 custom like hd44780
|
||||
}
|
||||
else if(value & HD44780_FUNCTIONSET)
|
||||
{
|
||||
// not supported
|
||||
}
|
||||
else if(value & HD44780_CURDISPSHIFT)
|
||||
{
|
||||
// not supported
|
||||
}
|
||||
else if(value & HD44780_DISPLAYCONTROL)
|
||||
{
|
||||
if(value & HD44780_DISPLAYON)
|
||||
devicewrite(CMD_DISPLAYON);
|
||||
else
|
||||
devicewrite(CMD_DISPLAYOFF);
|
||||
}
|
||||
else if(value & HD44780_ENTRYMODESET)
|
||||
{
|
||||
// not supported
|
||||
}
|
||||
else if(value & HD44780_RETURNHOME)
|
||||
{
|
||||
_cgmode = 0; // back to ddram mode
|
||||
devicewrite(CMD_SETDIGPOINTER);
|
||||
}
|
||||
else if(value & HD44780_CLEARDISPLAY)
|
||||
{
|
||||
_cgmode = 0; // back to ddram mode
|
||||
device_clear();
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
void device_clear()
|
||||
{
|
||||
devicewrite(CMD_SETDIGPOINTER);
|
||||
for(uint8_t col = 0; col < 16; col++)
|
||||
{
|
||||
devicewrite(' ');
|
||||
}
|
||||
devicewrite(CMD_SETDIGPOINTER);
|
||||
}
|
||||
|
||||
}; // end of class definition
|
||||
#endif
|
||||
Reference in New Issue
Block a user