pavius.net

The Dot Factory: An LCD Font and Image Generator
Thursday, 23 July 2009 07:10

The Dot Factory is a small, GPL, open source tool intended to generate the required C language information to store many fonts and images, as efficiently as possible, on a microcontroller. These fonts are then uploaded via the LCD driver (see the Drivers and Modules page for a few) to the actual dot matrix LCD. It is written in C# for Visual Studio 2008 and has been tested on Windows XP, 2003  and Vista.

Working with dot matrix LCDs with microcontrollers, while not difficult, is tedious. The actual LCD controller allows us to upload simple visual data (dot on or dot off) into the LCD's dot matrix, but not much else. It is up to our software to decide what to upload when we want to draw lines, circles and more importantly - text. While there are software graphic libraries that allow us to generate a character "on the fly" using vector graphics (the character is described as a series of drawing commands that allow scaling and decoration) - these are much too complex and large to integrate in a microcontroller environment. Consequently, we must store the exact appearance of a character as a series of 1s and 0s, equivalent to a "dot on" "dot off" on the LCD, and upload this as a bitmap when we want to display text. While it is possible to generate this manually, it is desired to have a tool to do our grunt work by converting windows fonts (given a size and decoration) into a series of bitmaps.

Using The Dot Factory


main-screen005TDF is comprised of two panes - the input pane on the left (what you want to generate) and the output pane  on the right (the generated output, in C code). The input pane can accept either a font of your choice (for writing text to the LCD) or an image. When generating a font, you have the option of either generating all the available letters (by selecting "All" in the Insert Text box and clicking the plus button) or by typing in which letters, numbers or symbols you are actually using in your application (for example: 0123abcd). If you are writing a simple application that has only a few sentences, you can type them wholly in this box without fear of duplicating letters - TDF takes care of that by discarding any duplicates. This way only the letters you use will take up space.

Once you have completed setting up what it is you'd like to generate (be it an image or font), select the output method in the output pane. If you are using the LCD drivers on this website, you want it to generate an MSb first output, otherwise images will come out wrong. If you have a compiler that supports the "0b" binary specifier, you can select "binary" rather than "hex". This will allow you to visually see the pixels you will set and allow for manual touch up by the user without having to calculate hex and experimentation. Click generate and your C code will be outputted to the text box below. Copy paste this into your application (it is recommended to put this in a separate module, not your LCD driver module, for organizational reasons).

Note that 5x7 and 5x8 fonts cannot be generated using this tool. While some TTF fonts can render characters this small they are usually distorted to the point of uselessness. Head over the the drivers page and download the dedicated 5x7 font.

What does it generate?


For font generation, three entities are generated.
  • The character bitmap array: This holds the actual characters as a bitmap (only the characters selected in the input pane). Each byte represents a single vertical page sent to the LCD. All vertical padding is removed from the characters
  • The character descriptor array: Allows O(1) mapping between a character's ASCII value and required meta information about the character - namely its width in bits and its offset into the character bitmap array. When the LCD driver needs to find where character X is located in the bitmap array, it will jump to index [X - font.startCharacter] in the descriptor array. The startCharacter is the first character (that is, the character with the lowest ASCII value) used for this font. By defining a startCharacter we can reduce the number of elements in the descriptor array.
  • The font information: This element is essentially the font descriptor for this font. It holds information regarding this font like the name of the character bitmap and descriptor arrays, the font start character and how many pixels wide a space character is for this font. The LCD driver will replace the space character with empty pixels (this saves both processing time, space in the character bitmap array and space in the character descriptor array - since the space is the first ASCII character and is commonly used).

The generated structures are generated with documentation, but you may want to see the bitmapDb header file in the drivers page for detailed info on the character descriptor array and font information structures.

For image generation, only the image's bitmap array and size descriptors are generated. Note that the height value is pixels (bits) and width values are in pages.

Revision History


  • Version 0.0.5 (23dec09): Added support for rotation (90 degree increments), space character generation, width (bit/byte) selection of character width and font height, optional generation of character height/width and font height, structures are now generated with documention, input text and font is persisted throughout invokations of the application, persistent preset management - add, edit, delete output configuration presets
  • Version 0.0.4 (31jul09): Added a space to end of comments in the char descriptor array to prevent preprocessor misinterpreting '\' as a newline
  • Version 0.0.3 (30jul09): Added output configuration: hex/binary, MSb First/LSb first, configurable padding removal, comment control, flip X/Y and more
  • Version 0.0.2 (28jul09): Vista support
  • Version 0.0.1 (25jul09): Initial release (flip not supported, output format not supported, not tested on Vista)

For the next version


I'm trying to get TDF to a point where it will be flexible enough to generate most of the formats people need (this will, of course, take time). Since I am not familiar with all possible formats, I will need your help. If you'd like to suggest an output format, drop me a line and I will try to make sense of it.

  • Select between generating pages from rows or columns (to allow more efficient 0/180 degree encoding) - as suggested by Darcy
  • Detect Unicode characters and modify output accordingly (i.e. do not generate a lookup array) - as pointed out by Christian Treczoks

Download


To run this executable, you must have the .NET framework installed. The stable binary has been in the wild for a month at least with no major bugs reported. Non stable binary contains new features and bug fixes (see revision history). Please mail me with any bugs and feature requests via the contact page.
 
Comments (9)
Great program
9 Sunday, 07 February 2010 09:08
Darcy
I just wanted to say thanks for such a fantastic program! I've been mucking around with LCDs for many years and have done numerous searches for software such as this. Brilliant

It doesn't quite output in the structure I use so maybe I could just use different methods. The format I use has LSB first (topmost), and then lists columns from left to right. As a lot of LCDs work in rows and columns it makes for faster output if you can write to the LCD from a sequential area (since each write moves the address across one column/pixel)

For example, the '!' character is stored as two pixels wide
0xFF,0xFF, (top left, top right)
0x0D,0x0D, (btm left, btm right)

That format is a left over from when I didn't have enough RAM for screen buffers though... which I now use. Maybe it's time to change my structs :)

On the downside, it would mean having to convert my 5x3 font set over. It only has numerals and capital letters but it's quite handy for some things.

Anyway, great program and thanks for making it available to everyone
Re: ISO8859 and Unicode
8 Saturday, 16 January 2010 17:19
Eran
Christian, it seems that TDF does not die on this sequence - it chokes. The problem is that TDF generates a direct lookup array for each character according to its ASCII value (offsetted by the first character in the sequence). When you generate 16bit Unicode characters, this array can grow to be insanely large - almost 9000 lines in your case (because you have a Unicode character whose value is almost 9000).

To be even more precise, TDF generates this just fine - its just that the syntax coloring mechanism i use is very simplistic and slow. If i override it, the 10,000 line text outputs just fine.

To summarize:
1) If you want a quick fix to generate unicode, simply comment out line outputSyntaxColoredString(resultStringSource, ref txtOutputTextSource); and replace it with txtOutputTextSource.Text = resultStringSource; This outputs the text with no coloring
2) Since obviously unicode will use a proprietary associative [character value] to [offset into character array] container, i will need to think how to format this to have people shove this into their proprietary associative container. I will do this in the following week or so.

If anyone has any input on this matter, feel free to comment or mail.
Support for ISO8859?
7 Tuesday, 12 January 2010 07:43
Christian Treczoks
I tried TheDotFactory, and basically it is great, BUT:
When I feed characters >127 to it, e.g. ISO8859-15 special characters (¡¢£€¥Š§š©ª«¬®¯°±²³Žµ¶·ž¹º»ŒœŸ¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ), the factory dies...
Any chance for a quick fix? I'd do it myself, but this windows stuff is not my home turf...
Rotation / 'horizontal' fonts, space character
6 Wednesday, 16 December 2009 15:10
Hanno
Yes, great prog - thanks!

Two things, would also like a rotate feature, have 2x large multiplexed LED displays that are addressed by row rather than column...

Option to include the space character 0x20 in the array... I have ample room on this micro and don't like having to make exceptions for the space char.

Will the C# source compile on the Express version? (Visual C# 2008 Express Edition).

Thanks again!
Re: Rotation
5 Wednesday, 09 December 2009 00:58
Mark
Great program! Needs to produce characters with 0 degrees rotation. Not everybody uses KS108, etc. and your modified example doesn't work. The height should remain constant, it's the width we need with proportional fonts.
Possible solution
4 Sunday, 11 October 2009 22:11
Eran

In convertCharacterToBitmap(), just under setting of alignment (line 266 in 0.0.4) add:


drawFormat.FormatFlags = StringFormatFlags.DirectionVertical;


Then fiddle around with flip x/flip y till you get what you want. I tested this quickly and it seems to work (see this example using this hack + horizontal flip and no vertical flip), but i will add this to the featurelist for the next release.


If you want to follow the code, there are two main functions: populateFontInfo() which creates an array of manipulated bitmaps (this also performs all border measurements) and generateStringsFromFontInfo() which converts these bitmaps into a formatted string.

Re: Rotate
3 Saturday, 10 October 2009 11:24
Robert
Unfortunately those options doesn't allow me to rotate the character as I need. Unless I'm completely blind I can't manage to do this:
http://files.badlysprained.net/out/504/privat/LCD/needed_dotfactory_output.png

Fortunately my limited experience allowed me to alter the code myself to make it rotate 270 degrees and get the result above.

Now I need to figure out how to make the "Tightest" option work without making the output look garbled (say you have a [.] and an [M] that you want to output it will then put linebreaks that matches the width of the [.] thus making the [M] look garbled up). Also, I need to see if I can make it output how many bytes are needed per row of pixels of each character.

I'm finding it hard going to follow the flow of the code though, it's all over the place hehe.
Re: Rotation
2 Friday, 09 October 2009 20:22
Eran
Version 0.0.3 and up supports flipping the characters both on the X axis and Y axis (clicking the little wrench thingie opens up a configuration dialogue) - that should allow you to rotate the character in 90 degree increments. Finer resolution (15, 24, 59 degrees etc) is possible to implement, but would probably open a pandora's box.
Rotate?
1 Monday, 05 October 2009 22:31
Robert
I was wondering if you might add a feature to rotate the fonts in the future? For my application I need the font data to be output so that the commented representation would be right side up so to speak.
I might be able to do it on the MCU but I suspect it would take quite a few cycles to do and would slow down output conciderable (and my code is already slow as is *sigh*)

Add your comment

Your name:
Subject:
Comment:
  The word for verification. Lowercase letters only with no spaces.
Word verification: