Decoding an LED display protocol - Page 1
Forum section: electronics / projects

author: ShadesOfSummer
author_rank: Newbie
timestamp: July 16, 2021, 07:29:14 pm
content: For starters, longtime lurker, new member here.I've got an excellent computer background and a decent hardware background mainly with microcontrollers and sbus (arduino and pi). I've done a little bit of work with i2c and spi. I'm faced with an unknown LED display from one of those Oct17 LED clocks (those fake woodgrain clocks on Amazon) and I'm trying to figure out the display protocol. In spite of what I've done in the past, I've never had occasion to work with a logic analyzer until this project. My goal is to swap out the simple controller with an ESP32 using NTP with a better temperature reader and some nifty add-ins like MQTT (for centralized alarms), photoresistor to control dimming throughout the day, and any other cool features I can think of (yup, feature creep!!).But, I need to start with driving this display. I went out and purchased a USB logic analyzer and connected it to a raspi using PulseView. I was pleasantly surprised when bits started showing up!! But, I used some of the built-in decoders (i2c, spi) but I'm having trouble understanding the results. The physical interface is JST PH 4-pin that looks like 1-GND, 2-SIG1, 3-SIG2, 4-VCC. The output is attached. This is a single sample from a pattern that repeats every 500ms. I'm giving two samples in hopes that some bright mind here can guide me towards the next steps -- or even tell me exactly what this protocol is and give references (prettypleasewithsugarontop).I figured I'd reach out to this fine community. Any help for a protocol analysis newbie??

author: ataradov
author_rank: Super Contributor
timestamp: July 16, 2021, 07:48:59 pm
content: You are sampling at 20 kHz. There is no way that protocol is actually that slow, so what you see here is just artifacts.Capture it with the fastest rate you can. And it will likely be I2C.

author: AndyC_772
author_rank: Super Contributor
timestamp: July 16, 2021, 07:49:53 pm
content: First thing I'd do is sample the logic lines faster.If they're a clock/data pair, I'd expect to always see the data line change on one edge and remain stable on the other, but your traces don't have that relationship and that suggests to me there may be something missing.An I2C start condtion is a falling edge on SDA while SCK is high - and that may indeed be how your captures start, but they don't follow I2C protocol from that point onwards.Do you have an oscilloscope? Can you capture one repeat of the signal using that, just to confirm the timing relationship between the two signals and ensure your captured signal does indeed look the same as the scope trace?

author: ShadesOfSummer
author_rank: Newbie
timestamp: July 16, 2021, 08:06:37 pm
content: Thanks for the quick replies!!I totally missed the sample rate. Pls see the attached picture with a 4MHz sample rate. I also added the decoder output for i2c and spi. It's only a 2-wire interface, but by the decoder output it sure looks more like spi?I think I've read that you can do a two-wire spiifit's send-only/receive-onlyandthere is only one device on the bus. Thoughts?

author: ataradov
author_rank: Super Contributor
timestamp: July 16, 2021, 08:19:40 pm
content: Can you show just a few bytes up close. Don't rely on the decoders, decode things by hand first.

author: ShadesOfSummer
author_rank: Newbie
timestamp: July 16, 2021, 10:34:52 pm
content: 2 examples attached. I'm trying to get a basic understanding. I'm still assuming that D2 is the clock and it looks like it's running at about 450kHz?The first file is the last trace zoomed in on a couple of bytes. The second is a new trace with the sample rate increased to 8Mhz.

author: ataradov
author_rank: Super Contributor
timestamp: July 16, 2021, 10:53:47 pm
content: This does not match I2C at all. And for SPI the irregular clock looks very strange.Do you ever see shorter packets? It would be helpful to capture a short isolated transfer.Do you have better pictures of the actual display? Any ICs with markings on it? It may just be some serial shift register.

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: July 16, 2021, 10:57:01 pm
content: Irregular clock could simply mean it's being bit-bashed instead of using a SPI peripheral

author: ShadesOfSummer
author_rank: Newbie
timestamp: July 16, 2021, 11:14:07 pm
content: I think this is what you're asking for. The signal is repeated every 500ms and there is some variation depending on what is on the screen -- it's a clock/thermometer so it changes every minute or more often if the temperature fluctuates. I also opened it up and took some pictures of the display board. No markings I could see on the main chip.Thanks so much, guys!!

author: ataradov
author_rank: Super Contributor
timestamp: July 16, 2021, 11:46:42 pm
content: 500 ms update is obviously to get the blinking dots. So the driver IC does dynamic scanning on its own.According to some reviews, it has brightness adjustment, so it would not be just serial data corresponding to the segments, but I also doubt it is a real protocol with commands. It looks like something much simpler.But see if your model has brightness adjustment, and capture the line while you are adjusting the brightness, see if it gives you shorter transfers. Or capture first transfers after the power is turned on.The next thing I personally would do is transcribe one of the waveforms, and bit bang it from another MCU (Arduino or whatever you have handy). And once you get it to display some static numbers, just play with the bits and see if you can make sense of it.

author: amyk
author_rank: Super Contributor
timestamp: July 17, 2021, 05:15:46 am
content: Which pins on the IC do the two signal pins and Vcc/Gnd go to?The captures look somewhat I2C-ish to me, e.g. Decode04 has a start condition, 8 bits (00000010) followed by stop, then start, 00000011 10111110 11011011 11111111 00000000 ...How many individually addressable segments does the display have?

author: ataradov
author_rank: Super Contributor
timestamp: July 17, 2021, 05:26:07 am
content: It can't be I2C, since the second time it starts, there is a NAK condition, so bytes would not continue, unless something is broken entirely.

author: ShadesOfSummer
author_rank: Newbie
timestamp: July 17, 2021, 09:45:30 am
content: Looks like 4 chars for the "clock" part, 3 chars for the temp part, a colon in the clock, am/pm LEDs, and a degree mark in the temperature.I was looking at ICs that might match the 24pin package in this piece and I ran across the MAX7219/MAX7221 (http://www.farnell.com/datasheets/1825883.pdf) that looks like it could be a candidate. SPI/QSPI, drives enough LEDs (64 max). Protocol decoder seems to find spi-like data there.I'd have to destroy the clock to really see the board -- that might have to be the next step

author: ShadesOfSummer
author_rank: Newbie
timestamp: July 17, 2021, 10:14:09 am
content: Another quick observation. If I completely detach the clk/sig lines while the display is running, it keeps displaying the same output.I'll run ataradov's startup capture and brightness tests this morning. There is a thumbwheel on the back but it controls several things and isn't directly attached to the display in any way. Clearly this is some kind of encoder wheel connected to whatever microcontroller runs this piece.

author: ShadesOfSummer
author_rank: Newbie
timestamp: July 17, 2021, 10:43:53 am
content: Display with brightness at highest: LEDDisplay-Decode08(Brightest)Display with brightness at dimmest but still visible: LEDDisplay-Decode09(Dimmest)Display at minimal brightness (i.e. nothing discernable on the display): Interestingly, I couldn't see anything on the wire for this one?Display startup (zoomed out): LEDDisplay-Decode10(Startup) -- shows nothing followed by what I assume is startup noise followed by the normal patternDisplay startup (zoomed in to first data sent): LEDDisplay-Decode11(Startup) -- other than the clock starting up at 0V, looks very similar to normal pattern

author: ShadesOfSummer
author_rank: Newbie
timestamp: July 17, 2021, 03:13:00 pm
content: Following the suggestions from this fine forum, my next step was to write down an entire sequence and I'm going to try to bit bang it. I think I've identified a few distinct patterns of CLK/DAT transitions. The list below shows the 6 types along with the patterns I think I've identified. The number at the end (in parens) is the approximate time for each pattern.Start: clk hi, dat hi, del 10, dat lo, del 10, clk lo (20)Bit0: dat lo, clk hi, del 10, clk lo, del 10 (20)Bit1: dat hi, clk hi, del 10, clk lo, del 10 (20)Mark: clk hi, del 10, dat hi, del 20, dat lo, del 10, clk lo (40)Space: del 20 (20)Clock: clk hiThe overall pattern is below with S for Start, 0 for Bit0, 1 for Bit1, M for Mark, " " for Space, and C for a high clock transition (used to end the entire sequence):S 00000010 M 00000011 11011010 11111101 00001101 00001101 01110011 10111110 11110110 00000000 00000000 11011010 00001100 11111111 S 00010001 M 00000010 ..............M 00000011 11011010 11111101 00001101 00001101 01110011 10111110 11110110 00000000 00000000 11011010 00001100 11111111 S 00010001 CThe "..." are used just to break the lines -- no action occurs here. Also, I noticed a repetition of the pattern starting with the third Mark. Looks like the actual data sequence is:Start, Byte A, Mark, Byte B, Byte C, Byte D, Byte E, Byte F, Byte G, Byte H, Byte I, Byte J, Byte K, Byte L, Byte M, Byte N, Start, Byte O, Mark, Byte P, Mark, Byte B, Byte C, Byte D, Byte E, Byte F, Byte G, Byte H, Byte I, Byte J, Byte K, Byte L, Byte M, Byte N, Start, Byte Q, Clock with each "byte" separated by a Space.In other words:Start, 1 Byte, Mark, 13 bytes, Mark, 1 Byte, 13 Bytes (repeated from before), Start, 1 byte, Clock hiI'm going to try to bit-bang this on an ESP32. digitalWrite is only .13us (using a bit of code to test digitalWrite 1000 times), so I'm going to round those out of the math.Wish me luck!!!

author: ataradov
author_rank: Super Contributor
timestamp: July 17, 2021, 04:26:23 pm
content: Don't worry about exact timings, the only thing that has any chance of being important is a longer pause between the transfers. There is no reason to emulate those pauses, just emulate the data.

author: ShadesOfSummer
author_rank: Newbie
timestamp: July 17, 2021, 04:30:54 pm
content: Holy Mackerel!!! The bit banging worked.Using the pattern above, I crafted an arduino program and uploaded to the ESP32 and it worked on.the.very.first.try!! (program below). I also changed one of the bytes and watched the display change from 11:02 to 10:02. Now for some trial and error and I should have a workable driver for this display. Thnx for the guidance -- will keep you updated.Code:#define CLK 21#define DAT 22const char sequence[] = "S 00000010 M 00000011 11011010 11111101 00001101 00001101 01110011 10111110 11110110 00000000 00000000 11011010 00001100 11111111 S 00010001 M 00000010 M 00000011 11011010 11111101 00001101 00001101 01110011 10111110 11110110 00000000 00000000 11011010 00001100 11111111 S 00010001 C";void setup() {// put your setup code here, to run once:Serial.begin(115200);pinMode(CLK, OUTPUT);pinMode(DAT, OUTPUT);}void loop() {// put your main code here, to run repeatedly:for (int i = 0; i < strlen(sequence); i++) {char c = sequence;switch(c) {case 'S':digitalWrite(CLK, HIGH);digitalWrite(DAT, HIGH);delayMicroseconds(10);digitalWrite(DAT, LOW);delayMicroseconds(10);digitalWrite(CLK, LOW);break;case ' ':delayMicroseconds(20);break;case '0':digitalWrite(DAT, LOW);digitalWrite(CLK, HIGH);delayMicroseconds(10);digitalWrite(CLK, LOW);delayMicroseconds(10);break;case '1':digitalWrite(DAT, HIGH);digitalWrite(CLK, HIGH);delayMicroseconds(10);digitalWrite(CLK, LOW);delayMicroseconds(10);break;case 'M':digitalWrite(CLK, HIGH);delayMicroseconds(10);digitalWrite(DAT, HIGH);delayMicroseconds(20);digitalWrite(DAT, LOW);delayMicroseconds(10);digitalWrite(CLK, LOW);break;case 'C':digitalWrite(CLK, HIGH);break;}}delay(495);Serial.println("!");}