Friday, January 6, 2012

8051-based LED Matrix Scrolling Message Board.

Some time in 2011 I turned my interest into retro computing and self made electronics. I was inspired by this brilliant home brew computer project by Matt Sarnoff:
Being Commodore 64 fan I decided to build my own 8-bit retro style computer based on MOS 6502 CPU. To warm myself up, since it has been years since I wielded soldering iron or designed/programmed any circuits, I decided to build some 8051 based electronic toy, since I studied 8051 a little bit while in college.
The result is a LED Matrix Message Scrolling Board based on Atmel's 89S8253 micro controller (See fig.1).

Fig.1: Circuit diagram.


    - Atmel AT89S8253.
    - Crystal 11.0592 MHz
    - 74LS373 latch.
    - 62256 CMOS static RAM (32 K x 8).
    - Intel Flash EPROM P28F256A-200 32 kB external program memory.
    - Serial port RS 232 adapter made with MAX232 mini board from e-bay.
    - 4 x LED matrix module DE-DP13112 ver. 1.0 connected
        as a cascade I got from e-bay.


    8051 system to LED Matrix board connector:

    DE-DP13112    ->    8051 board
    WR            ->    P10
    RD            ->    P11
    DATA          ->    P12
    CS1           ->    P13
    CS2           ->    P14
    CS3           ->    P15
    CS4           ->    P16
    GND(8)        ->    GND
    GND(11)       ->    GND
    GND(13)       ->    GND
    GND(15)       ->    GND
    Vcc(12)       ->    +5V
    Vcc(14)       ->    +5V
    Vcc(16)       ->    +5V

I assembled the circuit using point to point soldering method. LED matrix cascade and controller board are mounted on two wooden slats bought in Home Depot, positioned in parallel to each other. The device then can have "legs" attached or be hanged/suspended depending on the application. I use mine in the back window of the car. Device is powered from 12V source and has 5V regulator (7805). Communication with host PC application is done via RS-232 port. 

Host application is written in Java using JCreator LE. Controller firmware is written in C and compiled with SDCC. I equipped firmware with many features and options, such us scrolling and static texts sequential displaying and scripting engine (my favorite).

Micro controller part: ledmatrx
Host app. part: SerialIOBoard

I recorded my progress and some demos on you tube.

This project is free for personal/educational use.


  1. Hello Marek,

    I am currently doing a scrolling LED matrix as a hobby project.

    However, when the message scrolling, the pixel seems to be duplicated. Thus, the pixel cannot see clearly. When I decrease the scrolling speed. Pixel can be seen clearly, but the pixel seems to be jitters (not smooth).

    This is my algorithm that I used:

    Could you take a look and give me some suggestion?
    I read your source code, but it seems very difficult for me to follow. That is why I just want to ask you just the algorithm and then I implement it by myself.

    Thank you :)

    1. Hello,
      Thanks for looking at my blog.
      Pixel duplication is actually a side effect my algorithm experiences as well. The faster you scroll (or if you scroll too slow as well) the more you will see this. It happens because you can really scroll only one column at a time and then you have to sequentially go through entire matrix to shift each column to the left. So at these short times you have the same column displayed twice side by side. If you had a hardware LED matrix driver that allowed to shift data contents directly in the memory/register of the LED matrix controller, you would not see that effect. However, since you (and me) shift by software, there is a trade off. My LED matrix has its own controller, but the interface to it is serial. I can upload the data to the specific addresses in controller's memory. So, in each scroll loop step I upload the visible text part into the LED matrix and then in the next scrolling step I upload the message which is shifted one bit to the left in the internal software buffer. I am yet to analyze your code to see why do you have these extra side effects (jittery/blurry scrolling). Today I did not have enough time, sorry about that. It'd be great if you posted a link to the video clip that shows the problem. A (motion) picture is better than thousand words :-)

    2. Thank you so much for taking your time to help me.

      My camera on my phone is so bad, thus I cannot capture clearly display when it scrolling.

      This is the picture that can describe my problem.

      The letter on the left can be seen clearly when moving with low speed.
      The letter on the right shows the problem when the message moving with faster speed.

      I use row scanning method to display the letter.

    3. I can not access that link: "We're sorry, but you do not have access to this page".

    4. This comment has been removed by the author.

    5. Sorry I fixed the link.

    6. Hello,
      I looked at the pictures and code. I still can not say for sure what is the problem since I don't know the specifics of your hardware, however I think that you may want to try to refresh LED matrix in a reverse order:
      for(row = 0; row < NUM_ROW; row++)
      change to:
      for(row = NUM_ROW-1; row >= 0; row--)
      I also don't understand the purpose of shifting the data left by the number in variable 'time' and only then by 8 bits:
      dispBuffer[row]= ((dispBuffer_Backup[row] & 0x00FF) << time) >> 8;
      Shouldn't you shift only one bit left in one iteration?
      I also would like to know more about hardware configuration and LED matrix. Is dispBuffer directly interfaced to LED matrix? Is changing values in dispBuffer directly affecting which LED-s are on and which are off immediately? If not, what is the purpose of using separate buffer dispBuffer_Backup? Also, what is the purpose of latching data and how is it affecting the presentation on the LED matrix? (I am talking about colCtl(LATCH, 1); colCtl(LATCH, 0);)
      Sorry for so many questions instead of answers, however I am sure you understand that this is the part of the process of understanding the nature of the problem before we can fix it.
      Let me know, perhaps you already figured it out?

    7. First, I want to thank you for taking to look at my code. Thank you so much.

      Here is my hardware connection

      I use row scanning method.

      I looked at your font code, and I guess you used column scanning methond.

      " however I think that you may want to try to refresh LED matrix in a reverse order:
      for(row = 0; row < NUM_ROW; row++)
      change to:
      for(row = NUM_ROW-1; row >= 0; row--)"

      This cannot solve the problem. It is still the same.

      " dispBuffer[row]= ((dispBuffer_Backup[row] & 0x00FF) << time) >> 8; "

      What I want to do is just shifting one character code, which is hold
      in dispBuffer_Backup from the very right of the display to very left of the display.
      For example: The code is 1001_0001
      What I want to see on the display is:

      1st: 0000_0000
      2nd: 0000_0001
      3rd: 0000_0010
      4th: 0000_0100
      5th: 0000_1001
      . . .
      9th: 1001_0001
      10th: 0010_0010
      11th: 0100_0100
      16th: 1000_0000

      "Is dispBuffer directly interfaced to LED matrix?"
      Yes, it is.

      "Is changing values in dispBuffer directly affecting which LED-s are on and which are off immediately?"
      The changed value in the dispBuffer does not effective immediately until next scanning cycle of that row.

      "What is the purpose of latching data and how is it affecting the presentation on the LED matrix? (I am talking about colCtl(LATCH, 1); colCtl(LATCH, 0);)"
      Because I use 74HC595 IC which is connected to columns (Katod) of the LED matrix,
      Latching data is done in order to update new data present on the output of the IC.
      The new data for the next row is shift to 595 IC at the begining of the timer interrupt. However, the output of the 595 IC still does not change until
      the latching data is done.
      Then I turn the previous row off in order to eleminate the "ghosting effect" when updating the data for the new row.
      After turn the row off, I latch new data and turn the next row on.

      I try to scroll the message from the bottom up to the top or from top down to the bottom (this is easy than horizontal scrolling - for row scanning method),
      the problem seems to be disappeared. I can see the pixel clearly even when the moving speed is fast enough. I am currently trying to figure out what is the difference
      between these two method to find out the solution for my problem.

      Once again, I want to say thank you so much. :)
      With the best regards!