• We recently switched our forum platform. If you experience any issues please email support@crystalfontz.com

CFAF240320K-T-TS driver

MagIO2

New member
CFAF240320K-T-TS driver (more issues)

Hi,

I purchased a CFAF240320K-T-TS and try to write a driver for the Parallax Propeller microcontroller.

As a first step I wanted a quick and easy implementation to see if the display works. So I took the C demo code and converted it to SPIN. As SPIN is a interpreted language, the code is much slower than C code run by other microcontrollers. Do you see any problems when timing is slower or is the max. time uncritical?

I found the following deviation between demo code and SPFD5408B specs: In the timing diagram of the spec the RS signal ( in demo it's named CD ) is set before setting CS to low, in demo it's the other way around. Why? What's right then?

How comes that the initialization sequence and values look different in some places when comparing demo code with CFAF datasheet? Are there settings which are supply-voltage related? Is 3.3V fine for the demo-settings?

What I have currently is that the display is switched on showing a picture that reminds me on a TV without any signal attached - after initialization. If I call the synonym of Display_Home function (which only sets the GRAM adress and selects register $22) something strange happens. First the upper part of display shows pale vertical lines of different color. Some bottom lines (say 10 just to give you a number) keep the fuzzy content. Then the content of the whole display gets darker in a few seconds. Any ideas?

Do you have demo code for 8 bit interface as well? Do you have to set CS and clear it again between sending the 2 bytes, or is it enough to change data and send a WR impulse?

Thanks in advance.
Looking for additional LCD resources? Check out our LCD blog for the latest developments in LCD technology.
 
Last edited:
I don't have any experience with this display, but I can answer some questions regarding the interface signals.
Do you see any problems when timing is slower or is the max. time uncritical?
Slow timing is not a problem.
In the timing diagram of the spec the RS signal ( in demo it's named CD ) is set before setting CS to low, in demo it's the other way around. Why? What's right then?
Typically, for parallel bus interface hookups, it doesn't matter. You could actually leave the /CS signal low all the time, unless you have more than one device on the bus.
Do you have to set CS and clear it again between sending the 2 bytes, or is it enough to change data and send a WR impulse?
See previous comment. The /CS signal only needs to be switched when using SPI mode, as it synchronizes the packet.

Sorry I can't be more helpful.
 

MagIO2

New member
cosmicvoid:
thanks for your comment ... gave me some confidence, as that was exactly what I thought how the interface should work. So, when I figured out how to get the display running I'll optimize code in that sense.

Would be nice to have a Crystalfontz driven but user-maintained wiki to document all the "do's" AND "don't do's" per display. So, we could learn from or avoid mistakes already done by other users.
 

MagIO2

New member
So, I believe that I did everything right in the code.
I also checked the connections one after the other between propeller and display by sending a squarewave on each pin and checked it with a scope directly on the soldered flex connection.

Do you think that a breadboard setup with several jumps (propeller to incoming wires / incoming wires to floppy cable via connector / floppy cable to PCB via conector / flex of display soldered to PCB) could cause the problems?
 
I also checked the connections one after the other between propeller and display by sending a squarewave on each pin and checked it with a scope directly on the soldered flex connection.
Did you send the square wave simultaneously on all pins, or 1 pin at a time? If simultaneously, then you can't detect whether any pins are shorted to another (unless each pin has a different frequency).

As for multiple connections in series, it always less reliable than a single wire, but if you see the signals have good quality at the display input, then it shouldn't be an issue.

BTW, what are "the problems" you are referring to?
 

MagIO2

New member
Hi Cosmicvoid!

First of all, thank you for your patience and interest in helping.

Yes, I checked the connection one after another.

Well ... the problem is described in the last part of my first post:
What I have currently is that the display is switched on showing a picture that reminds me on a TV without any signal attached - after initialization. If I call the synonym of Display_Home function (which only sets the GRAM adress and selects register $22) something strange happens. First the upper part of display shows pale vertical lines of different color. Some bottom lines (say 10 just to give you a number) keep the fuzzy content. Then the content of the whole display gets darker in a few seconds. Any ideas?
 

MagIO2

New member
Thanks to all of you!

Problem solved .... and how can it be? It was my own fault .... well partially.

I ordered the display from a german distributor who also sells it soldered to a adapter-board. As I told before a floppy-cable perfectly matched. But it was so bad soldered that even all 4 backlights did not work in my first tests. So I re-soldered the whole flex-cable. In the end everything seemed to be fine except this small shortcut between DB15 and DB16, which I did not find in the first connection test.

Interested people should do this shortcut in software using the demo and see how strange that error looked like.

Again ... thanks for all the time you invested in trying to help.
 

MagIO2

New member
Scrolling?

How can you make the display scroll? Are there any special settings needed?

The display now works perfectly, but I can't get it scrolling. The code I have is in SPIN, but you should see what I do:

repeat y from 0 to 319
lcd.exec1( lcd#CMD_CMDOUT, $6a00)
lcd.exec1( lcd#CMD_DATAOUT, 2<<8 )

waitcnt( clkfreq/100+cnt )

I send $006a as a command followed by $0002. (LSB and MSB are reversed in the code above for easier handling in the propellers assembler). Shouldn't the display scroll up 2 lines then?
 

littlet

New member
I have the same issue MagicIO2 had originally.

I am using a Microchip Pic 18F4620 Microcontroller with a pickit 2 programmer, and when I run the driver code (adapted slightly because I'm using a pic rather than avr), I get an image that looks like a TV that has no input. Its basically random red, green or blue pixels.

I'm using pins from port A for control and port B for data bits.

my code:

Code:
#include <18F4620.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP,MCLR
#use delay(clock=10000000)	


#define	LCD_CD	PIN_A1   
#define	LCD_WR  PIN_A2
#define	LCD_RD  PIN_A3
#define	LCD_CS	PIN_A0
#define	LCD_RES	PIN_A4

#define CLR_CD OUTPUT_LOW(LCD_CD)
#define SET_CD OUTPUT_HIGH(LCD_CD)

#define CLR_CS OUTPUT_LOW(LCD_CS)
#define SET_CS OUTPUT_HIGH(LCD_CS)

#define CLR_RESET OUTPUT_LOW(LCD_RES)
#define SET_RESET OUTPUT_HIGH(LCD_RES)

#define CLR_WR OUTPUT_LOW(LCD_WR)
#define SET_WR OUTPUT_HIGH(LCD_WR)

#define CLR_RD OUTPUT_LOW(LCD_RD)
#define SET_RD OUTPUT_HIGH(LCD_RD)

// 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

/*************************************************/
void write_command(int16 command)
{
	CLR_CS;
	CLR_CD;
	SET_RD;
	SET_WR;

	output_b(command>>8);
	CLR_WR;
	SET_WR;
	delay_us(1);
	output_b(command);

	CLR_WR;
	delay_us(1);
	SET_WR;
	SET_CS;
}

/*************************************************/
void write_data(int16  data)
{
	CLR_CS;
	SET_CD;
	SET_RD;
	SET_WR;

	output_b(data>>8);
	CLR_WR;
	SET_WR;
	delay_us(1);
	output_b(data);

	CLR_WR;
	delay_us(1);
	SET_WR;
	SET_CS;
}
/*************************************************/
void initialization()
{
	SET_RD;
	SET_WR;
	SET_CS;
	SET_CD;
	output_b(0x00);

	CLR_RESET;
	delay_ms(1000);
	SET_RESET;
	delay_ms(50);

	write_command(0x0001);    // Driver Output Control Register (R01h)
	write_data(0x0000);       // Page 14, SPFD5408B Datasheet

	write_command(0x0002);    // LCD Driving Waveform Control (R02h)
	write_data(0x0700);       // Page 15, SPFD5408B Datasheet

	write_command(0x0003);    // Entry Mode (R03h)
	write_data(0x50A0);       // Page 15, SPFD5408B Datasheet

	write_command(0x0004);    // Scaling Control register (R04h)
	write_data(0x0000);       // Page 16, SPFD5408B Datasheet

	write_command(0x0008);    // Display Control 2 (R08h)
	write_data(0x0207);       // Page 17, SPFD5408B Datasheet

	write_command(0x0009);    // Display Control 3 (R09h)
	write_data(0x0000);       // Page 18, SPFD5408B Datasheet

	write_command(0x000A);    // Frame Cycle Control (R0Ah)
	write_data(0x0000);       // Page 19, SPFD5408B Datasheet

	write_command(0x000C);    // External Display Interface Control 1 (R0Ch)
	write_data(0x0000);       // Page 20, SPFD5408B Datasheet

	write_command(0x000D);    // Frame Maker Position (R0Dh)
	write_data(0x0000);       // Page 21, SPFD5408B Datasheet

	write_command(0x000F);    // External Display Interface Control 2 (R0Fh)
	write_data(0x0000);       // Page 21, SPFD5408B Datasheet

	write_command(0x0010);    // Power Control 1 (R10h)
	write_data(0x0000);       // Page 22, SPFD5408B Datasheet

	write_command(0x0011);    // Power Control 2 (R11h)
	write_data(0x0007);       // Page 23, SPFD5408B Datasheet

	write_command(0x0012);    // Power Control 3 (R12h)
	write_data(0x0000);       // Page 24, SPFD5408B Datasheet

	write_command(0x0013);    // Power Control 4 (R13h)
	write_data(0x0000);       // Page 25, SPFD5408B Datasheet
	delay_ms(200);      

	write_command(0x0007);    // Display Control (R07h)
	write_data(0x0101);       // Page 16, SPFD5408B Datasheet

	write_command(0x0010);    // Power Control 1 (R10h)
	write_data(0x12B0);       // Page 22, SPFD5408B Datasheet

	write_command(0x0011);    // Power Control 2 (R11h)
	write_data(0x0007);       // Page 23, SPFD5408B Datasheet

	write_command(0x0012);    // Power Control 3 (R12h)
	write_data(0x01BB);       // Page 24, SPFD5408B Datasheet
	delay_ms(50);

	write_command(0x0013);    // Power Control 4 (R13h)
	write_data(0x1300);       // Page 25, SPFD5408B Datasheet 

	write_command(0x0029);    // NVM read data 2 (R29h)
	write_data(0x0010);       // Page 30, SPFD5408B Datasheet 
	delay_ms(50);

	write_command(0x0030);    // Gamma Control 1
	write_data(0x000A);       // Page 32, SPFD5408B Datasheet 
	write_command(0x0031);    // Gamma Control 2
	write_data(0x1326);       // Page 32, SPFD5408B Datasheet  
	write_command(0x0032);    // Gamma Control 3
	write_data(0x0A29);       // Page 32, SPFD5408B Datasheet  
	write_command(0x0033);    // Gamma Control 4
	write_data(0x290A);       // Page 32, SPFD5408B Datasheet  
	write_command(0x0034);    // Gamma Control 5
	write_data(0x2613);       // Page 32, SPFD5408B Datasheet  
	write_command(0x0035);    // Gamma Control 6
	write_data(0x0A0A);       // Page 32, SPFD5408B Datasheet  
	write_command(0x0036);    // Gamma Control 7
	write_data(0x1E03);       // Page 32, SPFD5408B Datasheet  
	write_command(0x0037);    // Gamma Control 8
	write_data(0x031E);       // Page 32, SPFD5408B Datasheet 
	write_command(0x0038);    // Gamma Control 9
	write_data(0x0706);       // Page 32, SPFD5408B Datasheet  
	write_command(0x0039);    // Gamma Control 10
	write_data(0x0303);       // Page 32, SPFD5408B Datasheet  
	write_command(0x003A);    // Gamma Control 11
	write_data(0x0E04);       // Page 32, SPFD5408B Datasheet  
	write_command(0x003B);    // Gamma Control 12
	write_data(0x0E01);       // Page 32, SPFD5408B Datasheet  
	write_command(0x003C);    // Gamma Control 13
	write_data(0x010E);       // Page 32, SPFD5408B Datasheet  
	write_command(0x003D);    // Gamma Control 14
	write_data(0x040E);       // Page 32, SPFD5408B Datasheet  
	write_command(0x003E);    // Gamma Control 15
	write_data(0x0303);       // Page 32, SPFD5408B Datasheet  
	write_command(0x003F);    // Gamma Control 16
	write_data(0x0607);       // Page 32, SPFD5408B Datasheet  

	write_command(0x0050);    // Window Horizontal RAM Address Start (R50h)
	write_data(0x0000);       // Page 32, SPFD5408B Datasheet
	write_command(0x0051);    // Window Horizontal RAM Address End (R51h)
	write_data(0x00EF);       // Page 32, SPFD5408B Datasheet
	write_command(0x0052);    // Window Vertical RAM Address Start (R52h)
	write_data(0x0000);       // Page 33, SPFD5408B Datasheet
	write_command(0x0053);    // Window Vertical RAM Address End (R53h)
	write_data(0x013F);       // Page 33, SPFD5408B Datasheet

	write_command(0x0060);    // Driver Output Control (R60h)
	write_data(0x2700);       // Page 33, SPFD5408B Datasheet
	write_command(0x0061);    // Driver Output Control (R61h)
	write_data(0x0001);       // Page 35, SPFD5408B Datasheet

	write_command(0x006A);    // Vertical Scroll Control (R6Ah)
	write_data(0x0000);       // Page 35, SPFD5408B Datasheet

	write_command(0x0080);    // Display Position - Partial Display 1 (R80h)
	write_data(0x0000);       // Page 35, SPFD5408B Datasheet
	write_command(0x0081);    // RAM Address Start - Partial Display 1 (R81h)
	write_data(0x0000);       // Page 35, SPFD5408B Datasheet
	write_command(0x0082);    // RAM Address End - Partial Display 1 (R82h)
	write_data(0x0000);       // Page 36, SPFD5408B Datasheet
	write_command(0x0083);    // Display Position - Partial Display 2 (R83h)
	write_data(0x0000);       // Page 36, SPFD5408B Datasheet 
	write_command(0x0084);    // RAM Address Start - Partial Display 2 (R84h)
	write_data(0x0000);       // Page 36, SPFD5408B Datasheet 
	write_command(0x0085);    // RAM Address End - Partial Display 2 (R85h)
	write_data(0x0000);       // Page 36, SPFD5408B Datasheet 

	write_command(0x0090);    // Panel Interface Control 1 (R90h)
	write_data(0x0010);       // Page 36, SPFD5408B Datasheet 
	write_command(0x0092);    // Panel Interface Control 2 (R92h)
	write_data(0x0000);       // Page 37, SPFD5408B Datasheet 
	write_command(0x0093);    // Panel Interface control 3 (R93h)
	write_data(0x0103);       // Page 38, SPFD5408B Datasheet 
	write_command(0x0095);    // Panel Interface control 4 (R95h)
	write_data(0x0210);       // Page 38, SPFD5408B Datasheet 
	write_command(0x0097);    // Panel Interface Control 5 (R97h)
	write_data(0x0000);       // Page 40, SPFD5408B Datasheet
	write_command(0x0098);    // Panel Interface Control 6 (R98h)
	write_data(0x0000);       // Page 41, SPFD5408B Datasheet

	write_command(0x0007);    // Display Control (R07h)
	write_data(0x0173);       // Page 16, SPFD5408B Datasheet
}


/*************************************************/
void Display_Home()
{
	write_command( 0x0020); // GRAM Address Set (Horizontal Address) (R20h)
	write_data( 0x0000);
	write_command( 0x0021); // GRAM Address Set (Vertical Address) (R21h)
	write_data( 0x0000);
	write_command(0x0022);  // Write Data to GRAM (R22h)
}
/*************************************************/
void display_rgb(int16 data)
{
	int16 i,j;
	Display_Home();

	for(i=0;i<320;i++)
	{
		for(j=0;j<240;j++)
		{
			write_data(data);
		}
	}
}
/*************************************************/

void LCD_test()
{
	int16 i,j;
	Display_Home();

	write_data(BLACK);
	delay_ms(1000);
	write_data(BLUE);
	delay_ms(1000);
	write_data(GREEN);
	delay_ms(1000);
	write_data(CYAN);
	delay_ms(1000);
	write_data(RED);
	delay_ms(1000);
	write_data(MAGENTA);
	delay_ms(1000);
	write_data(YELLOW);
	delay_ms(1000);
	write_data(WHITE);

}

/*************************************************/
void main()
{
	output_low(PIN_C2);
	output_b(0xF8);	    // pull-up on switches, all others off

	output_a(0xFE);	    // all pins high

	// Initialize the display
	initialization();

	LCD_test();

blinkLED:	output_low(PIN_C2); //Blinks LED upon completion
	delay_ms(1000);
	output_high(PIN_C2);
	delay_ms(1000);
	goto blinkLED;
}
/*************************************************/
Any help is appreciated,

JT
 
In your write functions, it looks like your delays are applied differently for the two bytes:
Code:
void write_command(int16 command)
{
	CLR_CS;
	CLR_CD;
	SET_RD;
	SET_WR;

	output_b(command>>8);
[COLOR="Red"]	CLR_WR;
	SET_WR;
[/COLOR]	delay_us(1);
	output_b(command);

[COLOR="Magenta"]	CLR_WR;
	delay_us(1);
	SET_WR;
[/COLOR]	SET_CS;
}
I don't know your clock speed, to judge your pulse width without a delay. I wonder why you don't have a delay for the first pulse, like you do in the 2nd one. That would make 3 delays, including the one between bytes.
 

MagIO2

New member
Yep, ... cycle time for the display is 100ns. Running the PIC at 40MHz would not work - as fas as I remember PIC instructions run in one cycle, don't they?
But instead of calling the delay function I'd put nop's in between. You'll need the speed.
 

littlet

New member
MagicIO2: Pic instructions run in 4 clock cycles.

This code is running with a 10Mhz Crystal/clock. So instructions run at 2.5MHz; let's assume all my control statements (CLR_CS,CLR_CD, etc...) run in one instruction cycle. That means that they are happening at 2.5MHz. 1/2.5MHz = 400ns. This is 4x slower than the 100ns, so I would assume that's not the problem.

In general, can I assume all IO for the display is clocked at 100ns?

The whole reason I put delays in there was because the original driver file had some delays in it that I didn't want to remove in case they were important. I probably should have thought about it a little more before I added them randomly in places.

If I have them in bad places, or they aren't long enough can you suggest a good delay scheme to properly clock instructions both during and after initialization?

I forgot to mention before that I did not want to rely on the bitwise operators below from the original driver file, and besides it doesn't compile in on a PIC anyway:

Code:
#define CLR_CD PORTC &= ~(1 << LCD_CD)
#define SET_CD PORTC |=  (1 << LCD_CD)
etc...

So I changed it to:

Code:
#define CLR_CD OUTPUT_LOW(LCD_CD)
#define SET_CD OUTPUT_HIGH(LCD_CD)
etc...

This made the assumption that the proper state of a "CLR" is low or 0v on a Microcontroller output, and that a "SET" is a high or 5v on a Microcontroller output, REGARDLESS of whether it is an active low or active high. Is this assumption correct for the control pins on the display?

Thanks,

JT
 

MagIO2

New member
Yep, CLR is 0V and SET is 5V. These signals (WR,RD,CS) are low-active.

According to your setup, you don't need delays in between the WR cycle. I run my display with a propeller, which has a instruction cycle of 50ns and with two instructions it works perfectly.

I'd suggest to check your wiring. No contact, shortcuts, did you mix up pins?

PS:
Maybe it's hidden in code you did not post or I'm to blind to see, but where do you set direction of the port?
 
Last edited:

littlet

New member
Magic:

I'm coding this with the CCS C compiler (http://www.ccsinfo.com/).

Their compiler doesn't require setting the Data Direction Register like most other microcontroller languages. This was new to me when I started with PICs, and although you can actually manually set them, I was advised not to do so by a guru on their forums. The standard I/O functions allegedly take care of DDR automatically.

What you see in my original post is all of my code (minus the 18F4620 include file, but I wouldn't suspect anything in there).

I won't get a chance to debug the hardware until Monday, but I'll give it another round then.

JT
 

CF Support

Administrator
MagicIO2:

This made the assumption that the proper state of a "CLR" is low or 0v on a Microcontroller output, and that a "SET" is a high or 5v on a Microcontroller output, REGARDLESS of whether it is an active low or active high. Is this assumption correct for the control pins on the display?
Be advised, the controller is not 5v tolerant -- the controller as well as the display datasheets both list 3.3v as the maximum supply and input voltage.
 
Top