Thursday, August 11, 2011

A simple 3x5 binary font generator


In my LED-matrix-project, I needed some kind of possibility to display text.
Since the flash memory of an AVR, especially from the ATTiny series, is somewhat limited,
I had to find a good way to store the characters without using up to much of the space.
After a small discussion on, I had everything I needed to make it.
 Well, everything but the font.
As recommended, I'm using a 16-bit mono-color font, which means, I'm storing all the information needed in just two bytes. This makes it a bit hard to understand by just looking at the binary, so I wrote a small program
to generate the chars for me.

Using this and a routine from the forum-user "Peter Dannegger", I can now display the characters on the matrix. Here is the function, which is meant to be used together with the code I posted earlier:

void writeSign(uint8_t px, uint8_t py, uint16_t pattern, uint8_t color){
   for (int x = 0; x < 3; x++) {
      for (int y = 0; y < 5; y++) {
         if (pattern & 1) // LSB first
            ht1632_plot(px +x, py +y, color);
            ht1632_plot(px +x, py +y, BLACK);  
         pattern >>= 1; // next bit

You can download the program to generate the 16-bit fonts here:


Wednesday, August 10, 2011

DE-DP14211 LED-matrix

I've been looking quite a while for cheap LED matrices now and I finally found some.
SureElectronics has some really good ones, in all variants you could want.
Finally, I bought two DE-DP14211 matrices.
Featuring a 32x16 tricolor LED matrix, 4-bit PWM dimming and a SPI-like interface, they only cost about 25€ per item.

Well, I bought them without reading the datasheet, because what was named SPI-like was different enough from normal SPI, that you couldn't use the AVRs hardware SPI to control these devices.

After googling the misery, I found an Arduino library that could control the matrix.
Now, since I'm not using the Arduino bootloader, I had to change a few things.

First of all, you need to pick the functions, you need.
In my case, I only wanted the parts to be able to set or delete a pixel.
So what did I need?

First of all, go through the compiler definitions.
We won't use the DEBUGPRINT function, so don't copy it.
Here is what you need:

* commands written to the chip consist of a 3 bit "ID", followed by
* either 9 bits of "Command code" or 7 bits of address + 4 bits of data.
#define HT1632_ID_CMD 4 /* ID = 100 - Commands */
#define HT1632_ID_RD 6 /* ID = 110 - Read RAM */
#define HT1632_ID_WR 5 /* ID = 101 - Write RAM */

#define HT1632_CMD_SYSDIS 0x00 /* CMD= 0000-0000-x Turn off oscil */
#define HT1632_CMD_SYSON 0x01 /* CMD= 0000-0001-x Enable system oscil */
#define HT1632_CMD_LEDOFF 0x02 /* CMD= 0000-0010-x LED duty cycle gen off */
#define HT1632_CMD_LEDON 0x03 /* CMD= 0000-0011-x LEDs ON */
#define HT1632_CMD_BLOFF 0x08 /* CMD= 0000-1000-x Blink ON */
#define HT1632_CMD_BLON 0x09 /* CMD= 0000-1001-x Blink Off */
#define HT1632_CMD_SLVMD 0x10 /* CMD= 0001-0xxx-x Slave Mode */
#define HT1632_CMD_MSTMD 0x18 /* CMD= 0001-10xx-x Use on-chip clock */
#define HT1632_CMD_EXTCLK 0x1C /* CMD= 0001-11xx-x Use external clock */
#define HT1632_CMD_COMS00 0x20 /* CMD= 0010-ABxx-x commons options */
#define HT1632_CMD_COMS01 0x24 /* CMD= 0010-ABxx-x commons options */
#define HT1632_CMD_COMS10 0x28 /* CMD= 0010-ABxx-x commons options */
#define HT1632_CMD_COMS11 0x2C /* CMD= 0010-ABxx-x commons options */
#define HT1632_CMD_PWM 0xA0 /* CMD= 101x-PPPP-x PWM duty cycle */

// Dual 3216 LED Matrix
// If you have only one set these to:
// X_MAX=31
// Y_MAX=15

#define X_MAX 63 // 0 based X
#define Y_MAX 15 // 0 based Y
#define CHIP_MAX 4*2 // Number of HT1632C Chips
// 4 each board * 2 boards

// possible values for a pixel;
#define BLACK 0
#define GREEN 1
#define RED 2
#define ORANGE 3 

#define calcBit(y) (8>>(y&3)) 

 Next is the variable definition:
* Set these constants to the values of the pins connected to the SureElectronics Module

static const byte ht1632_data = 53; // Data pin (pin 7)
static const byte ht1632_clk = 52; // Data pin (pin 2)
static const byte ht1632_wrclk = 51; // Write clock pin (pin 5)
static const byte ht1632_cs = 50; // Chip Select (pin 1)
// The should be a common GND.
// The module with all LEDs like draws about 200mA,
// which makes it PROBABLY powerable via Arduino +5V

//(Apexys comment: The module will draw up to 1.5 Amps with all LEDs on,
// so forget about powering it with an Arduino and get it a good 
// switching PSU!) 

* we keep a copy of the display controller contents so that we can
* know which bits are on without having to (slowly) read the device.
* Note that we only use the low four bits of the shadow ram, since
* we're shadowing 4-bit memory. This makes things faster, but we
* COULD do something with the other half of our bytes !

byte ht1632_shadowram[63][CHIP_MAX] = {0};

Followed by the functions

 void OutputCLK_Pulse(void) //Output a clock pulse
void ht1632_chipselect(int select) //Select a chip
void ht1632_writebits (byte bits, byte firstbit) //Write bits on SPI
static void ht1632_sendcmd (byte chipNo, byte command) Send Command
static void ht1632_senddata (byte chipNo, byte address, byte data) //Data
void ht1632_clear() //Clear Display 
byte xyToIndex(byte x, byte y) //Get RAM position for a pixel
 int get_pixel(byte x, byte y) //Get a pixel's color at a position 
 void ht1632_plot (byte x, byte y, byte color) //Set a pixel
static void ht1632_initialize() //Init the display 

Now, simply replace byte with uint8_t.
Two last things are to do: You need to define four pins of any port as output and you need  a function to replace the digitalWrite function of the Arduino library. Here it is:

//Replace the Arduinos digitalWrite() function
void digitalWrite(uint8_t port, uint8_t value){
case 0:{
PORTC |= (1<<PC0);
PORTC &= ~(1<<PC0);
case 1:{
PORTC |= (1<<PC1);
PORTC &= ~(1<<PC1);
case 2:{
PORTC |= (1<<PC2);
PORTC &= ~(1<<PC2);
case 3:{
PORTC |= (1<<PC3);
PORTC &= ~(1<<PC3);

Now simply change the static const byte for the port values to something like

#define ht1632_cs 0
#define ht1632_clk 1
#define ht1632_wrclk 2
#define ht1632_data 3

And add a statement like

#define LOW 0
#define HIGH 1 

And your done!

Now you can set a pixel with ht1632_plot(x,y,color) and you can clear the matrix by calling

Now, back to development!