|
|
|
extern "C" {
|
|
|
|
#include <Wire/Wire.h>
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "../global.h"
|
|
|
|
#include "../configs/LCD/lcd.h"
|
|
|
|
#include "twiLCD.h"
|
|
|
|
|
|
|
|
#ifdef TWI_LCD_DPOT_CTRL
|
|
|
|
#include "../ds1803/ds1803.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
twiLCD::twiLCD()
|
|
|
|
{
|
|
|
|
#if defined(__AVR_ATmega168__) && !defined(TWI_LCD_SMALL)
|
|
|
|
#if defined(TWI_LCD_CTRL) && !defined(TWI_LCD_BL_PWM)
|
|
|
|
backlightStatus = 0;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef TWI_LCD_BL_PWM
|
|
|
|
pinMode(TWI_LCD_BACKLIGHT, HIGH);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
displayStatus = false;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef WIRE_LIB_SCAN_MOD
|
|
|
|
/*if (!Wire.isStarted())*/ Wire.begin();
|
|
|
|
#else
|
|
|
|
Wire.begin();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
twiLCD LCD = twiLCD();
|
|
|
|
|
|
|
|
void twiLCD::Init() {
|
|
|
|
#ifdef TWI_LCD_CTRL
|
|
|
|
backlightOff();
|
|
|
|
#ifdef TWI_LCD_DPOT_CTRL
|
|
|
|
setBrightness(0);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
delay(20);
|
|
|
|
/////////// 4 pin initialization
|
|
|
|
writeCommand(0x03); // function set: 4 pin initialization
|
|
|
|
delay(5);
|
|
|
|
writeCommand(0x03); // function set: 4 pin initialization
|
|
|
|
delay(1);
|
|
|
|
writeCommand(0x03); // function set: 4 pin initialization
|
|
|
|
delay(1);
|
|
|
|
writeCommand(0x02); // function set: 4 pin initialization
|
|
|
|
/////////// end of 4 pin initialization
|
|
|
|
|
|
|
|
|
|
|
|
writeCommand(LCD_FUNCTION_SET); // function set: 4-bit interface, 1 display lines, 5x7 font
|
|
|
|
writeCommand(LCD_ENTRY_MODE);
|
|
|
|
writeCommand(LCD_CURSOR);
|
|
|
|
clearScreen();
|
|
|
|
|
|
|
|
writeCommand(LCD_CLOSE_INIT);
|
|
|
|
|
|
|
|
#if defined(__AVR_ATmega168__) && !defined(TWI_LCD_SMALL)
|
|
|
|
#ifdef TWI_LCD_CTRL
|
|
|
|
#if defined(TWI_LCD_BL_PWM) || defined(TWI_LCD_DPOT_CTRL)
|
|
|
|
#ifdef TWI_LCD_DPOT_CTRL
|
|
|
|
setBrightness();
|
|
|
|
#endif
|
|
|
|
backlightOn(TWI_LCD_BL_LEVEL);
|
|
|
|
#else
|
|
|
|
backlightOn();
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
displayStatus = true;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
boolean twiLCD::checkLCDBusy(void)
|
|
|
|
{
|
|
|
|
Wire.requestFrom(PCF8574_RADDR, 1);
|
|
|
|
|
|
|
|
while (!Wire.available());
|
|
|
|
|
|
|
|
return (Wire.receive() & TWI_LCD_BUSY ? true : false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void twiLCD::writeCommand(uint8_t value)
|
|
|
|
{
|
|
|
|
int value1 = 0;
|
|
|
|
int control = 0; // stores RS and RW
|
|
|
|
|
|
|
|
#ifdef TWI_LCD_USE_TIMEOUT
|
|
|
|
previousMillis = millis();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
control = value >> 8; // get the control signals RS and RW
|
|
|
|
control >>= 5; // shift the control signals to the left
|
|
|
|
|
|
|
|
Wire.beginTransmission(PCF8574_WADDR);
|
|
|
|
|
|
|
|
value1 = value;
|
|
|
|
cbi(value1, TWI_LCD_DATAL); // Turn off LByte
|
|
|
|
|
|
|
|
cbi(value1, TWI_LCD_RS);
|
|
|
|
cbi(value1, TWI_LCD_RW);
|
|
|
|
|
|
|
|
sendPulse(value1);
|
|
|
|
|
|
|
|
delay(1);
|
|
|
|
|
|
|
|
cbi(value, TWI_LCD_DATAH); // Turn off HByte
|
|
|
|
value <<= 4;
|
|
|
|
|
|
|
|
cbi(value, TWI_LCD_RS);
|
|
|
|
cbi(value, TWI_LCD_RW);
|
|
|
|
|
|
|
|
sendPulse(value);
|
|
|
|
|
|
|
|
Wire.endTransmission();
|
|
|
|
|
|
|
|
delay(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void twiLCD::writeData(uint8_t value)
|
|
|
|
{
|
|
|
|
int value1 = 0;
|
|
|
|
int control = 0; // stores RS and RW
|
|
|
|
|
|
|
|
// Wait for the LCD to be ready
|
|
|
|
|
|
|
|
#ifdef TWI_LCD_USE_TIMEOUT
|
|
|
|
previousMillis = millis();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
control = value >> 8; // get the control signals RS and RW
|
|
|
|
control >>= 5; // shift the control signals to the left
|
|
|
|
|
|
|
|
value1 = value;
|
|
|
|
cbi(value1, TWI_LCD_DATAL); // Turn off LByte
|
|
|
|
sbi(value1, TWI_LCD_RS);
|
|
|
|
cbi(value1, TWI_LCD_RW);
|
|
|
|
|
|
|
|
while (checkLCDBusy());
|
|
|
|
|
|
|
|
Wire.beginTransmission(PCF8574_WADDR);
|
|
|
|
sendPulse(value1);
|
|
|
|
|
|
|
|
delay(1);
|
|
|
|
|
|
|
|
cbi(value, TWI_LCD_DATAH); // Turn off HByte
|
|
|
|
value <<= 4;
|
|
|
|
|
|
|
|
sbi(value, TWI_LCD_RS);
|
|
|
|
cbi(value, TWI_LCD_RW);
|
|
|
|
|
|
|
|
sendPulse(value);
|
|
|
|
Wire.endTransmission();
|
|
|
|
}
|
|
|
|
|
|
|
|
void twiLCD::sendPulse(int value)
|
|
|
|
{
|
|
|
|
cbi(value, TWI_LCD_ENABLE);
|
|
|
|
writeToPCF(value);
|
|
|
|
|
|
|
|
sbi(value, TWI_LCD_ENABLE);
|
|
|
|
writeToPCF(value);
|
|
|
|
|
|
|
|
cbi(value, TWI_LCD_ENABLE);
|
|
|
|
writeToPCF(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void twiLCD::writeToPCF(int value)
|
|
|
|
{
|
|
|
|
#if defined(TWI_LCD_CTRL) && !defined(TWI_LCD_BL_PWM)
|
|
|
|
if (backlightStatus)
|
|
|
|
sbi(value, TWI_LCD_BACKLIGHT);
|
|
|
|
else
|
|
|
|
cbi(value, TWI_LCD_BACKLIGHT);
|
|
|
|
|
|
|
|
Wire.send(value);
|
|
|
|
#else
|
|
|
|
Wire.send(value);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void twiLCD::clearScreen(void)
|
|
|
|
{
|
|
|
|
writeCommand(LCD_CLEAR);
|
|
|
|
delay(100);
|
|
|
|
|
|
|
|
#if defined(__AVR_ATmega168__) && !defined(TWI_LCD_SMALL)
|
|
|
|
currentLine = 1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef LCD_USE_CLRSCREEN_CALLBACK
|
|
|
|
if (twiLCDcallbackFunc[0]) twiLCDcallbackFunc[0]();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void twiLCD::printString_P(const char *data)
|
|
|
|
{
|
|
|
|
int ch;
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
ch = pgm_read_byte( data++ );
|
|
|
|
if ( !ch ) return;
|
|
|
|
writeData(ch);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(__AVR_ATmega168__) && !defined(TWI_LCD_SMALL)
|
|
|
|
#ifdef TWI_LCD_USE_TIMEOUT
|
|
|
|
boolean twiLCD::checkTimeout(void)
|
|
|
|
{
|
|
|
|
if (displayStatus && millis() - previousMillis > TWI_LCD_TIMEOUT) {
|
|
|
|
turnOff();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef TWI_LCD_CTRL
|
|
|
|
#ifdef TWI_LCD_BL_PWM
|
|
|
|
void twiLCD::backlightOn(void)
|
|
|
|
{
|
|
|
|
digitalWrite(TWI_LCD_BACKLIGHT, HIGH);
|
|
|
|
}
|
|
|
|
|
|
|
|
void twiLCD::backlightOn(uint8_t value)
|
|
|
|
{
|
|
|
|
analogWrite(TWI_LCD_BACKLIGHT, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void twiLCD::backlightOff(void)
|
|
|
|
{
|
|
|
|
digitalWrite(TWI_LCD_BACKLIGHT, LOW);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
#ifdef TWI_LCD_DPOT_CTRL
|
|
|
|
void twiLCD::backlightOn(void)
|
|
|
|
{
|
|
|
|
DPOT.setWiper2(TWI_LCD_BL_LEVEL);
|
|
|
|
}
|
|
|
|
|
|
|
|
void twiLCD::backlightOn(uint8_t value)
|
|
|
|
{
|
|
|
|
DPOT.setWiper2(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void twiLCD::backlightOff(void)
|
|
|
|
{
|
|
|
|
DPOT.setWiper2(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void twiLCD::setBrightness(void)
|
|
|
|
{
|
|
|
|
DPOT.setWiper1(TWI_LCD_DB_LEVEL);
|
|
|
|
}
|
|
|
|
|
|
|
|
void twiLCD::setBrightness(uint8_t value)
|
|
|
|
{
|
|
|
|
DPOT.setWiper1(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
void twiLCD::backlightOn(void)
|
|
|
|
{
|
|
|
|
int val = 0;
|
|
|
|
backlightStatus = 1;
|
|
|
|
sbi(val, TWI_LCD_BACKLIGHT);
|
|
|
|
|
|
|
|
Wire.beginTransmission(PCF8574_WADDR);
|
|
|
|
Wire.send(val);
|
|
|
|
Wire.endTransmission();
|
|
|
|
}
|
|
|
|
|
|
|
|
void twiLCD::backlightOff(void)
|
|
|
|
{
|
|
|
|
int val = 0;
|
|
|
|
backlightStatus = 0;
|
|
|
|
cbi(val, TWI_LCD_BACKLIGHT);
|
|
|
|
|
|
|
|
Wire.beginTransmission(PCF8574_WADDR);
|
|
|
|
Wire.send(val);
|
|
|
|
Wire.endTransmission();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void twiLCD::turnOff(void)
|
|
|
|
{
|
|
|
|
writeCommand(LCD_TURN_OFF);
|
|
|
|
#if defined(TWI_LCD_CTRL)
|
|
|
|
backlightOff();
|
|
|
|
#ifdef TWI_LCD_DPOT_CTRL
|
|
|
|
setBrightness(0);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
displayStatus = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This function needs a rewrite
|
|
|
|
**/
|
|
|
|
void twiLCD::setCursor(int index)
|
|
|
|
{
|
|
|
|
//0-79, index for one line display, 8 bit mode
|
|
|
|
//0-39 and 64-103 for lines one and two of two line display, not implemented yet
|
|
|
|
int cmd = 128+index;
|
|
|
|
writeCommand(cmd);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This function needs a rewrite
|
|
|
|
**/
|
|
|
|
void twiLCD::moveToXY(uint8_t row, uint8_t column)
|
|
|
|
{
|
|
|
|
int position;
|
|
|
|
|
|
|
|
// Determine the new position
|
|
|
|
position = (row * 20) + column;
|
|
|
|
|
|
|
|
// Send the correct commands to the command register of the LCD
|
|
|
|
if(position < 20)
|
|
|
|
writeCommand(0x80 | position);
|
|
|
|
else if(position >= 20 && position < 40)
|
|
|
|
writeCommand(0x80 | (position % 20 + 0x40));
|
|
|
|
else if(position >= 41 && position < 60)
|
|
|
|
writeCommand(0x80 | (position % 40 + 0x14));
|
|
|
|
else if(position >= 20 && position < 40)
|
|
|
|
writeCommand(0x80 | (position % 60 + 0x54));
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t twiLCD::getCurrentLine(void)
|
|
|
|
{
|
|
|
|
return currentLine;
|
|
|
|
}
|
|
|
|
|
|
|
|
void twiLCD::goToLine(uint8_t line)
|
|
|
|
{
|
|
|
|
if (line > LCD_ROWS) return;
|
|
|
|
moveToXY(line - 1, 0);
|
|
|
|
currentLine = line;
|
|
|
|
}
|
|
|
|
|
|
|
|
void twiLCD::goToNextLine(void)
|
|
|
|
{
|
|
|
|
if (currentLine+1 > LCD_ROWS) {
|
|
|
|
goToLine(1);
|
|
|
|
} else {
|
|
|
|
goToLine(currentLine+1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void twiLCD::goHome(void)
|
|
|
|
{
|
|
|
|
writeCommand(LCD_GO_HOME); // set cursor position to zero
|
|
|
|
currentLine = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void twiLCD::clearLine(void)
|
|
|
|
{
|
|
|
|
int ii;
|
|
|
|
moveToXY(currentLine-1, 0);
|
|
|
|
|
|
|
|
for (ii=0;ii<LCD_COLUMNS;ii++)
|
|
|
|
{
|
|
|
|
printString(" ");
|
|
|
|
}
|
|
|
|
|
|
|
|
moveToXY(currentLine-1, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void twiLCD::shiftDisplayLeft(void)
|
|
|
|
{
|
|
|
|
writeCommand(LCD_SHIFT_LEFT);
|
|
|
|
}
|
|
|
|
|
|
|
|
void twiLCD::shiftDisplayRight(void)
|
|
|
|
{
|
|
|
|
writeCommand(LCD_SHIFT_RIGHT);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool twiLCD::getCurrentStatus(void)
|
|
|
|
{
|
|
|
|
return displayStatus;
|
|
|
|
}
|
|
|
|
|
|
|
|
void twiLCD::printInteger(uint16_t integer, bool leadingZero)
|
|
|
|
{
|
|
|
|
uint8_t thousands = integer / 1000;
|
|
|
|
uint8_t hundreds = (integer - thousands*1000) / 100;
|
|
|
|
uint8_t tens = (integer - thousands*1000 - hundreds*100 ) / 10;
|
|
|
|
writeData(tens + 0x30);
|
|
|
|
|
|
|
|
uint8_t ones = (integer - thousands*1000 - hundreds*100 - tens*10);
|
|
|
|
writeData(ones + 0x30);
|
|
|
|
}
|
|
|
|
|
|
|
|
void twiLCD::printInteger(int16_t integer)
|
|
|
|
{
|
|
|
|
if (integer < 0) {
|
|
|
|
printString("-");
|
|
|
|
integer = 0 - integer;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Break down the original number into the thousands, hundreds, tens,
|
|
|
|
// and ones places and then immediately write that value to the LCD
|
|
|
|
uint8_t thousands = integer / 1000;
|
|
|
|
if (thousands > 0) writeData(thousands + 0x30);
|
|
|
|
|
|
|
|
uint8_t hundreds = (integer - thousands*1000) / 100;
|
|
|
|
if (hundreds > 0 || thousands > 0)
|
|
|
|
writeData(hundreds + 0x30);
|
|
|
|
|
|
|
|
uint8_t tens = (integer - thousands*1000 - hundreds*100 ) / 10;
|
|
|
|
if (tens || hundreds > 0 || thousands > 0)
|
|
|
|
writeData(tens + 0x30);
|
|
|
|
|
|
|
|
uint8_t ones = (integer - thousands*1000 - hundreds*100 - tens*10);
|
|
|
|
writeData(ones + 0x30);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef LCD_USE_CLRSCREEN_CALLBACK
|
|
|
|
void twiLCD::setClrscreenCallback(void (*userFunc)(void))
|
|
|
|
{
|
|
|
|
twiLCDcallbackFunc[0] = userFunc;
|
|
|
|
}
|
|
|
|
#endif
|