Had a look through my archives and found this - no guarantees but what it does is maintain an in-memory copy of the display for a 4x20 character LCD and displays this on a colour LCD display. It assumes that LCD Smartie is sending data for a Matrix Orbital 4x20 display. You should be able to modify the display calls to suit your own needs. Hope it helps.
Code: Select all
// UNO config
//#define LCD_RD 14 //A0 but not used
//#define LCD_WR 15 //A1
//#define LCD_RS 16 //A2
//#define LCD_CS 17 //A3
//#define LCD_RST 18 //A4
// DUE config
#define LCD_RD 54 //A0 but not used
#define LCD_WR 55 //A1
#define LCD_RS 56 //A2
#define LCD_CS 57 //A3
#define LCD_RST 58 //A4
//Duemilanove/Diecimila/UNO/etc ('168 and '328 chips) microcontoller:
// Color definitions
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
#define DISPLAY_WIDTH 20
#define DISPLAY_HEIGHT 4
#define DISPLAY_LINES 12
#define FONTSIZE 2
#define LCD_WIDTH 320
#define LCD_HEIGHT 240
#define XOFF 32
#define YOFF 80
#define XMULT FONTSIZE*6
#define YMULT FONTSIZE*8
#include <Wire.h>
#include <SPI.h>
#include <SdFat.h>
#include <UTFT.h>
UTFT LCD(SPFD5408A,LCD_RS,LCD_WR,LCD_CS,LCD_RST);
//UTFT LCD(SPFD5408A,16,15,17,18); // Remember to change the model parameter to suit your display module!
//UTFT LCD; // Remember to change the model parameter to suit your display module!
// Declare which fonts we will be using
extern uint8_t BigFont[];
static uint8_t inascii=0; // set to 1 if reading ascii data
static uint8_t received[DISPLAY_WIDTH][DISPLAY_HEIGHT] =
{ ' ',' ',' ',' ', ' ',' ',' ',' ', '*',' ',' ',' ', '*',' ',' ',' ', 'L',' ',' ',' ',
'C','o',' ',' ', 'D','n',' ',' ', ' ',' ',' ',' ', ' ',' ',' ',' ', 'S','A',' ',' ',
'M','r',' ',' ', 'A','d',' ',' ', 'R','u',' ',' ', 'T','i',' ',' ', 'I','n',' ',' ',
'E','o',' ',' ', '*',' ',' ',' ', '*',' ',' ',' ', ' ',' ',' ',' ', ' ',' ',' ',' ' };
static uint8_t displayed[DISPLAY_WIDTH][DISPLAY_HEIGHT];
/*
// Mapping table maps incoming characters - this needs work and verifying
#define MAP_SIZE 62
PROGMEM prog_uchar cmap[MAP_SIZE*2] = {
0x67, 0xE7, 0x6A, 0xEA, 0x70, 0xF0, 0x71, 0xF1, 0x79, 0xF9,
0xE4, 0xE1, 0xF1, 0xEE, 0xF6, 0xEF, 0xFC, 0xF5,
//accented -> plain equivalent and misc symbol translation
0xA3, 0xED, 0xB0, 0xDF, 0xB5, 0xE4, 0xC0, 0x41, 0xC1, 0x41,
0xC2, 0x41, 0xC3, 0x41, 0xC4, 0x41, 0xC5, 0x41, 0xC8, 0x45,
0xC9, 0x45, 0xCA, 0x45, 0xCB, 0x45, 0xCC, 0x49, 0xCD, 0x49,
0xCE, 0x49, 0xCF, 0x49, 0xD1, 0x43, 0xD2, 0x4F, 0xD3, 0x4F,
0xD4, 0x4F, 0xD5, 0x4F, 0xD6, 0x4F, 0xD8, 0x4F, 0xD9, 0x55,
0xDA, 0x55, 0xDB, 0x55, 0xDC, 0x55, 0xDD, 0x59, 0xDF, 0xE2,
0xE0, 0x61, 0xE1, 0x61, 0xE2, 0x61, 0xE3, 0x61, 0xE5, 0x61,
0xE7, 0x63, 0xE8, 0x65, 0xE9, 0x65, 0xEA, 0x65, 0xEB, 0x65,
0xEC, 0x69, 0xED, 0x69, 0xEE, 0x69, 0xEF, 0x69, 0xF2, 0x6F,
0xF3, 0x6F, 0xF4, 0x6F, 0xF5, 0x6F, 0xF8, 0x6F, 0xF7, 0xFD,
0xF9, 0x75, 0xFA, 0x75, 0xFB, 0x75
};
*/
static uint8_t custom_chars[8][8];
static unsigned int curx,cury;
// x=0 to 39, y=0 to 3
void lcd_setCursor( uint8_t x, uint8_t y )
{ if (x>=DISPLAY_WIDTH) x=0;
if (y>=DISPLAY_HEIGHT) y=0;
curx=x;
cury=y;
}
void draw_custom_char(uint8_t c, unsigned int x, unsigned int y)
{ uint8_t i,ch;
word j;
word temp;
LCD.printChar(' ',x,y);
for (i=0; i<8; i++) // for each row
{ ch=custom_chars[c][i]; // This row of the character - 1 row is 240/(12*8)=2 pixels high, each column is 320/40=8 pixels wide
for (j=0; j<6; j++) // for each column
{ if (((ch>>(5-j))&1)!=0)
{ for (int k=0; k<FONTSIZE; k++)
{ for (int l=0; l<FONTSIZE; l++)
{ LCD.drawPixel(x+(j*2)+k , y+(i*2)+l); }
}
}
}
}
}
void lcd_clear()
{ LCD.clrScr();
LCD.setFont(BigFont);
LCD.setColor(0, 0, 200);
LCD.fillRect(0, 0 , LCD_WIDTH-1, LCD_HEIGHT-1);
LCD.setColor(255,255,255);
lcd_setCursor(0,0);
}
//=============================================================================================
// setup code called at power up or reset
//=============================================================================================
void setup(void) {
Serial.begin(9600);
Serial.println("8 Bit LCD test!");
// for (int i=2; i<10; i++)
// { Serial.print("D"); Serial.print(i); Serial.print(" "); Serial.print((long unsigned int)g_APinDescription[i].pPort); Serial.print(" "); Serial.println((long unsigned int)g_APinDescription[i].ulPin); }
LCD.InitLCD();
lcd_clear();
lcd_setCursor(0,0);
}
//=============================================================================================
// Main program continually called till power off
// note: an http request ends with a blank line
//=============================================================================================
void loop()
{ static uint16_t x=0,y=0;
uint8_t c;
// ------------------ Check for commands from the serial port -------------------------------------
if (Serial.available()>0)
{ c = nextb();
emulate_matrix_orbital(c);
}
c=received[x][y];
if (c!=displayed[x][y])
{ displayed[x][y]=c;
if ( (c>0x00) && (c<0x09) ) // Custom characters
{ // Output the custom character
uint8_t cnum; if (c==0x08) cnum=0; else cnum=c; // 0-7
draw_custom_char(cnum,(x*XMULT)+XOFF,(y*YMULT)+YOFF);
}
else
{ // change accented char to plain, detect and change descenders
// if (c>=pgm_read_byte_near(cmap))
// { for (int i=0; i<MAP_SIZE;i++)
// { if (c==pgm_read_byte_near(cmap + (i*2)))
// { c=pgm_read_byte_near(cmap + (i*2+1)); break; } // if we find it change it
// }
// }
LCD.printChar(c,(x*XMULT)+XOFF,(y*YMULT)+YOFF);
}
}
x=x+1;
if (x>=DISPLAY_WIDTH) { x=0; y=y+1; }
if (y>=DISPLAY_HEIGHT) y=0;
delay(1);
}
//=======================================================================================================
// routine to wait and get the next character
//=======================================================================================================
uint8_t nextch()
{ static uint8_t c;
while (Serial.available()==0) delay(5); // Wait for the next character
c=(uint8_t) (Serial.read() & 0xff); // read the incoming byte
return c;
}
//=======================================================================================================
// routine to wait and get the next byte
//=======================================================================================================
uint8_t nextb()
{ unsigned int c,d;
if (inascii==0) return nextch(); // read the next byte as a byte if we are not in ascii mode
c=nextch()-'0'; if (c>9) c=((c+'0')-'A')+10; // read 2 digit hex as the byte
d=nextch()-'0'; if (d>9) d=((d+'0')-'A')+10; //
nextch(); // ignore , or ], or \n
return (((c*16)+d) & 0xff);
}
//=======================================================================================================
// routine to emulate the matrix orbital commands
//=======================================================================================================
void emulate_matrix_orbital(uint8_t c)
{ uint8_t rxbyte=c;
uint8_t i;
int num;
#define CASE break; case
// if (rxbyte == '[') // Ascii commands sent
// { inascii=1; // set ascii mode
// rxbyte=nextb(); // read the next byte
// }
// else inascii=0; // else we are in binary mode
if (rxbyte == 0xFE) // Matrix Orbital uses 254 prefix for commands
{ while (rxbyte == 0xFE) { rxbyte = nextb(); } // ignore multiple 0xFE's
switch (rxbyte)
{ case 0: // ignore nulls
CASE 0x23: // Read serial number (or place large number)
CASE 0X24: // Read version number
CASE 0X26: // Poll key presses
CASE 0X33: // Change I2C slave address (1 parameter, address)
CASE 0X36: Serial.print(1); // Read version number
CASE 0X37: Serial.print(9); // Read module type (9 for LK204-25)
CASE 0X39: // Change baud rate (1 parameter, baud rate)
CASE 0X3B: // Exit flow-control mode
// CASE 0X3D: nextb(); nextb(); // Place vertical bar (2 parameters, column, length)
CASE 0X40: // Change the startup screen (followed by 32 or whatever chars)
CASE 0X41: // Auto transmit keypresses on
CASE 0x42: nextb(); // ignore time character
// analogWrite(backlight_pin, 180); // Set the backlight on (at previously set brightness)
CASE 0X43: // Auto line wrap on
CASE 0X44: // Auto line wrap off
CASE 0X45: // Clear key buffer
CASE 0x46: num=nextb();//analogWrite(backlight_pin, 255-num); // Set the backlight off
CASE 0x47: lcd_setCursor(nextb()-1,nextb()-1); // set cursor position
CASE 0x48: lcd_setCursor(0,0); // cursor home (reset display position)
CASE 0x4A: //tft.cursor(); // show underline cursor
CASE 0x4B: //tft.noCursor(); // underline cursor off
CASE 0x4C: //lcd.command(16); // move cursor left
CASE 0x4D: //lcd.command(20); // move cursor right
CASE 0x4E: num=nextb(); // define custom char num
for (i=0; i<8; i++) custom_chars[num][i]=nextb(); // Bit patterns
//lcd.createChar(num,chars);
CASE 0X4F: // Auto transmit keypress off
CASE 0x50: num=nextb(); //analogWrite(contrast_pin, 256-num); // Set the contrast value (0-255) from the variable (0-100)
CASE 0X51: //lcd.autoscroll(); // Auto scroll on
CASE 0X52: //lcd.noAutoscroll(); // Auto scroll off
CASE 0x53: //lcd.blink(); // show blinking block cursor
CASE 0x54: //lcd.noBlink(); // hide blinking block cursor
CASE 0X55: // Set debounce time (1 paramater, time)
CASE 0X56: //if (nextb() == 1) digitalWrite(GPO1, LOW); // General Purpose Output off (1 parameter, number)
CASE 0X57: //if (nextb() == 0) digitalWrite(GPO1, HIGH); // General Purpose Output on (1 parameter, number)
CASE 0x58: lcd_clear(); // clear display, cursor home
CASE 0x5B: //lcd.noCursor(); // cursor off
CASE 0X60: // Auto repeat mode off
CASE 0X68: // Initialize horizontal bar
CASE 0X6D: // Initialize medium number
CASE 0X6E: // Initialize lange numbers
CASE 0X6F: // Place medium numbers
CASE 0X73: // Initialize narrow vertical bar
CASE 0X76: // Initialize wide vertical bar
CASE 0X7C: // Place horizontal bar graph (4 parameters, column, row, direction, length)
CASE 0X7E: // Set auto repeat mode (1 parameter, mode)
CASE 0x80: //
CASE 0x81: LCD.setColor(nextb(),nextb(),nextb()); // Set Background Colour
CASE 0x82: // Set Foreground Colour
CASE 0x91: //analogWrite(contrast_pin, 256-nextb()); // Set the contrast value (0-255) and remember from the variable (0-100)
CASE 0x98: num=nextb(); //analogWrite(backlight_pin, num); // Set the backlight value (0-255)and remember (doesn't save value, though)
CASE 0x99: //analogWrite(backlight_pin, nextb()); // Set the backlight value (0-255) from the variable (0-100)
CASE 0XA0: // Transmission protocol select (1 parameter, protocol)
CASE 0XA4: // Setting a non-standart baudrate (1 parameter, speed)
CASE 0XC0: // Load custom characters (1 parameter, bank)
CASE 0XC1: // Save custom character (3 parameters, bank, id, data)
CASE 0XC2: // Save startup screen custom characters (2 parameters, id, data)
CASE 0XC3: // Set startup GPO state (2 parameters, number, state)
// CASE 0XC8: switch (nextb()) // Dallas 1-Wire
// { case 1: // Dallas 1-Wire transaction (6 parameters, flags, send, bits, receive, bits, data)
// case 2: // Search for a 1-Wire device
// default: break;
// }
CASE 0XD5: break; // Assign keypad codes
default: break; // all other commands ignored and parameter byte discarded
}
}
else if (rxbyte!='\n')
{ received[curx][cury]=rxbyte;
curx=curx+1;
if (curx>=DISPLAY_WIDTH) { curx=0; cury=cury+1; }
if (cury>=DISPLAY_HEIGHT) cury=0;
}
}