Guest essele

LCD Experiments

Recommended Posts

Guest essele

Hi,

I'm just starting to experiment with connecting various LCD's to the Papilio ... I seem to be building up a collection of LCD's, my target application is around 3.8" and ideally sunlight readable, but I'll experiment with a range to build up some knowledge and experience. (Actually I've got my eyes on the DSi XL screen.)

I thought I'd share my experiments as I'm sure other people will be doing similar things.

So, my first experiment is with a 3.5" 320x240 (sunlight readable) from www.good-lcd.com, it's a GTT035HBHT1, the data sheet is here.

They were very helpful while I was making my mind up and ordering, but unfortunately have gone completely quiet to my requests for SPI information (since there's no register info etc in the data sheet) ... anyway my hope is that it will just work with the RGB data ... time will tell.

So this is phase 1 ... I put a breakout PCB together and had reasonable success soldering on a 50-way FFC connector...

web.jpg?ver=13186998260001

So first stage was just to fire up the backlight ... and that seems to work pretty well (although did highlight an open connection on my soldering)...

web.jpg?ver=13186998280001

So next stage is to get the papilio connected and generating a video signal, the timing information is in the data sheet, so I think this should just be a rework of my existing VGA code.

Hopefully I'll make some more progress in the next couple of days ... I'll also knock up some more breakouts as I've got a really nice (and very low cost) Sharp LQ038J7DH52 to play with as well.

Cheers,

Lee.

Share this post


Link to post
Share on other sites
Guest essele

Ok, further progress ...

I now have the Papilio One driving the correct timings (checked using the Open Bench logic sniffer!)

The display remains completely blank (other than the backlight) ... unfortunately I managed to put my scope probe through one of the FFC test points (luckily I have two of these screens) so I decided to see if I could get inside the LCD case to see if I could glean any more info about it.

Inside there is a different model number: TM035HBHT1

This is a screen produced by Tianma, and from their web site I found the driver to be a ILI9340, the datasheet contains all the SPI register info. I think I'll invest in a "Bus Pirate" to simplify the programming/testing before trying to do the SPI from the Papilio.

Lee.

Share this post


Link to post
Share on other sites
Guest essele

Hmmm ... I've got the Papilio One now setup with an AVR8 processor and a simple sketch to bit bang (because of the 9bit requirement) the SPI protocol.

The Papilio is working fine .... it's amazing how easy it is to get it running like an Arduino!

Unfortunately neither of my displays are responding at all ... I fear I may have destroyed them both through mishandling ... I really must get consistent about which colour jumper wire I use for the positive supply!

It could be that my SPI implementation isn't correct, but it looks ok ... I will confirm once the Bus Pirate arrives.

In the meantime I'll try to get hold of another couple of displays -- I don't want to be beaten by this.

Lee.

Share this post


Link to post
Share on other sites

Lee,

You inspired me to put some time into a 2.3" touchscreen and prototype Wing I had laying around. I was able to get it up and running this weekend using the adafruit tft library.

Here is a video of the touchscreen in action:

I also purchased one of these 4.3" LCD's from ebay. They will take VGA signals directly so we should be able to pretty easily make a Wing that can be run by any VGA core. The only challenge is the backlight but I did run across some example designs that we can use as reference.

Jack.

Share this post


Link to post
Share on other sites
Guest essele

Hi Jack,

Some good progress there ... I actually have one of those LCD's & touch panels, so I'll have an experiment with it as some point soon.

I've got a couple more of my original LCD's coming now, so hopefully I'll be able to make some progress with them in a week or so, once they arrive.

The 4.3" screen you reference doesn't look like it will take direct VGA to me ... it still looks like you need to feed RGB data in, and looking at the driver datasheet you still need to run through some setup, although given the lack of SPI this may well be implemented differently.

Lee.

Share this post


Link to post
Share on other sites
Guest essele

Hi Álvaro,

I'm not getting anything at all on SPI, but I really do think it's because I've fried the screens.

I've had a quick look at the ZPUino, it looks interesting (especially from a performance perspective) however this LCD (and quite a few others it seems) needs a 9 bit SPI implementation to send the commands.

Basically the first bit determins if it's a command or data, then the follow 8 bits are the relevant register or value. The reads all seem to be multiples of 8 bits, but writes require 9.

I can't find any hardware implementations that support 9 bit, so it will have to be bitbanging for now ... and the AVR8 is an easy way to do that (but I will test with the Bus Pirate as well.)

Cheers,

Lee.

Share this post


Link to post
Share on other sites

Hi Lee

usually 9 bit isn't supported by any hardware known to me. Have you checked to write two 8 bit words? As far as I remember SPI chips (like Allegro stepper control with 19 bit cmds)  all shift out the unused bits. So maybe you try to send 0000 000x yyyy yyyy or other way round if LSB first is used.

Just an idea and my first post here and sorry for my bad english

Cheers

Peter

Share this post


Link to post
Share on other sites
Guest essele

The data sheet for the driver chip is here:

http://www.allshore.com/pdf/IlitekILI9340.pdf

The serial description (which is 3-wire on this particular screen) is detailed starting on page 34. I could have completely misunderstood this, but it does seem similar to some other screens (including some of the nokia ones.)

Lee.

Share this post


Link to post
Share on other sites
Guest essele

Some good progress now ... finally!

My two new LCD's arrived ... plugged one of them up to the Bus Pirate and couldn't get anything out of it!  So back to the Papilio One with a sketch manually handling the SPI!

STILL NOTHING!!! Aaarrrgggghhhh.

Lots of messing around with resets and timing ... still nothing!

Just in case ... why don't I try using a different command?  I've been using 0x04 which is supposed to read 24bits of ID information back.

So, switch to 0x09 ... which reads 32bits of display setup info and ..... YES!  Valid responses!

It seems the ID command returns all zeros ... very helpful.

So I've put together a simple Arduino sketch that runs all of the info commands and displays the result every second ... I've included the code for reference, it's not pretty, or optimised ... but it does the job for now. (Note: for 24bit and 32bit responses you need to skip a bit, it's all in the ILI9340 datasheet.)

Next step is to run through the datasheet working out what I really need to initialise, then I'll probably play with the SPI framebuffer before I start looking at feeding it real-time RGB data.

Lee.

 

int MOSI = 0;
int MISO = 1;
int SS = 2;
int SCK = 3;
int RESET = 4;
int PWR = 5;
void setup() {
  Serial.begin(9600);
 
//  SPI.begin();
// SPI.setBitOrder(MSBFIRST);
  pinMode(SCK, OUTPUT);
  pinMode(MOSI, OUTPUT);
  pinMode(MISO, INPUT);
  pinMode(SS, OUTPUT);
 
  pinMode(RESET, OUTPUT);
  pinMode(PWR, OUTPUT);
 
  digitalWrite(SCK, LOW);
  digitalWrite(MOSI, LOW);
  digitalWrite(SS, HIGH);
  digitalWrite(RESET, HIGH);
  digitalWrite(PWR, LOW);
 
  delay(3000);
 
  digitalWrite(RESET, LOW);
  digitalWrite(PWR, HIGH);
  delay(10);
 
  digitalWrite(RESET, HIGH);
 
  delay(15);
}

void chip_select(boolean cs) {
  digitalWrite(SS, cs);
}
void send_9bit(byte dc, byte cmd) {
  // Make sure the clock is low...
  digitalWrite(SCK, LOW);

  // Setup and send the first bit (dc)
  digitalWrite(MOSI, dc);
  digitalWrite(SCK, HIGH);
 
  // Now write our eight bits...
  for(char j=0; j < 8; j++) {
    digitalWrite(SCK, LOW);
    digitalWrite(MOSI, (cmd & 0x80) == 0x80);
    digitalWrite(SCK, HIGH);
    cmd <<= 1;
  } 
}
void skip_bit() {
    digitalWrite(SCK, LOW);
    digitalWrite(SCK, HIGH);
}
byte read_byte() {
  byte rc = 0;

  for(char j=0; j < 8; j++) {
    rc <<= 1;
    digitalWrite(SCK, LOW);
    // delay here ... but it's short so we don't really need it
    rc |= digitalRead(MISO);
    digitalWrite(SCK, HIGH);
  }
  return(rc);
}
byte cmd_8bit(byte cmd) {
  byte rc;
 
  chip_select(0);
  send_9bit(0, cmd);
  rc = read_byte();
  chip_select(1);
  return(rc);
}
unsigned long cmd_24bit(byte cmd) {
  byte rc1, rc2, rc3;
  unsigned long rc;
 
  chip_select(0);
  send_9bit(0, cmd);
  skip_bit();
  rc1 = read_byte();
  rc2 = read_byte();
  rc3 = read_byte();
  chip_select(1);
  rc = ((unsigned long)rc1<<16) | ((unsigned long)rc2<<8) | rc3;
  return(rc);
}
unsigned long cmd_32bit(byte cmd) {
  byte rc1, rc2, rc3, rc4;
  unsigned long rc;
 
  chip_select(0);
  send_9bit(0, cmd);
  skip_bit();
  rc1 = read_byte();
  rc2 = read_byte();
  rc3 = read_byte();
  rc4 = read_byte();
  chip_select(1);
  rc = ((unsigned long)rc1<<24) | ((unsigned long)rc2<<16) | ((unsigned long)rc3<<8) | rc4;
  return(rc);
}
void loop() {
    unsigned long l;
   
    l = cmd_32bit(0x09);
    Serial.print("0x09 -- Got return ");
    Serial.println( l, HEX);
 
    l = cmd_24bit(0x04);
    Serial.print("0x04 -- Got return ");
    Serial.println( l, HEX);
   
    byte x;
    for(x=0x0A; x < 0x10; x++) {
      byte b = cmd_8bit(x);
      Serial.print("0x");
      Serial.print(x, HEX);
      Serial.print(" -- Got return ");
      Serial.println( b, HEX);
    }
   
  delay(1000);
}

Share this post


Link to post
Share on other sites
Guest essele

Two SPI commands (turn off sleep, and then turn on display) and then a quick write to memory ...

web.jpg?ver=13194726030001

It's horrendously slow though ... but that's because it's SPI bit banged using the standard Arduino api's, I imagine we could get it reasonably quick using the port registers directly.

In any case, this isn't a major concern for me ... when I get a chance I'll be looking at feeding it RGB data in real time ... and now I have a C/RAM wing (arrived today :-)) I can start trying to put together the frame buffer.

Lee.

Share this post


Link to post
Share on other sites

Excellent! Looks promising.

One thing of note, there is a SPI core built into the AVR8, its not actually bit banging... So if you are using a bit banging library you should be able to use the SPI hardware core for faster speeds.

Take a look at the example sketches for the uSD Wing, there are examples in there of what you need to do to move the SPI pins to whatever Papilio pins you want and use the hardware SPI core.

Post any questions you have about it here. :)

Jack.

Share this post


Link to post
Share on other sites
Guest icebear

Hi,

interesting stuff! Actually, I was just noodling on similar and started designing a PCB wing for two kinds of TFT screens (no touch, I'm afraid). One 128x128 and 240x320. However, they're using a parallel host CPU style interface, so they should be fast enough to play games on them. Since I'm no expert to the Wings concept, I'm happy for some input/comments. I'm gonna submit them for manufacture in a week or so. It's the first quick shot, and I'm trying out other stuff (with USB interfaces), so I don't expect this to turn out 100% working from the box. Esp. since I am still waiting for the Papilio board to arrive.

Put up some PDFs here if you're nosy to see:

http://section5.ch/tmp/lcd-papilio.pdf

http://section5.ch/tmp/lcd-schematics.pdf

Cheers,

- icebear

Share this post


Link to post
Share on other sites
Guest icebear

I had actually forgotten about something else:

On my uC driven board, I have some ROM space for the character table to do some fancy text I/O.

Question: Does the on-Papilio-SPI-flash have enough space (64kByte) left for bitmap storage?

Greetings,

- icebear

Share this post


Link to post
Share on other sites

Yes,

The Papilio has a 4Mbit SPI flash and the P1 250K uses 1.3Mbit for configuration and the P1 500K uses 2.2Mbit. So there is a good amount of flash space left over.

Jack.

Share this post


Link to post
Share on other sites

You might be interested in my SmallFS project. It creates a very compact filesystem for flash devices (read-only), with minimal code size and filesystem size.

https://github.com/alvieboy/smallfs

Right now it's SPI tuned for ZPUino, but should work with any micro with small effort. All it needs is the flash offset where your filesystem resides.

Álvaro

Share this post


Link to post
Share on other sites
Guest icebear

Hi,

finally got the PCBs for the tiny 128x128 LCD and 240x320 option and gave it a go. Turns out the ZPU is good enough to send the initialization sequences to the Sitronix controller sitting on the LCD, but too slow to actually blit data, you can watch the screen fill. Therefore I guess I'll go for the "hard" solution with a little blitting engine mapped into the ZPUs I/O space that will fetch the 4x8 font data directly from the SPI flash.

Picture from the current setup (excuse the dirty wiring because of missing 16x connectors...):

lcdwing.jpg

If there's interest, I might look into kicking out a few more PCBs of that sort. The real problem actually is finding a reliable and cheap source for the LCD screens.

Share this post


Link to post
Share on other sites
Guest icebear

Hi Alvaro,

See code below.


161    void lcd_fill(unsigned short col)
162    {
163        unsigned short n = 128 * 128;
164   
165        unsigned char c0 = col >> 8;
166   
167        *ioLCD_CMD = R_LCD_ColumnAddress;
168        *ioLCD_D = 0; *ioLCD_D = 0;
169        // *ioLCD_D = 0; *ioLCD_D = 0;
170        *ioLCD_CMD = R_LCD_PageAddress;
171        *ioLCD_D = 0; *ioLCD_D = 0;
172        // *ioLCD_D = 0; *ioLCD_D = 0;
173   
174        *ioLCD_CMD = R_LCD_MemoryWrite;
175        while (n--) {
176            *ioLCD_D = c0; *ioLCD_D = col;
177        }
178    }

Honestly, I didn't try optimizing on the assembly level yet. I'm using  the Zealot zpu_small variant, I guess there are quite a few cycles burnt  inside emulation routines (byte loads for the col values). But since  this is more or less a fun project, I'll put effort into the blitter  rather than enhancing the ZPU (which might be replaced by another core  later). But I'm always open for interesting other aspects.

Share this post


Link to post
Share on other sites

Looking pretty cool!

Are you hot bar soldering the connector to the PCB?

Are these LCD's available on ebay or do you have to track them down through some other sources?

Might be good to put the PCB's up on batchpcb and make a couple bucks if anyone decides to buy them.

Jack.

Share this post


Link to post
Share on other sites
Guest icebear

I'm just using the SMD tip to solder the flex connectors onto the PCB. Same reversed procedure for the ripping, btw, the cheapest source (with a lot of variation though) I found from those keychain DPFs available on DealExtreme. Most of them have some kind of Sitronix 77xx command style controllers. Quality is varying, some are nice TFTs, some rather crappy STNs.

Anyhow, for tinkering numbers the ripping option is probably cheapest. There's been quite some "hacking" activity on these DPFs, see also http://tech.section5.ch/news/?p=68

I'm not familiar with the batchpcb principle, but it sounds like some idea. Before I release the full PCB, I wanted to do more testing though (actually, there is a second population option for a USB display or FIFO extender for the Papilio)

Share this post


Link to post
Share on other sites

Hi Alvaro,

See code below.


161    void lcd_fill(unsigned short col)
162    {
163        unsigned short n = 128 * 128;
164   
165        unsigned char c0 = col >> 8;
166   
167        *ioLCD_CMD = R_LCD_ColumnAddress;
168        *ioLCD_D = 0; *ioLCD_D = 0;
169        // *ioLCD_D = 0; *ioLCD_D = 0;
170        *ioLCD_CMD = R_LCD_PageAddress;
171        *ioLCD_D = 0; *ioLCD_D = 0;
172        // *ioLCD_D = 0; *ioLCD_D = 0;
173   
174        *ioLCD_CMD = R_LCD_MemoryWrite;
175        while (n--) {
176            *ioLCD_D = c0; *ioLCD_D = col;
177        }
178    }

Care to try using "unsigned" only, instead of "short" and "char" ? ZPU is 32-bit.

Honestly, I didn't try optimizing on the assembly level yet. I'm using  the Zealot zpu_small variant, I guess there are quite a few cycles burnt  inside emulation routines (byte loads for the col values). But since  this is more or less a fun project, I'll put effort into the blitter  rather than enhancing the ZPU (which might be replaced by another core  later). But I'm always open for interesting other aspects.

I don't remember if Zealot implements byte/word addressing in hardware. ZPU does however.

That code on ZPU should output at very fast frequencies. What's the maximum input freq of LCD?

Álvaro

Share this post


Link to post
Share on other sites
Guest icebear

Hi Alvaro,

The setup/hold times for data bursts are typically like 20ns each (-> 25MHz/2 pixel clock). The Zealot indeed went into emulation (loadb isn't implemented), so DWORD accesses speed it up. Might swap out the Zealot for the Zpuino core later...I assume you've cycle/pipeline optimized that?

I'm still a bit confused about the current ZPU development, the mailing list appears pretty dead. Are you the only one left working on the ZPU 'cutting edge' fronts?

Cheers,

- icebear

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now