CFAG128128 graphic mode column swapping


New member

I might be posting in the wrong forum, because I am using some parallel port code that I found here to test out my display before connecting it to my final circuit using an 8051 based micro. I'm not sure if this is a hardware problem or not...

I also have a CFAG320240 that I have wired in exactly the same way, and it works fine using the CFAG320240C_WinTest sample code, so I am pretty sure the module is wired correctly.

I have modified the CFAG160160B_WinTest code to use this 128 x 128 pixel resolution screen (CFAG128128) instead of 160 x 160 pixels.

When I try to write a bitmap to the screen there is a problem. It seems that some columns are being switched. First the display is set to graphics mode and the cursor address is set to 0x0000. The character pitch(Hp) is set to 8, and Hn is set to 16. The duty cycle is set to 128. (If I set the duty cycle to 64 like the manual suggests, the screen is cut in half and the bits are duplicated in the top and bottom half of the screen!)

Then I start writing bytes to the display to show my bitmap. If I step through my code, I can see 8 pixels at a time turning on, starting at the top left of the screen. So there are 16 bytes per row.

However, here is what happens. Bytes 1 through 10 display as they should, turning on the pixels across the top row of the screen. Bytes 11 and 12 shows up where bytes 15 and 16 should be (on the last 16 pixels of the top row). Then bytes 13 through 16 show up where bytes 11-14 should be, but on the second row! Then the next line starts where it should on the second row, and the last 4 bytes of the second row show up on the third row..

The result is that my bitmap shows up with the last 16 columns swapped with the 32 columns before them. I can find no reason for this...

Can you help me? This is for a customer who needs it yesterday, of course!

I am attaching my original bitmap and a bitmap that shows what the screen is looking like.

Thank you very much,
Looking for additional LCD resources? Check out our LCD blog for the latest developments in LCD technology.


When you write a parameter to a control register, are you setting the value to "n-1"? E.g. for a duty (Nx) of 128, the register contains 127; for Hn of 16, register contains 15, etc.

Have you tried doing a (redundant) cursor addr write before each byte, to see if the behavior changes?


New member

Thanks for your reply.

Yes, I am setting the registers to "n-1" on setup. Here is part of the setup code:
	CP_COMMAND(0x00,0x32);	    // set graphics mode

	CP_COMMAND(0x01,0x07);	// Character pitch setting = 8

	CP_COMMAND(0x02,15);      //Character number setting     128/8=16 Chars in one line

	CP_COMMAND(0x03,127);	// Display duty setting - Set 1/128 duty

	CP_COMMAND(0x08,0x00); // Display low address setting - Low address start from 00

	CP_COMMAND(0x09,0x00);// Display high address setting - High address start from 00
I tried resetting the cursor address as you suggested before writing every screen byte, but got exactly the same result. I watched as each byte was slowly written to the screen with the same column shift. Here is that test code:
	int row,col;
	unsigned char *scrPtr;
	WORD csrAddr;

	csrAddr = 0;
	scrPtr = (unsigned char *)screen128x128; // bitmap buffer

			CP_COMMAND(0x0A,(BYTE)csrAddr);          //Cursor low address setting
			CP_COMMAND(0x0B,(BYTE)(csrAddr>>8));  //Cursor high address setting

			SET_RS;	//Send data command
			STROBE_E;       // SET_E;   CLR_E;
			DATA( *scrPtr++ );
Do you think this could be a wiring problem? Or a faulty LCD? Is there a parallel port test test program available for this particular screen? I don't quite see how it could be a wiring problem as the left half of the screen looks fine...

Thank you again!

Your init looks OK, your code looks OK. Next I would suspect a bit swap in the wiring or a faulty LCD module.

I only have experience on the CFAG160160, but since it has the same controller chip, it should work the same.

My init sequence is slightly different, going into character mode first, and then graphic mode at the end. I don't remember why I did that, and I don't see why it would make a difference.
#define GR_MODE		0		// mode register
#define GR_PITCH	1		// character H & V pitch register
#define GR_HORIZ	2		// horiz chars or bytes register
#define GR_DUTY		3		// duty cycle register
#define GR_CURP		4		// cursor posn register
#define GR_STRTL	8		// display start addr L register
#define GR_STRTH	9		// display start addr H register
#define GR_CURAL	0xA		// cursor addr L register
#define GR_CURAH	0xB		// cursor addr H register
#define GR_WRITE	0xC		// write instruction
#define GR_READ		0xD		// read instruction
#define GR_BCLR		0xE		// bit clear instruction
#define GR_BSET		0xF		// bit set instruction

#define GR_INILEN	10		// number of items in init table

static const BYTE LCDIni[GR_INILEN][2] = {
		GR_MODE, 0x10,
		GR_PITCH, 0x77,
		GR_HORIZ, 19,
		GR_DUTY, 159,
		GR_CURP, 0,
		GR_STRTL, 0,
		GR_STRTH, 0,
		GR_CURAL, 0,
		GR_CURAH, 0,
		GR_MODE, 0x32	// graphic mode

CF Tech

Try modifying your loop so it writes a single '1' shifted:

DATA( 0x01<<(row&0x07) );

That should make diagonal lines. If it does not then there is a wiring problem somewhere in D0-D7.


New member
I tried writing diagonal lines with the same shifted result. We had bought two of these LCDs so I wired up the other one and got the same results. So, since my client is in such a hurry, I made it work by pre-shifting the columns in my bitmaps, and made a nice scrolling marquis, like credits on a movie -I think the D0-D7 are wired ok... I'm stuck for now on this one, and off to another project. Thank you for your help anyway!

-If you're interested, I can send you my LCD hardware setup and code...



New member
No problem. I took the 160160 code and modified it to 128128.

I'm including a utility that I wrote to print out hex characters from a bitmap, modified for Crystalfontz screens.

Jeff Platt
Motion Design


CF Tech

Thanks for the post. I am sure this sample code for the CFAG128128 will be useful to others.


New member
So I sent it ( the CFAG128128 with parallel port cable ) to my client and it didn't work... It turned out that I had changed the Delay loop timing on my machine that set the pulse timing parameters, in order to make the LCD update faster. It worked fine on my machine, but the client's machine ran faster, so I boosted the software delay loop time back to 10,000 and then it worked for him.
-Still having the column swap though! If anybody tries this code out please let me know.