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.

CDM102

We will start with a photo.

CDM102 LED Array

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".

Connecting

There are six pins, with pin one marked.

  1. Data Enable
  2. V+
  3. Data Clock
  4. Ground
  5. Data
  6. Reset

Signals

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.

SPI timing for CDM102

Commands

Command byte (CDM102 LSB first)Command byte (MSB first)ResultComment
0x050xA0Set row counter to 0 in Group 0. Set green flag.Next byte(s) of pixel data will light green LEDs in Group 0.
0x850xA1Set row counter to 0 in Group 1. Set green flag.Next byte(s) of pixel data will light green LEDs in Group 1.
0x450xA2Set row counter to 0 in Group 0. Set red flag.Next byte(s) of pixel data will light red LEDs in Group 0.
0xC50xA3Set row counter to 0 in Group 1. Set red flag.Next byte(s) of pixel data will light red LEDs in Group 1.
...
0x030xC0Set no rows to yellow.Clear the display.
0x830xC1Set row 0 to yellow.
0x430xC2Set row 1 to yellow.
0xC30xC3Set rows 0 and 1 to yellow.
0x230xC4Set row 2 to yellow.
0xA30xC5Set rows 0 and 2 to yellow.
0x630xC6Set rows 1 and 2 to yellow.
...
See the binary count pattern forming?
...
0x3B0xDCSet all rows, except 0 and 1, to yellow.
0xBB0xDDSet all rows, except 1, to yellow.
0x7B0xDESet all rows, except 0, to yellow.
0xFB0xDFSet all rows to yellowSend this one byte command for a lamp-test function.
...
0x070xE0Set maximum brightness for entire display.
0x870xE1Reduce brightness one step from maximum brightness for entire display.
0x470xE2Reduce brightness two steps from maximum brightness for entire display.
...
See the pattern forming?
...
0xE70xE7Reduce brightness six steps from maximum brightness for entire display.Minimum illumination level.
0x130xE8Set 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.

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.

Code

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.

CDM102 Demo pattern

   
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* 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);
   
  

Closing

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!