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.

Files at this revision

API Documentation at this revision

Comitter:
AndyA
Date:
Fri Nov 07 09:24:10 2014 +0000
Child:
1:46e0549c2bfb
Commit message:
Added comments/doucmentation

Changed in this revision

miniFont.cpp Show annotated file Show diff for this revision Revisions of this file
miniFont.h Show annotated file Show diff for this revision Revisions of this file
--- /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;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/miniFont.h	Fri Nov 07 09:24:10 2014 +0000
@@ -0,0 +1,127 @@
+#ifndef __miniFont_h__
+#define __miniFont_h__
+
+#include "mbed.h"
+
+/** A basic low resolution font
+*
+* This font is intened 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. The least significant
+* 5 bits of each char represent the pixels on that line.
+*
+* e.g. For the letter X the returnd data is
+* { 0x11, 0x0a, 0x04, 0x0a, 0x11 }
+*
+* As bits this translates to
+* > 10001
+* > 01010
+* > 00100
+* > 01010
+* > 10001
+*
+* example use
+*
+* @code
+*
+* #include "miniFont.h"
+* miniFont myFont;
+*
+* int main() {
+*    
+*    char characterData[5];
+*    if (getChar('x',&characterData)) {
+*        // display letter
+*        }
+*    
+*    }
+* @code
+*
+* 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 characers 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 capitalised.
+*
+* Not tested excessivly, if you find any problems please let me know.
+*/
+class miniFont
+{
+public:
+
+/** Initalise the font
+*/
+    miniFont();
+
+/** Returns the width of the requested character
+@param letter The character to measure
+@return The width in pixels
+*/    
+    uint8_t getPixWidth(char letter);
+
+/** Returns the height of the requested character
+@param letter The character to measure
+@return The height in pixels (currently always 5)
+*/    
+    uint8_t getPixHeight(char letter);
+
+/** get the data for a given character
+@param letter The chatacter to retrieve the data for
+@param rowArray An array containing the pixel data
+@return Flag indicating that rowArray is valid.
+*/
+    bool getChar(char letter, const char **rowArray);
+    
+/** get current fixed width mode
+@return true if fixed width is enabled
+*/
+    bool isFixedWidth() {return fixedWidth;};
+/** set fixed width mode
+@param newValue True to enable fixed width, false to disable
+*/
+    void setFixedWidth(bool newValue) {fixedWidth = newValue;};
+    
+/** get current rotation mode
+@return true if font is rotated
+*/
+    bool isRotated() {return rotate90;};
+
+/** set rotation mode
+@param newValue True to rotate text 90 degrees anti-clockwise (except in the USA where it rotates counterclockwise instead)
+*/
+    void setRotated(bool newValue) {rotate90 = newValue;};
+
+private:
+
+
+    uint8_t getMinPixWidth(char letter);
+    bool getRawChar(char letter, const char **rowArray);
+    bool getVerticalChar(char letter, const char **rowArray);
+
+    static const uint8_t maxWidth = 5;
+    static const uint8_t maxHeight = 5;
+
+    bool rotate90;
+    bool fixedWidth;
+    char letterBuffer[5];
+    char rotateBuffer[5];
+
+
+    static const char letters[26][5];
+
+    static const char numbers[10][5];
+
+    static const char dot[5];
+    static const char space[5];
+    static const char exclam[5];
+    static const char quest[5];
+
+};
+
+
+#endif