You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

435 lines
8.0 KiB

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