The techniques described here take advantage of the fact that having a fixed character width of 16 pixels. That makes it easy to define 2 bytes of data and to do it by hand. You want to make a smaller font it would also be extremely easy to define characters that were exactly 8 pixels wide. Such a definition might look like this.

//01 Upper left arrow /*| 8 4 2 1 8 4 2 1 |*/ /*| X X X X . . . . |*/ 0xf0, /*| X X . . . . . , |*/ 0xc0, /*| X . X . . . . , |*/ 0xa0, /*| X . . X . . . , |*/ 0x90, /*| . . . . X . . , |*/ 0x08, /*| . . . . . X . , |*/ 0x04, /*| . . . . . . X , |*/ 0x02, /*| . . . . . . . X |*/ 0x01,

Technically, it is possible to make characters 12 pixels wide but it's a little more difficult to encode the data by hand. The first two bytes of data in code 12 bits from the first row of pixels and 4 bits from the next row. This is followed by a single byte that encodes the remaining 8 bits of the second row. Then the pattern repeats with 12 bits from the third row in the first 4 bits from the fifth row. I've encoded lots of 16 bit symbols and I can tell you that just doing 3 or 4 examples here using the 12 bit method was about twice as hard. I made way more mistakes along the way. Here are some samples.

//00 Test square /*| 8 4 2 1 8 4 2 1 8 4 2 1 |*/ /*| X X X X X X X X X X X X |*/ 0xff,0xf8, //12 bits from 1st row and 4 bits from 2nd row /*| X . . . . . . , . . . X |*/ 0x01, //remaining 8 bits of the 2nd row /*| X . . . . . . , . . . X |*/ 0x80,0x18, //12 bits from 3rd row and 4 bits from 4th row /*| X . . . . . . , . . . X |*/ 0x01, //remaining 8 bits of 4th row /*| X . . . . . . , . . . X |*/ 0x80,0x18, //12 bits from 5th row and 4 bits from 6th row /*| X . . . . . . , . . . X |*/ 0x01, //remaining 8 bits of 6th row /*| X . . . . . . , . . . X |*/ 0x80,0x18, //12 bits from 7th row and 4 bits from 8th row /*| X . . . . . . , . . . X |*/ 0x01, /*| X . . . . . . , . . . X |*/ 0x80,0x18, /*| X . . . . . . , . . . X |*/ 0x01, /*| X . . . . . . , . . . X |*/ 0x80,0x18, /*| X . . . . . . , . . . X |*/ 0x01, /*| X . . . . . . , . . . X |*/ 0x80,0x18, /*| X . . . . . . , . . . X |*/ 0x01, /*| X X X X X X X X X X X X |*/ 0xff,0xf0, //12 bits from final row. Last 4 bits unused. //Total of 23 bits of data //01 upper left arrow /*| 8 4 2 1 8 4 2 1 8 4 2 1 |*/ /*| X X X X X X X . . . . . |*/ 0xfe,0x08, //12 bits from 1st row and 4 bits from 2nd row /*| X X . . . . . , . . . . |*/ 0x00, //remaining 8 bits of the 2nd row /*| X . X . . . . , . . . . |*/ 0xa0,0x09, //12 bits from 3rd row and 4 bits from 4th row /*| X . . X . . . , . . . . |*/ 0x00, //remaining 8 bits of 4th row /*| X . . . X . . , . . . . |*/ 0x88,0x08, //12 bits from 5th row and 4 bits from 6th row /*| X . . . . X . , . . . . |*/ 0x40, //remaining 8 bits of 6th row /*| X . . . . . X , . . . . |*/ 0x82,0x08, //12 bits from 7th row and 4 bits from 8th row /*| . . . . . . . X . . . . |*/ 0x10, /*| . . . . . . . , X . . . |*/ 0x00,0x80, /*| . . . . . . . , . X . . |*/ 0x04, /*| . . . . . . . , . . X . |*/ 0x00,0x20, /*| . . . . . . . , . . . X |*/ 0x01, //18 bites

We hope that this tutorial sparks your imagination and you will come up with other creative uses of this method. Perhaps a set of chess pieces or other game tokens might be useful.