LED Matrix Font

I have written a font for an RGB matrix that uses PWM [TLC5940] to get soft edges and stuff. It's actually a 5*7 for most characters. But some things are smaller, some bigger.

I adapted an actual font and arranged the data in separate multi-dimensional arrays like this:

// 0 (Zero)
int 0[][]= {0x3FF, 0x7FF, 0xFFF, 0xFFF 0x7FF, 0x3FF,
0x7FF, 0xFFF, 0x00, 0x00 0xFFF, 0x7FF,
0xFFF, 0xFFF, 0x00, 0xFFF, 0xFFF, 0xFFF,
0xFFF, 0xFFF, 0x00, 0x00, 0xFFF, 0xFFF,
0xFFF, 0xFFF, 0xFFF, 0x00, 0xFFF, 0xFFF,
0x7FF, 0xFFF, 0x00, 0x00 0xFFF, 0x7FF,
0x3FF, 0x7FF, 0xFFF, 0xFFF 0x7FF, 0x3FF};

[Contains hexadecimal data for 1/2, 3/4 and full brightness]

But I'm not sure the best way to display these on an LED matrix (using the TLC5940 Library btw) without filling the font in with 0x00 which would suck and be Noob!

/me

  1. Make sure you store the font in PROGMEM. You've got a lot more of that than RAM, and if it's in RAM, it's already eating away at PROGMEM as the program has to copy it from Flash to RAM during startup.

  2. Since all characters are going to always be 7 dots high, just store them that way. Use a table to point to the start of any character and the number of columns to read. So, you'd use something like

const char chr0[4][7] PROGMEM = { ..... };

const char *chrs[] PROGMEM = { chr0, chr1... };

You can compute the size by looking at the address of the next character as the stop. Have a dummy character at the end that you don't use to act as a sentinel.

Ah thank you, that makes sense. I was planning to convert the font to PROGMEM, but would have done it sooner if I had understood it!

Cheers, /me

Here is the updated and complete font file:

Cheers! /me

Why not use the internal eeprom to store the fonts?

EEPROM - 1KB, need to use a completely separate sketch to load it up

PROGMEM - 32KB minus your program size, loaded up every time you upload the sketch

I thought that using 8 bits for storing one of three possible states was a bit overkill, so I've played with your code and made something that stores a font character using 21 bytes, as opposed to 42.

It has a maximum of 16 states per 'dot'.

Pastebin code dump, upload and see what is the result of below sketch

Arduino Client Sketch:

/*
|| LED Matrix Font Client
||
|| Contributed:
|| BetaDelta
|| Alexander Brevig
*/

//#include "FontData.h"

void printChar( const FontChar& printme );

void setup(){
Serial.begin(9600);

printChar(A);
printChar(R);
printChar(D);
printChar(U);
printChar(I);
printChar(N);
printChar(O);

}

void loop(){}

void printChar( const FontChar& printme ){
//Serial.println("\n\nSample on how to access values");
for (byte y=0; y<7; y++){
for (byte x=0; x<6; x++){
if (printme.get(x,y)){
Serial.print( printme.get(x,y) , DEC );
} else {
Serial.print(" ");
}
}
Serial.println();
}
Serial.println();
}

Result:

 1331 
 3333 
33  33
33  33
333333
33  33
33  33

3331  
33 33 
33 33 
33 33 
3331  
33 33 
33 33 

33311 
33 131
33  33
33  33
33  33
33 131
33311 

33 33 
33 33 
33 33 
33 33 
33 33 
33 33 
13331 

3333  
 33   
 33   
 33   
 33   
 33   
3333  

31  33
331 33
333133
33 333
33  33
33  33
33  33

113311
13  31
33  33
33  33
33  33
13  31
113311

Wow that's great! Didn't fully understand that implementation but...

Cheers, /me

If there is anything in particular I'll gladly try to explain :slight_smile:

A nice font BTW.

Um yeah kinda, all of it. Just don't really understand how it all stitches together.; probably due to my lack of knowledge:(

/me

Well then, basically I made a container called FontChar that holds 6*7 bytes constrained to use 4 bits.

struct FontChar{
  byte value : 4;
};

This is what caused the RAM usage to get halved.

Then I made a constructor of that struct to enable simple construction of characters. The usual way to use structs is:

FontChar char;

char.value = 3;

But since you set 42 values that would take a while with that syntax.

Bu using the constructor you get kind of a visual feedback as well.

I added a function called byte get(byte x,byte y); which returns the corresponding byte if this was a 2d matrix.

The constants
const byte V = 0; //Void
const byte QR = 1; //Quarter
const byte HAL = 2; //Half
const byte FULL = 3;
const byte NO_SUCH_INDEX = 0;

Was created to provide a gretaer visual feedback when initializing FontChars.

The rest is basically just initializing instances of the struct FontChar and the client only uses the get(x,y) function.

Wikipedia on clases and structs

PM me for a more in-depth examination / explanation if you want. :slight_smile:

Ah that makes more sense to me. Cheers for all the effort!

/me

It's nice to see people using the Arduino Pastebin. Just don't forget to C++ syntax colouring.

/me