c++arduinoprogmem

Trouble with Char arrays, how to properly construct and display them


For a product I am co-designing I want to display bitmap icons on an LCD screen. Inspired by among others this tutorial I created a separate C-file with the byte array of the icon I am trying to display.

When I try to display the icon directly it seems to work. But when I try to do it indirectly - which is going to be nessecary eventually - it fails.

What really baffles me and what I seek to understand is; when I print out the array of the garbage icon (CHAR ARRAY) to the serial monitor and compare it to the byte array it is suppose to represent they match correctly. But when I do the same for the image that is displayed correctly (ICON ARRAY), what I print to the serial monitor does not match the byte array it is displaying, the information I printed is not even consistent... How can this be ?!

I have been cracking my head over this for a week now so any help would be greatly appreciated.

The main file:

// --------------------------------------------------------------------------------------
// |   This program is made for an arduino mega 2560 used in conjunction with the       |
// |           (chinese) OPEN-SMART 3.2 inch TFT LCD Shield ILI9327                     |
// | This version of the program is a slimmed down one to clearly convey the problem    |
// |           I am currenlty having drawing pictures on this setup                     |
// --------------------------------------------------------------------------------------
// This program is based on the library obtained from
// https://drive.google.com/open?id=0B6uNNXJ2z4CxYktCQlViUkI1Sms
// There is also a demo available on YouTube
// https://www.youtube.com/watch?v=JQHGYnKeC0M&t=2s

#include <Adafruit_GFX.h>    // Core graphics library
#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;

// -------------------------------------------------------------------------------------
// |                            Variable declaration                                   |
// -------------------------------------------------------------------------------------

// Set colors
#define BLACK            0x0000
#define BACKGROUND       0x07FF

// No idea with this does tbh
uint16_t g_identifier;

// Spacing variables
uint8_t   cube_size = 75;
uint8_t   padding = 3;
uint8_t     ix1 = 5+2 * padding;
uint8_t     ix2 = 5+3 * padding + cube_size;
uint8_t     ix3 = 5+4 * padding + 2 * cube_size;
uint8_t     ix4 = 5+5 * padding + 3 * cube_size;
uint16_t    ix5 = 5+(6 * padding) + 4 * cube_size;
uint8_t     iy1 = 5+1 * padding;
uint8_t     iy2 = 5+3 * padding + cube_size;
uint8_t     iy3 = 5+4 * padding + 2 * cube_size;

//Progmem Icon init
extern uint8_t icon_from_progmem[];

// -------------------------------------------------------------------------------------
// |                                  Functions                                        |
// -------------------------------------------------------------------------------------
// Standard drawbitmap function

void drawBitmap(int16_t x, int16_t y,  const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color) {

  int16_t byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte
  uint8_t byte = 0;
  for (int16_t j = 0; j < h; j++, y++) {
    for (int16_t i = 0; i < w; i++) {
      if (i & 7) byte <<= 1;
      else      byte   = pgm_read_byte(&bitmap[j * byteWidth + i / 8]);
      if (byte & 0x80) tft.drawPixel(x + i, y, color);
    }
  }
}

// -------------------------------------------------------------------------------------
// |                                   Setup                                           |
// -------------------------------------------------------------------------------------
// I just copied this part to get the screen to work

void setup(void) {
  Serial.begin(9600);
  Serial.println(F("TFT LCD test"));

  //    tft.reset();                 //we can't read ID on 9341 until begin()
  g_identifier = tft.readID(); //
  Serial.print("ID = 0x");
  Serial.println(g_identifier, HEX);
  if (g_identifier == 0x00D3 || g_identifier == 0xD3D3) g_identifier = 0x9481; // write-only shield
  if (g_identifier == 0xFFFF) g_identifier = 0x9341; // serial
  //    g_identifier = 0x9329;                             // force ID


  tft.begin(g_identifier); //to enable ILI9327 driver code
  tft.setRotation(3);      //Change orientation (landscape and portrait)

}

// -----------------------------------------------------------------------------------
// |                                 Loop                                            |
// -----------------------------------------------------------------------------------

void loop(void) {
  tft.fillScreen(BACKGROUND); //

  unsigned char myCharArray[512];
  byte myChar;

  for (int k = 0; k < 512; k++) {

    // Create myCharArray from icon_from_progmem
    myChar = pgm_read_byte(icon_from_progmem + k);
    myCharArray[k] = char(myChar);

    // Print data from myCharArry to the serial monitor
    Serial.print("CHAR ARRAY: ");
    Serial.print(k);
    Serial.print("     ");
    Serial.println(myChar);
  }

  // Visual separtion string
  Serial.println("------------------------------------------------------------------");

  // Print data from icon_from_progmem to serial monitor
  for (int k=0; k<512; k++){
    Serial.print("ICONS ARRAY: ");
    Serial.print(k);
    Serial.print("     ");
    Serial.println(icon_from_progmem[k]);    
  }

  // Draw the two icons on the screen
  drawBitmap(ix2, iy1, myCharArray,       64, 64, BLACK);
  drawBitmap(ix4, iy1, icon_from_progmem, 64, 64, BLACK);

  delay(600000);

} // end of void loop

The separate file for the bitmap:

#include <avr/pgmspace.h>

// 'PlafLamp', 64x64px
const unsigned char icon_from_progmem [] PROGMEM = {
    0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xc0, 0x00, 0x00, 
    0x00, 0x00, 0x0f, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xf8, 0x00, 0x00, 
    0x00, 0x00, 0x7f, 0xc0, 0x03, 0xfe, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x7f, 0x00, 0x00, 
    0x00, 0x01, 0xfc, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x0f, 0xc0, 0x00, 
    0x00, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x03, 0xf0, 0x00, 
    0x00, 0x0f, 0x80, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 
    0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 
    0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 
    0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 
    0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 
    0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 
    0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 
    0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 
    0x00, 0x00, 0x07, 0xc0, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x03, 0xc0, 0x00, 0x00, 
    0x00, 0x00, 0x03, 0xe0, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x1f, 0x80, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x3f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xf8, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x1c, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x7c, 0x00, 0x00, 
    0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x01, 0x80, 0x3f, 0x00, 0x00, 
    0x00, 0x01, 0xf8, 0x03, 0xc0, 0x1f, 0x80, 0x00, 0x00, 0x03, 0xf0, 0x03, 0xc0, 0x0f, 0xc0, 0x00, 
    0x00, 0x07, 0xe0, 0x03, 0xc0, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xc0, 0x03, 0xc0, 0x03, 0xe0, 0x00, 
    0x00, 0x07, 0x80, 0x03, 0xc0, 0x01, 0xe0, 0x00, 0x00, 0x03, 0x00, 0x03, 0xc0, 0x00, 0xc0, 0x00, 
    0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00
};

What is displayed on the screen

The image on the left is the CHAR ARRAY and the image on the right is the ICON ARRAY.


Solution

  • in drawBitmap() you are iterating through bytes via pgm_read_byte()

    In the avr-libc docs it says

    Read a byte from the program space with a 16-bit (near) address. Note: The address is a byte address. The address is in the program space.

    Your array that is a copy of the bitmap, "myCharArray", is not in program space so pgm_read_byte() does not operate correctly.