A low resolution font for LED matrix displays e.g. neopixels

Dependents:   WS2812Text

A basic low resolution font

This font is intend for very low resolution display systems e.g. LED matrix displays. All characters are 5 pixels high and 5 or less pixels wide.

Data for a given character is returned as an array of 5 chars each char represents one row of the image reading from the top down. The least significant 5 bits of each char represent the pixels on that line.

e.g. For the letter X the returned data is { 0x11, 0x0a, 0x04, 0x0a, 0x11 } As bits this translates to

  • 10001
  • 01010
  • 00100
  • 01010
  • 10001

The following code will output the bit pattern for the selected character.

#include "miniFont.h"
miniFont myFont;

int main()
{

    const char **charData = NULL;
    char letter = 'x';

    if (myFont.getChar(letter,charData)) {
        for (int row = 0; row < myFont.getPixHeight(letter); row++) {
            for (int col = myFont.getPixWidth(letter) - 1; col >= 0; col--) { // start at the left not the right
                if ( *(*charData + row) & (0x01<<col))
                    printf("1");
                else
                    printf("0");
            }
            printf("\n");
        }
    }
}

Note - In order to avoid pointless copying of data getChar modifies the value in the supplied char to point to the start of the character array. However in some situations this means that the data will only be valid until the next time getChar is called. If you need to keep the data longer than that make a copy.

Characters are right justified, e.g. if getWidth() returns a value of 3 then only the 3 least significant bits of each row contain data. There are options to force fixed width characters (narrow characters will be shifted to the middle of a 5 pixel width) and to rotate characters 90 degrees Supported characters are A-Z 0-9 . ! ? <space> Any lower case letters are automatically capitalized. Not tested excessively, if you find any problems please let me know.

Revision:
0:29155ff9313e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/miniFont.cpp	Fri Nov 07 09:24:10 2014 +0000
@@ -0,0 +1,167 @@
+#include "miniFont.h"
+
+const char miniFont::dot[5] = { 0x00,0x00,0x00,0x03,0x03};
+const char miniFont::space[5] = { 0x00,0x00,0x00,0x00,0x00};
+const char miniFont::exclam[5] = { 0x01,0x01,0x01,0x00,0x01};
+const char miniFont::quest[5] = { 0x0f,0x09,0x02,0x00,0x02};
+
+const char miniFont::numbers[10][5] = {
+    { 0x0e, 0x11, 0x11, 0x11, 0x08 }, // 0
+    { 0x06, 0x02, 0x02, 0x02, 0x07 }, // 1
+    { 0x1f, 0x01, 0x06, 0x18, 0x1f }, // 2
+    { 0x1f, 0x01, 0x0f, 0x01, 0x1f }, // 3
+    { 0x10, 0x10, 0x14, 0x1f, 0x04 }, // 4
+    { 0x1f, 0x10, 0x1e, 0x01, 0x1e }, // 5
+    { 0x1f, 0x10, 0x1f, 0x11, 0x1f }, // 6
+    { 0x1f, 0x01, 0x01, 0x02, 0x02 }, // 7
+    { 0x1f, 0x11, 0x08, 0x11, 0x1f }, // 8
+    { 0x1f, 0x11, 0x1f, 0x01, 0x1f } // 9
+};
+
+const char miniFont::letters[26][5] = {
+    { 0x1f, 0x11, 0x1f, 0x11, 0x11 }, // A
+    { 0x1e, 0x11, 0x1e, 0x11, 0x1e }, // B
+    { 0x1f, 0x10, 0x10, 0x10, 0x1f }, // C
+    { 0x1e, 0x11, 0x11, 0x11, 0x1e }, // D
+    { 0x1f, 0x10, 0x1e, 0x10, 0x1f }, // E
+    { 0x1f, 0x10, 0x1e, 0x10, 0x10 }, // F
+    { 0x1f, 0x10, 0x13, 0x11, 0x1f }, // G
+    { 0x11, 0x11, 0x1f, 0x11, 0x11 }, // H
+    { 0x07, 0x02, 0x02, 0x02, 0x07 }, // I
+    { 0x01, 0x01, 0x01, 0x11, 0x1f }, // J
+    { 0x11, 0x12, 0x1c, 0x12, 0x11 }, // K
+    { 0x10, 0x10, 0x10, 0x10, 0x1f }, // L
+    { 0x11, 0x1b, 0x15, 0x11, 0x11 }, // M
+    { 0x11, 0x19, 0x15, 0x13, 0x11 }, // N
+    { 0x1f, 0x11, 0x11, 0x11, 0x1f }, // O
+    { 0x1f, 0x11, 0x1f, 0x10, 0x10 }, // P
+    { 0x1f, 0x11, 0x15, 0x1f, 0x04 }, // Q
+    { 0x1f, 0x11, 0x1f, 0x12, 0x11 }, // R
+    { 0x1f, 0x10, 0x1f, 0x01, 0x1F }, // S
+    { 0x1f, 0x04, 0x04, 0x04, 0x04 }, // T
+    { 0x11, 0x11, 0x11, 0x11, 0x1F }, // U
+    { 0x11, 0x11, 0x11, 0x0a, 0x04 }, // V
+    { 0x11, 0x11, 0x15, 0x1b, 0x11 }, // W
+    { 0x11, 0x0a, 0x04, 0x0a, 0x11 }, // X
+    { 0x11, 0x11, 0x1f, 0x04, 0x04 }, // Y
+    { 0x1f, 0x02, 0x04, 0x08, 0x1f } // Z
+};
+
+
+miniFont::miniFont() {
+
+    rotate90 = false;
+    fixedWidth = false;
+     }
+
+
+uint8_t miniFont::getMinPixWidth(char letter)
+{
+    switch(letter) {
+        case '.':
+            return 2;
+        case ' ':
+        case '1':
+        case 'I':
+        case 'i':
+            return 3;
+        case '!':
+            return 1;
+        case '?':
+            return 4;
+        default:
+            return maxWidth;
+    }
+}
+
+
+uint8_t miniFont::getPixWidth(char letter)
+{
+    if (fixedWidth)
+        return maxWidth;
+    else
+        return getMinPixWidth(letter);
+}
+
+uint8_t miniFont::getPixHeight(char letter)
+{
+    return 5;
+}
+
+// gets the proportional letter
+bool miniFont::getRawChar(char letter, const char **rowArray)
+{
+
+    if ((letter>='A') && (letter<='Z')) { // upper
+        *rowArray = letters[letter-'A'];
+        return true;
+    }
+    if ((letter>='a') && (letter<='z')) { // lower
+        *rowArray = letters[letter-'a'];
+        return true;
+    }
+    if ((letter>='0') && (letter <='9')) {
+        *rowArray = numbers[letter-'0'];
+        return true;
+    }
+    if (letter == '.') {
+        *rowArray = dot;
+        return true;
+    }
+    if (letter == '!') {
+        *rowArray = exclam;
+        return true;
+    }
+    if (letter == '?') {
+        *rowArray = quest;
+        return true;
+    }
+    if (letter == ' ') {
+        *rowArray = space;
+        return true;
+    }
+    return false;
+}
+
+// converts to fixed width if needed.
+bool miniFont::getVerticalChar(char letter, const char **rowArray)
+{
+    if (!fixedWidth)
+        return getRawChar(letter,rowArray);
+
+    uint8_t shift = (maxWidth - getMinPixWidth(letter)) / 2;
+    if (shift == 0)
+        return getRawChar(letter,rowArray);
+
+    const char *rawletter;
+    if (getRawChar(letter,&rawletter)) {
+        for (int i = 0; i < maxHeight; i++) {
+            letterBuffer[i] = rawletter[i]<<shift;
+        }
+        *rowArray = (const char *)letterBuffer;
+        return true;
+    }
+    return false;
+}
+
+// rotates if needed.
+bool miniFont::getChar(char letter, const char **rowArray)
+{
+    if (!rotate90) return getVerticalChar(letter,rowArray);
+
+    const char *vertical;
+    if (!getVerticalChar(letter,&vertical))
+        return false;
+
+    for (int i = 0; i < maxWidth; i++) {
+        rotateBuffer[i] = 0;
+    }
+
+    for (int i = 0; i < maxHeight; i++) {
+        for (int j = 0; j < maxWidth; j++) {
+            rotateBuffer[i] = vertical[j] << j;
+        }
+    }
+    *rowArray = vertical;
+    return true;
+}