Skip to content

Instantly share code, notes, and snippets.

@albal
Created July 13, 2014 13:01
Show Gist options
  • Select an option

  • Save albal/5486214995efa7b653bd to your computer and use it in GitHub Desktop.

Select an option

Save albal/5486214995efa7b653bd to your computer and use it in GitHub Desktop.
Tisplay
/*
Al West, 2014, UK.
compiles to 6,240 bytes
Demonstrates the use a 20x4 LCD display as Matrix Orbital Device in LCD Smartie.
This should work all LCD displays that are compatible with the Hitachi HD44780 driver.
This sketch takes data from LCD Smartie emulating a Matrix Orbital and shows desired data.
The circuit:
+ LCD K pin 16 Backlight GND to GND
+ LCD A pin 15 Backlight VDD to digital pin 10 (PWM) Brightness
+ LCD D7 pin 14 Data 7 to digital pin 12
+ LCD D6 pin 13 Data 6 to digital pin 11
+ LCD D5 pin 12 Data 5 to digital pin 9
+ LCD D4 pin 11 Data 4 to digital pin 8
- LCD D3 pin 10 NC
- LCD D2 pin 9 NC
- LCD D1 pin 8 NC
- LCD D0 pin 7 NC
+ LCD E pin 6 Enabled to digital pin 6
+ LCD RW pin 5 Read/Write to digital pin 5
+ LCD RS pin 4 Register Select to digital pin 4
+ LCD VO pin 3 Contrast to digital pin 3 (PWM) Contrast (use 100uf Cap between this pin and GND)
+ LCD 5V pin 2 Supply to 5V
+ LCD Gnd pin 1 Ground to GND
D1-D4 not connected.
Public Domain - some parts used from other code in the Public Domain
some graphic functions not possible with HD44780 type devices but template code left in place
*/
// include the library code:
#include <LiquidCrystal.h>
#include <EEPROM.h>
// Bit Rate - using 19200 but LCD Smartie defaults to 9600
const int baud = 19200;
// EEPROM address values
const byte BRIGHTNESS = 0; // Brightness
const byte CONTRAST = 1; // Contrast
const byte SERIAL_LO = 2; // Serial number low byte
const byte SERIAL_HI = 3; // Serial number high byte
// IO
const byte GPIO = 13; // Built in LED on Nano V3.0
const byte backLight = 10; // Use PWM to change brightness
const byte contrast = 3; // Use PWM to change contrast Connect 100uF between pin and GND
// Variables used in code - can probably optimise some of these out....
byte rxbyte;
byte temp;
byte addr;
byte level;
int val;
int i;
byte data[8]; // buffer for user character data
// initialize the library with the numbers of the interface pins
// LiquidCrystal(rs, rw, enable, d4, d5, d6, d7)
LiquidCrystal lcd(4, 5, 6, 8, 9, 11, 12);
void setup() {
// Set the use ouf our output pins
pinMode(GPIO, OUTPUT);
pinMode(backLight, OUTPUT);
pinMode(contrast, OUTPUT);
// Gather default values from EEPROM (could add code here to handle default if EEPROM has never been written to)
digitalWrite(GPIO, LOW);
analogWrite(backLight, EEPROM.read(BRIGHTNESS)); // Read brightness level out of EEPROM
analogWrite(contrast, EEPROM.read(CONTRAST)); // Read contrast level out of EEPROM
// set up the LCD's number of columns and rows:
lcd.begin(20, 4);
lcd.clear();
lcd.print(" Tisplay - TSEW, UK ");
// Custom Characters for the TSEW Logo
byte tsew1[8] = { B00000, B11111, B00100, B00100, B00100, B00100, B00000, B00000 };
byte tsew2[8] = { B00000, B11111, B10000, B11111, B00001, B11111, B00000, B00000 };
byte tsew3[8] = { B00000, B11111, B10000, B11110, B10000, B11111, B00000, B00000 };
byte tsew4[8] = { B00000, B10001, B10101, B10101, B10101, B11111, B00000, B00000 };
lcd.createChar(4, tsew1);
lcd.createChar(5, tsew2);
lcd.createChar(6, tsew3);
lcd.createChar(7, tsew4);
lcd.setCursor(1, 2);
lcd.write(4);
lcd.setCursor(2, 2);
lcd.write(5);
lcd.setCursor(3, 2);
lcd.write(6);
lcd.setCursor(4, 2);
lcd.write(7);
lcd.setCursor(8, 2);
// End of custome character generation and display
lcd.print("Input Ready");
lcd.setCursor(8, 3);
lcd.print("19200,8,N,1");
Serial.begin(baud);
// Wait until we receive some data - note we want to hold what data it is as we use it the first iteration
rxbyte = serial_getch();
// Clear display, wait a little and load in the custom icons
lcd.clear();
delay(200);
// Generate 3 different bar graph values for 33% 66% and 100%
byte bara[8] = { B10000, B10000, B10000, B10000, B10000, B10000, B11111, B10000 };
byte barb[8] = { B11100, B11100, B11100, B11100, B11100, B11100, B11111, B11100 };
byte barc[8] = { B11111, B11111, B11111, B11111, B11111, B11111, B11111, B11111 };
// Characters for CPU, Nivida Graphics Card, C: drive and D: drive and degrees symbol (DegC)
byte cpu[8] = { B10111, B10101, B10111, B00000, B11101, B10101, B11101, B00000 };
byte nv[8] = { B11101, B10110, B00000, B11111, B11101, B11111, B01100, B00000 };
byte cdrive[8] = { B01100, B10001, B10000, B01101, B00000, B11111, B11101, B11111 };
byte ddrive[8] = { B11000, B10101, B10100, B11001, B00000, B11111, B11101, B11111 };
byte degs[8] = { B11000, B11000, B00000, B00110, B01000, B01000, B00110, B00000 };
// Write characters into LCD RAM
lcd.createChar(1, barc);
lcd.createChar(2, bara);
lcd.createChar(3, barb);
lcd.createChar(4, cpu);
lcd.createChar(5, nv);
lcd.createChar(6, cdrive);
lcd.createChar(7, ddrive);
lcd.createChar(8, degs);
delay(20);
lcd.clear();
}
// Helper function to read serial input as clean 8 bit byte
byte serial_getch(){
int ch;
while (Serial.available() == 0){}
// read the incoming byte:
ch = Serial.read();
return (byte)(ch & 0xff);
}
// Main loop - note we come into it with rxbyte already set from exit of Setup() function
void loop(){
if (rxbyte == 254) //Matrix Orbital uses 254 prefix for commands
{
switch (serial_getch())
{
case 52: //set serial number /*USING EEPROM*/
EEPROM.write(SERIAL_HI, serial_getch());
EEPROM.write(SERIAL_LO, serial_getch());
break;
case 53: //read serial number /*USING EEPROM*/
Serial.write(EEPROM.read(SERIAL_HI));
Serial.write(EEPROM.read(SERIAL_LO));
break;
case 54: //read version number
Serial.write(0x11); //'v1.1
break;
case 55: //read module type
Serial.write(0x05); //'lcd_type'}='LCD2041'
break;
case 59: //exit flow-control mode
break;
case 64: // EEPROM Write (address, value)
addr = serial_getch();
val = serial_getch();
EEPROM.write(addr, val);
break;
case 65: // EEPROM Read (address)
addr = serial_getch(); // EEPROM address
val = EEPROM.read(addr); //
Serial.print(val);
break;
case 66: //backlight on (at previously set brightness)
// not implemented
analogWrite(backLight, level);
temp = serial_getch(); // time value - not used
break;
case 67: //auto line-wrap on
case 68: //auto line-wrap off
break;
case 70: //backlight off
analogWrite(backLight, 0);
break;
case 71: //set cursor position
temp = (serial_getch() - 1); //get column byte
lcd.setCursor(temp, serial_getch() - 1);
break;
case 72: //cursor home (reset display position)
lcd.setCursor(0, 0);
break;
case 74: //show underline cursor
lcd.command(0b00001110);
break;
case 75: //underline cursor off
case 84: //block cursor off
lcd.command(0b00001100);
break;
case 76: //move cursor left
lcd.command(16);
break;
case 77: //move cursor right
lcd.command(20);
break;
case 78: //define custom char
temp = serial_getch(); // Character ram value
for (i = 0; i < 8; i++){
data[i] = serial_getch();
}
lcd.createChar(temp, data);
break;
case 80: // Set contrast (but we save anyway)
case 145: // Set Contrast and save
level = 255 - serial_getch(); // Contrast value
analogWrite(contrast, level);
EEPROM.write(CONTRAST, level);
break;
case 81: //auto scroll on
case 82: //auto scroll off
break;
case 83: //show blinking block cursor
lcd.command(0b00001111);
break;
case 86: //GPO OFF
temp = serial_getch(); // GPIO Pin
digitalWrite(GPIO, LOW);
break;
case 87: //GPO ON
temp = serial_getch(); // GPIO Pin
digitalWrite(GPIO, HIGH);
break;
case 88: //clear display, cursor home
lcd.clear();
break;
case 96: //auto-repeat mode off (keypad)
break;
case 98: //Draw bitmap
temp = serial_getch(); // refid
temp = serial_getch(); // x
temp = serial_getch(); // y
break;
case 99: // set drawing color
temp = serial_getch();
break;
case 101: //Draw line continue
temp = serial_getch(); // x
temp = serial_getch(); // y
break;
case 104: //init horiz bar graph
temp = serial_getch(); // x1
temp = serial_getch(); // y1
temp = serial_getch(); // x2
temp = serial_getch(); // y2
break;
case 108:
temp = serial_getch(); // x1
temp = serial_getch(); // y1
temp = serial_getch(); // x2
temp = serial_getch(); // y2
break;
case 109: //init med size digits
break;
case 112: // Draw Pixel
temp = serial_getch(); // x
temp = serial_getch(); // y
break;
case 114: //draw rect
temp = serial_getch(); // colour
temp = serial_getch(); // x1
temp = serial_getch(); // y1
temp = serial_getch(); // x2
temp = serial_getch(); // y2
break;
case 115: //init narrow vert bar graph
case 118: //init wide vert bar graph
break;
case 120: //draw rect solid
temp = serial_getch(); // colour
temp = serial_getch(); // x1
temp = serial_getch(); // y1
temp = serial_getch(); // x2
temp = serial_getch(); // y2
break;
// case 145: //defined above see case 80:
case 152: //set brightness and save
level = serial_getch();
analogWrite(backLight, level);
EEPROM.write(BRIGHTNESS, level);
break;
case 153: //set backlight brightness
level = serial_getch();
analogWrite(backLight, level);
break;
default:
//all other commands ignored and parameter byte discarded
temp = serial_getch(); //dump the command code
break;
}
} //END OF COMMAND HANDLER
else
{
// Not a command character but still might be a special character
//change accented char to plain, detect and change descenders
switch (rxbyte)
{
//chars that have direct equivalent in LCD charmap
/* case 0x67: //g
rxbyte = 0xE7;
break;
case 0x6A: //j
rxbyte = 0xEA;
break;
case 0x70: //p
rxbyte = 0xF0;
break;
case 0x71: //q
rxbyte = 0xF1;
break;
case 0x79: //y
rxbyte = 0xF9;
break;
*/ case 0xE4: //ASCII "a" umlaut
rxbyte = 0xE1;
break;
case 0xF1: //ASCII "n" tilde
rxbyte = 0xEE;
break;
case 0xF6: //ASCII "o" umlaut
rxbyte = 0xEF; //was wrong in v0.86
break;
case 0xFC: //ASCII "u" umlaut
rxbyte = 0xF5;
break;
//accented -> plain equivalent
//and misc symbol translation
case 0xA3: //sterling (pounds)
rxbyte = 0xED;
break;
case 0xAC: //sterling (pounds)
rxbyte = 0xB0;
break;
case 0xB0: //degrees symbol
rxbyte = 0xDF;
break;
case 0xB5: //mu
rxbyte = 0xE4;
break;
case 0xC0: //"A" variants
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC4:
case 0xC5:
rxbyte = 0x41;
break;
case 0xC8: //"E" variants
case 0xC9:
case 0xCA:
case 0xCB:
rxbyte = 0x45;
break;
case 0xCC: //"I" variants
case 0xCD:
case 0xCE:
case 0xCF:
rxbyte = 0x49;
break;
case 0xD1: //"N" tilde -> plain "N"
rxbyte = 0x43;
break;
case 0xD2: //"O" variants
case 0xD3:
case 0xD4:
case 0xD5:
case 0xD6:
case 0xD8:
rxbyte = 0x4F;
break;
case 0xD9: //"U" variants
case 0xDA:
case 0xDB:
case 0xDC:
rxbyte = 0x55;
break;
case 0xDD: //"Y" acute -> "Y"
rxbyte = 0x59;
break;
case 0xE0: //"a" variants except umlaut
case 0xE1:
case 0xE2:
case 0xE3:
case 0xE5:
rxbyte = 0x61;
break;
case 0xE7: //"c" cedilla -> "c"
rxbyte = 0x63;
break;
case 0xE8: //"e" variants
case 0xE9:
case 0xEA:
case 0xEB:
rxbyte = 0x65;
break;
case 0xEC: //"i" variants
case 0xED:
case 0xEE:
case 0xEF:
rxbyte = 0x69;
break;
case 0xDF: //beta // LCDSmartie degree symbol??
case 0xF2: //"o" variants except umlaut
case 0xF3:
case 0xF4:
case 0xF5:
case 0xF8:
rxbyte = 0x6F;
break;
case 0xF7: //division symbol
rxbyte = 0xFD;
break;
case 0xF9: //"u" variants except umlaut
case 0xFA:
case 0xFB:
rxbyte = 0x75;
break;
default:
break;
}
// By now either special character is converted or it was printable already
lcd.print((char)rxbyte); //print it to lcd
}
rxbyte = serial_getch(); // Wait for the next byte and use value for next iteration
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment