Some years ago, I bought a nice looking LED matrix at an area surplus dealer. The part number was prominently displayed on the back, I figured that a datasheet would easily be found. Not true. At the time there was not a single relevant result to be found on the web. With a bit of prodding, I identified the power, ground, and reset pins. The enable pin revealed itself after a bit more experimentation. With only two pins remaining to control what appeared to be 72 LEDs, I figured that some sort of serial interface was needed. I grabbed a nearby Z-8 dev board and began sending bits. Oops, level shifting was needed to connect the 5V display module to the 3.3V processor. That adjustment made, more bits were sent. Aside from the stray flash of the display, there were no results that I could make sense of. The module proceeded to sit on my bench for a few years.
May 2016, after the CDM102 collected enough dust and I grew tired of its silent mocking, I dusted it off and tried another search for a datasheet.
This time, I was rewarded with a machine translated page showing that some progress had been made unlocking the module's mysteries. Encouraged, I fished
out another dev board and began coding. In short order, a few interesting flashes were extracted from the display. After a day or so of tinkering, I
believed that I had unlocked most of the module's secrets. The was just one column of LEDs that would not light. It was such an intolerable state of
affairs, that I took a knife to the display. As it turned out, the covering is simply a self-adhesive bit of plastic film. What I found under it was
that there are no LEDs populating that column.
Though we disagree on the number of bits to be transmitted and data rate. What I present here is, mostly, a simple re-describing of this page, with a few embellishments and without being scrambled by machine translation.
We will start with a photo.
The module separates the LEDs in to two groups. They will be called Group 0 and Group 1. The topmost available pixel is set by sending 0x80, while setting the bottom pixel requires 0x08 to be sent. To illuminate all pixels on a row, send 0xF8. The first pixel value sent will illuminate the first row on the left in the group that was selected by the most recently send group command. Each pixel byte sent will illuminate the next row to the right until row 6 is reached, when the display will ignore the pixel data, not perform a "wrap".
There are six pins, with pin one marked.
An ordinary Serial Peripheral Interface (SPI) port can be used to send data to the CDM102. You will need a total of four I/O pins, SPI-Clock, SPI-Data, SPI-Select, and finally a pin to handle Reset. Keep in mind that this is a 5V device, so adjust your logic levels accordingly.
|Command byte (CDM102 LSB first)||Command byte (MSB first)||Result||Comment|
|0x05||0xA0||Set row counter to 0 in Group 0. Set green flag.||Next byte(s) of pixel data will light green LEDs in Group 0.|
|0x85||0xA1||Set row counter to 0 in Group 1. Set green flag.||Next byte(s) of pixel data will light green LEDs in Group 1.|
|0x45||0xA2||Set row counter to 0 in Group 0. Set red flag.||Next byte(s) of pixel data will light red LEDs in Group 0.|
|0xC5||0xA3||Set row counter to 0 in Group 1. Set red flag.||Next byte(s) of pixel data will light red LEDs in Group 1.|
|0x03||0xC0||Set no rows to yellow.||Clear the display.|
|0x83||0xC1||Set row 0 to yellow.|
|0x43||0xC2||Set row 1 to yellow.|
|0xC3||0xC3||Set rows 0 and 1 to yellow.|
|0x23||0xC4||Set row 2 to yellow.|
|0xA3||0xC5||Set rows 0 and 2 to yellow.|
|0x63||0xC6||Set rows 1 and 2 to yellow.|
|See the binary count pattern forming?|
|0x3B||0xDC||Set all rows, except 0 and 1, to yellow.|
|0xBB||0xDD||Set all rows, except 1, to yellow.|
|0x7B||0xDE||Set all rows, except 0, to yellow.|
|0xFB||0xDF||Set all rows to yellow||Send this one byte command for a lamp-test function.|
|0x07||0xE0||Set maximum brightness for entire display.|
|0x87||0xE1||Reduce brightness one step from maximum brightness for entire display.|
|0x47||0xE2||Reduce brightness two steps from maximum brightness for entire display.|
|See the pattern forming?|
|0xE7||0xE7||Reduce brightness six steps from maximum brightness for entire display.||Minimum illumination level.|
|0x13||0xE8||Set brightness to 0 (off)||The status of all LEDs is preserved while the display is in this mode.|
If you send a Reset Row Count code followed by some pixel data, then send the same Reset Row Count code and more pixel data. The original pixels will be over-written by the new pixel data.
Sending a 1 in a bit position will turn a LED on with the color selected by the most recent Reset Row Count code, and a 0 will turn a pixel. Remember, the display expects that the pixel values are contained in the highest five bit positions of a byte.
Here is a bit of pseudo-code that shows how to set the display to look like this photo. Apologies for the pitiful image quality and weak color rendering, I used a Nykon camera.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Module reset and LSB-first SPI transmission is left as an exercise for the reader. * As is the implementation of a high-frame rate video driver. */ Send_SPI_LSB_First(0x03); // Clear the display, though this is not needed after Reset Send_SPI_LSB_First(0x05); // Set row counter to 0 in Group 0 for green pixel data //send green pixel data for Group 0 Send_SPI_LSB_First(0x20); Send_SPI_LSB_First(0x50); Send_SPI_LSB_First(0xA8); Send_SPI_LSB_First(0x88); Send_SPI_LSB_First(0x50); Send_SPI_LSB_First(0x88); Send_SPI_LSB_First(0x85); // Set row counter to 0 in Group 1 for green pixel data //send green pixel data for Group 1 Send_SPI_LSB_First(0x38); Send_SPI_LSB_First(0x78); Send_SPI_LSB_First(0x78); Send_SPI_LSB_First(0x78); Send_SPI_LSB_First(0x78); Send_SPI_LSB_First(0x38); Send_SPI_LSB_First(0x45); // Set row counter to 0 in Group 0 for red pixel data //send red pixel data for Group 0 Send_SPI_LSB_First(0x88); Send_SPI_LSB_First(0x50); Send_SPI_LSB_First(0x88); Send_SPI_LSB_First(0xA8); Send_SPI_LSB_First(0x50); Send_SPI_LSB_First(0x20); Send_SPI_LSB_First(0xC5); // Set row counter to 0 in Group 1 for redpixel data //send red pixel data for Group 1 Send_SPI_LSB_First(0x00); Send_SPI_LSB_First(0x40); Send_SPI_LSB_First(0xC0); Send_SPI_LSB_First(0xC0); Send_SPI_LSB_First(0x40); Send_SPI_LSB_First(0x00);
I hope this is useful for someone who has happened to find this display module. I find it to be a rather nice display, it has already been put to work as a clock display and in a guitar tuner. There are likely some commands and subtleties that I have not noticed. If you find something, publish!