PROGMEM and Library creation

Hi Everyone,

I'm trying to do something that I don't know if it is possible.
So, this is the code I know works:

#include <avr/pgmspace.h>
#include "menu.h"

prog_char menu1_label[] PROGMEM = "Function 1";
prog_char menu2_label[] PROGMEM = "Function 2";
prog_char menu3_label[] PROGMEM = "Function 3";
PROGMEM const char *menu_items[] = {menu1_label, menu2_label, menu3_label};

void setup()
{
  char buffer[22];
  Serial.begin(9600);
  for (int i=0;i<SIZE(menu_items);i++)
  {
    strcpy_P(buffer, (char * )pgm_read_word(&(menu_items[i])));
    Serial.println(buffer);
  }
}

void loop()
{
}

At this moment the only thing I have inside menu.h is:

#define SIZE(array) (sizeof(array) / sizeof(*array))

The reason I use buffer is because I need a char* to be able to print to my LCD. So, just imagine that Serial.println is actually LCD.print(char *text).
Everything works fine and I get the buffer filled with the correct strings.
What I'm trying to accomplish now is:

#include <avr/pgmspace.h>
#include "menu.h"

prog_char menu1_label[] PROGMEM = "Function 1";
prog_char menu2_label[] PROGMEM = "Function 2";
prog_char menu3_label[] PROGMEM = "Function 3";
PROGMEM const char *menu_items[] = {menu1_label, menu2_label, menu3_label};

void setup()
{
  Serial.begin(9600);
  PrintStrings(); //This is the function I'd like to create inside menu library
}

void loop()
{
}

and inside the menu library I would like to place the code that would actually read from flash and print the strings.
My question is:
Is it possible to read flash from a library?
If so, how do I do that?

Thank you,
Roberto.

Is it possible to read flash from a library?

Sure is.

If so, how do I do that?

Just like you do in the sketch. The only real difference is that you need to pass the location of flash data to read, and the size of the data, to the function, rather than having the function figure out the size.

Hey Paul,

Just like you do in the sketch. The only real difference is that you need to pass the location of flash data to read, and the size of the data, to the function, rather than having the function figure out the size.

size of the string or size of the array?
If I pass only 1 pointer and size to library, won't I get just one string?
Does it mean my for statement has to be in the main code instead of library?

Strings are null-terminated arrays of characters. The length of a string (the important size) can always be determined. In a function, given a pointer to the first element of an array (of strings), the size of the array (the number of pointers in the array) can not be determined, so, you need to tell the function the number of elements in the array.

Hi Paul,

I understand that, but in this case, we are talking about an array of 3 strings and not just a array of characters.
If it were just 1 string, I can understand passing a pointer and length of string, but how would I do with an array of strings?

RI

Pass the array and the number of items in the array. Maybe I don't understand the issue. Passing arrays to functions is quite easy.

Hi Paul,

If I pass an array to a function, wouldn't that in turn be using up RAM memory, defeating the purpose of progmem?
All I'm trying to do is minimize the usage of RAM by using progmem.
But the real problem is that I would like to place the function that actually reads the flash, inside a library function.
I'd like to be able to change the strings in the program code and have the function that actually reads them inside a library, so the code is all hidden in the library and the code is as clean as calling 1 function.
Was I able to explain what I want to achieve?

RI

The best thing to do, in my opinion, is to try it and see what happens. When you pass a pointer to an array to a function, the array is not copied, I see no reason why you should not be able to write a function that takes a PROGMEM const char * argument.

On the other hand, I've never tried, so I could be all wrong.

Ok, it worked.

My code:

#include <avr/pgmspace.h>
#include "menu.h"

prog_char menu1_label[] PROGMEM = "Function 1";
prog_char menu2_label[] PROGMEM = "Function 2";
prog_char menu3_label[] PROGMEM = "Function 3";
PROGMEM const char *menu_items[] = {menu1_label, menu2_label, menu3_label};

void setup()
{
  Serial.begin(9600);
  PrintMenu(pgm_read_word(&(menu_items[0])),SIZE(menu_items));

}

void loop()
{
}

menu.h

#ifndef      menu_h
#define menu_h

#define SIZE(array) (sizeof(array) / sizeof(*array))

void PrintMenu(int pointer, int num);

#endif

menu.cpp:

#include "menu.h"
#include <WProgram.h> 
#include <avr/pgmspace.h>

void PrintMenu(int pointer, int num)
{
      for (int a=0;a<num;a++)
      {
            char buffer[22];
            strcpy_P(buffer, (char * )pointer++);
            pointer+=strlen(buffer);
            Serial.println(buffer);
      }
}

Thanks Paul :slight_smile: