Skip to content

2.2″ Colour LCD for Olduino

February 27, 2014

I got a new toy.

For $15.00 shipped, I got a 2.2″ colour LCD already mounted on a shield. I ordered it from eBay but it came from Elecfreaks http://www.elecfreaks.com/store/tft22sp-shield-p-687.html  The best documentation I found was on another web site http://www.micro4you.com/store/2-2-tft-lcd-shield.html

It is nominally SPI compatible but isn’t wired to the hardware SPI pins that an arduino would use.  Instead those pins are connected to an on-board micro-sd card socket and the LCD is bit-bang controlled over Arduino pins 3 through 7.  Mounted on the shield adapter I could use the high speed hardware SPI to address the SD card and bit-bang the LCD but it will be slow.  I can understand separating them though because I have found the SD card to be tricky in terms of getting it to release the SPI bus.  Still, I think I’ll end up re-wiring it a bit when I get home.  For now, I can play with bit-banging it because the pins it uses are right in the range that I connect to.  Arduino digital pin 3 is the olduino’s pin 0 and up from there.

The protocol for talking to the lcd is similar to that of the nokia n5110.  Besides the SPI data, clock, and select lines, there’s a reset pin and a data/command pin that tells the lcd what you’re sending.  I can probably adapt some of what works for the N5110.

There’s a sample Arduino sketch at http://www.micro4you.com/files/ElecFreaks/TFT2_2SPI_CODE.zip that paints the whole screen in solid colours one after another.  Even on the arduino it’s pretty slow bit-banging.  It looks like it has to write a colour byte to each of 240*320 locations.  Visually that’s a couple of seconds per screen – i can only imagine how long it would take the olduino – maybe 80,000*100/100000 seconds=a minute or so.  Still worth the experiment as a start.  Their bit-bang code looks like:

void LCD_Writ_Bus(char data)
{
  *P_CS &= ~B_CS; //7
  for (unsigned char c=0; c<8; c++)
  {
	if (data & 0x80)
		*P_MOSI |= B_MOSI;
	else
		*P_MOSI &= ~B_MOSI; //3
	data = data<<1;
	*P_SCK &= ~B_SCK;
	asm ("nop");
	*P_SCK |= B_SCK; //4
  }
  *P_CS |= B_CS; //7
}

I’m going to try to leave the lcd selected all the time so mine will start as

void LCD_Writ_Bus(unsigned char value){
  int i;
  digitalWrite(LCD_CS,LOW);
  for(i=0;i<8;i++){
    digitalWrite(btbmosi,(value&0x80));      //by setting mosi for each bit
    digitalWrite(btbsck,HIGH);              //then pulsing the clock
    digitalWrite(btbsck,LOW);
  }
  digitalWrite(LCD_CS,HIGH);
}

his data/command wrappers are as follows:

void LCD_Write_COM(char VL)
{
  digitalWrite(LCD_DC,LOW);
  LCD_Writ_Bus(VL);
}

void LCD_Write_DATA(char VL)
{
  digitalWrite(LCD_DC,HIGH);
  LCD_Writ_Bus(VL);
}

I’ll copy them directly.

Jumping up to the top level, his Setup/Loop code is as follows ((the code consistently uses pant for [paint])

void setup()
{
  unsigned char p;
  for(p=0;p<14;p++)
    pinMode(p,OUTPUT);
  LCD_Init();
}

void loop()
{
  Pant(0xFF);
  Pant(0xF0);
  Pant(0xE0);
  Pant(0x05);
  Pant(0x1F);
  Pant(0x00);
}

I will start with:

void main()
{
  LCD_Init();
  Pant(0xF0);   //hopefully this gets me something other than black or white
}

His lcd initialization procedure is bulky as heck. The first part is to do with direct port manipulation so i’ll drop it but use the rest as is until I understand it better.

void LCD_Init(void)
{
        P_SCK	= portOutputRegister(digitalPinToPort(LCD_WR));
        B_SCK	= digitalPinToBitMask(LCD_WR);
	P_MOSI	= portOutputRegister(digitalPinToPort(LCD_RS));
	B_MOSI	= digitalPinToBitMask(LCD_RS);
	P_DC	= portOutputRegister(digitalPinToPort(LCD_DC));
	B_DC	= digitalPinToBitMask(LCD_DC);
	P_RST	= portOutputRegister(digitalPinToPort(LCD_REST));
	B_RST	= digitalPinToBitMask(LCD_REST);
	P_CS	= portOutputRegister(digitalPinToPort(LCD_CS));
	B_CS	= digitalPinToBitMask(LCD_CS);

        *P_RST &= ~B_RST;
	delay(10);
	*P_RST |= B_RST;

        LCD_Write_COM(0xCB);
        LCD_Write_DATA(0x39);
        LCD_Write_DATA(0x2C);
        LCD_Write_DATA(0x00);
        LCD_Write_DATA(0x34);
        LCD_Write_DATA(0x02);

        LCD_Write_COM(0xCF);
        LCD_Write_DATA(0x00);
        LCD_Write_DATA(0XC1);
        LCD_Write_DATA(0X30);

        LCD_Write_COM(0xE8);
        LCD_Write_DATA(0x85);
        LCD_Write_DATA(0x00);
        LCD_Write_DATA(0x78);

        LCD_Write_COM(0xEA);
        LCD_Write_DATA(0x00);
        LCD_Write_DATA(0x00);

        LCD_Write_COM(0xED);
        LCD_Write_DATA(0x64);
        LCD_Write_DATA(0x03);
        LCD_Write_DATA(0X12);
        LCD_Write_DATA(0X81);

        LCD_Write_COM(0xF7);
        LCD_Write_DATA(0x20);

        LCD_Write_COM(0xC0);    //Power control
        LCD_Write_DATA(0x23);   //VRH[5:0]

        LCD_Write_COM(0xC1);    //Power control
        LCD_Write_DATA(0x10);   //SAP[2:0];BT[3:0]

        LCD_Write_COM(0xC5);    //VCM control
        LCD_Write_DATA(0x3e);   //Contrast
        LCD_Write_DATA(0x28);

        LCD_Write_COM(0xC7);    //VCM control2
        LCD_Write_DATA(0x86);   //--

        LCD_Write_COM(0x36);    // Memory Access Control
        LCD_Write_DATA(0x48);   //C8	   //48 68??//28 E8 ??

        LCD_Write_COM(0x3A);
        LCD_Write_DATA(0x55);

        LCD_Write_COM(0xB1);
        LCD_Write_DATA(0x00);
        LCD_Write_DATA(0x18);

        LCD_Write_COM(0xB6);    // Display Function Control
        LCD_Write_DATA(0x08);
        LCD_Write_DATA(0x82);
        LCD_Write_DATA(0x27);

        LCD_Write_COM(0x11);    //Exit Sleep
        delay(120);

        LCD_Write_COM(0x29);    //Display on
        LCD_Write_COM(0x2c);
}

His Pant procedure is

void Pant(char VL)
{
  int i,j;
  Address_set(0,0,240,320);
  for(i=0;i<320;i++)
  {
    for (j=0;j<480;j++)     {       LCD_Write_DATA(VL);     }   } } 

which I will crib directly and the last thing I need is Address_set which looks like:

 void Address_set(unsigned int x1,unsigned int y1,unsigned int x2,unsigned int y2) {    LCD_Write_COM(0x2a);    LCD_Write_DATA(x1>>8);
   LCD_Write_DATA(x1);
   LCD_Write_DATA(x2>>8);
   LCD_Write_DATA(x2);

   LCD_Write_COM(0x2b);
   LCD_Write_DATA(y1>>8);
   LCD_Write_DATA(y1);
   LCD_Write_DATA(y2>>8);
   LCD_Write_DATA(y2);

   LCD_Write_COM(0x2C);
}

Again, I’ll leave that alone until I understand it better.

First try running the code the LCD lit up but nothing else happened.  Time for the logic analyzer I guess.

Advertisements

From → Uncategorized

Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: