GLCD library version 3 (end of life - no longer supported)

wbphelps:
Is there some way to change pin assignments without editing the .h files? I tried doing a #define in my sketch but it doesn't seem to make any different. Also tried #undef and #define.

Thanks...

Not really. The glcd library does not use any of the arduino core code to drive the lcd pins. It converts the defines in the header
files to direct AVR pin i/o at compile time. The advantage of this is speed. Direct i/o is MUCH faster than using the arduino core code.
( digitalRead(), digitalWrite() functions)
It does come with some drawbacks. One of them being that the all the pins must be defined when the library code
is built, which is built separately from the sketch so it is not possible to re-define the pins inside a sketch file or runtime
inside a sketch.

What is the driving need?
Are you looking for a way to preserve your pin changes when updating the library?

--- bill

Makes perfect sense, glcd is amazingly fast.

bperrybap:
What is the driving need?

I2C on A4,A5. Everything else I can move.

Thanks,
William

Hi Bill,

Thank you for your time on this great update.

I just installed v3 RC2 on my Teensy++ v2 and it works great. It shows 16.4 FPS.

A request -- Please consider including the ks0108_Teensy++.h config file, attached.

Thanks again for your time on this project.

Regards,
Larry

ks0108_Teensy++.h (965 Bytes)

larrykluger:
Hi Bill,

Thank you for your time on this great update.

I just installed v3 RC2 on my Teensy++ v2 and it works great. It shows 16.4 FPS.

A request -- Please consider including the ks0108_Teensy++.h config file, attached.

Thanks again for your time on this project.

Regards,
Larry

I'm not understanding what this teensy++ config file would be used for.
(with respect to the latest glcd library)

Maybe if you explained a bit more what you are needing, it would help.

=== more details.

The way things are configured in the latest version of the library is very different from the previous version.
The define names are different and now every glcd pin can be defined separately.
teensy++ should work "out of the box" by selecting the teensy or teensy++
board type in the Arduino IDE (with teensyduino installed).
The IDE will set the processor type and the glcd library auto-configuration
header files will key off that to automatically select an appropriate pin configuration file.
The final pin configuration file included for teensy/teensy++ boards glcd/config/ks0108_Teensy.h
supports both teensy and teensy++

A bit of detail:
glcd/glcd_Config.h includes the top level configuration file. By default this is set to include
glcd/config/ks0108_Panel.h which is the top level auto-configuration file for a ks0108 glcd panel.
The ks0108_Panel.h header file will then use the processor type
(which is set by selecting the board type in the Arduino IDE)
to determine which pin configuration file to include.
If you have your board type set to teensy or teensy++ then glcd/config/ks0108_Teensy.h
is included. Then inside glcd/config/ks0108_Teensy.h there are ifdefs to select which set of defines are used
to define the pins for teensy vs teensy++.

Michael and I set up the pin defines in the teensy pin configuration file as Paul had requested so it matches the
pin descriptions in his examples and on his web pages for both the teensy and teensy++.

NOTE:
Paul has not yet updated the teensy website yet, for the latest version of the glcd library. He
has a modified version of the ks0108 v2 library available on his site for use with teensyduino.

From looking at the header file you attached, the supplied teensy/teensy++ pin configuration
file appears to use the same pins, but the file you attached seems to be more in a form for the
older version 2 of the library.
Thats why I'm a bit confused as to what this header file would be used for?

--- bill

Hi Bill,

Thank you for an informative reply. I've tested it, and you're 100% right, stock GLCD v3 rc2 works great with the Teensy++ v2. No extra files are needed.

I was confused when I saw that the v2 glcd lib had two separate .h files for teensy and teensy++. -- So I copied over the v2 header file as you surmised.
Anyhow, as Emily Litella used to say, "Never mind."

Thanks and regards,

Larry

This library looks awesome - thanks for all the hard work.

Out of curiosity does it support KS0713 chips? I've seen some people say that they're compatible with KS0108 and others say no.

What happened to the "Pinout D panels" that were described on Arduino Playground - GLCDks0108??
I have the same display as described on AN #148 - LCD display with touchscreen and AVR - MCS Electronics and was trying to hook it up to de V3 GLCD library.
Any ideas???

I made a function that creates a bar graph, for anyone interested. To use it, simply add this to your glcd.cpp file:

void glcd::BarGraph(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t fullval, uint8_t currentval){
	float range = (float)width / (float)fullval;
	int currentwidth = currentval * range;
	GLCD.DrawRect(x, y, width, height);
	for (int i = 1; i < height; i++) {
		GLCD.DrawHLine(x, y+i, currentwidth);}
	GLCD.FillRect(x+currentwidth+1, y+1, width-currentwidth-2, height-2, WHITE);
}

And this to your glcd.h file:

void BarGraph(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t max, uint8_t current);

Here is an example, that fills the graph as a clock counts up:

#include <glcd.h>
#include "fonts/fixednums15x31.h"

long sec = 0;
int min = 0;
long starttime;

	
void setup() {

	GLCD.Init(NON_INVERTED);
	GLCD.ClearScreen(); 
}


void loop() {

	gText ClockArea;
	ClockArea.DefineArea(20, 0, 6, 1, fixednums15x31);
	ClockArea.CursorToXY(2,0);
	
	sec = (millis() - starttime) / 1000;
	if (sec > 59) {
		min++;
		sec = 0;
		starttime = millis();
	}
	if (min < 10) {
		ClockArea.print(0);}
	ClockArea.print(min);
	ClockArea.print(":");
	if (sec < 10) {
		ClockArea.print(0);}
	ClockArea.print(sec);
	GLCD.BarGraph(10, 40, 108, 8, 59, sec);
}

Syntax:

GLCD.BarGraph(toprightx, toprighty, width, height, fullvalue, currentvalue);

Alban:
What happened to the "Pinout D panels" that were described on Arduino Playground - GLCDks0108??
I have the same display as described on AN #148 - LCD display with touchscreen and AVR - MCS Electronics and was trying to hook it up to de V3 GLCD library.
Any ideas???

To honest, I've never really been a fan of the A, B, C.... display types. I know that it can make it easier to hook up panels
for less technical folks but it comes with some potential serious consequences. The biggest being if people start
to simply try them one after the other or simply pick the wrong one,
rather than compare it to the real datasheet to determine which one is the correct one,
it is possible that their display will be damaged.

The other issue that we ran into recently (which is what you are probably noticing) is the ks0108 playground is a "wiki"
page that is open for anyone to edit. The table has been updated/extended - which is what we wanted. Unfortunately, the
updates to the table were done incorrectly and have caused a deviation from the original table
and a deviation from the documentation included with the library.
i.e. the A, B, C, D.... display types on the wiki page no longer match the display types in the included library documentation.
This is very problematic because when they don't match, if someone says I have type "X" or vendor display "Y" is type "Z"
and they go by the table on the wiki, it can cause someone to wire it up incorrectly, which might damage the display.
The table on the wiki also currently does include the pinouts for the Teensy boards, whereas
the table included in the library HTML & PDF documentation does.
New table entries must always be added to end of the table and existing table entries cannot be modified.
Since the wiki is open for anyone to update,
I'm not sure how to really resolve this other than to remove the ability for people to update the wiki
or simply remove the table from wiki all together and only supply it with the library itself.

The safest thing to do is to always go by the data sheet and the "GLCD functions"
and Board type columns rather than use the display panel type columns in the table.
In other words, ignore the panel types columns in the table and match up your modules glcd pin functions
with the appropriate pins column for your board type.
It is simply a matter of looking at the table in a slightly different way.

To do this, you will be looking at your data-sheet, along with the "GLCD function" column
and then the appropriate board type column in table in the documentation included in the library.
(I prefer the HTML documentation)

So for example, if you want to know where to wire up the pin for glcd data bit 0,
scan down the "GLCD function" column until you see D0.
Then scan over to the board type you have.
If you have a standard Arduino board, you can see that glcd function pin D0 gets hooked up
to arduino pin 8.
Regardless of the panel, or panel type (A, B, C,....X...) glcd function pin D0 is always hooked up
to pin 8 on a standard Arduino. The columns for the different panel types were accounting for the
different pin numbers for glcd function pin D0 on the different glcd modules.

In your case, I would recommend that you hook up your display using this method.
Actually, I'd recommend this method for everyone, but some folks just want a simple table :frowning:
The reason I prefer this method is that it works for any glcd module as long as you have the
data-sheet.


Assuming your data-sheet is correct. (That pinout is very rare BTW).
Then start hooking up the pins by matching up your glcd functions to the correct
"arduino" pin. Assuming you have standard Arduino, here is are a few examples
to get you started.

Use the table that is included HTML documentation.

Pin 1 on your GLCD is cs1 (This is the same as CSEL1 in the table)
If you look in the table in the "GLCD Function" column, scan down until
you see the "CSEL1" entry. Then scan left until you get to the column
for your board type. Assuming you have a standard arduino, you will
see that CSEL1 connects to Arduino pin 14/Analog-0

So that means that GLCD pin 1 (CS1/CSEL1) connects to Arduino Pin 14/Analog-0.

Anther pin.
GLCD pin 6 is Cd - (same as D_I)
[ Cd is command/data; D_I is for Data/Instruction - but are the same]
So scanning through the table, GLCD pin 6 (Cd/D_I) would be hooked up to Arduino pin 17/Analog-3

A few more pins for example
GLCD pin 8 Enable, would go to the EN Function or Arduino pin 18/Analog-4
GLCD pin 9 Db0, would go to the D0 Function or Arduino pin 8


If you have a mega or a Teensy, then use the appropriate board type column.

Hope that helps.

--- bill

thehobojoe:
I made a function that creates a bar graph, for anyone interested. To use it, simply add this to your glcd.cpp file:

While this works well, it will be expensive in terms of code space because of the use of floating point.
It should be possible to re-arrange the calculations to use simple integer math.

--- bill

bperrybap:

thehobojoe:
I made a function that creates a bar graph, for anyone interested. To use it, simply add this to your glcd.cpp file:

While this works well, it will be expensive in terms of code space because of the use of floating point.
It should be possible to re-arrange the calculations to use simple integer math.

--- bill

If you know of a better way, I'd be happy to hear it. I'm fairly new to coding so there are lots of basic tricks that slip by me. I tried a few other things but none seemed to work, hence finally resorting to using floating point.

thehobojoe:
If you know of a better way, I'd be happy to hear it. I'm fairly new to coding so there are lots of basic tricks that slip by me. I tried a few other things but none seemed to work, hence finally resorting to using floating point.

I think just instead of:

float range = (float)width / (float)fullval;
int currentwidth = currentval * range;

do this:

int currentwidth = (currentval * width) / fullval;

thehobojoe:
I made a function that creates a bar graph, for anyone interested. To use it, simply add this to your glcd.cpp file:

void glcd::BarGraph(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t fullval, uint8_t currentval){
float range = (float)width / (float)fullval;
int currentwidth = currentval * range;
GLCD.DrawRect(x, y, width, height);
for (int i = 1; i < height; i++) {
	GLCD.DrawHLine(x, y+i, currentwidth);}
GLCD.FillRect(x+currentwidth+1, y+1, width-currentwidth-2, height-2, WHITE);

}

I'm confused - why are you drawing a completely different horizontal line for every pixel of the height, can't you use FillRect to do the same thing? In fact just 2 FillRects should do for the entire bar (although you might see a little flicker):

void glcd::BarGraph(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t fullval, uint8_t currentval)
{
	int currentwidth = (currentval * width) / fullval;
	GLCD.FillRect(x, y, width, height, BLACK); // put the entire area as black
	GLCD.FillRect(x+currentwidth+1, y+1, width-currentwidth-2, height-2, WHITE); // white out the non-filled area
}

I haven't tested this, just throwing my hat in the ring with an idea :slight_smile:

Wow, I feel like an idiot now, can't believe I missed those obvious things. >_<
I thought for sure I had tried using (currentval * width) / fullval; , though. Guess not!

Thanks for your suggestions, here's the updated function:

void glcd::BarGraph(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t fullval, uint8_t currentval){
	int currentwidth = (currentval * width) / fullval;
	GLCD.DrawRect(x, y, width, height);
	GLCD.FillRect(x+1, y+1, currentwidth-1, height-2);
	GLCD.FillRect(x+currentwidth+1, y+1, width-currentwidth-2, height-2, WHITE);
}

@ Telek:

I tried your idea, blacking the whole thing out and using a blank rect to wipe the empty portion of the bar, it's a good idea, but in practice it doesn't really work, the flicker makes the part of the bar that supposed to be blank almost completely dark. Thanks for the suggestion though, I need to start thinking more efficiently for my coding. Can't believe I filled it with lines and a for loop >_<

It's going to depend on the refresh rate - if you are constantly calling this function then no it won't work. However you only need to call it once per second in which case it will work.

You're probably right though, the one extra library call is likely not going to impact performance so your function will work better.

In this specific situation, you can get away with using simple 16 bit integer math because
all the values are 8 bit and an 8 bit value multiplied by an 8 bit value is a 16 bit value.
If the numbers start to get larger (which might be the case in a more generic bar graph function),
then things start to get a bit more tricky.
I would recommend using an unsigned int vs a simple int to avoid any sign extension issues.

To avoid the issues it might be better to use the Arduino map() function, which will work
for larger than 8 bit values.
It could also be used to simultaneously do the mapping and map the value into the needed pixel coordinate,
if the code were slightly "tweaked".

To avoid flicker you can change the code to only update the display when needed rather updating it constantly.
Sample code:

#include <glcd.h>
#include "fonts/fixednums15x31.h"

long sec = 0;
long lastsec = 1; // must be different from sec for initial update
int min = 0;
long starttime;

gText ClockArea;
	
void setup() {

	GLCD.Init(NON_INVERTED);
	GLCD.ClearScreen(); 
	ClockArea.DefineArea(20, 0, 5, 1, fixednums15x31);
}

void BarGraph(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t fullval, uint8_t currentval){

unsigned int currentwidth = currentval * width / fullval;

#ifdef SAMPLE_MAP
// example of using map() function
// It could be combined with calculations below to do the full pixel calculation
unsigned int currentwidth = map(currentval, 0, fullval, 0, width);
#endif

	GLCD.DrawRect(x, y, width, height);		// draw boarder
	GLCD.FillRect(x, y, currentwidth, height);	// draw left "busy" part
	GLCD.FillRect(x+currentwidth+1, y+1, width-currentwidth-2, height-2, WHITE); // clear right part
}


void loop() {
	sec = (millis() - starttime) / 1000;
	if (sec > 59) {
		min++;
		sec = 0;
		starttime = millis();
	}
	if(sec != lastsec) // check to see if update needed
	{
		ClockArea.Printf("%02d:%02d", min, sec); // update new time (auto erases older output)
		BarGraph(10, 40, 108, 16, 59, sec);
		lastsec = sec; // save last update time
	}
}

This code keeps track of the last update and only updates the display when the second changes.
This code also uses the Printf() function and takes advantage of the text area scrolling.
NOTE: Printf() does come with a cost.... It sucks in about 1.5-1.8k of code. In some cases it can be less code if
you are doing lots of formatting and avoid the Arduino print functions,
but for something simple like this, it is less code to do it the
way it was originally done. I just tossed it in, to show its use.

Since the text area is defined to be exactly 5 characters wide, which exactly matches the MM:SS format
and the font is a fixed width font, the old values will automatically be cleared out when the new
values are re-written.
While this example uses Printf(), you could still use the previous code that used the Arduino print
functions and the older formatted data would be scrolled out as the new data were written.

--- bill

bperrybap:
In this specific situation, you can get away with using simple 16 bit integer math because
all the values are 8 bit and an 8 bit value multiplied by an 8 bit value is a 16 bit value.
If the numbers start to get larger (which might be the case in a more generic bar graph function),
then things start to get a bit more tricky.
I would recommend using an unsigned int vs a simple int to avoid any sign extension issues.

To avoid the issues it might be better to use the Arduino map() function, which will work
for larger than 8 bit values.

Hey Bill - isn't the map() function essentially doing the same except with longs? Seems like overhead not really needed here. However I agree with your comment on the 8-bit problem - using uint16_t is probably better.

Since you're responding :slight_smile: Out of curiosity does GLCD work with KS0713 chips? I've seen some people say that they're compatible with KS0108 and others say no. I also saw another post of yours mentioning about starting a port but I don't know if that was ever finished.

Thanks!

Telek:
Hey Bill - isn't the map() function essentially doing the same except with longs? Seems like overhead not really needed here. However I agree with your comment on the 8-bit problem - using uint16_t is probably better.

Correct. The only reason I brought up map() is that for a more generic function that would be be
part of the library map() might be more appropriate since people may be using larger than 8 bit values.
For example if you were mapping an analog input to a bar graph an 8 bit value is not large enough.
8 bits is probably not large enough to map a temperature either particularly if you multiple the value by 10 to
get an integer value that includes 1 decimal point.

Since you're responding :slight_smile: Out of curiosity does GLCD work with KS0713 chips? I've seen some people say that they're compatible with KS0108 and others say no. I also saw another post of yours mentioning about starting a port but I don't know if that was ever finished.

Thanks!

ok, ok, on the responding. There was an absence.
But I have a good excuse. :slight_smile: I was away from home for a month. With no electricity or running water, in
the highlands of Papua New Guinea.

No movement on the ks0713 support. Michael and I basically froze the support for the v3 release to maintain the
stability. What we need to do is call it "done" and go ahead and kick it out the door.
Then, determine what to pull in for the next release.

--- bill

bperrybap:
ok, ok, on the responding. There was an absence.
But I have a good excuse. :slight_smile: I was away from home for a month. With no electricity or running water, in
the highlands of Papua New Guinea.

No movement on the ks0713 support. Michael and I basically froze the support for the v3 release to maintain the
stability. What we need to do is call it "done" and go ahead and kick it out the door.
Then, determine what to pull in for the next release.

--- bill

No Worries! Just wanted to make sure that you didn't miss my other comments :slight_smile:

I have some experience with KS0713 (hacked together a library for both computer via LPT, LPC2148 and 8051) and knowing my impatience I may end up hacking it into your code base before you do. If you have any notes or guidelines I'd be happy to work with you on this one and even send you a display if that helps.

Is there a description of how the library functions overall? I've been sifting through the code, but it's hard to see how all the pieces fit together, and therefor what is needed to add support for a new controller chip.
I see color is used to describe a pixel state, but it's limited to black and white. The display I'm looking at supports 4-bit greyscale, but it seems like a lot of the code would need rewriting to make use of that. Even setting a pixel to its on or off state looks like it could require additional code.