0

Ok here it goes, my first ever question posted to stackexchange! Please be gentle on me!

I am using an Arduino UNO (at the moment, will move to a faster micro later - but still use an Arduino sketch) to read in data as an SPI slave to extract the display data off of a commercial product that has no other exploitable data output that I can use. I am using a very generic sketch that Nick Gammon posted for the purpose of demonstrating the capability - and I can read the SPI data coming in ok. (Thanks Nick!)

The data is being pulled from a commercial product that has a 8 character, 5X7 dot matrix LED display that was specially made for this product and after exhaustive searches and emails to Broadcom/Avago - has no datasheet, but there are slightly similar products that I was able to use to get a bit of a handle on how the part works, I just went on the assumption that even if the interfaces are not the same, they probably didn't reinvent their command structure. However; the display doesn't have a nice driver chip embedded like your typical parallel LCD display.

I had to do a bit of reverse engineering using a logic analyzer to figure out:

  1. It is SPI data at 4MHz.
  2. The gist of the commands coming in and in what order
  3. Used excel to convert the pixel mapping of the display to the font actually getting displayed on the device.
  4. That the displayed font/text for each of the 8 characters is made up of 5 bytes - where the bit positions of those bites end up lighting a tiny LED in the display so the letter 'H' looks like 0x7F, 0x08, 0x08, 0x08, 0x7F. Each byte controls a column of 7 LEDs, ignoring a row.

Right now:

  • I am using a modified version of Nick's slave sketch to simply extract the first 44 bytes of the command string to display something on the display
  • all that is important to me is the 40 bytes after the first 4
  • because those bytes are what get displayed. I am taking 5 elements of the 44 byte array that I know correspond to a character and spitting them out on the serial monitor such as:
    0x00, 0x01, 0x5F, 0x11, 0x00 // i
    0x7F, 0x08, 0x08, 0x08, 0x7F // H
    etc...
    

And now after a lengthy introduction - my actual question:

I need to parse the patterns of each of the 5 bytes that makes up a letter and convert it to ASCII text so that the actual word is displayed on the serial monitor.

Back when I used to use another programming language / environment on PICs we had things like LOOKUP and LOOKDOWN which made comparing patterns a bit more abstracted, which is weird considering Arduinos...

I need help coming up with a function that takes the 5 bytes that I need to build each letter from and maybe compares it to an array that represents each possible letter and then maybe passes the matching result to another function to build / concatenate the displayed word out of those characters? That method sounds wildly inefficient, but it's all my little brain can come up with and I'm drawing a blank on how to even do that... I don't need a lot of error checking because thus far the data I'm getting is spot on with what I see on the actual display - we are also talking one 8 character word (max) at a time and it is fairly static, no scrolling words or a lot of chatter - just a single word or some data that changes relatively infrequently. But the displayed data can be different enough than the last to make trying to match entire words out of the question unless it's a side feature to speed things up. I think work properly it needs to work on one character out of 8 - one at a time. Another thought is maybe summing the 5 bytes to determine if we have a match or not, but I'm not sure if two different characters might end up having the same sum? Math is not my strong suit. Thanks for any and all help.

8
  • i see no reason for such a lengthy post ... it appears that you want to decode the data going to a 5x7 dot matrix display and determine which character is being displayed ... the data arrives on SPI .... am I understanding it correctly? – jsotola Aug 21 '20 at 3:38
  • How many different characters are likely to be displayed? 10? Can't you just use a lookup table? – Nick Gammon Aug 21 '20 at 6:39
  • So it is a 5x7 LED (so 35 different LEDs per character) and thus the 5 characters (at 8 bits each) would allow for 40 combinations, and so 5 are unused. Is this right so far? A lookup table of all the actual characters that arrive is probably the easiest, you could store that in PROGMEM. – Nick Gammon Aug 21 '20 at 6:42
  • Comparing all the bytes for every character may sound inefficient, but the MCU is pretty fast. So unless you have something else that requires a lot of computation, this will be plenty fast enough. Though you could indeed try to do some tricks, like adding the bytes (as you suggested), or XOR the five bytes. I like to use excel for these things. Put the 5 bytes in five columns. Put your formula in the last column. Then check if all calculated values are unique. You could also try using only certain pixel-columns. – Gerben Aug 21 '20 at 9:05
  • If you post the pixel data for all the characters, I'm willing to do this for you, as it sounds like a fun exercise. Though as I stated, it's probably unnecessary. – Gerben Aug 21 '20 at 9:07
2

This is really a pure programming problem rather than an Arduino one, but to get you started, you could do a table lookup, like this:

#include <stdio.h>
#include <string.h>

// number of items in an array
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
    
unsigned char patterns [] [5] =
  {

    { 0x7F, 0x08, 0x08, 0x08, 0x7F },   // H

    // other byte patterns here

  };  // end of patterns

char patterns_converted [] =
  {

  'H',

  // other letter equivalents here

  };  // end of patterns_converted


char convert_pattern (unsigned char what [5])
  {
  for (int i = 0; i < ARRAY_SIZE (patterns_converted); i++)
    if (memcmp (what, patterns [i], 5) == 0)
      return patterns_converted [i];

  return '?';

  } // end of convert_pattern


int main ()
{

  unsigned char test1 [5] = { 0x7F, 0x08, 0x08, 0x08, 0x7F };
  unsigned char test2 [5] = { 0xAA, 0xBB, 0xCC, 0xDD, 0xEE };  // won't be found

  char x = convert_pattern (test1);

  printf ("Result for test1 is %c\n", x);

  x = convert_pattern (test2);

  printf ("Result for test2 is %c\n", x);

}

You would find out all your bit patterns and put them in the patterns array, and then put the equivalent letter in the patterns_converted array.

The function convert_pattern does a linear search of the table of patterns, returning the corresponding letter, or "?" if not found.

I coded that in pure C++, but since the Arduino IDE basically uses C++ you should be able to convert it for your use.

1
  • Thank you-Thank you! Nick Gammon saves the day yet again! I was able to convert your pure C++ to Arduino-C++ and build my lookup table and test cases and it works beautifully! Now I just have to add a little code to compare the last displayed data to new to keep it from needlessly updating. Sorry for all the words - I do have trouble with being concise. – Ryan Aug 22 '20 at 22:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.