Go Down

Topic: Graphic LCD (KS0108) library now available (Read 134588 times) previous topic - next topic


Hi Argo,

If your panel is wired correctly then the most likely cause of garbled display is that its being driven too quickly.  You can add delays into the library (there is information here: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210427907/42#42) but it is not easy to do if you are not an experienced programmer.

As hulk says, I am working on a new version of the library that adapts to the speed of the panel that should  get you going. I expect to have a version you could try in the next few  days, I will post here when it is available.


thanks for the quick replies.  I'll follow the suggested link post ( lcd driven to quickly...) and also be on the look out for the updated library.

thanks again, :)


Hello all,
Interesting find.  I had to add about 46  "nop\n\t" to the ks0108.cpp file for it to finally work.  thanks for the solution and still will download your latest update mem.  

The GLCD I bought is from sparkfun.  http://www.sparkfun.com/commerce/product_info.php?products_id=710

thanks again.


Nov 02, 2008, 06:20 pm Last Edit: Nov 02, 2008, 06:21 pm by Frisken Reason: 1
I wanted to get the GLCD to work with the 74HC595 to be able to save 5 pins on the arduino. To test this fast I just did a fask hack to try if it was possible to do.
The answer to that is that it is possible. The big loss with this is that it is not possible read from the GLCD and therefor if you write to the same area more then one time with different data only the last data will show.
For me that has not been a big problen because I mostly present text in the display and I use a font with fixed width. Therefor all the old characters are coverd with the new ones if the same amount of characters are used.

If someone is interested in how I did this fast hack here is the answer.
This is what I did in the ks0108.h file:
1.      I defined the pins needed for the 74HC595 to work.
Code: [Select]

#define DataPin      2
#define ClockPin      3
#define LatchPin      4

2.      I added the ShiftOut macro from MartinFick that he posted in the thread "Arduino Forum ? Software ? Bugs & Suggestions ? Higher Performance IO".
Code: [Select]

#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))

#define sbipin(pin) sbi((pin)<8 ? PORTD:PORTB, (pin) - ((pin)<8 ? 0:8))
#define cbipin(pin) cbi((pin)<8 ? PORTD:PORTB, (pin) - ((pin)<8 ? 0:8))

#define bitWrite(pin, val) { \
 if ((val) == LOW) cbipin(pin); \
 else              sbipin(pin); \

#define shiftOutBit(dataPin, clockPin, val, bit) { \
 bitWrite(dataPin, ((val) & (1 << (bit))) ? HIGH:LOW); \
 bitWrite(clockPin, HIGH); \
 bitWrite(clockPin, LOW); \

#define shiftOutByte(dataPin, clockPin, bitOrder, val) { \
 shiftOutBit(dataPin, clockPin, val, (bitOrder) == LSBFIRST ?0:7); \
 shiftOutBit(dataPin, clockPin, val, (bitOrder) == LSBFIRST ?1:6); \
 shiftOutBit(dataPin, clockPin, val, (bitOrder) == LSBFIRST ?2:5); \
 shiftOutBit(dataPin, clockPin, val, (bitOrder) == LSBFIRST ?3:4); \
 shiftOutBit(dataPin, clockPin, val, (bitOrder) == LSBFIRST ?4:3); \
 shiftOutBit(dataPin, clockPin, val, (bitOrder) == LSBFIRST ?5:2); \
 shiftOutBit(dataPin, clockPin, val, (bitOrder) == LSBFIRST ?6:1); \
 shiftOutBit(dataPin, clockPin, val, (bitOrder) == LSBFIRST ?7:0); \

3.      In the private section I added a new function.
Code: [Select]

void lcdDataShiftOut(uint8_t data);

In the ks0108.cpp file I did these changes:
1.      All the lines that uses the ReadData() function I changed to a fake readout with 0. This is because it's no longer possible to read from the GLCD.
e.g. "data = this->ReadData();" became
data = 0x00; //this->ReadData();
2.      In the "Init(Boolean invert)" function I added the outputs needed for the 74HC595.
Code: [Select]


3.      A shiftout function was added to write to the GLDC using the macros in the .h file.
Code: [Select]

void ks0108::lcdDataShiftOut(uint8_t data)
     shiftOutByte(DataPin, ClockPin, MSBFIRST, data);

4.      And finally in the "WriteData(uint8_t data)" and "WriteCommand(uint8_t cmd, uint8_t chip)" functions I commented out the use of "lcdDataOut()" macro and replaced it with the "lcdDataShiftOut(uint8_t data)".
e.g. "lcdDataOut(cmd);" was commented out and "lcdDataShiftOut(cmd);" was added.

I hope that someone find this usefull. It works fine with my GLCD (ATM12864D). If I test it with the testcode made by mem I got 12 FPS but it do not look that good in the display because there is not possible to read anything from the GLCD. Do not use the 74HC595 if you tend to use a lot of graphics in the GLCD.


Nov 02, 2008, 08:51 pm Last Edit: Nov 02, 2008, 08:52 pm by mem Reason: 1
Firsken, good to hear you have that going with the shift register.  As you say, that solution works well with text.  The next version of the library will contain a 5x7 fixed pitch 'system' font which gives up to  8x20 character text display on a 128x64 panel. The release is taking a little longer than I had expected so FWIW, here is the fixed pitch system font definition for those that want do something similar to you:
Code: [Select]
* System5x7
* File Name           : System5x7.h
* Date                : 28 Oct 2008
* Font size in bytes  : 470
* Font width          : 5
* Font height         : 7
* Font first char     : 32
* Font last char      : 127
* Font used chars     : 94
* The font data are defined as
* struct _FONT_ {
*     uint16_t   font_Size_in_Bytes_over_all_included_Size_it_self;
*     uint8_t    font_Width_in_Pixel_for_fixed_drawing;
*     uint8_t    font_Height_in_Pixel_for_all_characters;
*     unit8_t    font_First_Char;
*     uint8_t    font_Char_Count;
*     uint8_t    font_Char_Widths[font_Last_Char - font_First_Char +1];
*                  // for each character the separate width in pixels,
*                  // characters < 128 have an implicit virtual right empty row
*     uint8_t    font_data[];
*                  // bit field of all characters

#include <inttypes.h>
#include <avr/pgmspace.h>

#ifndef SYSTEM5x7_H
#define SYSTEM5x7_H

#define SYSTEM5x7_WIDTH 5
#define SYSTEM5x7_HEIGHT 7

static uint8_t System5x7[] PROGMEM = {
   0x0, 0x0, // size of zero indicates fixed width font, actual length is width * height
   0x05, // width
   0x07, // height
   0x20, // first char
   0x7f, // char count
   // Fixed width; char width table not used !!!!
   // font data
   0x00, 0x00, 0x00, 0x00, 0x00,// (space)
     0x00, 0x00, 0x5F, 0x00, 0x00,// !
     0x00, 0x07, 0x00, 0x07, 0x00,// "
     0x14, 0x7F, 0x14, 0x7F, 0x14,// #
     0x24, 0x2A, 0x7F, 0x2A, 0x12,// $
     0x23, 0x13, 0x08, 0x64, 0x62,// %
     0x36, 0x49, 0x55, 0x22, 0x50,// &
     0x00, 0x05, 0x03, 0x00, 0x00,// '
     0x00, 0x1C, 0x22, 0x41, 0x00,// (
     0x00, 0x41, 0x22, 0x1C, 0x00,// )
     0x08, 0x2A, 0x1C, 0x2A, 0x08,// *
     0x08, 0x08, 0x3E, 0x08, 0x08,// +
     0x00, 0x50, 0x30, 0x00, 0x00,// ,
     0x08, 0x08, 0x08, 0x08, 0x08,// -
     0x00, 0x60, 0x60, 0x00, 0x00,// .
     0x20, 0x10, 0x08, 0x04, 0x02,// /
     0x3E, 0x51, 0x49, 0x45, 0x3E,// 0
     0x00, 0x42, 0x7F, 0x40, 0x00,// 1
     0x42, 0x61, 0x51, 0x49, 0x46,// 2
     0x21, 0x41, 0x45, 0x4B, 0x31,// 3
     0x18, 0x14, 0x12, 0x7F, 0x10,// 4
     0x27, 0x45, 0x45, 0x45, 0x39,// 5
     0x3C, 0x4A, 0x49, 0x49, 0x30,// 6
     0x01, 0x71, 0x09, 0x05, 0x03,// 7
     0x36, 0x49, 0x49, 0x49, 0x36,// 8
     0x06, 0x49, 0x49, 0x29, 0x1E,// 9
     0x00, 0x36, 0x36, 0x00, 0x00,// :
     0x00, 0x56, 0x36, 0x00, 0x00,// ;
     0x00, 0x08, 0x14, 0x22, 0x41,// <
     0x14, 0x14, 0x14, 0x14, 0x14,// =
     0x41, 0x22, 0x14, 0x08, 0x00,// >
     0x02, 0x01, 0x51, 0x09, 0x06,// ?
     0x32, 0x49, 0x79, 0x41, 0x3E,// @
     0x7E, 0x11, 0x11, 0x11, 0x7E,// A
     0x7F, 0x49, 0x49, 0x49, 0x36,// B
     0x3E, 0x41, 0x41, 0x41, 0x22,// C
     0x7F, 0x41, 0x41, 0x22, 0x1C,// D
     0x7F, 0x49, 0x49, 0x49, 0x41,// E
     0x7F, 0x09, 0x09, 0x01, 0x01,// F
     0x3E, 0x41, 0x41, 0x51, 0x32,// G
     0x7F, 0x08, 0x08, 0x08, 0x7F,// H
     0x00, 0x41, 0x7F, 0x41, 0x00,// I
     0x20, 0x40, 0x41, 0x3F, 0x01,// J
     0x7F, 0x08, 0x14, 0x22, 0x41,// K
     0x7F, 0x40, 0x40, 0x40, 0x40,// L
     0x7F, 0x02, 0x04, 0x02, 0x7F,// M
     0x7F, 0x04, 0x08, 0x10, 0x7F,// N
     0x3E, 0x41, 0x41, 0x41, 0x3E,// O
     0x7F, 0x09, 0x09, 0x09, 0x06,// P
     0x3E, 0x41, 0x51, 0x21, 0x5E,// Q
     0x7F, 0x09, 0x19, 0x29, 0x46,// R
     0x46, 0x49, 0x49, 0x49, 0x31,// S
     0x01, 0x01, 0x7F, 0x01, 0x01,// T
     0x3F, 0x40, 0x40, 0x40, 0x3F,// U
     0x1F, 0x20, 0x40, 0x20, 0x1F,// V
     0x7F, 0x20, 0x18, 0x20, 0x7F,// W
     0x63, 0x14, 0x08, 0x14, 0x63,// X
     0x03, 0x04, 0x78, 0x04, 0x03,// Y
     0x61, 0x51, 0x49, 0x45, 0x43,// Z
     0x00, 0x00, 0x7F, 0x41, 0x41,// [
     0x02, 0x04, 0x08, 0x10, 0x20,// "\"
     0x41, 0x41, 0x7F, 0x00, 0x00,// ]
     0x04, 0x02, 0x01, 0x02, 0x04,// ^
     0x40, 0x40, 0x40, 0x40, 0x40,// _
     0x00, 0x01, 0x02, 0x04, 0x00,// `
     0x20, 0x54, 0x54, 0x54, 0x78,// a
     0x7F, 0x48, 0x44, 0x44, 0x38,// b
     0x38, 0x44, 0x44, 0x44, 0x20,// c
     0x38, 0x44, 0x44, 0x48, 0x7F,// d
     0x38, 0x54, 0x54, 0x54, 0x18,// e
     0x08, 0x7E, 0x09, 0x01, 0x02,// f
     0x08, 0x14, 0x54, 0x54, 0x3C,// g
     0x7F, 0x08, 0x04, 0x04, 0x78,// h
     0x00, 0x44, 0x7D, 0x40, 0x00,// i
     0x20, 0x40, 0x44, 0x3D, 0x00,// j
     0x00, 0x7F, 0x10, 0x28, 0x44,// k
     0x00, 0x41, 0x7F, 0x40, 0x00,// l
     0x7C, 0x04, 0x18, 0x04, 0x78,// m
     0x7C, 0x08, 0x04, 0x04, 0x78,// n
     0x38, 0x44, 0x44, 0x44, 0x38,// o
     0x7C, 0x14, 0x14, 0x14, 0x08,// p
     0x08, 0x14, 0x14, 0x18, 0x7C,// q
     0x7C, 0x08, 0x04, 0x04, 0x08,// r
     0x48, 0x54, 0x54, 0x54, 0x20,// s
     0x04, 0x3F, 0x44, 0x40, 0x20,// t
     0x3C, 0x40, 0x40, 0x20, 0x7C,// u
     0x1C, 0x20, 0x40, 0x20, 0x1C,// v
     0x3C, 0x40, 0x30, 0x40, 0x3C,// w
     0x44, 0x28, 0x10, 0x28, 0x44,// x
     0x0C, 0x50, 0x50, 0x50, 0x3C,// y
     0x44, 0x64, 0x54, 0x4C, 0x44,// z
     0x00, 0x08, 0x36, 0x41, 0x00,// {
     0x00, 0x00, 0x7F, 0x00, 0x00,// |
     0x00, 0x41, 0x36, 0x08, 0x00,// }
     0x08, 0x08, 0x2A, 0x1C, 0x08,// ->
     0x08, 0x1C, 0x2A, 0x08, 0x08 // <-


save the above as SystemFont5x7.h.

usage in sketch:
#include <SystemFont5x7.h>
void setup(){
 for(int line=0; line < 64; line+=8){
    GLCD.GotoXY(0, line);  // note that y position should be evenly divisable by 8
 GLCD.Puts("line ");
 GLCD.PutChar(line + '0');


Thanks for the font mem.

In the library there is a private function called WriteData. Is it private for a reason or can you make it public in the next release?



Hi Frisken, I was thinking about  adding a method that enables writing of bitmap data to the panel which would be a wrapper around writeData. But if you think having writeData public would be more useful, then I can do that if someone could test it thoroughly.

As you can probably see from looking at the source code, driving this chip is complicated, particularly when data is not written to an even vertical page boundary or if individual pixels need to be set. Alsothe chip requires lots of data contortions because it needs to be read twice to get a single byte of data out, and each double read increments the chips internal address counter which needs to be set back when data is written.  All those GotoXYs in the code should take care of it but it really would need some testing if you were accessing writeData externally.

I am almost ready with a beta copy of the new version, I would be happy if you wanted to test using writeData from a sketch.


I would be happy to try it out for you. Is there any specific combination that you think could be troublesome or are you just interested in random testing?


Anything with complex graphics,  particularly where individual pixels are written that cross over between controller chips (x = 64) would be a good test. Also where pixels and/or lines are drawn across page boundaries (there are eight pages in the controller, each 8 bits high starting from line 0)

A simple but effective test is to copy small monochrome bitmaps to the various locations in the panel using WriteData.

I probably won't have the version ready tonight, I will pm you and Hulk when it is available.


Anybody know what the maximum cable lenght between the panel and Arduino is?
Are we talking about 30-50cm or just 10cm, at some point the cable lenght has to disturb the signals.

I am sure i can test this myself but hopefully somebody of you have that experience allready  :)


Hey guys. New member and new Arduino user here. I've been seeing the same issues as Argo. I also have an LCD-00710 screen from Sparkfun. It was garbled just as Argo said. I've tried editing the .cpp file with the "nop\n\t" fix that Argo did as well as add the code that mem posted.

Both of these do in fact clear up the screen a bit, but it's still nothing close to what the pic in the tutorial shows.

Let me know what you guys think I should do. Thanks!


Nov 07, 2008, 01:47 am Last Edit: Nov 07, 2008, 01:48 am by skeo Reason: 1
The forum wouldn't let me add a link in my first post, so this is what it currently looks like:

I know it's hard to see. But the circle with the lines from the corner is pretty garbled. In fact it looks like two columns need to be swapped.

Edit: Also note that I'm using twisted pair wire for the data pins. Is this bad?


.. never mind. Turns out that one of my twisted pairs was twisted a little too much (read: hooked up backwards).

All is fixed and I look forward to mem's update!


Hi skeo, good to hear you have it going. Yes, I am also looking forward to the update  ;)  Sorry its taken so long but I am testing with lots of different displays and I am still working on code to get the best performance out of some of the slower ones. Progress is slow but steady, hope to have something up real soon now.


Cool, can't wait - I've got a graphical lcd and I want to try and get it working.  :)

Go Up