Accessing value from large lookup table (using PROGMEM). Strange random numbers

I'm trying to create program to look up data from large array. Using the Arduino Uno

Thing is it returns the wrong data from font_bit if i use my font_bits(Lookup(char)), despite Lookup(char) returning the correct value. If I give an exact an exact position at design time, the lookup from font_bits works:. Below is a snippet inside the void loop():

                Serial.println(Lookup('K'));
                
                unsigned int x = Lookup('K');
                unsigned  int y = 1892;
                Serial.println(x);
                
                if (x == y)
                  Serial.println("well done");
                
                Serial.println(font_bits[x]);
                Serial.println(font_bits[y]);

on serial port monitor said :

1892 1892 well done 40 0

The 40 is incorrect - it should be 0. Sometimes after slight additions/modifications of my code, 40 changes to another random number. Why? Is the lookup table not being stored in the code memory properly?

my look up function returns a position (unsigned int) which is a location in the array font_bits:

unsigned int Lookup(char input)
{
    unsigned int position;
    switch (input)
    {
      case ' ':
        position =  0;
        break;
      case 'A':
        position = 1452;
        break;
      case 'a':
        position = 2860;
        break;
      case 'B':
         position =  1496;
         break;
...
      case 'K:
         position =  1892;
         break;
...
return position;
}

Finally,

font_bits is declared like:

PROGMEM const prog_uint8_t font_bits[4136]

I'm stumped.

Thanks Kiwi

Why are you comparing and int and an unsigned int? Consistency is a good thing. So is posting ALL of your code.

my look up function returns a position (int) from the array front_bits:

No, it doesn't. It returns a value that you might use as an index into that array. The value that it returns does not come FROM the array.

Modified it.

The lookup table is pretty big, so is the lookup function. I don't think it would help to post any more than the snippets above

PROGMEM const prog_uint8_t font_bits[4136]   = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,                         // Char 001 ( )
   0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
   0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,                         // Char 002 (!)

.... alot more

Been debugging:

When I took just a small part of the look up table and put it into SRAM instead (removed the PROGMEM). It now works fine, so the problem is that it isn't being stored correctly in the code memory. I have to stored it in the code memory as I don't have enough SRAM on the Uno to store the whole lookup table. Please assist .

Thanks Kiwi

----(O) ( '--., ,___/ | \ ^ ^

Please assist .

Sure. "Post ALL of your code" means something different from "Post random snippets that may or may not be relevant".

#include <inttypes.h>
#include <ctype.h>
#include <avr/pgmspace.h>

//Font table with lookup function
#include "C:\Users\watanya\Documents\Arduino\Paper_Text\font_table.h"

//If we comment the include above and uncomment the below, we can successfully read the ! 
//   const prog_uint8_t font_bits[88]   = {
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,							// Char 001 ( )
//   0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
//   0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x00, 0x00,
//   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // Char 002 (!)




// images
PROGMEM const
#define unsigned
#define char uint8_t
#undef char
#undef unsigned

PROGMEM const
#define unsigned
#define char uint8_t
#include PICTURE
#undef char
#undef unsigned



// Arduino IO layout
const int Pin_PANEL_ON = 2;
const int Pin_BORDER = 3;
const int Pin_DISCHARGE = 4;
const int Pin_PWM = 5;
const int Pin_RESET = 6;
const int Pin_BUSY = 7;
const int Pin_EPD_CS = 8;
const int Pin_RED_LED = 13;


// LED anode through resistor to I/O pin
// LED cathode to Ground
#define LED_ON  HIGH
#define LED_OFF LOW


// pre-processor convert to string
#define MAKE_STRING1(X) #X
#define MAKE_STRING(X) MAKE_STRING1(X)



// I/O setup
void setup() {
  pinMode(Pin_RED_LED, OUTPUT);
  pinMode(Pin_PWM, OUTPUT);
  pinMode(Pin_BUSY, INPUT);
  pinMode(Pin_RESET, OUTPUT);
  pinMode(Pin_PANEL_ON, OUTPUT);
  pinMode(Pin_DISCHARGE, OUTPUT);
  pinMode(Pin_BORDER, OUTPUT);
  pinMode(Pin_EPD_CS, OUTPUT);

  digitalWrite(Pin_RED_LED, LOW);
  digitalWrite(Pin_PWM, LOW);
  digitalWrite(Pin_RESET, LOW);
  digitalWrite(Pin_PANEL_ON, LOW);
  digitalWrite(Pin_DISCHARGE, LOW);
  digitalWrite(Pin_BORDER, LOW);
  digitalWrite(Pin_EPD_CS, LOW);

  SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE0);
  SPI.setClockDivider(SPI_CLOCK_DIV4);

  Serial.begin(9600);
#if !defined(__MSP430_CPU__)
  // wait for USB CDC serial port to connect.  Arduino Leonardo only
  while (!Serial) {
  }
#endif

}


static int state = 0;


// main loop
void loop() {         
  

  //Split string into array of char[16] 
  
  	String inputText = "1234567890123456";
	//char inputText[16];
        //inputText[0] = 66;
        for(int row = 0; row<22; row++)
  	{
		
		uint8_t letter = 0;									//restart at first charector everytime when start new new row
		
		//accumulate line
		prog_uint8_t lineBuffer[33];                        

		for(int col = 0; col<32; col = col + 2)
		{	


//                        Serial.println(row);
//                        Serial.println(font_bits[(row)]);
//                        Serial.println(font_bits[(int) 2]);
			lineBuffer[letter] = font_bits[ Lookup('!') + (row*2) ];
                        ////Serial.println(font_bits[44+ (row*2)]);
                        letter++;
                        lineBuffer[letter] = font_bits[ Lookup('!') + (row*2) + 1];

                        
                        //Serial.println(lineBuffer[letter]);
			//Serial.println(lineBuffer[letter+1]);
			letter++;									// move to next charector [position]

		}

                lineBuffer[32] = 0xff;

                //Now push a line
	
    }
    delay (5000);
 
}
//font_table.h
 PROGMEM const prog_uint8_t font_bits[]  = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,							// Char 001 ( )
   0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
   0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 		 					// Char 002 (!)
   0x00, 0x00, 0x38, 0x07, 0x38, 0x07, 0x38, 0x07, 0x38, 0x07, 0x10, 0x02,
   0x10, 0x02, 0x10, 0x02, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,							// Char 003 (")
   0x80, 0x08, 0x80, 0x08, 0x80, 0x08, 0x40, 0x04, 0x40, 0x04, 0x40, 0x04,
   0xf8, 0x3f, 0x40, 0x04, 0x40, 0x04, 0x40, 0x04, 0x40, 0x04, 0xf8, 0x3f,
   0x40, 0x04, 0x40, 0x04, 0x40, 0x04, 0x20, 0x02, 0x20, 0x02, 0x20, 0x02,
   0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,							// Char 004 (#)
   0x80, 0x00, 0xe0, 0x01, 0x10, 0x0e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00,
   0x08, 0x00, 0x70, 0x00, 0x80, 0x07, 0x00, 0x08, 0x00, 0x10, 0x00, 0x10,
   0x04, 0x10, 0x04, 0x08, 0x1c, 0x0c, 0xf4, 0x03, 0x80, 0x00, 0x80, 0x00,
..... lots more
};  


prog_uint16_t Lookup(char input)
{
	prog_uint16_t  position;
	switch (input)
    {
      case ' ':
        position =  0;
		break;
      case 'A':
		position = 1452;
		break;
      case 'a':
		position = 2860;
		break;
      case 'B':
		 position =  1496;
		 break;
      case 'b':
		position = 2904 ;
		break;	
      case 'C':
		position =  1540;
		break;
      case 'c':
        position = 2948;
		break;
      case 'D':
		position =  1584; 
		break;
      case 'd':
		position = 2992;
		break;
      case 'E':
		position = 1628;
		break;
      case 'e':
		position = 3036;
		break;
      case 'F':
		position = 1672;
		break;
      case 'f':
		 position = 3080 ;
		break;
      case 'G':
		position = 1716;
		break;
      case 'g':
        position = 3124 ;
		break;
      case 'H':
		position = 1760 ;
		break;
      case 'h':
		position = 3168 ;
		break;
      case 'I':
		position = 1804 ;
		break;
      case 'i':
		position = 3212 ;
		break;
      case 'J':
		position =1848 ;
		break;
      case 'j':
		position = 3256;
		break;
      case 'K':
		position = 1892;
		break;
      case 'k':
       position = 3300;
		break;
      case 'L':
	   position = 1936 ;
		break;
      case 'l':
		position = 3344 ;
		break;         
      case 'M':
		position = 1980;
		break;
      case 'm':
        position = 3388 ;
		break;
      case 'N':
		position = 2024;
		break;
      case 'n':
		position = 3432;
		break;
      case 'O':
		position = 2068;
		break;
      case 'o':
        position = 3476;
		break;
      case 'P':
		position = 2112;
		break;
      case 'p':
        position = 3520;
		break;
      case 'Q':
		position = 2156;
		break;
      case 'q':
        position = 3564;
		break;
      case 'R':
		position = 2200;
		break;
      case 'r':
        position = 3608;
		break;
      case 'S':
		position = 2244;
		break;
      case 's':
        position = 3652;
		break;
      case 'T':
		position = 2288;
		break;
      case 't':
		position = 3696;
		break;
      case 'U':
		position = 2332;
		break;
      case 'u':
        position = 3740;
		break;
      case 'V':
		position = 2376;
		break;
      case 'v':
        position = 3784;
		break;
      case 'W':
		position = 2420;
		break;
      case 'w':
		position = 3828;
		break;
      case 'X':
		position = 2404;
		break;
      case 'x':
       position = 3872;
		break;
      case 'Y':
		position = 2508;
		break;
      case 'y':
        position = 3916;
		break;
      case 'Z':
		position = 2552;
		break;
      case 'z':
        position = 3960;
		break;
      case '0':
		position = 704;
		break;
      case '1':
		position = 748;
		break;
      case '2':
		position = 792;
		break;
      case '3':
    	position = 836;
		break;  
      case '4':
    	position = 880;
		break;
      case '5':
     	position = 924;
		break;
      case '6':
    	position = 968;
		break;
      case '7':
   		position = 1012;
		break;
      case '8':
  		position = 1056;
		break;
      case '9':
    	position = 1100;
		break;
      case '!':
    	position = 44;
		break;
      case '"':
    	position = 88;
		break;
	  case '#':
    	position = 132;
		break;
      case '

Let me know if you need more. The problem seems to lie with trying to put the table into the program memory, rather than the SRAM.

Thanks
Kiwi
----(O)
( '--., ,__/
|
^ ^:
    position = 176;
break;
     case ‘%’:
    position = 220;
break;
     case ‘&’:
    position = 264;
break;
     case ‘(’:
    position = 352;
break;
     case ‘)’:
    position = 396 ;
break;
     case ‘*’:
    position = 440;
break;
     case ‘+’:
    position = 484;
break;
     case ‘,’:
    position = 528;
break;
     case ‘-’:
    position = 572;
break;
     case ‘.’:
    position = 616;
break;
     case ‘/’:
    position = 660;
break;
 case ‘:’:
    position = 1144;
break;
     case ‘;’:
    position = 1188;
break;
     case ‘<’:
    position = 1232;
break;
     case ‘=’:
    position = 1276;
break;
     case ‘>’:
    position = 1320;
break;
     case ‘?’:
    position = 1364;
break;
     case ‘@’:
    position = 1408;
break;
     case ‘[’:
    position = 2596;
break;
     case ‘]’:
    position = 2684;
break;
     case ‘^’:
    position = 2728;
break;
     case '
’:
    position = 2772;
break;
     case ‘{’:
    position = 4004;
break;
     case ‘|’:
    position = 4048;
break;
 case ‘}’:
    position = 4092;
break;
 case ‘’’:
    position = 2816;
break;

  case '\n':

position = 0;
break;
   }

return position;	

}


Let me know if you need more. The problem seems to lie with trying to put the table into the program memory, rather than the SRAM.

Thanks
Kiwi 
----(O)
( `'--.,
`,___/
| \
^ ^
// images
PROGMEM const
#define unsigned
#define char uint8_t
#undef char
#undef unsigned

PROGMEM const
#define unsigned
#define char uint8_t
#include PICTURE
#undef char
#undef unsigned

WTF?

T o ACCESS memory that has been defined in flash by PROGMEM, you have to use special methods. The reference page gives us this example:

// read back a char 
myChar =  pgm_read_byte_near(signMessage + k);

Hey TanHadron, yes, I managed to found the answer as well after a little more indepth googling. It now works :). I didn't realise you also had to use an special function for flash access. PaulS, yeah, all the code, the original project comes from a new display module that has only just released some c++ libraries. I stripped away most of the code, but I guess I left this behind. Anyway, as suspected it was to do with the accessing the memory. I thought that by using PROGMEM, somehow when accessing the look up table, the address space would be transposed to automatically access storage medium. Seems a little bit more googling earlier would of found the answer.

Many Thanks Kiwi ----(O) ( '--., ,___/ | \ ^ ^