Weird problem...

I have a weird problem that I’m hoping someone can help me to troubleshoot. This is on an ATMega 2560 being compiled on MacOS X Mountain Lion.

I’m working on interfacing with an 80x7 lightboard. I’ve written the interface code, and I can control any pixel and color. Now I’m writing the code to actually display characters.

Here is the relevant code (this is just an example, it won’t compile):

PROGMEM struct character_t {
  byte col1;
  byte col2;
  byte col3;
  byte col4;
  byte col5;
} font[] = {
  { B00000000, B00000000, B01011111, B00000000, B00000000},
  { B00000000, B00000011, B00000000, B00000011, B00000000},
  { B00010100, B00111110, B00010100, B00111110, B00010100},
  NULL
};

void printChar(unsigned char c, byte offset) {
  byte array_offset = 0;
  byte i;
  
  Serial.println(c);
 
  array_offset = c - 33;
  
  Serial.println(array_offset);
  
  for (i = 0; i < 7; i++) {
    
    if ((font[array_offset].col1 >> i & B00000001) == 1) {
      setPixel(offset, i, 2, 0);
    } else {
      setPixel(offset, i, 0, 0);
    }

    if ((font[array_offset].col2 >> i & B00000001) == 1) {
      setPixel(offset + 1, i, 2, 0);
    } else {
      setPixel(offset + 1, i, 0, 0);
    }

    if ((font[array_offset].col3 >> i & B00000001) == 1) {
      setPixel(offset + 2, i, 2, 0);
    } else {
      setPixel(offset + 2, i, 0, 0);
    }

    if ((font[array_offset].col4 >> i & B00000001) == 1) {
      setPixel(offset + 3, i, 2, 0);
    } else {
      setPixel(offset + 3, i, 0, 0);
    }
    
    if ((font[array_offset].col5 >> i & B00000001) == 1) {
      setPixel(offset + 4, i, 2, 0);
    } else {
      setPixel(offset + 4, i, 0, 0);
    }
  }
}   
  
void loop() {

  printChar('!', 0);
  
  delay(1000);
  
}

The first bit of code defines character structures - I’ve got three (a !, ", and #). The second bit of code is supposed to print one character to the board at x offset offset. The third function is obvious and calls the print routine.

The issue is this: passing the character into the function as ‘c’ just doesn’t work. If I set array_offset to 0 in the code, it works (prints a ! at offset 0). If I reset c (c = 33) in the printChar function it works properly. If I do neither I get random pixels being activated. I’ve debugged the code to the point where I know that array_offset is the correct value in all cases, and c is the correct value in all cases. So I simply don’t understand why the code will not work if I pass in the character as the argument.

Has anyone else seen anything like this?

I probably have your ‘setPixel’ parameters wrong but something a lot less complicated -

#define ELEMENT_COUNT(ARRAY)        (sizeof(ARRAY) / sizeof(ARRAY[0]))

PROGMEM struct glyph_t
{
    uint8_t     _v[5];
};

glyph_t glyphs[] =
{
    { 0b00000000, 0b00000000, 0b01011111, 0b00000000, 0b00000000 }  // !
  , { 0b00000000, 0b00000011, 0b00000000, 0b00000011, 0b00000000 }  // "
  , { 0b00010100, 0b00111110, 0b00010100, 0b00111110, 0b00010100 }  // #
};

void printChar(unsigned char c, byte offset)
{
    int     iGlyph = c - '!';

    for ( int mask = 1, i = 7; i--; mask <<= 1 )
    {
        for ( int row = ELEMENT_COUNT(glyphs[iGlyph]._v); row--; )
        {
            setPixel(offset, row, ((glyphs[iGlyph]._v[row] & mask) ? 2 : 0), 0);
        }
    }
}

Probably going to need a call to pgm_read_byte.

PROGMEM struct glyph_t
{
    uint8_t     _v[5];
};

glyph_t glyphs[] = ...

I don't think that works. I vaguely recall PROGMEM has to be attached to the definition (compiler bug)...

glyph_t glyphs[] PROGMEM = ...

MacOS

There's your problem :wink:

I'm not a fan of the memory model and these required declaration modifiers!

Hey everyone, thanks for the help. The problem did indeed turn out to be PROGMEM being in the wrong place.

lloyddean I’ll try that, it does look more efficient. I was going to clean that up after I got it to working, but you saved me the trouble. :slight_smile:

Just to close the loop, the lightboard is now working exactly as intended :slight_smile: Thanks all!

Turns out that I also had a race condition - I was trying to set the clock and data on the shift register in the same operation. That doesn’t work. Data, then clock. Bam.

Picture attached, if you’re interested.