PROGMEM Menu system

Hello!! :slight_smile:

I'm trying to build a simple menu sistem for my oled display but I have some problem with PROGMEM and pointer :confused:

This is the code:

#ifndef Test_H
#define Test_H

#include <avr/pgmspace.h>
#include <Arduino.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

const char lbl_start[] PROGMEM  = {"Start"};
const char lbl_MainMenu[] PROGMEM  = {"Main Menu"};
const char lbl_Info[] PROGMEM  = {"Info"};
const char lbl_Storico[] PROGMEM  = {"Storico"};

	
typedef void (*FunctionMenu) (boolean is_back);

typedef struct menu menu ;
struct menu {
	const char *title;
	void (*command)(boolean is_back);
	short num_submenus;
	struct menu  *submenu[10];
	struct menu  *back;
};


class Menu
{

  public:
	Menu() {};		
	
	menu menu_start  = { lbl_start, NULL };
	menu menu_storico = { lbl_start, NULL, 0 };
	menu menu_info = { lbl_start, NULL, 0 };
	
	menu main_menu =  { lbl_start, NULL, 3,{ &menu_start, &menu_storico, &menu_info } };

	menu *current_menu = &main_menu;
	unsigned int index = 0;
	boolean in_command = false;			
	
	Adafruit_SSD1306* display;
	
	void init(Adafruit_SSD1306 *screenref);
	
	void display_menu(menu* mnu);
	menu* get_user_selection(menu *mnu, char c);
	bool use_menu(menu *mnu);
	void change_menu(char c);
	
	void attach_function(menu *mnu, FunctionMenu function);

};

#endif

I would like to store the menu title in FLASH memory and the print over serial and over the oled display.

In the menu struct I want to store the pointer to title, but when I try to read the FLASH memory with the code below I can't get any string, actually my arduino uno reboot continuously. I think that I try to read a NULL address value.

char buffer[30];
	//const char *str =(char*) pgm_read_word(mnu->title);
	strcpy_P(buffer, (char*)pgm_read_word(&(mnu->title))); 
	Serial.println("test");
	Serial.println(buffer);
	//Serial.println(str);

Where I'm wrong?

:confused: :confused: :confused:

 strcpy_P(buffer, (char*)pgm_read_word(&(mnu->title)));

Your menu structures are not in FLASH so no need to read the pointer from FLASH. Just fetch the pointer and pass it to the function that knows it points to FLASH:

 strcpy_P(buffer, mnu->title);

D4ng3R92:
Hello!! :slight_smile:

I would like to store the menu title in FLASH memory and the print over serial and over the oled display.

In the menu struct I want to store the pointer to title, but when I try to read the FLASH memory with the code below I can't get any string, actually my arduino uno reboot continuously. I think that I try to read a NULL address value.

char buffer[30];

//const char str =(char) pgm_read_word(mnu->title);
strcpy_P(buffer, (char*)pgm_read_word(&(mnu->title)));
Serial.println("test");
Serial.println(buffer);
//Serial.println(str);





Where I'm wrong?

:confused: :confused: :confused:

pgm_read_word() returns a word (16bit value from program Memory, The AVR CPU's are Harvard architecture, The program memory is totally separate from the data memory.

you have to copy each byte or word from Program Memoryto a DATA

char buffer[30];
uint8_t i=0;
do{
  buffer[i]=pgm_read_byte_near(mnu->title+i);
  i++;
  }while(buffer[i-1]!=0);

Serial.println("test");
Serial.println(buffer);

Your code was reading the first two characters (word) from PROGMEM then treating this Word value as a pointer into DataRam, and moving a random number of bytes into your 30 byte buffer, strcpy_p() assumes null terminated Strings. If the two character "pointer" resulted in an address outside of physical RAM (0x0000 .. 0x08FF for UNO, 0x0000 .. 0x021FF for MEGA2560) the value read would be 0xFF. NEVER ZERO.

So all of the time a pointer made from two displayable characters pointed outside of 'real' RAM, so effectively every time this code executed you filled from buffer[0] to buffer[0xFFFF] with 0xff. Totally destroying all variables, All of the Stack.

Chuck.

What type is menu->title? What type is the value assigned to it? They are not the same types.

I found a simple Menu Helper that create list in Flash memory.....