Saturday, May 16, 2009

Scrolling issue

Mr. BroHogan, of Life Clock and X10 book fame, pointed to a bug in Wide Clock's scrolling. Not exactly sure what, but it looked weird. Took me some time to notice that the left-most character disappears all of a sudden, instead of being scrolled out to the left.
After a long investigation, I found the culprit, a one-liner, in this function:
void setScreenMem(byte sprite1[8], byte sprite2[8], byte sprite3[8], byte sprite4[8])
{
  unsigned long row[16] = {0};
  
  // for each row;
  for (byte i = 0; i < 8; i++)
  {
      byte c1 = sprite1[i] >> 1;
      byte c2 = sprite2[i] >> 1;
      byte c3 = sprite3[i] >> 1;
      byte c4 = sprite4[i] >> 1;
      row[i] = ((((((unsigned long) c1<<5)+c2)<<5)+c3)<<5)+c4;
  }
  
  // scroll 5 times to the left (5 being the max width of a char, as defined);
  for (byte x = 1; x <= 5; x++)
  {
    // for each row;
    for (byte i = 0; i < 8; i++)
    {
      screenMem[i] = row[i] >> (5-x);
    }
    delay(wait);
  }
}
The cast to unsigned long (4 bytes) was missing. Since the default type was int (2 bytes), some of the most significant bits were lost after shifting.
This piece of code

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  shiftLong(31, 0, 17, 12);
  shiftLong(30, 0, 17, 12);
  delay(3000);
}

void shiftLong(byte c1, byte c2, byte c3, byte c4)
{
      unsigned long row = (((((c1<<5)+c2)<<5)+c3)<<5)+c4;
      Serial.print(c1, DEC);
      Serial.print(", ");
      Serial.print(c2, DEC);
      Serial.print(", ");
      Serial.print(c3, DEC);
      Serial.print(", ");
      Serial.print(c4, DEC);
      Serial.print(", ");
      Serial.println(row, BIN);
}
should lead to better understanding. It displays this result (in Arduino IDE 11 and 14, compiled for Diecimila):
31, 0, 17, 12, 11111111111111111000001000101100
30, 0, 17, 12, 1000101100
More to come on the topic of scrolling characters.

No comments:

Post a Comment