mirror of https://github.com/boxtec/tinyLCD_I2C
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.
237 lines
5.4 KiB
237 lines
5.4 KiB
// $Id: tinyLCD_I2C.ino,v 1.13 2013-07-03 14:59:55 obiwan Exp $
|
|
|
|
#include <TinyWireS.h>
|
|
#include <LiquidCrystal.h>
|
|
#include <EEPROM.h>
|
|
|
|
// Debug Mode
|
|
//#define DBGME
|
|
|
|
// commands
|
|
#define LCD_CLEARDISPLAY 0x01
|
|
#define LCD_RETURNHOME 0x02
|
|
#define LCD_ENTRYMODESET 0x04
|
|
#define LCD_DISPLAYCONTROL 0x08
|
|
#define LCD_CURSORSHIFT 0x10
|
|
#define LCD_FUNCTIONSET 0x20
|
|
#define LCD_SETCGRAMADDR 0x40
|
|
#define LCD_SETDIMENSION 0x9f
|
|
#define LCD_SETCURSOR 0x9e
|
|
#define LCD_SHOWFIRMWAREREVISION 0x9d
|
|
#define LCD_SETADDRESS 0x9c
|
|
#define LCD_SETCONTRAST 0x9b
|
|
|
|
// flags for backlight control
|
|
#define LCD_BACKLIGHT 0x81
|
|
#define LCD_NOBACKLIGHT 0x80
|
|
#define LCD_SETBACKLIGHT 0x82
|
|
|
|
// I2C default address
|
|
#define I2C_SLAVE_ADDRESS 0x50
|
|
|
|
#define CONTRAST_PIN 2
|
|
#define BACKLIGHT_PIN 3
|
|
|
|
#define EEBASE_ADDR 24
|
|
|
|
// Timeout in us after which we close the buffer and write it out
|
|
#define CHARBUF_TIMEOUT 150
|
|
|
|
volatile uint8_t i2c_regs[] =
|
|
{
|
|
0xDE,
|
|
0xAD,
|
|
0xBE,
|
|
0xEF,
|
|
};
|
|
// Tracks the current register pointer position
|
|
volatile byte reg_position;
|
|
// buffer index for lcd.print strings
|
|
unsigned int buf_ix = 0;
|
|
// store time when the last char to print was received
|
|
unsigned long lastwrite = 0;
|
|
// more data expected
|
|
volatile byte data_expected = 0;
|
|
|
|
|
|
// initialize the library with the numbers of the interface pins
|
|
// LiquidCrystal(rs, enable, d4, d5, d6, d7);
|
|
// Breadboard:
|
|
//LiquidCrystal lcd(0, 3, 7, 8, 9, 10);
|
|
// tinyLCD_I2C:
|
|
LiquidCrystal lcd(3, 1, 9, 8, 7, 5);
|
|
uint8_t slave_address;
|
|
|
|
void setup() {
|
|
slave_address = read_address();
|
|
if (! slave_address) {
|
|
slave_address = I2C_SLAVE_ADDRESS;
|
|
}
|
|
TinyWireS.begin(slave_address);
|
|
TinyWireS.onReceive(receive_event);
|
|
//TinyWireS.onRequest(requestEvent);
|
|
|
|
analogWrite(CONTRAST_PIN, 10);
|
|
analogWrite(BACKLIGHT_PIN, 255);
|
|
lcd.begin(16,2);
|
|
lcd.clear();
|
|
//test_lcd();
|
|
}
|
|
|
|
void loop() {
|
|
TinyWireS_stop_check();
|
|
}
|
|
|
|
|
|
// not used yet:
|
|
void request_event()
|
|
{
|
|
TinyWireS.send(i2c_regs[reg_position]);
|
|
// Increment the reg position on each read, and loop back to zero
|
|
reg_position = (reg_position+1) % sizeof(i2c_regs);
|
|
lcd.setCursor(3, 1);
|
|
lcd.print("=");
|
|
}
|
|
|
|
void receive_event(uint8_t howMany) {
|
|
//static int buf_ix = 0;
|
|
if (howMany < 1) {
|
|
// Sanity-check
|
|
return;
|
|
}
|
|
while (TinyWireS.available()) {
|
|
char cmd = TinyWireS.receive();
|
|
// wait for a command
|
|
if ( cmd == 0 && howMany > 1 ) {
|
|
char rxbuffer = TinyWireS.receive();
|
|
command_byte(rxbuffer, howMany - 2);
|
|
} else if ( cmd > 1 ) {
|
|
lcd.print(cmd);
|
|
}
|
|
}
|
|
}
|
|
|
|
void command_byte(char c, byte bytesInBuffer) {
|
|
uint8_t col, row, addr, val;
|
|
if (c & 0xC0 == LCD_SETCGRAMADDR) {
|
|
// construct character
|
|
uint8_t cdata[8];
|
|
uint8_t i;
|
|
for (i = 0; i < 8; i++) {
|
|
cdata[i] = TinyWireS.receive();
|
|
}
|
|
lcd.createChar((c & 0x38) >> 3, cdata);
|
|
} else if (c & 0xF8 == LCD_DISPLAYCONTROL || c & 0xF0 == LCD_CURSORSHIFT || c & 0xFC == LCD_ENTRYMODESET) {
|
|
lcd.command(c);
|
|
}
|
|
switch (c) {
|
|
case LCD_CLEARDISPLAY:
|
|
lcd.clear();
|
|
break;
|
|
case LCD_RETURNHOME:
|
|
lcd.home();
|
|
break;
|
|
case LCD_BACKLIGHT:
|
|
analogWrite(BACKLIGHT_PIN, 255);
|
|
break;
|
|
case LCD_NOBACKLIGHT:
|
|
analogWrite(BACKLIGHT_PIN, 0);
|
|
break;
|
|
case LCD_SETBACKLIGHT:
|
|
val = TinyWireS.receive();
|
|
analogWrite(BACKLIGHT_PIN, val);
|
|
break;
|
|
case LCD_SETCONTRAST:
|
|
val = TinyWireS.receive();
|
|
analogWrite(CONTRAST_PIN, val);
|
|
break;
|
|
case LCD_SETDIMENSION:
|
|
col = TinyWireS.receive();
|
|
row = TinyWireS.receive();
|
|
lcd_begin(col, row);
|
|
break;
|
|
case LCD_SETCURSOR:
|
|
col = TinyWireS.receive();
|
|
row = TinyWireS.receive();
|
|
lcd.setCursor(col, row);
|
|
break;
|
|
case LCD_SHOWFIRMWAREREVISION:
|
|
lcd_revision();
|
|
break;
|
|
case LCD_SETADDRESS:
|
|
addr = TinyWireS.receive();
|
|
if (addr && ! (addr & 0x80)) {
|
|
write_address(addr);
|
|
}
|
|
break;
|
|
default:
|
|
#ifdef DBGME
|
|
lcd.print("Unknown Com!");
|
|
lcd.setCursor(1,1);
|
|
lcd.print(int(c));
|
|
#endif
|
|
break;
|
|
}
|
|
}
|
|
|
|
// start the display, helper for init()
|
|
void lcd_begin(uint8_t cols, uint8_t rows) {
|
|
lcd.begin(cols,rows);
|
|
lcd.home();
|
|
lcd.clear();
|
|
}
|
|
|
|
// display revision
|
|
void lcd_revision() {
|
|
lcd.clear();
|
|
lcd.print("tinyLCD_I2C :");
|
|
lcd.setCursor(0, 1);
|
|
lcd.print("$Revision: 1.13 $");
|
|
}
|
|
|
|
|
|
void test_lcd() {
|
|
lcd.print("==T=E=S=T=======");
|
|
delay(1200);
|
|
lcd.setCursor(0,1);
|
|
lcd.print("XXXXXXXXXXXXXXX");
|
|
delay(1200);
|
|
lcd.clear();
|
|
lcd.print("XXXXXXXXXXXXXXXX");
|
|
lcd.setCursor(0,1);
|
|
lcd.print("================");
|
|
delay(2000);
|
|
lcd.clear();
|
|
lcd.setCursor(0,1);
|
|
lcd.print("Address: ");
|
|
lcd.print(slave_address, HEX);
|
|
delay(3000);
|
|
lcd.clear();
|
|
lcd.print("Uptime now (s):");
|
|
while ( 1 ) {
|
|
lcd.setCursor(0,1);
|
|
lcd.print(millis()/1);
|
|
lcd.print(" ms");
|
|
}
|
|
}
|
|
|
|
void write_address(uint8_t address) {
|
|
EEPROM.write(EEBASE_ADDR, address);
|
|
// write marker to know that we have a custom I2C address
|
|
EEPROM.write(EEBASE_ADDR + 1, 't');
|
|
EEPROM.write(EEBASE_ADDR + 2, 'L');
|
|
EEPROM.write(EEBASE_ADDR + 3, 'C');
|
|
EEPROM.write(EEBASE_ADDR + 4, 'D');
|
|
EEPROM.write(EEBASE_ADDR + 5, 0x00); // no more configs for the moment
|
|
}
|
|
|
|
uint8_t read_address() {
|
|
if (EEPROM.read(EEBASE_ADDR + 1) == 't' &&
|
|
EEPROM.read(EEBASE_ADDR + 2) == 'L' &&
|
|
EEPROM.read(EEBASE_ADDR + 3) == 'C' &&
|
|
EEPROM.read(EEBASE_ADDR + 4) == 'D') {
|
|
return EEPROM.read(EEBASE_ADDR);
|
|
}
|
|
return 0;
|
|
}
|