Pages: 1 2 [3] 4 5 ... 21   Go Down
Author Topic: GLCD library version 3  (Read 66885 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:

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

do this:

Code:
int currentwidth = (currentval * width) / fullval;
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Code:
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):

Code:
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 smiley
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 25
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:

Code:
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 >_<
« Last Edit: June 15, 2011, 03:43:28 pm by thehobojoe » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Dallas, TX USA
Offline Offline
Edison Member
*
Karma: 47
Posts: 2341
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 smiley 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!
Logged

Dallas, TX USA
Offline Offline
Edison Member
*
Karma: 47
Posts: 2341
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

Quote
Since you're responding smiley 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. smiley 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
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ok, ok, on the responding. There was an absence.
But I have a good excuse. smiley 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 smiley

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.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 25
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I was wondering if I could get some input into how text areas work, and more specifically, scrolling. My initial thought was that you could define a text area, say 20 characters wide and 5 lines high, fill it via println, and that any more lines printed would simply push the other lines out via scrolling, but this is only half true. It does push the other lines, but it pushes them outside the confines of the defined text area. If I am using the bottom half of the screen for a text area, and I fill it and then start printing more lines with println, the first lines will get pushed up, eventually filling the entire screen. How can I keep that from happening?

In addition to that, is there any kind of built in functionality that will allow scrolling up and down through a series of lines without having to do it manually? Hope that's not asking too much.  smiley

Thanks in advance.
Logged

Dallas, TX USA
Offline Offline
Edison Member
*
Karma: 47
Posts: 2341
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Text areas should work as you expected. When you send characters to the text area, the library code will try to fit
the characters on the current line. If the character does not fit, it wraps to the next line.
If there is no next line available, it scrolls all the lines (up or down depending on the text area option)
to make room for the new line.

The only thing I can think of is if the parameters passed in to DefineArea() fail to pass some sanity checking when creating
the text area, the code creates a text area that is entire display.
Michael and went back and forth a few times on this and decided to create a full display text area
rather than no text area.

The return status from DefineArea() will indicate whether or not it succeeded. If false/0 it failed
and if true/1 it succeeded.
It could be that the font selected does not allow a text area of 20 x5 characters at the
indicated x,y position.

Try checking the return value and see if the DefineArea() call is "failing".

As far as scrolling goes, the code only uses memory inside the glcd module,
so once the data is scrolled off the display it is lost forever.
There is no "scroll bar" type functionality.

--- bill

Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 25
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for the reply. Since I need a type of menu functionality for my current project, I ended up going back to a more manual method that stores the lines in an array and tracks an independent cursor and the menu position to go up/down. It's not pretty, but it works. Still, I am going to need non-menu scrolling for status and debug purposes, so your reply should help with that.

Thanks for all the work you've done with this, by the way, it's a great library.
Logged

Germany
Offline Offline
Edison Member
*
Karma: 100
Posts: 1235
If you believe something is right, you won't see what's wrong (David Straker).
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Great Lib!
It worked without modification with my KS0108 display.
I wonder that this lib is not mentioned on the Playground.

Oliver
Logged

Dallas, TX USA
Offline Offline
Edison Member
*
Karma: 47
Posts: 2341
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Great Lib!
It worked without modification with my KS0108 display.
I wonder that this lib is not mentioned on the Playground.

Oliver

But it is:
http://www.arduino.cc/playground/Code/GLCDks0108
There is a note a few paragraphs down about the v3 release candidate thread.

"glcd" is the v3 version of the "ks0108" library.
Michael and I have left the v3 code in pre-release stage quite a bit longer
than we anticipated.

I'll talk with Michael but I think it is time to wrap up any small remaining issues and call it "done"/"released"
and then begin to look at what could be added going forward.

So if anyone has any issues or updates (in code or documentation) that are not new functionality
that they would like to see addressed, speak up now
so we can get them into the final release.


--- bill
« Last Edit: June 20, 2011, 01:04:25 am by bperrybap » Logged

Germany
Offline Offline
Edison Member
*
Karma: 100
Posts: 1235
If you believe something is right, you won't see what's wrong (David Straker).
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Quote
But it is:
http://www.arduino.cc/playground/Code/GLCDks0108
There is a note a few paragraphs down about the v3 release candidate thread.

Ah, ok, that was too difficult for me to find. I think it might be easier if there is a direct reference to your google-code page from here: http://arduino.cc/playground/Code/LCD

Quote
So if anyone has any issues or updates (in code or documentation) that are not new functionality
that they would like to see addressed, speak up now
  • A full, but simple example for drawing text, with and/or without drawing area would be nice
  • Some installation guidelines on the google code page itself (provide information that "the zip file should be extracted to libraries directory")

Thanks a lot, Oliver

Logged

Pages: 1 2 [3] 4 5 ... 21   Go Up
Jump to: