PROGMEM question - dynamic pgm_read_word()

Hi there,

first the slightly modified PROGMEM-Example from www.arduino.cc for better understanding my problem

#include <avr/pgmspace.h>
prog_char string_01_0[] PROGMEM = "String 1 0";   // "String 0" etc are strings to store - change to suit.
prog_char string_01_1[] PROGMEM = "String 1 1";
prog_char string_01_2[] PROGMEM = "String 1 2";
prog_char string_01_3[] PROGMEM = "String 1 3";
prog_char string_01_4[] PROGMEM = "String 1 4";
prog_char string_01_5[] PROGMEM = "String 1 5";

prog_char string_02_0[] PROGMEM = "String 2 0";   
prog_char string_02_1[] PROGMEM = "String 2 1";
prog_char string_02_2[] PROGMEM = "String 2 2";
prog_char string_02_3[] PROGMEM = "String 2 3";
prog_char string_02_4[] PROGMEM = "String 2 4";
prog_char string_02_5[] PROGMEM = "String 2 5";

// Then set up a table to refer to your strings.

PROGMEM const char *string_table_01[] = 	   // change "string_table" name to suit
{   
  string_01_0,
  string_01_1,
  string_01_2,
  string_01_3,
  string_01_4,
  string_01_5 };
  
  PROGMEM const char *string_table_02[] = 	   // change "string_table" name to suit
{   
  string_02_0,
  string_02_1,
  string_02_2,
  string_02_3,
  string_02_4,
  string_02_5 };

char buffer[30];    // make sure this is large enough for the largest string it must hold

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


void loop()			  
{
  for (int i = 0; i < 6; i++)
  {
    strcpy_P(buffer, (char*)pgm_read_word(&(string_table_01[i]))); // Necessary casts and dereferencing, just copy. 
    Serial.println( buffer );
    delay( 500 );
  }
}

and now the problem

i want to change »string_table_XX« in »pgm_read_word(string_table_XX*)« dynamically.*
So that the same »strcpy_P« function reads either from »string_table_01« or from »string_table_02«.
thanks for any replys
simon

i want to change »string_table_XX« in »pgm_read_word(string_table_XX)« dynamically.

string_table_01 and string_table_02 are names. The compiler translates them to addresses that are actually passed to the pgm_read_word function. You can not, at run time, map a name that no longer exists, to an address.

Hey PaulS,

thanks for your reply.

string_table_01 and string_table_02 are names. The compiler translates them to addresses that are actually passed to the pgm_read_word function.

Is it possible to change the addresses, that are passed to the »pgm_read_word«-function?

My knowledge in c is poor so please excuse silly questions :(

simon

Maybe you could think about using EEPROM to handle this type of scenario

You could try something like this. Haven’t compiled it so you could call it psuedocode :grin:

const char** table = 0;

void setup()			  
{
  Serial.begin(9600);
  do
  {
    Serial.println("Which table would you like, 1 or 2?");
    while (!Serial.available());
    char c = Serial.read();
    Serial.println(c);
    if ( c == '1' )
      table = string_table_01;
    else if ( c == '2' )
      table = string_table_02;
  }
  while ( table == 0 );
}

void loop()			  
{
  for (int i = 0; i < 6; i++)
  {
    strcpy_P(buffer, (char*)pgm_read_word(table + i)); 
    Serial.println( buffer );
    delay( 500 );
  }
}

The short answer is that pointers to progmem work like pointers to data memory. The differences show up when you need to qualify declarations (so the compiler knows the data is in progmem), and when you need to cast and use macros in order to access the data (because it's a bit more involved than simply loading from an address).

Good resources (for me, maybe for you):

http://www.nongnu.org/avr-libc/user-manual/pgmspace.html http://arduino.cc/en/Reference/PROGMEM and pgmspace.h (to look at what the macros produce)

The code I finally got working is at

http://arduino.cc/forum/index.php/topic,88305.0.html

and, although not written by an expert, may help by providing example of required casts and macro use.