Compiling data into program memory for runtime access (Solved)

I want to compile an array of string pointers (and the strings they point to) in program memory for retrieval at runtime. If I use the following declaration,

const char *fdata[] = { "This is the first (and only)  entry." }

will the data be located in program memory so that I can retrieve it with something like

   strcpy_P(buffer,fdata[0]);

Or do I need to declare it differently?

Have you tried this... http://arduiniana.org/libraries/flash/

I just did. AFAICT, it describes a library intended to facilitate accessing data stored in program memory, which is not what I'm looking for information about. I'm wanting it in program memory so I can retrieve selected pieces into SRAM as they're needed.

How do I ensure that it gets loaded into program memory and [u]not[/u] into SRAM (except when I retrieve pieces)?

[quote author=Morris Dovey link=topic=88305.msg663379#msg663379 date=1327305074]AFAICT, it describes a library intended to facilitate accessing data stored in program memory[/quote]

Exactly.

which is not what I'm looking for information about.

That's what you wanted in your original post. Have you changed your mind?

I'm wanting it in program memory so I can retrieve selected pieces into SRAM as they're needed.

So you have not changed your mind.

How do I ensure that it gets loaded into program memory and [u]not[/u] into SRAM (except when I retrieve pieces)?

See reply #1.

I'm missing the connection between the question (which is about the compile/link/load process) and the answer (which is about a runtime library). Would you provide a connection, please?

http://arduino.cc/en/Reference/PROGMEM ..about two-thirds the way down.

...answers your original question.

I'm missing the connection between the question (which is about the compile/link/load process) and the answer (which is about a runtime library). Would you provide a connection, please?

The Flash Library provides both data definition (fdata would only consume Flash / program memory) and simplified data access (you don't need to fiddle with strcpy_P and its ilk).

Thanks. The info at http://www.nongnu.org/avr-libc/user-manual/pgmspace.html, at the link you provided, and in pgmspace.h were all helpful.

With some good coaching from Coding Badly, I think I have this sorted out - or at least sorted out well enough to get a clean compile and correct output to the Serial monitor. XD I’ll post the code in the hope that anyone who spots a goof will let me know…

#include <avr/pgmspace.h>
#include <stdarg.h>

#define PC PROGMEM char
#define MAXLIN 128                     /* Output line buffer size             */
#define SUB '#'                        /* Substitution character              */
/*----------------------------------------------------------------------------*/
/* Define the format strings                                                  */
/*----------------------------------------------------------------------------*/
PC f000[] = "<p>The phone number of # is #</p>";
PC f001[] = "<p>#'s membership type is #</p>";
/*----------------------------------------------------------------------------*/
/* Array of pointers to above format strings                                  */
/*----------------------------------------------------------------------------*/
PROGMEM PGM_P fdata[] =                /* There must be an entry here for     */
{  f000,f001                           /*  each string above                  */
};                                     /*  end: array of pointers             */
/*----------------------------------------------------------------------------*/
/* Retrieve format string, make substitutions, and output formatted line      */
/*----------------------------------------------------------------------------*/
void putline(unsigned fmt,...)
{  static char buffer[MAXLIN];         /* Line buffer (SRAM)                  */
   char c;                             /* Character from format string        */
   char *p = buffer;                   /* Output pointer                      */
   PGM_P f = (PGM_P)pgm_read_word(&(fdata[fmt]));  /* Format string pointer   */
   char *q;                            /* Substitution data pointer           */
   va_list ap;                         /* Parameter list reference            */

   va_start(ap,fmt);                   /* Initialize ap                       */
   while (c = pgm_read_byte(f))        /* While format characters remain      */
   {  ++f;                             /* Advance format pointer              */
      if (c == SUB)                    /* Is this a substitution character    */
      {  q = va_arg(ap,char *);        /* If so, get string pointer param     */
         while (*q) *p++ = *q++;       /* Append param string to buffer       */
      }                                /*  end: if substitution               */
      else *p++ = c;                   /* Output ordinary char to buffer      */
   }                                   /*  end: while format chars remain     */
   va_end(ap);                         /* Done with parameter list            */
   *p = '\0';                          /* Terminate the output string         */
   Serial.println(buffer);             /* Output the buffered string          */
}                                      /*  end: putline()                     */
/*----------------------------------------------------------------------------*/
/* Test program (Arduino)                                                     */
/*----------------------------------------------------------------------------*/
void setup(void)
{  char *name = "John Smith";          /* 1st substitution item               */
   char *phone = "123-456-7890";       /* 2nd substitution item               */
   char *mtype = "Senior";             /* 3rd substitution item               */

   Serial.begin(115200);               /* Initialize serial connection        */
   putline(0,name,phone);              /* O/P formatted line with subs        */
   putline(1,name,mtype);              /* O/P second formatted line           */
}                                      /*  end: setup()                       */
void loop(void)
{  /* stub */
}