Archive for November, 2010

S1D13700 Graphic LCD Timing Shenanigans

The S1D13700 is an LCD controller IC made by Epson. It is common among 320×240 monochrome LCDs. It has a software interface that is similar or identical to the SED1335 and Raio RA8835. Recently, I had the pleasure of writing some software for it. Several quirks made it kind of a pain, so I thought I share for the next guy.

First, have a look at the timing diagram found in the S1D13700 Datasheet.

S1D13700 Datasheet Timing

S1D13700 Datasheet Timing

OK, now stop looking at it because it’s wrong. For some reason, following that timing pattern produces unstable results when writing to the graphics layer. Here is a video demonstrating the type of problems you end up with:

It turns out the trick is to only activate the CS line while you transition the WR or RD pin on its sensitive edge but not the other edge. So, when writing, you would only hold CS low long enough to transition WR from high to low. The opposite applies to RD. Here are some working code snippets:

void GLCD_WriteCommand(unsigned char commandToWrite)
{

SED1335_DATA_PORT = commandToWrite;
SED1335_DATA_DIR = 0;
SED1335_CONTROL_PORT &= ~(SED1335_WR);
SED1335_CONTROL_PORT &= ~SED1335_CS;
SED1335_CONTROL_PORT |= (SED1335_WR);
SED1335_CONTROL_PORT |= SED1335_CS;
}

and

unsigned char GLCD_ReadData(void)
{
unsigned char tmp;
SED1335_CONTROL_PORT &= ~(SED1335_CS);
SED1335_DATA_DIR = 0xFF;
SED1335_CONTROL_PORT &= ~(SED1335_RD);
READDELAY();
tmp =  SED1335_DATA_PIN;
SED1335_CONTROL_PORT |= (SED1335_CS);
SED1335_CONTROL_PORT |= (SED1335_RD);
return tmp;
}

Since that did not cause enough frustration and productivity loss, there is another gotcha. There is an apparently vital but unmentioned (I couldn’t find it in the datasheet) delay that must be inserted after the initial system set command and before the parameters are passed for that command. If you don’t ensure a proper delay, the LCD either won’t start or, strangely, will output the wrong data when you attempt to do a read. So the start of  the initialization routine should look something like this:

GLCD_HardReset();

GLCD_WriteCommand(SED1335_SYSTEM_SET);
_delay_us(500);
GLCD_WriteData(SED1335_SYS_P1);
GLCD_WriteData(SED1335_SYS_P2);  
GLCD_WriteData(SED1335_FY);
GLCD_WriteData(SED1335_CR);
GLCD_WriteData(SED1335_TCR);
GLCD_WriteData(SED1335_LF);
GLCD_WriteData(SED1335_APL);
GLCD_WriteData(SED1335_APH);

I hope that helps someone struggling with this controller.

The full code examples can be found here