To define a small bitmap, start from a grid/matrix on paper (see photo below). Each square of the matrix will represent a pixel. Blacken the squares until the matrix resembles your bitmap. Next step is to translate the content of the matrix to numbers.
Let's take a closer look at the example below, a bitmap of 5x5 pixels.
This translates into an array of 5 numbers, one number per line. Each number is calculated by adding the values (at the top) of the selected columns.
So, the number for the first line is 14 (2 + 4 + 8), second number is 21 (1 + 4 + 16) and so on.
For the binary oriented fellows :), the hex values are between brackets.
Let's now jump to the actual code. The bitmap definition will look like this:
byte PROGMEM smallBitmap[3][5] = {
{
0x0E, // _XXX_
0x15, // X_X_X
0x1F, // XXXXX
0x1F, // XXXXX
0x15, // X_X_X
},
...
}
The above piece of code declares a two-dimensional ("[3][5]") array of bytes, in program space ("PROGMEM"). The first dimension ("3") represents the number of defined bitmaps. The second dimension ("5") represents the number of lines in each bitmap. A line in the bitmap definition is referenced using values for both dimensions. For example smallBitmap[0][4] is 0x15 and represents the last (index 4) line of the first (index 0) bitmap. [Note that array indexes start with 0, that is, first element in an array has index 0.]
Similarly, snippets of font definitions are shown below:
// define all ascii characters starting with 32 (blank);
unsigned char PROGMEM myfont[95][8] = {
{
0x00, // ________ blank (ascii 32)
0x00, // ________
0x00, // ________
0x00, // ________
0x00, // ________
0x00, // ________
0x00, // ________
0x00 // ________
},
{
0x00, // ________ !
0x08, // ____X___
0x08, // ____X___
0x08, // ____X___
0x08, // ____X___
0x00, // ________
0x08, // ____X___
0x00, // ________
},
...
{
0x00, // ________ 0
0x1C, // ___XXX__
0x26, // __X__XX_
0x26, // __X__XX_
0x26, // __X__XX_
0x26, // __X__XX_
0x1C, // ___XXX__
0x00, // ________
},
{
0x00, // ________ 1
0x0C, // ____XX__
0x1C, // ___XXX__
0x0C, // ____XX__
0x0C, // ____XX__
0x0C, // ____XX__
0x1E, // ___XXXX_
0x00, // ________
},
{
0x00, // ________ 2
0x1C, // ___XXX__
0x26, // __X__XX_
0x0C, // ____XX__
0x18, // ___XX___
0x30, // __XX____
0x3E, // __XXXXX_
0x00, // ________
},
{
0x00, // ________ 3
0x3E, // __XXXXX_
0x06, // _____XX_
0x1C, // ___XXX__
0x06, // _____XX_
0x26, // __X__XX_
0x1C, // ___XXX__
0x00, // ________
},
...
}
The data structure "myfont" above is an array of 95 character-bitmaps, each bitmap having 8 lines and 6 columns.
Bigger bitmaps, those having more than 8 columns, require more than a byte for each line.
Take a look at the definition of the Pacman bitmaps below.
uint16_t PROGMEM bitmap[7][14] = {
{
0x02E0, // ____XXXXX_____
0x0FF8, // __XXXXXXXXX___
0x07FC, // ___XXXXXXXXX__
0x03FC, // ____XXXXXXXX__
0x01FE, // _____XXXXXXXX_
0x00FE, // ______XXXXXXX_
0x007E, // _______XXXXXX_
0x007E, // _______XXXXXX_
0x00FE, // ______XXXXXXX_
0x01FE, // _____XXXXXXXX_
0x03FC, // ____XXXXXXXX__
0x07FC, // ___XXXXXXXXX__
0x0FF8, // __XXXXXXXXX___
0x02E0, // ___XXXXX______
},
{
0x03E0, // ____XXXXX_____
0x0FF8, // __XXXXXXXXX___
0x1FFC, // _XXXXXXXXXXX__
0x1FFC, // _XXXXXXXXXXX__
0x07FE, // ___XXXXXXXXXX_
0x01FE, // _____XXXXXXXX_
0x007E, // _______XXXXXX_
0x007E, // _______XXXXXX_
0x01FE, // _____XXXXXXXX_
0x07FE, // ___XXXXXXXXXX_
0x1FFC, // _XXXXXXXXXXX__
0x1FFC, // _XXXXXXXXXXX__
0x0FF8, // __XXXXXXXXX___
0x03E0, // ____XXXXX_____
},
{
0x03E0, // ____XXXXX_____
0x0FF8, // __XXXXXXXXX___
0x1FFC, // _XXXXXXXXXXX__
0x1FFC, // _XXXXXXXXXXX__
0x3FFE, // XXXXXXXXXXXXX_
0x07FE, // ___XXXXXXXXXX_
0x00FE, // ______XXXXXXX_
0x00FE, // ______XXXXXXX_
0x07FE, // ___XXXXXXXXXX_
0x3FFE, // XXXXXXXXXXXXX_
0x1FFC, // _XXXXXXXXXXX__
0x1FFC, // _XXXXXXXXXXX__
0x0FF8, // __XXXXXXXXX___
0x03E0, // ____XXXXX_____
},
{
0x03E0, // ____XXXXX_____
0x0FF8, // __XXXXXXXXX___
0x1FFC, // _XXXXXXXXXXX__
0x1FFC, // _XXXXXXXXXXX__
0x3FFE, // XXXXXXXXXXXXX_
0x3FFE, // XXXXXXXXXXXXX_
0x3FFE, // XXXXXXXXXXXXX_
0x3FFE, // XXXXXXXXXXXXX_
0x3FFE, // XXXXXXXXXXXXX_
0x3FFE, // XXXXXXXXXXXXX_
0x1FFC, // _XXXXXXXXXXX__
0x1FFC, // _XXXXXXXXXXX__
0x0FF8, // __XXXXXXXXX___
0x03E0, // ____XXXXX_____
},
...
};
And this is the function that uses the actual Pacman bitmaps defined above.
/************************
* load and display a given bitmap (defined in bitmaps.h);
*/
void putBitmap(int x, int y, byte nBmp, byte color)
{
for (byte row=0; row < 14; row++)
{
uint16_t rowDots = pgm_read_word_near(&bitmap[nBmp][row]);
for (byte col=0; col<14; col++)
{
if (rowDots & (1<<(13-col)))
ht1632_plot(x+col, y+row, color);
else
ht1632_plot(x+col, y+row, BLACK);
}
}
Now you should be all set to start your own animation (which is just a sequence of bitmaps).
Why using HEX here if you are actually working with binary data?
ReplyDeleteSo if you'd use binary instead you could “read” the bitmap pattern just of the code, especially if you have a monospace font in your IDE, e.g.:
{
B00111100,
B01111110,
B11111111,
B11111111,
B11111111,
B11111111,
B01111110,
B00111100
}
You are right, thanks.
Delete