0

I've just configured a segment LCD and driver, everything works fine, but because I decided to not use vias on the PCB, the connections between the two are mixed.

To be more precise, in order to display the number 12, both memory addresses should be accessed.

So right now it's impossible to display a single digit without mapping all the segments.

In static mode, this is how RAM memory is allocated to SEG0-SEG7 and SEG8-SEG15 respectively: backplane mapping

What I've tried was to create two multidimensional arrays and map possible combinations of the two digits, like this:

// 01 to 09
const byte map1[10][2] = {
  {B01110111, B111111 },
  {B01110001, B100111},
  {B01111011, B011111},
  {B01111011, B110111},
  {B01111101, B100111},
  {B01111110, B110111},
  {B01111110, B111111},
  {B01110011, B100111},
  {B01111111, B111111},
  {B01111111, B110111}
};

// 10 to 19
const byte map2[10][2] {
  {B00010111, B111100},
  {B00010001, B100100},
  {B00011011, B011100},
  {B00011011, B110100},
  {B00011101, B100100},
  {B00011110, B110100},
  {B00011110, B111100},
  {B00010011, B100100},
  {B00011111, B111100},
  {B00011111, B110100}
};

If there is no way to mix or map them in a dynamic way so any possible combination between 00 and 99 can be achieved, the only solution is to add vias on the PCB and rewire everything as explained in the datasheet.

Any ideas?

Thanks

closed as off-topic by jsotola, sempaiscuba, VE7JRO, Greenonline, Filip Franik Mar 26 at 12:57

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "This question does not appear to be about Arduino, within the scope defined in the help center." – jsotola, sempaiscuba, VE7JRO, Greenonline, Filip Franik
If this question can be reworded to fit the rules in the help center, please edit the question.

  • 1
    please explain how this post is about an Arduino – jsotola Mar 15 at 16:16
  • 1
    Have a lookup table, to map each segments to a bit in LCDs memory (14 (or 2x7) segments, mapping (probably easiest) a uint16_t for the bit). Then another lookup table for numbers (0-9) to segments. There's multiple ways to do this. I've done this myself, where having an easier layout meant some additional abstraction in my code to fix the weird pinout choice. What I've done sometimes was write some separate code that generated the 0-99 array; copy-paste that into my sketch. This makes the code run really fast, as it's just a lookup. To save RAM I've used PROGMEM, to keep the table in flash. – Gerben Mar 15 at 16:26
0

The trick here is to employ both a local memory buffer, and digit masking.

Step one: create a pair of masks that define which bits of the memory are associated with which digit.

Imagine you have your digits wired in this order in memory. For simplicity I am working with 16-bit values, but there is no reason why you can't split them into two 8 bit values each if you find that easier (P is the decimal point. Lower case is the left digit, upper case the right digit):

      MSB                         LSB
      a C d g E B p A c D f b e G F P

You would then create a pair of corresponding 16-bit values that represent which bits are associated with each digit.

      MSB                         LSB
      a C d g E B p A c D f b e G F P
Left  1 0 1 1 0 0 1 0 1 0 1 1 1 0 0 0 
Right 0 1 0 0 1 1 0 1 0 1 0 0 0 1 1 1 

The right is just the inverse of the left, so for right you can actually use ~left and save yourself 2 bytes.

So that would end up as:

uint16_t leftDigit = 0xB2B8;
uint16_t rightDigit = 0x4D47;

Now you create yourself a table of which segments create which numbers. Now the magic here is that you don't want individual digits. Not yet. What you want is a table of 16-bit values that represent the numbers 00, 11, 22, 33, 44, 55, 66, 77, 88, 99 (and optionally two spaces, but that's just 0x0000, so you may not need to store that explicitly).

You may end up with something like:

uint16_t digits[] = {
    0b1110110111111010, // 00
    0b0100010010010000, // 11
    0b1011110101011100, // 22
    // ... etc ...
};

Now the real magic happens.

You need a memory buffer that mirrors the contents of your driver memory. You don't directly modify the driver memory - you modify your memory buffer, and then send both bytes of it to the display driver at once, updating all the segments together.

uint16_t buffer = 0;

Now to set a digit you first need to erase whatever is in the bits that correspond to the digit you want. Let's say we want to display the number 12. We'll start with the left digit.

// Step one, erase the left digit
buffer &= ~leftDigit;
// Step two, place into it the bits for 1 with the left digit mask imposed:
buffer |= (digits[1] & leftDigit);

// Step three, erase the right digit
buffer &= ~rightDigit;
// Step four, place into it the bits for 1 with the left digit mask imposed: 
buffer |= (digits[2] & leftDigit);

That is actually quite a long winded way. But it does allow you to just change one digit without affecting the other. If you want to just replace the entire content of the display (both digits at once) then you don't need as much work:

buffer = (digits[1] & leftDigit) | (digits[2] & rightDigit);

I'll just dismantle that for you so you can see what it does.

            MSB                         LSB
            a C d g E B p A c D f b e G F P
 digits[1]: 0 1 0 0 0 1 0 0 1 0 0 1 0 0 0 0
 leftDigit: 1 0 1 1 0 0 1 0 1 0 1 1 1 0 0 0
       AND: 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 // b and c enabled

 digits[2]: 1 0 1 1 1 1 0 1 0 1 0 1 1 1 0 0
rightDigit: 0 1 0 0 1 1 0 1 0 1 0 0 0 1 1 1
       AND: 0 0 0 0 1 1 0 1 0 1 0 0 0 1 0 0 // A B D E and G enabled

OR of ANDS: 0 0 0 0 1 1 0 1 1 1 0 1 0 1 0 0 // b c A B D E G enabled

And map those segments on to the standard layout of a 7 segment display:

enter image description here

And you form the number 12.

Then you take the buffer value and write it out to your display memory. You can split the 16 bit value into 8 bit values with bit masking (& 0xFF) and bit shifting (>> 8).

uint8_t b1 = buffer & 0xFF; // Lower byte of memory
uint8_t b2 = (buffer >> 8) & 0xFF; // Upper byte of memory
  • An excellent answer, thank you so much for your time and effort. I'll give it a try today and get back to you with updates. – Meepo Mar 17 at 12:29

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