How to compare a memory bits in C++?

Hi,

I need help with a memory bit comparison function.

I bought a LED Matrix here with 4 x HT1632C chips and I’m using it on my arduino mega2560.

There’re no code available for this chipset(it’s not the same as HT1632) and I’m writing on my own. I have a plot function that get x,y coordinates and a color and that pixel turn on. Only this is working perfectly.

But I need more performance on my display so I tried to make a shadowRam variable that is a “copy” of my device memory. Before I plot anything on display it checks on shadowRam to see if it’s really necessary to change that pixel. When I enabled this(getShadowRam) on plot function my display has some, just SOME(like 3 or 4 on entire display) ghost pixels(pixels that is not supposed to be turned on).

If I just comment the prev_color if’s on my plot function it works perfectly.

Also, I’m cleaning my shadowRam array setting all matrix to zero.

#define BLACK  0
#define GREEN  1
#define RED    2
#define ORANGE 3
#define CHIP_MAX 8
byte shadowRam[63][CHIP_MAX-1] = {0};
byte HT1632C::getShadowRam(byte x, byte y) {
  byte addr, bitval, nChip;

  if (x>=32) {
    nChip = 3 + x/16 + (y>7?2:0);
  } else {
    nChip = 1 + x/16 + (y>7?2:0);
  }

  bitval = 8>>(y&3);

  x = x % 16;
  y = y % 8;
  addr = (x<<1) + (y>>2);

  if ((shadowRam[addr][nChip-1] & bitval) && (shadowRam[addr+32][nChip-1] & bitval)) {
    return ORANGE;
  } else if (shadowRam[addr][nChip-1] & bitval) {
    return GREEN;
  } else if (shadowRam[addr+32][nChip-1] & bitval) {
    return RED;
  } else {
    return BLACK;
  }
}
void HT1632C::plot (int x, int y, int color)
{
 if (x<0 || x>X_MAX || y<0 || y>Y_MAX)
  return;

 if (color != BLACK && color != GREEN && color != RED && color != ORANGE)
     return;

 char addr, bitval;
 byte nChip;

 byte prev_color = HT1632C::getShadowRam(x,y);

 bitval = 8>>(y&3);

 if (x>=32) {
  nChip = 3 + x/16 + (y>7?2:0);
 } else {
  nChip = 1 + x/16 + (y>7?2:0);
 }

 x = x % 16;
 y = y % 8;
 addr = (x<<1) + (y>>2);

 switch(color) {
  case BLACK:
   if (prev_color != BLACK) { // compare with memory to only set if pixel is other color
    // clear the bit in both planes;
    shadowRam[addr][nChip-1] &= ~bitval;
    HT1632C::sendData(nChip, addr, shadowRam[addr][nChip-1]);
    shadowRam[addr+32][nChip-1] &= ~bitval;
    HT1632C::sendData(nChip, addr+32, shadowRam[addr+32][nChip-1]);
   }
   break;
     case GREEN:
      if (prev_color != GREEN) { // compare with memory to only set if pixel is other color
       // set the bit in the green plane and clear the bit in the red plane;
       shadowRam[addr][nChip-1] |= bitval;
       HT1632C::sendData(nChip, addr, shadowRam[addr][nChip-1]);
       shadowRam[addr+32][nChip-1] &= ~bitval;
       HT1632C::sendData(nChip, addr+32, shadowRam[addr+32][nChip-1]);
      }
      break;
     case RED:
      if (prev_color != RED) { // compare with memory to only set if pixel is other color
    // clear the bit in green plane and set the bit in the red plane;
    shadowRam[addr][nChip-1] &= ~bitval;
    HT1632C::sendData(nChip, addr, shadowRam[addr][nChip-1]);
    shadowRam[addr+32][nChip-1] |= bitval;
    HT1632C::sendData(nChip, addr+32, shadowRam[addr+32][nChip-1]);
     }
     break;
     case ORANGE:
     if (prev_color != ORANGE) { // compare with memory to only set if pixel is other color
    // set the bit in both the green and red planes;
    shadowRam[addr][nChip-1] |= bitval;
    HT1632C::sendData(nChip, addr, shadowRam[addr][nChip-1]);
    shadowRam[addr+32][nChip-1] |= bitval;
    HT1632C::sendData(nChip, addr+32, shadowRam[addr+32][nChip-1]);
     }
     break;
 }
}

If anyone can help me, you can answer here if you wish!

Thanks,

Wagner sartori Junior

I think you may be having problems due to your initialisation.

byte shadowRam[63][CHIP_MAX-1] = {0};

I do not think this piece of code does what you want it to do. First off, if shadowRam is defined globally, it should be automatically zeroed anyway due to POSIX standards. If it’s not, I don’t think it’s zeroed at all.

Try to set it manually to zero to be sure of the correct initial values. So, just zero it one by one in a double for loop.

If this does not work, I’d advise you to recheck your code on a PC with a regular C++ compiler. A type-safe, neat C++ way to build your program up from would be something like this:

#include <iostream>

enum Colour { BLACK = 4, GREEN, RED, ORANGE };
const size_t CHIP_MAX = 8;

Colour shadowRam[64][CHIP_MAX];

bool hasColour(size_t x, size_t y, Colour col) {
      return shadowRam[x][y] == col;
}
void setColour(size_t x, size_t y, Colour col) {
      shadowRam[x][y] = col;
}

int main() {

      // Setting memory explicitly
      for (size_t x = 0; x < 64; ++x)
            for (size_t y = 0; y < CHIP_MAX; ++y)
                  shadowRam[x][y] = BLACK;

      std::cout << "Is pixel (2,3) GREEN?: " << hasColour(2, 3, GREEN) << '\n';
      std::cout << "Is pixel (34,6) BLACK?: " << hasColour(34, 6, BLACK) << '\n';
      
      setColour(2, 3, GREEN);
      std::cout << "Is pixel (2,3) GREEN?: " << hasColour(2, 3, GREEN) << '\n';
}

(I’ve made the value of BLACK ‘4’ here because shadowRam is zeroed in global memory and we want to see the difference in the example.)

POSIX is a standard that describes operating system features and its API. It does not specify any part of the C/C++ core language. Since there is no OS, no one will zero your memory for you and you get whatever was in memory last (often total garbage).

I think there may be some compilers that zero memory for you but I know gcc will not since it is not in the specification, can impact performance and code size, and the programmer doesn’t always need it.

As a side note, all modern OSs zero memory before turning it over to programs as a security feature–but it’s very bad form to rely on this.

Globals and statics are initialised to zero before 'main' is called unless explicitly initialised to some other value.

POSIX is a standard that describes operating system features and its API. It does not specify any part of the C/C++ core language.

Oh, I'm sorry, I should not have said "POSIX", but "ANSI/ISO". My mistake; I understand the confusion. It does not change my message though, the rest of your statements are (as Groove already posted) untrue.

You can count on any C++ compiler to initialise global or static variables, because otherwise it would not be a C++ compiler.

Globals and statics are initialised to zero before 'main' is called unless explicitly initialised to some other value.

whoops! Your right that IS in the ANSI C spec. I'm sorry. I confused it with dynamic memory. :-[

I have a clear method that sets byte per byte to zero. The garbage content is not a problem.

The full content of HT1632C class is here:
https://bitbucket.org/trunet/trunetclock/src/479993f27306/HT1632C/HT1632C.cpp

Note: I comment the check pixel method from the plot function.

Thanks,

Wagner Sartori Junior