Structrures are pain in the ass

Go To Last Post
18 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dear freaks, no matter how I try I cannot get the touch of it.
Structures are quite a burden for me.
Please, someone, a good tutorial!!!

Let me explain you my problem.
I am trying to use an ATMEGA16, a LCD and a keyboard to do something. So I figured out that a state machine would be quite usefull.
And voila... I get my hands on the gcc ported avr butterfly code. In there, there is a file called menu.h
that defines the states and the menu texts that are viewed on the LCD.
Here is the original code...

// menu.h

// mt __flash typedef struct
typedef struct PROGMEM
{
    unsigned char state;
    unsigned char input;
    unsigned char nextstate;
} MENU_NEXTSTATE;


// mt __flash typedef struct
typedef struct PROGMEM
{
    unsigned char state;
    // char __flash *pText;
    PGM_P pText;
    char (*pFunc)(char input);
} MENU_STATE;


// Menu text
// mtA, these where all of the same structure as in the follow. line
// __flash char MT_AVRBF[]                         = "AVR Butterfly";
//const char MT_AVRBF[] PROGMEM                     = "AVR Butterfly GCC";
const char MT_AVRBF[] PROGMEM                     = 
	{'A','V','R',' ','B','U','T','T','E','R','F','L','Y',' ','G'+0x80,'C'+0x80,'C'+0x80,'\0'};
const char MT_TIME[] PROGMEM                      = "Time";
const char MT_TIME_CLOCK[] PROGMEM                = "Clock";
const char MT_TIME_CLOCK_ADJUST[] PROGMEM         = "Adjust Clock";
const char MT_TIME_CLOCKFORMAT_ADJUST[] PROGMEM   = "Change Clock Format";
const char MT_TIME_DATE[] PROGMEM                 = "Date";
const char MT_TIME_DATE_ADJUST[] PROGMEM          = "Adjust Date";
const char MT_TIME_DATEFORMAT_ADJUST[] PROGMEM    = "Change Date Format";
const char MT_MUSIC[] PROGMEM                     = "Music";
const char MT_VCARD[] PROGMEM                     = "Name";
const char MT_ENTERNAME[] PROGMEM                 = "Enter name";
const char MT_TEMPERATURE[] PROGMEM               = "Temperature";
const char MT_VOLTAGE[] PROGMEM                   = "Voltage";
const char MT_LIGHT[] PROGMEM                     = "Light";
const char MT_OPTIONS[] PROGMEM                   = "Options";
const char MT_OPTIONS_DISPLAY[] PROGMEM           = "Display";
const char MT_OPTIONS_DISPLAY_CONTRAST[] PROGMEM  = "Adjust contrast";
// mt - never used: const char MT_OPTIONS_DISPLAY_SEG[] PROGMEM       = "Browse segments";
const char MT_VCARD_DOWNLOAD_NAME[] PROGMEM       = "Download Name";
const char MT_OPTIONS_BOOT[] PROGMEM              = "Bootloader";
const char MT_OPTIONS_POWER_SAVE[] PROGMEM        = "Power Save Mode";
const char MT_OPTIONS_AUTO_POWER_SAVE[] PROGMEM   = "Auto Power Save";
const char MT_OPTIONS_KEYCLICK[] PROGMEM          = "Key Click";
// mtE

// mt MENU_NEXTSTATE menu_nextstate[] = { 
const MENU_NEXTSTATE menu_nextstate[] PROGMEM = {
//  STATE                       INPUT       NEXT STATE
    {ST_AVRBF,                  KEY_PLUS,   ST_OPTIONS},
    {ST_AVRBF,                  KEY_NEXT,   ST_AVRBF_REV},
    {ST_AVRBF,                  KEY_MINUS,  ST_TIME},

    {ST_AVRBF_REV,              KEY_PREV,   ST_AVRBF},

    {ST_TIME,                   KEY_PLUS,   ST_AVRBF},
    {ST_TIME,                   KEY_NEXT,   ST_TIME_CLOCK},
    {ST_TIME,                   KEY_PREV,   ST_AVRBF},
    {ST_TIME,                   KEY_MINUS,  ST_MUSIC},

    {ST_TIME_CLOCK,             KEY_PLUS,   ST_TIME_DATE},
    {ST_TIME_CLOCK,             KEY_NEXT,   ST_TIME_CLOCK_FUNC},
    {ST_TIME_CLOCK,             KEY_PREV,   ST_TIME},
    {ST_TIME_CLOCK,             KEY_MINUS,  ST_TIME_DATE},

    {ST_TIME_CLOCK_ADJUST,      KEY_PLUS,   ST_TIME_CLOCKFORMAT_ADJUST}, 
    {ST_TIME_CLOCK_ADJUST,      KEY_ENTER,  ST_TIME_CLOCK_ADJUST_FUNC},
    {ST_TIME_CLOCK_ADJUST,      KEY_PREV,   ST_TIME_CLOCK_FUNC},    
    {ST_TIME_CLOCK_ADJUST,      KEY_MINUS,  ST_TIME_CLOCKFORMAT_ADJUST}, 

    {ST_TIME_CLOCKFORMAT_ADJUST, KEY_PLUS,  ST_TIME_CLOCK_ADJUST},
    {ST_TIME_CLOCKFORMAT_ADJUST, KEY_ENTER, ST_TIME_CLOCKFORMAT_ADJUST_FUNC},
    {ST_TIME_CLOCKFORMAT_ADJUST, KEY_PREV,  ST_TIME_CLOCK_FUNC},
    {ST_TIME_CLOCKFORMAT_ADJUST, KEY_MINUS, ST_TIME_CLOCK_ADJUST},

    {ST_TIME_DATE,              KEY_PLUS,   ST_TIME_CLOCK},
    {ST_TIME_DATE,              KEY_NEXT,   ST_TIME_DATE_FUNC},
    {ST_TIME_DATE,              KEY_PREV,   ST_TIME},
    {ST_TIME_DATE,              KEY_MINUS,  ST_TIME_CLOCK},

    {ST_TIME_DATE_ADJUST,       KEY_PLUS,   ST_TIME_DATEFORMAT_ADJUST},
    {ST_TIME_DATE_ADJUST,       KEY_ENTER,  ST_TIME_DATE_ADJUST_FUNC},
    {ST_TIME_DATE_ADJUST,       KEY_PREV,   ST_TIME_DATE_FUNC},
    {ST_TIME_DATE_ADJUST,       KEY_MINUS,  ST_TIME_DATEFORMAT_ADJUST},

    {ST_TIME_DATEFORMAT_ADJUST, KEY_PLUS,   ST_TIME_DATE_ADJUST},
    {ST_TIME_DATEFORMAT_ADJUST, KEY_ENTER,  ST_TIME_DATEFORMAT_ADJUST_FUNC},
    {ST_TIME_DATEFORMAT_ADJUST, KEY_PREV,   ST_TIME_DATE_FUNC},
    {ST_TIME_DATEFORMAT_ADJUST, KEY_MINUS,  ST_TIME_DATE_ADJUST},

    {ST_MUSIC,                  KEY_PLUS,   ST_TIME},
    {ST_MUSIC,                  KEY_NEXT,   ST_MUSIC_SELECT},
    {ST_MUSIC,                  KEY_PREV,   ST_AVRBF},
    {ST_MUSIC,                  KEY_MINUS,  ST_VCARD},

    {ST_SOUND_MUSIC,            KEY_NEXT,   ST_MUSIC_SELECT},
    {ST_SOUND_MUSIC,            KEY_PREV,   ST_MUSIC},

    {ST_VCARD,                  KEY_PLUS,   ST_MUSIC},
    {ST_VCARD,                  KEY_NEXT,   ST_VCARD_FUNC},
    {ST_VCARD,                  KEY_PREV,   ST_AVRBF},
    {ST_VCARD,                  KEY_MINUS,  ST_TEMPERATURE},

    {ST_VCARD_ENTER_NAME,       KEY_PLUS,     ST_VCARD_DOWNLOAD_NAME},
    {ST_VCARD_ENTER_NAME,       KEY_ENTER,    ST_VCARD_ENTER_NAME_FUNC},
    {ST_VCARD_ENTER_NAME,       KEY_PREV,     ST_VCARD_FUNC},    
    {ST_VCARD_ENTER_NAME,       KEY_MINUS,    ST_VCARD_DOWNLOAD_NAME},

    {ST_VCARD_DOWNLOAD_NAME,    KEY_PLUS,     ST_VCARD_ENTER_NAME},
    {ST_VCARD_DOWNLOAD_NAME,    KEY_ENTER,    ST_VCARD_DOWNLOAD_NAME_FUNC},
    {ST_VCARD_DOWNLOAD_NAME,    KEY_PREV,     ST_VCARD_FUNC},    
    {ST_VCARD_DOWNLOAD_NAME,    KEY_MINUS,    ST_VCARD_ENTER_NAME},    

    {ST_TEMPERATURE,            KEY_PLUS,   ST_VCARD},
    {ST_TEMPERATURE,            KEY_NEXT,   ST_TEMPERATURE_FUNC},
    {ST_TEMPERATURE,            KEY_PREV,   ST_AVRBF},
    {ST_TEMPERATURE,            KEY_MINUS,  ST_VOLTAGE},

    {ST_VOLTAGE,                KEY_PLUS,   ST_TEMPERATURE},
    {ST_VOLTAGE,                KEY_NEXT,   ST_VOLTAGE_FUNC},
    {ST_VOLTAGE,                KEY_PREV,   ST_AVRBF},
    {ST_VOLTAGE,                KEY_MINUS,  ST_LIGHT},

    {ST_LIGHT,                  KEY_PLUS,   ST_VOLTAGE},
    {ST_LIGHT,                  KEY_NEXT,   ST_LIGHT_FUNC},
    {ST_LIGHT,                  KEY_PREV,   ST_AVRBF},
    {ST_LIGHT,                  KEY_MINUS,  ST_OPTIONS},

    {ST_OPTIONS,                KEY_PLUS,   ST_LIGHT},
    {ST_OPTIONS,                KEY_NEXT,   ST_OPTIONS_DISPLAY},
    {ST_OPTIONS,                KEY_PREV,   ST_AVRBF},
    {ST_OPTIONS,                KEY_MINUS,  ST_AVRBF},

    {ST_OPTIONS_DISPLAY,        KEY_PLUS,   ST_OPTIONS_KEYCLICK},
    {ST_OPTIONS_DISPLAY,        KEY_NEXT,   ST_OPTIONS_DISPLAY_CONTRAST},
    {ST_OPTIONS_DISPLAY,        KEY_PREV,   ST_OPTIONS},
    {ST_OPTIONS_DISPLAY,        KEY_MINUS,  ST_OPTIONS_BOOT},

    {ST_OPTIONS_DISPLAY_CONTRAST, KEY_ENTER,    ST_OPTIONS_DISPLAY_CONTRAST_FUNC},
    {ST_OPTIONS_DISPLAY_CONTRAST, KEY_PREV,     ST_OPTIONS_DISPLAY},

    {ST_OPTIONS_BOOT,             KEY_PLUS,     ST_OPTIONS_DISPLAY},
    {ST_OPTIONS_BOOT,             KEY_NEXT,     ST_OPTIONS_BOOT_FUNC},
    {ST_OPTIONS_BOOT,             KEY_PREV,     ST_OPTIONS},
    {ST_OPTIONS_BOOT,             KEY_MINUS,    ST_OPTIONS_POWER_SAVE},

    {ST_OPTIONS_POWER_SAVE,       KEY_PLUS,     ST_OPTIONS_BOOT},
    {ST_OPTIONS_POWER_SAVE,       KEY_NEXT,     ST_OPTIONS_POWER_SAVE_FUNC},
    {ST_OPTIONS_POWER_SAVE,       KEY_PREV,     ST_OPTIONS},
    {ST_OPTIONS_POWER_SAVE,       KEY_MINUS,    ST_OPTIONS_AUTO_POWER_SAVE},

    {ST_OPTIONS_AUTO_POWER_SAVE,  KEY_PLUS,     ST_OPTIONS_POWER_SAVE},
    {ST_OPTIONS_AUTO_POWER_SAVE,  KEY_NEXT,     ST_OPTIONS_AUTO_POWER_SAVE_FUNC},
    {ST_OPTIONS_AUTO_POWER_SAVE,  KEY_PREV,     ST_OPTIONS},
    {ST_OPTIONS_AUTO_POWER_SAVE,  KEY_MINUS,    ST_OPTIONS_KEYCLICK},

    {ST_OPTIONS_KEYCLICK,         KEY_PLUS,     ST_OPTIONS_AUTO_POWER_SAVE},
    {ST_OPTIONS_KEYCLICK,         KEY_NEXT,     ST_OPTIONS_KEYCLICK_FUNC},
    {ST_OPTIONS_KEYCLICK,         KEY_PREV,     ST_OPTIONS},
    {ST_OPTIONS_KEYCLICK,         KEY_MINUS,    ST_OPTIONS_DISPLAY},
        
    {0,                         0,          0}
};


// mt MENU_STATE menu_state[] = {
const MENU_STATE menu_state[] PROGMEM = {
//  STATE                               STATE TEXT                  STATE_FUNC
    {ST_AVRBF,                          MT_AVRBF,                   NULL},
    {ST_AVRBF_REV,                      NULL,                       Revision},
    {ST_TIME,                           MT_TIME,                    NULL},
    {ST_TIME_CLOCK,                     MT_TIME_CLOCK,              NULL},
    {ST_TIME_CLOCK_FUNC,                NULL,                       ShowClock},
    {ST_TIME_CLOCK_ADJUST,              MT_TIME_CLOCK_ADJUST,       NULL},
    {ST_TIME_CLOCK_ADJUST_FUNC,         NULL,                       SetClock},
    {ST_TIME_CLOCKFORMAT_ADJUST,        MT_TIME_CLOCKFORMAT_ADJUST, NULL},
    {ST_TIME_CLOCKFORMAT_ADJUST_FUNC,   NULL,                       SetClockFormat},
    {ST_TIME_DATE,                      MT_TIME_DATE,               NULL},
    {ST_TIME_DATE_FUNC,                 NULL,                       ShowDate},
    {ST_TIME_DATE_ADJUST,               MT_TIME_DATE_ADJUST,        NULL},
    {ST_TIME_DATE_ADJUST_FUNC,          NULL,                       SetDate},    
    {ST_TIME_DATEFORMAT_ADJUST,         MT_TIME_DATEFORMAT_ADJUST,  NULL},
    {ST_TIME_DATEFORMAT_ADJUST_FUNC,    NULL,                       SetDateFormat},     
    {ST_MUSIC,                          MT_MUSIC,                   NULL},
    {ST_MUSIC_SELECT,                   NULL,                       SelectSound},
    {ST_MUSIC_PLAY,                     NULL,                       Sound},
    {ST_VCARD,                          MT_VCARD,                   NULL},
    {ST_VCARD_FUNC,                     NULL,                       vCard},
    {ST_VCARD_ENTER_NAME,               MT_ENTERNAME,               NULL},
    {ST_VCARD_DOWNLOAD_NAME,            MT_VCARD_DOWNLOAD_NAME,     NULL},
    {ST_VCARD_ENTER_NAME_FUNC,          NULL,                       EnterName},
    {ST_VCARD_DOWNLOAD_NAME_FUNC,       NULL,                       RS232},
    {ST_TEMPERATURE,                    MT_TEMPERATURE,             NULL},
    {ST_TEMPERATURE_FUNC,               NULL,                       TemperatureFunc},
    {ST_VOLTAGE,                        MT_VOLTAGE,                 NULL},
    {ST_VOLTAGE_FUNC,                   NULL,                       VoltageFunc},
    {ST_LIGHT,                          MT_LIGHT,                   NULL},
    {ST_LIGHT_FUNC,                     NULL,                       LightFunc},
    {ST_OPTIONS,                        MT_OPTIONS,                 NULL},
    {ST_OPTIONS_DISPLAY,                MT_OPTIONS_DISPLAY,         NULL},
    {ST_OPTIONS_DISPLAY_CONTRAST,       MT_OPTIONS_DISPLAY_CONTRAST,NULL},
    {ST_OPTIONS_DISPLAY_CONTRAST_FUNC,  NULL,                       SetContrast},
    {ST_OPTIONS_BOOT,                   MT_OPTIONS_BOOT,            NULL},
    {ST_OPTIONS_BOOT_FUNC,              NULL,                       BootFunc},    
    {ST_OPTIONS_POWER_SAVE,             MT_OPTIONS_POWER_SAVE,      NULL},
    {ST_OPTIONS_POWER_SAVE_FUNC,        NULL,                       PowerSaveFunc},
    {ST_OPTIONS_AUTO_POWER_SAVE,        MT_OPTIONS_AUTO_POWER_SAVE, NULL},
    {ST_OPTIONS_AUTO_POWER_SAVE_FUNC,   NULL,                       AutoPower},
    {ST_OPTIONS_KEYCLICK,               MT_OPTIONS_KEYCLICK,        NULL},
    {ST_OPTIONS_KEYCLICK_FUNC,          NULL,                       KeyClick},

    {0,                                 NULL,                       NULL},

};

It is pretty good and does what I mostly need, but I use a 2x16 LCD and most of my messages shown on the LCD are dual lines (for the first and second row of the LCD).

Show I decided to typedef a structure, so that I can reference each line using structure pointers
ex.

SendToLCD(welcome->line1);
SendToLCD(welcome->line2);

So here is my modified menu.h
I have taken out most of the states to make it small and simple since everything are based on similar types

typedef struct PROGMEM
{
	const char* line1;
	const char* line2;
}LCD_MSG;  //typedef for LCD_MSGs 

typedef struct PROGMEM
{
    unsigned char state;
    unsigned char input;
    unsigned char nextstate;
} MENU_NEXTSTATE;

typedef struct PROGMEM
{
    unsigned char state;
    LCD_MSG* pText;
    char (*pFunc)(char input);
} MENU_STATE;

#define KEY_NULL    0
// Menu text

const LCD_MSG MT_WELCOME		PROGMEM= {"THE AVR","POTENTIOSTAT"};

const MENU_NEXTSTATE menu_nextstate[] PROGMEM = {
//  STATE                       INPUT       NEXT STATE
    {ST_WELCOME,           KEY_NULL,   		ST_MODES},
	 {0,                          0,         0}
};

const MENU_STATE menu_state[] PROGMEM = {
//  STATE                               STATE TEXT                  STATE_FUNC
    {ST_WELCOME,                        MT_WELCOME,                 NULL},
    
    {0,                                 NULL,                       NULL},

};

I get compile errors for menu.h like

Quote:

../menu.h:166: error: initializer element is not constant
../menu.h:166: error: (near initialization for 'menu_state[0].pText')

which are talking about MT_WELCOME in menu_state array

const MENU_STATE menu_state[] PROGMEM = {
//  STATE                               STATE TEXT                  STATE_FUNC
    {ST_WELCOME,                      MT_WELCOME,                 NULL},
    
    {0,                                 NULL,                       NULL},

};

Could anyone help me on this.
Actually I am using

typedef struct PROGMEM
{
	const char* line1;
	const char* line2;
}LCD_MSG;  //typedef for LCD_MSGs 

in order to make structures that line1 is a message shown in LCD at first row and line2 is a message shown in LCD at second row.

So

const LCD_MSG MT_WELCOME		PROGMEM= {"THE AVR","POTENTIOSTAT"};

here I try to initialize the lines for each structure.

Thank you very much a priori for any help or reference.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
I get compile errors for menu.h like ...
MENU_STATE contains a pointer to a LCD_MSG, but in the initialization you try to put the whole LCD_MSG into it instead.

const MENU_STATE menu_state[] PROGMEM = {
    {ST_WELCOME, MT_WELCOME, NULL},

->

const MENU_STATE menu_state[] PROGMEM = {
    {ST_WELCOME, &MT_WELCOME, NULL},
const LCD_MSG MT_WELCOME      PROGMEM= {"THE AVR","POTENTIOSTAT"};

Here the strings are not in FLASH. Have a look at the original version how to put the strings into FLASH too.

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

make sure your file is a lower case .c or .h if it is an uppercase .C or .H you will invoke the C++ compiler instead of the C compiler, and this error is one of those symptoms.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
typedef struct PROGMEM
{
    unsigned char state;
    LCD_MSG* pText;
    char (*pFunc)(char input);
} MENU_STATE; 


I thought that I was making a pointer to the structure here... for the menu_state array.

Quote:

Code:
const LCD_MSG MT_WELCOME      PROGMEM= {"THE AVR","POTENTIOSTAT"};

Here the strings are not in FLASH. Have a look at the original version how to put the strings into FLASH too.

In the original version strings are stored in flash with PROGMEM one by one. I am trying to do it twice faster (...) by storing two strings in a structure stored in flash. It is not doable?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

glitch wrote:
make sure your file is a lower case .c or .h if it is an uppercase .C or .H you will invoke the C++ compiler instead of the C compiler, and this error is one of those symptoms.
The missing '&' definitely triggers this error.
I tried it to be sure. ;-)

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
I thought that I was making a pointer to the structure here... for the menu_state array.
???
pText is a pointer to a LCD_MSG and you initialize it with a whole LCD_MSG instead of a pointer.

Quote:
I am trying to do it twice faster (...) by storing two strings in a structure stored in flash. It is not doable?
You don't have two strings in a structure, only two pointers. And what do you mean with "faster"? Faster compiling?

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

You don't have two strings in a structure, only two pointers. And what do you mean with "faster"? Faster compiling?

Faster in my head...
Instead of writing two lines for each screen I only write one...

sternst, I tried your code but now I get

Quote:
../menu.h:166: warning: initialization discards qualifiers from pointer target type

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kakarot wrote:
Instead of writing two lines for each screen I only write one...
It is no problem to combine two lines of text into a single structure, but you have to change the initialization of it. As already said, simply orientate yourself towards the original code.

kakarot wrote:
sternst, I tried your code but now I get ...

LCD_MSG* pText;
->
const LCD_MSG* pText;

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I was thinking what you said about

Quote:

Code:
const LCD_MSG MT_WELCOME      PROGMEM= {"THE AVR","POTENTIOSTAT"};

Here the strings are not in FLASH. Have a look at the original version how to put the strings into FLASH too.

So I guess this is better considering that I want to define a type of structure that has line1 and line2 strings stored in flash program memory?

typedef struct PROGMEM
{
	PGM_P line1;
	PGM_P line2;
}LCD_MSG;  //typedef for LCD_MSGs 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kakarot wrote:

typedef struct PROGMEM
{
    unsigned char state;
    LCD_MSG* pText;
    char (*pFunc)(char input);
} MENU_STATE; 


I thought that I was making a pointer to the structure here... for the menu_state array.

Quote:

Code:
const LCD_MSG MT_WELCOME      PROGMEM= {"THE AVR","POTENTIOSTAT"};

Here the strings are not in FLASH. Have a look at the original version how to put the strings into FLASH too.

In the original version strings are stored in flash with PROGMEM one by one. I am trying to do it twice faster (...) by storing two strings in a structure stored in flash. It is not doable?

You are confusing a number of things. No, it is not possible to utilize PROGMEN as you are trying.

First, here is a clarification on structure verses pointer:

typedef struct mystruct_t{
char strval[20];
} mystruct_t;

mystruct_t structVar;
mystruct_t *structPtr;

-> is a pointer member derefrence
. is to access a structure member

example:

structVar.strval = "Hello World";
structPtr->strval = "Hello World";

secondly, PROGMEM is a pre-processor declaration defining the allocations should be stored in the program space rom instead of ram. You cannot have pointers directly to a variable in program space. You must use a memcpy_P derivative to copy values from program space to ram. See the help link below for more details.

http://www.nongnu.org/avr-libc/u...

Hope this helps.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
So I guess this is better considering that I want to define a type of structure that has line1 and line2 strings stored in flash program memory?
Doesn't make a difference. You have to change the initialization, not the structure definition.

Is it really necessary to give you the complete solution? You don't see the difference between the original code and yours concerning the flash strings?

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sternst wrote:
The missing '&' definitely triggers this error.

Oh that'll do it too. I didn't look into the code, I just recognized the error as one that comes up when trying to use some progmem constants with the C++ compiler.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ok Stefan.
I prefer to learn than copy. Because knowledge is power.

The original code says for example

const char MT_TIME[] PROGMEM                      = "Time";

That, I understand that forces MT_TIME string to be stored into flash program memory.

I want a structure stored in flash program memory with two members each of one stored also in flash program memory.

I know that if I write:

typedef struct PROGMEM
{
	char* line1;
	char* line2;
}LCD_MSG;  //typedef for LCD_MSGs 

const struct LCD_MSG MT_WELCOME PROGMEM;
const MT_WELCOME.line1 PROGMEM= "THE AVR";
const MT_WELCOME.line2 PROGMEM= "POTENTIOSTAT";

it will do the trick.

I am just trying to do it the way I thought it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Excuse me if I am too stubborn to understand exactly what you are trying to tell me.
Perhaps you are implying that I cannot do it at once
but I must initialize it in two steps.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, then let's take the easy way and give you the code:

const char MT_STR1[] PROGMEM = "str1";
const char MT_STR2[] PROGMEM = "str2"; 

const LCD_MSG MT_TEST PROGMEM = { MT_STR1, MT_STR2 }; 

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Stefan that was mean!
So I guess it cannot be done the way I thought it at first.
Thanks for your help.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Or, if you wish to assign a PROGMEM constant to a variable (by copying from ROM to RAM), you do the following:

PROGMEM const char SOMEBYTES[]="12345";

uint16_t charByteIndx=(uint16_t)&(SOMEBYTES);
char bts[5];

for (uint8_t i=0; i<5;i++){
  bts[i]=(char)pgm_read_byte(charByteIndx+i);
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Stefan what you were saying was right, tested and working (after checking the bytes of the code).

Now I have another problem, I would appreciate if anyone could help me with.

typedef struct PROGMEM
{
	PGM_P line1;
	PGM_P line2;
}LCD_MSG;  //typedef for LCD_MSGs 

const char MT_WELCOME1[] PROGMEM = "Testing line 1";
const char MT_WELCOME2[] PROGMEM = "Testing line 2";
const LCD_MSG MT_WELCOME PROGMEM = { MT_WELCOME1, MT_WELCOME2 }; 

//Copies string from flash memory to LCD at x y position
void CopyStringtoLCD(const unsigned char *FlashLoc, unsigned char x, unsigned char y)
{
	unsigned char i;
	LCDGotoXY(x,y);
	for(i=0;(unsigned char)pgm_read_byte(&FlashLoc[i]);i++)
	{
		LCDsendChar((unsigned char)pgm_read_byte(&FlashLoc[i]));
	}
}

void LCD_Show_Message(const LCD_MSG *message)
{
	LCDclr();
	CopyStringtoLCD(((const unsigned char*)message->line1),0,0);
	CopyStringtoLCD(((const unsigned char*)message->line2),0,1);
}


int main (void)
{
LCD_MSG *statetext = NULL;
...
*statetext = MT_WELCOME;

LCD_Show_Message(statetext);
...
statetext =  (LCD_MSG*) pgm_read_word(&menu_state[i].pText);

...
...
return 0;
}

The above code is almost working ... The welcoming works perfectly but when I change state and statetext to show to LCD with

statetext =  (LCD_MSG*) pgm_read_word(&menu_state[i].pText);

I do not get what I want. Plus (I have mkII JTAG) the code seems to get in a hole (black).
I believe I misuse the structure pointers.

Any indication or help would be great.

Thanks in advance.