October 15, 2013
by andyi
|
Here is the code I used for the Sainsmart 3.2 tft with SSD1289 controller.
I have stripped out everything else in case you wonder why there are so many switch statements with only one option.
As I said earlier it is based on UTFT (fonts stripped out to fit on 168).
Pin defs:-
MCU GLCD
PC0-5 -> DB0-5
PB1 -> DB6
PB2 -> DB7
PD0-7 -> DB08-15
PB0 -> CS
PB3 -> RS
PB4 -> WR
PB5 -> RESET
other GLCD pins
GND -> 0V
VCC -> 5V
LEDA -> 3.3V
RD -> 3.3V
I have used 10K resistors from the MCU to level shift down to ~3.4V
(also tried level shifting ICs but they take seem to be slower)
// Sainsmart 3.2 tft lcd test script
#include <avr/pgmspace.h>
#include "../../code/libnerdkits/delay.h"
#include "lcdtest.h"
//#include <stdint.h>
//#include <math.h>
// MCU setup
void mcu_setup()
{
// define pins
// CS - PB0
// WR - PB4
// RS - PB3
// RESET - PB5
// RD - tied high to 3.3v
// ALE - define for LATCHED 16 bit
// SDA - define for SERIAL
// SCL - define for SERIAL
// switch off UART
UCSR0B=0;
// define direction of all pins
switch (display_transfer_mode)
{
case 16:
DDRB |= 0x3F;
DDRC |= 0x3F;
DDRD |= 0xFF;
break;
// other modes not yet implemented
}
// set all pins low
//PORTB &= ~(0x3F);
//PORTC &= ~(0x3F);
//PORTD &= 0x00;
PORTB=0;
PORTC=0;
PORTD=0;
}
void initialise(byte orientation)
{
orient=orientation; // PORTRAIT or LANDSCAPE
display_model=SSD1289; // SSD1289, SSD1289_8 or SSD1289LATCHED for 3.2" or ST7735 for 1.8"
switch (display_model)
{
case SSD1289:
disp_x_size=239;
disp_y_size=319;
display_transfer_mode=16;
break;
//other models not implemented
}
}
void setCS()
{
PORTB|=(1<<PB0);
}
void clearCS()
{
PORTB&=~(1<<PB0);
}
void setWR()
{
PORTB|=(1<<PB4);
}
void clearWR()
{
PORTB&=~(1<<PB4);
}
void setRS()
{
PORTB|=(1<<PB3);
}
void clearRS()
{
PORTB&=~(1<<PB3);
}
void setRESET()
{
PORTB|=(1<<PB5);
}
void clearRESET()
{
PORTB&=~(1<<PB5);
}
void lcd_write_bus(char VH, char VL, byte mode)
{
switch (mode)
{
case 16:
// 16 bit
// clear port b,c,d data bits
PORTB &= ~(0x06);
PORTC &= ~(0x3F);
PORTD = VH;
PORTC |= (VL & 0x3F);
PORTB |= (VL>>5)&0x06;
// pulse WR low
clearWR();delay_us(1);setWR(); // need 10us delay for voltage level shifters - only 1 us if 10k resistors used for level shifting instead
break;
// no other modes implemented
}
}
void lcd_write_com(char VL)
{
clearRS();
lcd_write_bus(0x00,VL,display_transfer_mode);
}
void lcd_write_data(char VH, char VL)
{
setRS();
lcd_write_bus(VH, VL,display_transfer_mode);
}
void lcd_write_data2(char VL)
{
setRS();
lcd_write_bus(0x00,VL,display_transfer_mode);
}
void lcd_write_com_data(char com1, int dat1)
{
lcd_write_com(com1);
lcd_write_data(dat1>>8,dat1);
}
void setcolor(byte r, byte g, byte b)
{
fch=((r&248)|g>>5);
fcl=((g&28)<<3|b>>3);
}
void setcolor2(word color)
{
fch=(byte)(color>>8);
fcl=(byte)(color&0xFF);
}
word getcolor()
{
return (fch<<8) | fcl;
}
void setbackcolor(byte r, byte g, byte b)
{
bch=((r&248)|g>>5);
bcl=((g&28)<<3|b>>3);
_transparent=false;
}
void setbackcolor2(uint32_t color)
{
if (color==VGA_TRANSPARENT)
_transparent=true;
else
{
bch=(byte)(color>>8);
bcl=(byte)(color & 0xFF);
_transparent=false;
}
}
word getbackcolor()
{
return (bch<<8) | bcl;
}
void setxy(word x1, word y1, word x2, word y2)
{
if (orient==LANDSCAPE)
{
swap(word, x1, y1);
swap(word, x2, y2)
y1=disp_y_size-y1;
y2=disp_y_size-y2;
swap(word, y1, y2)
}
switch(display_model)
{
case SSD1289:
lcd_write_com_data(0x44,(x2<<8)+x1);
lcd_write_com_data(0x45,y1);
lcd_write_com_data(0x46,y2);
lcd_write_com_data(0x4e,x1);
lcd_write_com_data(0x4f,y1);
lcd_write_com(0x22);
break;
}
}
void _fast_fill_16(int ch, int cl, long pix)
{
long blocks;
PORTD = ch;
PORTB &= ~(0x06);
PORTB |= ((cl>>5)&0x06);
PORTC &= ~(0x3F);
PORTC |= (cl & 0x3F);
blocks = pix/16;
int i;
for (i=0; i<blocks; i++)
{
clearWR();delay_us(1);setWR();
clearWR();delay_us(1);setWR();
clearWR();delay_us(1);setWR();
clearWR();delay_us(1);setWR();
clearWR();delay_us(1);setWR();
clearWR();delay_us(1);setWR();
clearWR();delay_us(1);setWR();
clearWR();delay_us(1);setWR();
clearWR();delay_us(1);setWR();
clearWR();delay_us(1);setWR();
clearWR();delay_us(1);setWR();
clearWR();delay_us(1);setWR();
clearWR();delay_us(1);setWR();
clearWR();delay_us(1);setWR();
clearWR();delay_us(1);setWR();
clearWR();delay_us(1);setWR();
}
if ((pix % 16) != 0)
for (i=0; i<(pix % 16)+1; i++)
{
clearWR();delay_us(1);setWR();
}
}
void clrxy()
{
if (orient==PORTRAIT)
setxy(0,0,disp_x_size,disp_y_size);
else
setxy(0,0,disp_y_size,disp_x_size);
}
void clrscr()
{
clearCS();
clrxy();
setRS();
_fast_fill_16(0,0,((disp_x_size+1)*(disp_y_size+1)));
setCS();
}
void setpixel(word color)
{
lcd_write_data((color>>8),(color&0xFF)); // rrrrrggggggbbbbb
}
void drawpixel(int x, int y)
{
clearCS();
setxy(x, y, x, y);
setpixel((fch<<8)|fcl);
setCS();
clrxy();
}
void fillscr(word color)
{
char ch, cl;
ch=(byte)(color>>8);
cl=(byte)(color & 0xFF);
clearCS();
clrxy();
setRS();
_fast_fill_16(ch,cl,((disp_x_size+1)*(disp_y_size+1)));
setCS();
}
void fillscr2(byte r, byte g, byte b)
{
word color = ((r&248)<<8 | (g&252)<<3 | (b&248)>>3);
fillscr(color);
}
void drawhline(int x, int y, int l)
{
if (l<0)
{
l = -l;
x -= l;
}
clearCS();
setxy(x, y, x+l, y);
setRS();
_fast_fill_16(fch,fcl,l);
setCS();
clrxy();
}
void drawvline(int x, int y, int l)
{
if (l<0)
{
l = -l;
y -= l;
}
clearCS();
setxy(x, y, x, y+l);
setRS();
_fast_fill_16(fch,fcl,l);
setCS();
clrxy();
}
void drawline(int x1, int y1, int x2, int y2)
{
if (y1==y2)
drawhline(x1, y1, x2-x1);
else if (x1==x2)
drawvline(x1, y1, y2-y1);
else
{
unsigned int dx = (x2 > x1 ? x2 - x1 : x1 - x2);
short xstep = x2 > x1 ? 1 : -1;
unsigned int dy = (y2 > y1 ? y2 - y1 : y1 - y2);
short ystep = y2 > y1 ? 1 : -1;
int col = x1, row = y1;
clearCS();
if (dx < dy)
{
int t = - (dy >> 1);
while (true)
{
setxy (col, row, col, row);
lcd_write_data (fch, fcl);
if (row == y2)
return;
row += ystep;
t += dx;
if (t >= 0)
{
col += xstep;
t -= dy;
}
}
}
else
{
int t = - (dx >> 1);
while (true)
{
setxy (col, row, col, row);
lcd_write_data (fch, fcl);
if (col == x2)
return;
col += xstep;
t += dy;
if (t >= 0)
{
row += ystep;
t -= dx;
}
}
}
setCS();
}
clrxy();
}
void drawcircle(int x, int y, int radius)
{
int f = 1 - radius;
int ddF_x = 1;
int ddF_y = -2 * radius;
int x1 = 0;
int y1 = radius;
clearCS();
setxy(x, y + radius, x, y + radius);
lcd_write_data(fch,fcl);
setxy(x, y - radius, x, y - radius);
lcd_write_data(fch,fcl);
setxy(x + radius, y, x + radius, y);
lcd_write_data(fch,fcl);
setxy(x - radius, y, x - radius, y);
lcd_write_data(fch,fcl);
while(x1 < y1)
{
if(f >= 0)
{
y1--;
ddF_y += 2;
f += ddF_y;
}
x1++;
ddF_x += 2;
f += ddF_x;
setxy(x + x1, y + y1, x + x1, y + y1);
lcd_write_data(fch,fcl);
setxy(x - x1, y + y1, x - x1, y + y1);
lcd_write_data(fch,fcl);
setxy(x + x1, y - y1, x + x1, y - y1);
lcd_write_data(fch,fcl);
setxy(x - x1, y - y1, x - x1, y - y1);
lcd_write_data(fch,fcl);
setxy(x + y1, y + x1, x + y1, y + x1);
lcd_write_data(fch,fcl);
setxy(x - y1, y + x1, x - y1, y + x1);
lcd_write_data(fch,fcl);
setxy(x + y1, y - x1, x + y1, y - x1);
lcd_write_data(fch,fcl);
setxy(x - y1, y - x1, x - y1, y - x1);
lcd_write_data(fch,fcl);
}
setCS();
clrxy();
}
void fillcircle(int x, int y, int radius)
{
int y1;
int x1;
for(y1=-radius; y1<=0; y1++)
for(x1=-radius; x1<=0; x1++)
if(x1*x1+y1*y1 <= radius*radius)
{
drawhline(x+x1, y+y1, 2*(-x1));
drawhline(x+x1, y-y1, 2*(-x1));
break;
}
}
void drawrect(int x1, int y1, int x2, int y2)
{
if (x1>x2)
{
swap(int, x1, x2);
}
if (y1>y2)
{
swap(int, y1, y2);
}
drawhline(x1, y1, x2-x1);
drawhline(x1, y2, x2-x1);
drawvline(x1, y1, y2-y1);
drawvline(x2, y1, y2-y1);
}
void drawroundrect(int x1, int y1, int x2, int y2)
{
if (x1>x2)
{
swap(int, x1, x2);
}
if (y1>y2)
{
swap(int, y1, y2);
}
if ((x2-x1)>4 && (y2-y1)>4)
{
drawpixel(x1+1,y1+1);
drawpixel(x2-1,y1+1);
drawpixel(x1+1,y2-1);
drawpixel(x2-1,y2-1);
drawhline(x1+2, y1, x2-x1-4);
drawhline(x1+2, y2, x2-x1-4);
drawvline(x1, y1+2, y2-y1-4);
drawvline(x2, y1+2, y2-y1-4);
}
}
void fillrect(int x1, int y1, int x2, int y2)
{
if (x1>x2)
{
swap(int, x1, x2);
}
if (y1>y2)
{
swap(int, y1, y2);
}
clearCS();
setxy(x1, y1, x2, y2);
setRS();
_fast_fill_16(fch,fcl,(((long)(x2-x1)+1)*((long)(y2-y1)+1)));
setCS();
}
void fillroundrect(int x1, int y1, int x2, int y2)
{
if (x1>x2)
{
swap(int, x1, x2);
}
if (y1>y2)
{
swap(int, y1, y2);
}
if ((x2-x1)>4 && (y2-y1)>4)
{
int i;
for (i=0; i<((y2-y1)/2)+1; i++)
{
switch(i)
{
case 0:
drawhline(x1+2, y1+i, x2-x1-4);
drawhline(x1+2, y2-i, x2-x1-4);
break;
case 1:
drawhline(x1+1, y1+i, x2-x1-2);
drawhline(x1+1, y2-i, x2-x1-2);
break;
default:
drawhline(x1, y1+i, x2-x1);
drawhline(x1, y2-i, x2-x1);
}
}
}
}
// lcd on
void lcdon()
{
clearCS();
setCS();
}
// LCD_Init
void lcd_init()
{
setRESET();
delay_ms(5);
clearRESET();
delay_ms(15);
setRESET();
delay_ms(15);
clearCS();
switch(display_model)
{
case SSD1289:
lcd_write_com_data(0x00,0x0001);
lcd_write_com_data(0x03,0xA8A4);
lcd_write_com_data(0x0C,0x0000);
lcd_write_com_data(0x0D,0x080C);
lcd_write_com_data(0x0E,0x2B00);
lcd_write_com_data(0x1E,0x00B7);
lcd_write_com_data(0x01,0x2B3F);
lcd_write_com_data(0x02,0x0600);
lcd_write_com_data(0x10,0x0000);
lcd_write_com_data(0x11,0x6070);
lcd_write_com_data(0x05,0x0000);
lcd_write_com_data(0x06,0x0000);
lcd_write_com_data(0x16,0xEF1C);
lcd_write_com_data(0x17,0x0003);
lcd_write_com_data(0x07,0x0233);
lcd_write_com_data(0x0B,0x0000);
lcd_write_com_data(0x0F,0x0000);
lcd_write_com_data(0x41,0x0000);
lcd_write_com_data(0x42,0x0000);
lcd_write_com_data(0x48,0x0000);
lcd_write_com_data(0x49,0x013F);
lcd_write_com_data(0x4A,0x0000);
lcd_write_com_data(0x4B,0x0000);
lcd_write_com_data(0x44,0xEF00);
lcd_write_com_data(0x45,0x0000);
lcd_write_com_data(0x46,0x013F);
lcd_write_com_data(0x30,0x0707);
lcd_write_com_data(0x31,0x0204);
lcd_write_com_data(0x32,0x0204);
lcd_write_com_data(0x33,0x0502);
lcd_write_com_data(0x34,0x0507);
lcd_write_com_data(0x35,0x0204);
lcd_write_com_data(0x36,0x0204);
lcd_write_com_data(0x37,0x0502);
lcd_write_com_data(0x3A,0x0302);
lcd_write_com_data(0x3B,0x0302);
lcd_write_com_data(0x23,0x0000);
lcd_write_com_data(0x24,0x0000);
lcd_write_com_data(0x25,0x8000);
lcd_write_com_data(0x4f,0x0000);
lcd_write_com_data(0x4e,0x0000);
lcd_write_com(0x22);
break;
}
setCS();
setcolor(255,255,255);
setbackcolor(0,0,0);
cfont.font=0;
_transparent=false;
}
// Main
int main()
{
// initialise variables
initialise(PORTRAIT);
// set up MCU
mcu_setup();
// lcd on is not strictly necessary for SSD1289
lcdon();
// lcd_init produces a fuzzy coloured screen if it works
lcd_init();
// some example drawing
clrscr();
fillscr(VGA_YELLOW);
delay_ms(500);
fillscr(VGA_BLUE);
setcolor2(VGA_RED);
fillcircle(100,150, 50);
setcolor(0,255,0);
drawcircle(100,200,50);
drawrect(60,270,100,300);
fillrect(120,270,180,300);
drawroundrect(60,60,120,10);
fillroundrect(130,60,200,10);
setcolor2(VGA_SILVER);
drawline(1,1,239,319);
drawpixel(130,280);
drawpixel(131,280);
drawpixel(132,280);
drawpixel(130,281);
drawpixel(131,281);
drawpixel(132,281);
drawpixel(130,282);
drawpixel(131,282);
drawpixel(132,282);
return 0;
}
|