Mystified trying to edit library routine

I am testing a colour LCD (Nokia 6100) using “LCD_Library” originally written by James P. Lynch and modified by Peter Davenport. This is not a class but rather a set of subroutines. I have a sketch which works that I use to draw text and change parameters to see how it looks.

To draw characters, there is a font table declared as “const unsigned char FONT8x16[97][16]” followed by 97 lines of 16 bytes. I want to add another line to draw the symbol for degree. I add one line of 16 bytes at the end and change the declaration to “const unsigned char FONT8x16[98][16]”. (In the LCDPutChar subroutine there is another declaration: “extern const unsigned char FONT8x16[97][16];” where I also change 97 to 98.)

Now my sketch hangs at the first call to LCDPutStr which calls LCDPutChar for each character in the buffer. It hangs even though I am not yet using the extra character.

I can find nothing in LCD_Library that is dependent on the length of the table. In fact, if I put out characters that would be beyond the end of the table, it simply draws strange Martian characters as one would expect.

The relevant portion of the code from LCD_driver.c in the original LCD_Library (down as far as the first part of the font table) is:

//Draws an ASCII character at the specified (x,y) address and color
//c      = character to be displayed
//x      = row address (0 .. 131)
//y      = column address (0 .. 131)
//size   = font pitch (SMALL, MEDIUM, LARGE)
//fcolor = 12-bit foreground color value
//bcolor = 12-bit background color value
//Returns: nothing
// Author: James P Lynch, August 30, 2007
// Edited by Peter Davenport on August 23, 2010
//For more information on how this code does it's thing look at this
void LCDPutChar(char c, int x, int y, int fColor, int bColor) {
	y	=	(COL_HEIGHT - 1) - y; // make display "right" side up
	x	=	(ROW_LENGTH - 2) - x;
extern const unsigned char FONT8x16[97][16];

int             i,j;
unsigned int    nCols;
unsigned int    nRows;
unsigned int    nBytes;
unsigned char   PixelRow;
unsigned char   Mask;
unsigned int    Word0;
unsigned int    Word1;
unsigned char   *pFont;
unsigned char   *pChar;
// get pointer to the beginning of the selected font table
pFont = (unsigned char *)FONT8x16;
// get the nColumns, nRows and nBytes
nCols = *pFont;
nRows = *(pFont + 1);
nBytes = *(pFont + 2);
// get pointer to the last byte of the desired character
pChar = pFont + (nBytes * (c - 0x1F)) + nBytes - 1;
// Row address set (command 0x2B)
LCDData(x + nRows - 1);
// Column address set (command 0x2A)
LCDData(y + nCols - 1);
// loop on each row, working backwards from the bottom to the top
for (i = nRows - 1; i >= 0; i--) {
  // copy pixel row from font table and then decrement row
  PixelRow = *pChar++;
  // loop on each pixel in the row (left to right)
  // Note: we do two pixels each loop
  Mask = 0x80;
  for (j = 0; j < nCols; j += 2) {
    // if pixel bit set, use foreground color; else use the background color
    // now get the pixel color for two successive pixels
    if ((PixelRow & Mask) == 0)
    Word0 = bColor;
    Word0 = fColor;
    Mask = Mask >> 1;
    if ((PixelRow & Mask) == 0)
    Word1 = bColor;
    Word1 = fColor;
    Mask = Mask >> 1;
    // use this information to output three data bytes
    LCDData((Word0 >> 4) & 0xFF);
    LCDData(((Word0 & 0xF) << 4) | ((Word1 >> 8) & 0xF));
    LCDData(Word1 & 0xFF);
// terminate the Write Memory command
// *************************************************************************************************
//Draws a null-terminates character string at the specified (x,y) address and color
// Inputs: pString = pointer to character string to be displayed
// x = row address (0 .. 131)
// y = column address (0 .. 131)
// Size = font pitch (SMALL, MEDIUM, LARGE)
// fColor = 12-bit foreground color value rrrrggggbbbb
// bColor = 12-bit background color value rrrrggggbbbb
// Returns: nothing
// Notes: Here's an example to display "Hello World!" at address (20,20)
// LCDPutChar("Hello World!", 20, 20, WHITE, BLACK);
// Author: James P Lynch, August 30, 2007
// Edited by Peter Davenport on August 23, 2010
//For more information on how this code does it's thing look at this
// *************************************************************************************************
void LCDPutStr(char *pString, int x, int y, int fColor, int bColor) {
  x = x + 16;
  y = y + 8;
  // loop until null-terminator is seen
  while (*pString != 0x00) {
    // draw the character
    LCDPutChar(*pString++, x, y, fColor, bColor);
    // advance the y position
    y = y + 8;
    // bail out if y exceeds 131
    if (y > 131) break;

const unsigned char FONT8x16[97][16] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Space
0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, // !
0x00,0x63,0x63,0x63,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // "

By the way, I am using XCode to edit the library routines since the Arduino IDE doesn’t want to open anything other than .pde files.

I am mystified as to why adding an extra 16 bytes to the table should make the routine go belly up.

Memory of the read/write kind, called SRAM sometimes in connection with the Arduino is a precious resource. Depending on your chip there is not much of it. On the 328 there is 2k (2048) bytes of it.

The core (basic Arduino stuff that calls the loop() handles the timers, does the serial and so on uses a few hundred bytes. The LCD library probably uses a few handfulls.

All your variables use space, and what is worse, every string you specify also resides in RAM (even though it never changes)

Your array 97*16 bytes is 1552 bytes large.

I think you have exceeded the RAM. No, there is no error message from the compiler.

Use the MemoryFree library/call to see what you have left (you first temporarily have to make it smaller). Look for the PROGMEM method for putting your large array in Flash.

It is my understanding that constants are stored in Flash memory. This array is declared with the “const” specifier.

I could only find a reference to writing my own “MemoryFree” routine. I will do that but for the moment, as a test of whether I am running out of SRAM, I added a variable array of size 600 bytes and the sketch still ran with the original LCD_Library.

I added a variable array of size 600 bytes and the sketch still ran with the original LCD_Library.

What did you do with that array? If you didn’t reference it meaningfully, it got optimized away.

How right you are. The sketch now bombs until I reduce the size of the added array to 8 bytes.

I shall begin to investigate the mysteries of ProgMem.

Thanks for the insights.

Do I have to write (copy - I found the code) my own MemoryFree or can it be found somewhere? I tried #include and #include “MemoryFree” but the compiler said no such file.

Copy it; as far as I know it isn’t part ofthe Arduino distribution.