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

lain,
One good thing about your comment was that it caused me to go back and look
at the documentation and when I went back an looked,
I noticed that it really isn't very clear in this area since the documenation
currently only shows the function prototypes for each use of Puts(), DrawString() etc...
The included html documentation doesn't really show how to actually use them which
sometimes bears little resemblance to the function prototype.
Also, I've not seen any documentation on the Arduino Print class so each library
that uses it is kindof documenting it in their own documentation.

So I'm updating the glcd documentation to include
code examples on how to use the various functions
I think it will make things much clearer and the documentation
better overall.

Thank you for your comments.

--- bill

Bill,

Is there any way to suppress this warning message produced by gText.h?

Arduino-1.0\libraries\glcd/include/gText.h:171: warning: 'FontRead' defined but not used

Iain

sixeyes:
Bill,

Is there any way to suppress this warning message produced by gText.h?

Arduino-1.0\libraries\glcd/include/gText.h:171: warning: 'FontRead' defined but not used

Iain

Yes. Definitely. I have fixed it. It will be corrected in the next release.
You must be using 1.0 which shows the warnings.
If you want to get rid of this in your code in the mean time.

Move this:

static FontCallback	FontRead;               // font callback shared across all instances

from gText.h to the top of gText.cpp. Put it just above:

/*
 * Experimental defines
 */

at line 35

There are a few others, I'll also get rid of.
I'm not sure I can get rid of the warnings about the progmem stuff used by the fonts though.

--- bill

bperrybap:
Move this:

static FontCallback	FontRead;               // font callback shared across all instances

from gText.h to the top of gText.cpp. Put it just above:

/*
  • Experimental defines
    */


at line 35

Thanks. That's great. Job done.

There are a few others, I'll also get rid of.
I'm not sure I can get rid of the warnings about the progmem stuff used by the fonts though.

Not seeing any others here at present.

Iain

Bill,

The way my system is set up, I've 390us to do any single blocking operation. Writing a single character is fine (< 130us) and wrapping is OK (< 230us) but if a scroll is required it's much larger than 390us.

I'd like to disable the scrolling but I can't see any way to do this.

I'd also like my strings to truncate if they're longer than the current line rather than wrapping onto the next line and potentially causing a costly scroll. Just to make things more awkward I'm using a variable pitch font.

Iain

lain,
You are correct in that the v3.0 API does not allow any control over wrapping/scrolling it only allows
choosing scroll direction.

It's been a while since I looked at the low level timing, (I'll have to do that again) but the timing looks
longer than what I would expect.
(but I don't know the size of your font and the text area boundary you are using)

However, it is a good time get this feedback as I was just in the process of creating the list of things for the 3.1 release.
(Was doing this just last night)
Wrapping & Scrolling is one item that I was going back and forth on.
It turns out that it really isn't that difficult so I'll add it to the list of things to put into the 3.1 release.
While the actual code is pretty minor, it more than likely will require a new API call,
as currently there is only a SetTextMode() call and more than likely the way I'll want to do it
will need the creation of a ClearTextMode() call as well. (so capabilities can be turned on or off)
This creates some ripple effects through the documentation but shouldn't be that bad.

In the mean time, for your specific situation, there are some things you can do to potentially speed things up
and eliminate a potential wrap/scroll.

To render characters at the maximum speed, use fonts that are 1 pixel shorter than an 8 bit multiple.
i.e. 5x7, 9x15, etc... also make sure the text area starts on a 8 pixel vertical boundary. y = 0, 8, 16, etc...
(The horizontal boundary does not matter)

Fixed width fonts will render faster than variable width fonts. not because of the variable width differences but
mainly because of the font data format (There is no direct pointer/offset for each individual character's data)
It requires scanning through the character set data and adding up the width of every character prior to the one
to be rendered to locate the data offset for the desired character. (This format existed before the Arduino library was created)
Since the font data is flash it requires going through a access routine since you can't access flash directly given the AVRs
Harvard architecture which adds to the overhead.

Another thing you can do if you have enough SRAM to spare is to turn on the READ cache.
Set the READ_CACHE define in glcd_Config.h and that will eliminate all read accesses to the glcd module
which can really speed up things like scrolling.

Also, if you are using a 1 line text area, and overwriting the line with a new string of the same length
after sending a newline, it is faster to call SetCursor(0,0) before each string and not send the newline
as this way will avoid the line being "scrolled out".

To permanently prevent a wrap and a scroll you can make a one line mod to PutChar().
Change this:

	/*
	 * If the character won't fit in the text area,
	 * fake a newline to get the text area to wrap and 
	 * scroll if necessary.
	 * NOTE/WARNING: the below calculation takes into consideration the 1 pixel pad.
	 */
	if(this->x + width - (isNoPadFixedFont(this->Font)) > this->tarea.x2)
	{
		this->PutChar('\n'); // fake a newline to cause wrap/scroll

to this:

	/*
	 * If the character won't fit in the text area,
	 * dump it on the floor
	 */
	if(this->x + width - (isNoPadFixedFont(this->Font)) > this->tarea.x2)
	{
		return(0); // dump character on the floor rather than wrap/scroll

This may not be what you really want but it may get you by until there is a way to handle
it properly through the 3.1 API which will allow configuring it on a text area by text area basis.

--- bill

Thanks for such a comprehensive reply.

My font is based on the SystemFont5x7, I just edited most of the characters to make a proportional font. I've been playing with CharWidth() and I think I can use this to work out when a line is going to cause wrapping and truncate the rest of the string myself.

I was just trying to verify timing issues today. I'm not be ready to write the code for the display right now, so maybe v3.1 will be released before I'm ready.

Iain

With respect to wrapping and scrolling there are many possibilities
but I'd prefer to limit the capabilities to 2 options which can be set/cleared:

  1. Auto Wrap/ No Auto Wrap
    This enables automatically wrapping text to the next line and scrolls if necessary.
    The default being "AutoWrap" and the API allows setting/clearing "No AutoWrap".

  2. Normal scroll/Reverse scroll.
    Scrolling is either normal (up) or reversed (down).
    The default being "normal/up" and the API allows setting/clearing "down/Reverse" scroll.

Option 1 sets whether text wrapping is done.
If you disable auto wrap, text that overflows a line will stop printing at the right hand side
of the text area until you either send a newline or re-position the cursor.
But you can still send newlines and force scrolling.
Example: (assuming system5x7 font and a 128 pixel wide display - which holds 21 characters/line)
print a 50 character string using println() or that includes a newline.
The first 21 character print and the last 29 characters are dumped on the floor.
The next println/print will start on the next line and will scroll to make room if
necessary because a newline was sent on the previous string.
If no newline was sent, by using say print() or Puts() instead of println()
then the characters keep getting dumped until the cursor is repositioned.

Option 2 simple sets the scrolling direction when a scroll is done.
Scrolling direction will default to normal/up and the API allows
setting/clearing reverse scrolling.

Anyone have any thoughts or comments/suggestions on this or feel there needs to be
more wrapping options?

--- bill

The No Auto Wrap sounds like it's exactly what I need. I would just call GLCD.write() repeatedly for the whole line (I only have enough time to write one character per loop). If it doesn't fit on the display, it gets silently dropped.

Iain

If you insert the small patch into PutChar() in gText.cpp you will get permanent "no auto wrap" for all text areas.
Just don't send any newlines as that will still cause a wrap and potentially a scroll.

The code I posted earlier is from the 3.1 code I'm working on. oops... :blush:
The code in the gText.cpp in v3 RC3 will look like this:

	if(this->x + width > this->tarea.x2)
	{
		this->PutChar('\n'); // fake a newline to cause wrap/scroll

to this:

	if(this->x + width > this->tarea.x2)
	{
		return(0); // drop the char on the floor

If you want to play with no autowrap behavior.

Out of curiosity, what kind of project are you working on and how do you end up with strings that can
be too long?

--- bill

I'm developing a shunting program for our model railway. For years it ran on a PC / laptop but when I heard about Arduino's I had the idea to use those instead. Instant on and a separate display for each operator. The only downer is that on the PC we had plenty of width to display the full wagon name and other stuff such and colour, style etc.

Using Arduino Megas and ks0108 / GLCD and SystemFont5x7 I can get 21 characters and 8 rows. However that leads wagon names abbreviated / truncated, so I hacked at SystemFont5x7 to create Iain5x7 which is proportional (see below). This allows me to create more meaningful descriptions but I can't be sure that the text won't spill over the edge of the display. Since I need all 8 rows to display the list of wagons, any auto wrapping would ruin the display.

One of the displays also incorporates a matrix display to indicate the selected route be used in the goods yard. That display needs to be refreshed every 390us to avoid flicker, so I need to write each character to GLCD in less than 390us (preferably less since I also have to update the matrix as well in that 390us). From my tests, some characters take longer to write than others. From your previous post I believe this is related to the font definition :frowning:

#include <fonts/Iain5x7.h>
#include <fonts/SystemFont5x7.h>
#include <glcd.h>

void setup()
{
    uint32_t start, stop;

    Serial.begin(115200);
    GLCD.Init(NON_INVERTED);
    GLCD.ClearScreen();
    GLCD.SelectFont(Iain5x7);
    //GLCD.SelectFont(SystemFont5x7);
    for (uint8_t i = 0; i < 95; i++)
    {
        char ch = i + 33;

        GLCD.CursorToXY(0, 0); // Ensure each character doesn't wrap.
        start = micros();
        GLCD.write(ch);
        stop = micros();
        Serial.write(ch);
        Serial.print("(");
        Serial.print(ch);
        Serial.print("): ");
        Serial.print(stop - start);
        Serial.println("us");
        delay(100);
    }
}

void loop(
    void)
{
}

and here's my font (Iain5x7.h)

#ifndef IAIN5X7_H_INCLUDED
#define IAIN5X7_H_INCLUDED


/*
 *
 * Iain5x7
 *
 * created with FontCreator
 * written by F. Maximilian Thiele
 *
 * http://www.apetech.de/fontCreator
 * me@apetech.de
 *
 * File Name           : Iain5x7.h
 * Date                : 28.12.2010
 * Font size in bytes  : 2461
 * Font width          : 5
 * Font height         : 7
 * Font first char     : 32
 * Font last char      : 128
 * Font used chars     : 96
 *
 * 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>

// Workaround for http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34734
#ifdef PROGMEM
#undef PROGMEM
#define PROGMEM __attribute__((section(".progmem.data")))
#endif

#define IAIN5X7_WIDTH 5
#define IAIN5X7_HEIGHT 7

static uint8_t Iain5x7[] PROGMEM = {
    0x09, 0x9D, // size
    0x05, // width
    0x07, // height
    0x20, // first char
    0x60, // char count

    // char widths
    0x01, 0x01, 0x03, 0x05, 0x05, 0x05, 0x05, 0x01, 0x02, 0x02,
    0x05, 0x03, 0x01, 0x02, 0x01, 0x03, 0x04, 0x02, 0x04, 0x04,
    0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x01, 0x01, 0x03, 0x03,
    0x03, 0x04, 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
    0x04, 0x03, 0x04, 0x05, 0x03, 0x05, 0x05, 0x05, 0x04, 0x05,
    0x04, 0x04, 0x03, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x02,
    0x03, 0x02, 0x03, 0x03, 0x01, 0x04, 0x04, 0x04, 0x04, 0x04,
    0x04, 0x04, 0x04, 0x01, 0x03, 0x04, 0x01, 0x05, 0x04, 0x04,
    0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x05, 0x03, 0x04,
    0x04, 0x03, 0x01, 0x03, 0x05, 0x00,

    // font data
    0x00, // 32
    0xBE, // 33
    0x0E, 0x00, 0x0E, // 34
    0x28, 0xFE, 0x28, 0xFE, 0x28, // 35
    0x48, 0x54, 0xFE, 0x54, 0x24, // 36
    0x46, 0x26, 0x10, 0xC8, 0xC4, // 37
    0x6C, 0x92, 0xAA, 0x44, 0xA0, // 38
    0x06, // 39
    0x3C, 0x42, // 40
    0x42, 0x3C, // 41
    0x00, 0x54, 0x38, 0x54, 0x00, // 42
    0x10, 0x38, 0x10, // 43
    0xC0, // 44
    0x10, 0x10, // 45
    0x40, // 46
    0xC0, 0x38, 0x06, // 47
    0x7C, 0x82, 0x82, 0x7C, // 48
    0x04, 0xFE, // 49
    0xC4, 0xA2, 0x92, 0x8C, // 50
    0x82, 0x92, 0x92, 0x6C, // 51
    0x30, 0x28, 0x24, 0xFE, // 52
    0x4E, 0x92, 0x92, 0x72, // 53
    0x78, 0x94, 0x92, 0x60, // 54
    0x02, 0xE2, 0x12, 0x0E, // 55
    0x6C, 0x92, 0x92, 0x6C, // 56
    0x0C, 0x92, 0x52, 0x3C, // 57
    0x6C, // 58
    0x6C, // 59
    0x10, 0x28, 0x44, // 60
    0x28, 0x28, 0x28, // 61
    0x44, 0x28, 0x10, // 62
    0x04, 0xA2, 0x12, 0x0C, // 63
    0x64, 0x92, 0xF2, 0x82, 0x7C, // 64
    0xFC, 0x22, 0x22, 0xFC, // 65
    0xFE, 0x92, 0x92, 0x6C, // 66
    0x7C, 0x82, 0x82, 0x44, // 67
    0xFE, 0x82, 0x82, 0x7C, // 68
    0xFE, 0x92, 0x92, 0x82, // 69
    0xFE, 0x12, 0x12, 0x02, // 70
    0x7C, 0x82, 0xA2, 0x64, // 71
    0xFE, 0x10, 0x10, 0xFE, // 72
    0x82, 0xFE, 0x82, // 73
    0x40, 0x80, 0x80, 0x7E, // 74
    0xFE, 0x10, 0x28, 0x44, 0x82, // 75
    0xFE, 0x80, 0x80, // 76
    0xFE, 0x04, 0x08, 0x04, 0xFE, // 77
    0xFE, 0x08, 0x10, 0x20, 0xFE, // 78
    0x7C, 0x82, 0x82, 0x82, 0x7C, // 79
    0xFE, 0x12, 0x12, 0x0C, // 80
    0x7C, 0x82, 0xA2, 0x42, 0xBC, // 81
    0xFE, 0x32, 0x52, 0x8C, // 82
    0x4C, 0x92, 0x92, 0x64, // 83
    0x02, 0xFE, 0x02, // 84
    0x7E, 0x80, 0x80, 0x7E, // 85
    0x3E, 0x40, 0x80, 0x40, 0x3E, // 86
    0xFE, 0x40, 0x30, 0x40, 0xFE, // 87
    0xC6, 0x28, 0x10, 0x28, 0xC6, // 88
    0x06, 0x08, 0xF0, 0x08, 0x06, // 89
    0xC2, 0xA2, 0x92, 0x8A, 0x86, // 90
    0xFE, 0x82, // 91
    0x06, 0x38, 0xC0, // 92
    0x82, 0xFE, // 93
    0x04, 0x02, 0x04, // 94
    0x80, 0x80, 0x80, // 95
    0x06, // 96
    0x40, 0xA8, 0xA8, 0x70, // 97
    0x7E, 0x90, 0x88, 0x70, // 98
    0x70, 0x88, 0x88, 0x50, // 99
    0x70, 0x88, 0x90, 0x7E, // 100
    0x70, 0xA8, 0xA8, 0x30, // 101
    0x10, 0xFC, 0x12, 0x04, // 102
    0x10, 0xA8, 0xA8, 0x78, // 103
    0xFE, 0x10, 0x08, 0xF0, // 104
    0xFA, // 105
    0x40, 0x80, 0x7A, // 106
    0xFE, 0x20, 0x50, 0x88, // 107
    0xFE, // 108
    0xF8, 0x08, 0x30, 0x08, 0xF0, // 109
    0xF8, 0x10, 0x08, 0xF0, // 110
    0x70, 0x88, 0x88, 0x70, // 111
    0xF8, 0x28, 0x28, 0x10, // 112
    0x10, 0x28, 0x28, 0xF8, // 113
    0xF8, 0x10, 0x08, 0x10, // 114
    0x90, 0xA8, 0xA8, 0x48, // 115
    0x08, 0x7E, 0x88, 0x40, // 116
    0x78, 0x80, 0x40, 0xF8, // 117
    0x78, 0x80, 0x78, // 118
    0x78, 0x80, 0x60, 0x80, 0x78, // 119
    0xD8, 0x20, 0xD8, // 120
    0x18, 0xA0, 0xA0, 0x78, // 121
    0xC8, 0xA8, 0xA8, 0x98, // 122
    0x10, 0x6C, 0x82, // 123
    0xEE, // 124
    0x82, 0x6C, 0x10, // 125
    0x10, 0x08, 0x10, 0x20, 0x10, // 126

};

#endif

You might be interested in this bit that I added to stop the warnings:

// Workaround for http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34734
#ifdef PROGMEM
#undef PROGMEM
#define PROGMEM __attribute__((section(".progmem.data")))
#endif

I think the Arduino team need to do the same thing to Tone.cpp in the library.

If you run the test you'll see that some of the letters are taking a bit too long to display but I'm pretty sure we won't have a ~ in our wagon names (but you never know...).

Iain

You could switch to a wider display like a 192x64 to get longer names.
I picked up one of the JHD19264 displays off ebay for under $19 USD shipped.
They are not as tall so the characters are actually a bit smaller but you do
get quite a bit more pixels and characters on the display.

You've got me curious on the timings now.
I'll load up your font and do some timings with my logic analyzer and see where the real time is lost.
(I can isolate things down the individual glcd library routine)
It is always a good exercise to see where the time is lost to ensure that any updates that are made
are made to the areas that matter the most.

Something else to think about is that
another one of the things I'm looking for 3.1 is support for the Chipkit UNO32 and MAX32 boards.
They are WAY faster than arduino 80Mz vs 16Mz, 32bit vs 8bit,
with more flash, more RAM and more pins and the chipkit UNO32 has a lower cost than the official Arduino UNO.
There are some differences that make it not suitable for a total drop in replacement, but so
far it looks very promising especially since the mpide it uses seamlessly supports AVR based arduinos
and Chipkit MIPS based boards so you can switch back and forth between the different boards using the same IDE.
(Maple's ARM based boards requires a different IDE and I'm not sure what the Arduino guys are going to do for Due)

I've already worked with one person to get a "hacked" version of v3 up and going on the ChipKit
but its not the way I want to do the code so I'll be updating things for the Chipkit boards in 3.1

--- bill

bperrybap:
You could switch to a wider display like a 192x64 to get longer names.
I picked up one of the JHD19264 displays off ebay for under $19 USD shipped.
They are not as tall so the characters are actually a bit smaller but you do
get quite a bit more pixels and characters on the display.

Sadly the hardware is already purchased and I'm using 4 screens, so replacement costs would be too high. I originally rejected the 192x64 screens because my brother didn't think he'd be able to read them. Thanks for the suggestion.

You've got me curious on the timings now.
I'll load up your font and do some timings with my logic analyzer and see where the real time is lost.
(I can isolate things down the individual glcd library routine)
It is always a good exercise to see where the time is lost to ensure that any updates that are made
are made to the areas that matter the most.

Indeed. I'm thinking about getting out my logic analyzer as well so I can pin down the timings in my own code more precisely.

If there's anything easy you can do to improve timings for a proportional font, I'd really appreciate it. Worst case, I can always revert to SystemFont5x7 and get faster timings if I can't make Iain5x7 work within my timing constraints.

Something else to think about is that
another one of the things I'm looking for 3.1 is support for the Chipkit UNO32 and MAX32 boards.
They are WAY faster than arduino 80Mz vs 16Mz, 32bit vs 8bit,
with more flash, more RAM and more pins and the chipkit UNO32 has a lower cost than the official Arduino UNO.
There are some differences that make it not suitable for a total drop in replacement, but so
far it looks very promising especially since the mpide it uses seamlessly supports AVR based arduinos
and Chipkit MIPS based boards so you can switch back and forth between the different boards using the same IDE.
(Maple's ARM based boards requires a different IDE and I'm not sure what the Arduino guys are going to do for Due)

I've already worked with one person to get a "hacked" version of v3 up and going on the ChipKit
but its not the way I want to do the code so I'll be updating things for the Chipkit boards in 3.1

Again Arduino Megas already purchased. It's a large project and I've got over 10 of the boards. I've bought Megas because most of my circuits require 50+ I/O. The board I'm currently concerned with only has 30 I/O but if I stick with one board, my code base can be used across all the boards. My one concession is the main scheduler software. I plan to use a Netduino so I can debug it easily and it's much easier to handle lots of strings in C# than C++. I actually was able to write most of the scheduler over Christmas using a simulator. What a great help it is to be able to debug something rather than insert trace statements.

Iain

sixeyes:

You've got me curious on the timings now.
I'll load up your font and do some timings with my logic analyzer and see where the real time is lost.
(I can isolate things down the individual glcd library routine)
It is always a good exercise to see where the time is lost to ensure that any updates that are made
are made to the areas that matter the most.

Indeed. I'm thinking about getting out my logic analyzer as well so I can pin down the timings in my own code more precisely.

If there's anything easy you can do to improve timings for a proportional font, I'd really appreciate it. Worst case, I can always revert to SystemFont5x7 and get faster timings if I can't make Iain5x7 work within my timing constraints.

Well, I did have a look. There really isn't anything that is "easy". What you are seeing is mainly the inefficiency of the
variable font format itself. (there are much faster ways to store and lookup the font data but it does require a bit more flash space)
With the current variable font format, to locate the data position for a character you have to
to add up the width of each previous character in the font. It is time consuming, especially on a Harvard Architecture
chip like the AVR since you have to call access functions. That is why you see each character taking longer and longer
to render. Each lookup and font width add for each character along the way
adds about 3us or so to the overall rendering.
The MIPs (used on Chipkit) and ARM (used on Maple) architectures are Von Neumann so they can directly access data in flash
which would be little bit faster even if the clock rate were the same.
But the real issue is the font format itself.

There are few other things that could shave off 3-4 us here and there 2 or 3 times in the rendering
at the expense of using up a few bytes of ram for each text area,
but that won't solve the issue you are facing.

BTW, the call GLCD.CursorToXY(0,0) doesn't really reposition the glcd hardware.
It only saves the coordinates for later. The actual hardware positioning is not done until a character is rendered.
So you are measuring the time for that as well. You can print the character an additional time before your micros() call
if you want to eliminate that positioning overhead. It is 3-4us or so.

One thing that you could do is create a more limited font that has say just the characters
from 'A' to 'z'. 0x41 to 0x7A
That way the flash width scans are shorter.
I tried this out and it reduces the render times around 40-80us on my setup.
40us being for 'A' and 80us shorter for 'z'.
So I see 156us for 'A' and 260us for 'z'.
But that eliminates and the numbers which may not be acceptable.
Note: you can use multiple fonts at the same time by
using a different font in each text area.
If you can use the shorter/smaller font you could use that font
for some text areas while the full font or even the system5x7 font could be used in other text areas.

Again Arduino Megas already purchased. It's a large project and I've got over 10 of the boards. I've bought Megas because most of my circuits require 50+ I/O.
Iain

10 boards of 50+ i/o. Thats A LOT of i/o!
What all is going on? This is for toy/model railroad stuff?
Can you shift any of your time critical code sections
to use interrupts so that it can interrupt the glcd library code?
The glcd library has no timing requirements and can be interrupted literally forever.

--- bill

bperrybap:
BTW, the call GLCD.CursorToXY(0,0) doesn't really reposition the glcd hardware.
It only saves the coordinates for later. The actual hardware positioning is not done until a character is rendered.
So you are measuring the time for that as well. You can print the character an additional time before your micros() call
if you want to eliminate that positioning overhead. It is 3-4us or so.

I only added that call to stop the wrapping affecting the timing. I wasn't planning to use it in my code. Useful to know it was adding some time.

One thing that you could do is create a more limited font that has say just the characters
from 'A' to 'z'. 0x41 to 0x7A
That way the flash width scans are shorter.
I tried this out and it reduces the render times around 40-80us on my setup.
40us being for 'A' and 80us shorter for 'z'.
So I see 156us for 'A' and 260us for 'z'.
But that eliminates and the numbers which may not be acceptable.
Note: you can use multiple fonts at the same time by
using a different font in each text area.
If you can use the shorter/smaller font you could use that font
for some text areas while the full font or even the system5x7 font could be used in other text areas.

I think I'll try my font. If that's too slow, I'll try SystemFont5x7. If that's too limiting I'll look at writing my own font format to speed things up.

Again Arduino Megas already purchased. It's a large project and I've got over 10 of the boards. I've bought Megas because most of my circuits require 50+ I/O.
Iain

10 boards of 50+ i/o. Thats A LOT of i/o!
What all is going on? This is for toy/model railroad stuff?

Yes. I'm controlling points (I believe you may call them turnouts), detecting point positions, detecting locomotives, route planning, route selection, turntables etc.

Can you shift any of your time critical code sections
to use interrupts so that it can interrupt the glcd library code?
The glcd library has no timing requirements and can be interrupted literally forever.

I've considered it but I'd prefer to avoid them if possible.
Once I get a chance to hook up my logic analyzer I should be able to figure out what my options are.

Iain

lain,
There is one other thing that you can try.
The old/original rendering code is still in the gText.cpp module.
It is the original Thiele code for rendering fonts. It has many issues depending on the font size
and the y pixel boundary and when using inverse modes.
However, it does work for many cases, and should work fine for your font.
Since it is simpler, it is faster when the fonts are multiples of a page size.
I measured it as saving about 20us with your font.
You can try it by editing gText.cpp and uncommenting the #define GLCD_OLD_FONTDRAW

--- bill

bperrybap:
Well, I did have a look. There really isn't anything that is "easy". What you are seeing is mainly the inefficiency of the
variable font format itself. (there are much faster ways to store and lookup the font data but it does require a bit more flash space)
With the current variable font format, to locate the data position for a character you have to
to add up the width of each previous character in the font. It is time consuming, especially on a Harvard Architecture
chip like the AVR since you have to call access functions. That is why you see each character taking longer and longer
to render. Each lookup and font width add for each character along the way
adds about 3us or so to the overall rendering.

I think it would be well worth using 1 additional byte of flash per character by ditching the byte count and instead having a table of pointers to the start of the data for each character, plus one extra pointer to enable the byte count of the last character to be calculated.

As a short term improvement, you could consider caching the address of the data for the character that is half way through the table, giving you an alternative place to start searching from.

dc42:

bperrybap:
Well, I did have a look. There really isn't anything that is "easy". What you are seeing is mainly the inefficiency of the
variable font format itself. (there are much faster ways to store and lookup the font data but it does require a bit more flash space)
With the current variable font format, to locate the data position for a character you have to
to add up the width of each previous character in the font. It is time consuming, especially on a Harvard Architecture
chip like the AVR since you have to call access functions. That is why you see each character taking longer and longer
to render. Each lookup and font width add for each character along the way
adds about 3us or so to the overall rendering.

I think it would be well worth using 1 additional byte of flash per character by ditching the byte count and instead having a table of pointers to the start of the data for each character, plus one extra pointer to enable the byte count of the last character to be calculated.

As a short term improvement, you could consider caching the address of the data for the character that is half way through the table, giving you an alternative place to start searching from.


I like the idea about having an offset value for a character that is half way through the table
This is an interesting idea that I may look further into as that can be calculated runtime and
saved in RAM as the font is selected. It also does not require modifying the existing font data format.


As far as font formats go, let me start of by saying I am not a fan of the current variable font data format.
Michael and I were painfully aware of its issues and limitations when we moved forward with it going into v3.
It existed before I started working on the glcd library and even before Michael converted
Thiele's original C library to C++ for Arduino.
There are other issues with the variable font data format that are also irritating and also cost time,
like the residual bits in a font data byte when the font is not exactly a multiple of 8 bits.
The bits in the font data are shifted the wrong direction for aligning with the glcd page byte.
(This is different from how bits are stored for fixed fonts and bitmaps)
This causes additional code and checks to have to be done, while rendering,
to detect when the last byte in a column is being rendered
and to shift the bits around when the font is a variable font and not a multiple of 8 bits in height.
Michael and I had some long discussions about changing the font data format to at least get rid of the incorrectly shifted bits.
I would be nice for rendering in that all the rendering would then
be the same whether the "glyph" was a fixed font, bitmap, or variable font.

The issue early on of the v3 development was that it would break compatibility with ks0108/glcd v2 library
since none of the v2 fonts would work and a major goal of v3 was backward compatibility with v2.

Having a new font format also means re-doing the fontcreator2 JAVA app to be able to generate the new format.
While its not that bad, we opted not to do that for v3.


With respect to the current variable font format, there is no "byte count" for each character.
The data byte for each character is the width of the given character. I assume that is what you meant.
(byte counts and widths are not the same for fonts that are taller than 8 pixels)
I didn't follow your comment about: "plus one extra pointer to enable the byte count of the last character to be calculated".
I assume you meant that the width could be replaced with 16 bit offset values.
And that the width could be back calculated fairly easily knowing the address of the "next" character
and the height of the font.
But it does require and offset value for a "next" character just after the real last character in the table.

Definitely worth considering going forward.

There is also the possibility of having the width and formatting information inside the "glpyh" data.
So the offsets point to a "glyph" and the glyph data has all the needed sizing and leading information
which is a closer match to some of the other font formats used in Operating systems.

I really want to get away from this font format. I also want to be able to either directly use BDF format or
write a small script/tool that can convert from BDF fonts to the embedded format.
That will instantly allow the creation of hundreds of fonts - which will ease the pain of people
having to deal with the loss of their existing font formats should the font data format be changed.
Yes it would be possible to support multiple formats, but that takes extra code since all the rendering for
all the formats would have to exist and be selected runtime
based on the font. It also adds to the maintenance and support load of the library.

There are several other issues such as the current way the font data is compiled & linked in that needs to be resolved.
Currently they are all "static" data arrays that are all compiled in and the linker removes
out the unused fonts.
This creates real problems for implementations that use more than a single source code module.
There are many ways to resolve this but most won't work with the Arduino IDE and its goofy way
of doing things.

I have many ideas and things that could be done, it is a matter of trying to pick the highest priority
items moving forward that can offer the best trade-off of new & improved functionality and backward compatibility.

--- bill

It becomes difficult to follow this HUGE thread, but let me allow to make some small notes.

BDF: Yes, i think BDF is an excellent source for fonts. It is easy to parse, there is a ttf to bdf converter (called OTF2BDF) and there are already very good open source BDF fonts in the X11 distribution: freedesktop.org git repository browser

Inner glyph offset: After profiling of my font format i found that the searching for the glyph data start position required a big fraction of the overall time for rendering. I added the offset of the lower case 'a' and the upper case 'A', to my font format, which was great speedup (about overall factor 2, if I remember correctly).

Fonts in PROGMEM area: A big issue. In principle one can place one font in one C file (did not check C++ files), declared with the PROGMEM attribute. All other parts of the program will only see the external declaration from some .h file, e.g.

extern uint8_t my_font_data[] PROGMEM;

For the linker to be able to remove the font from the final hex file, it is required to place all fonts in separate C files. Unfortunately this becomes impractical as soon as there are several hundred fonts.
Simply the compile time of the Arduino IDE gets very high. After several hours of investigation of the gcc garbage collector I found that it is possible to put all fonts into the same C file, if the font data are assigned to different progmem sections.
This will look like this:

extern uint8_t my_font_data1[] __attribute__ (( section(".progmem.font1") ));
extern uint8_t my_font_data2[] __attribute__ (( section(".progmem.font2") ));

Oliver

I needed help with the GLCD library version 3 I am also new to the Ardunio world, I have an KS0108 (B pin setup) it is labeled JHD521M7 12864AB ,

I have been trying to get work for about two weeks now , i have cross checked the wring more than 1001 ( I have Tomas Edison beat on this one) and I have also learned how to labeling all wires makes things easy , the GLCD work on my PIC so I know its good, however with the Arduiono there are no pixels displayed, I could adjust the contrast and the back light is working fine , and I have ran GLCDdiags and i got this

Diag Loop: 3
Initializing GLCD
GLCD initialization Failed: RESET wait Timeout (status code: 2)

the pins are configured right, so is there any one brave enough to help me

GLCD data sheet

http://www.itron.com.cn/PDF_file/JHD12864AB.pdf