structure pointers in pgmspace

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

I would appreciate if anyone could help me with this kind of problem.
I am using the butterfly gcc code modified for my own menu (details here:)
https://www.avrfreaks.net/index.p...
,
but I try to have a structure filled with message lines instead of raw strings.

Here is my code.

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.

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

Why have you cross posted this? Just as in the other copy you posted you haven't shown menu_state[]

(but it seems to me you probably have two levels of PROGMEM data (strings and then pointers to strings) but you are only making one pgm_read*() level of dereference)

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

sorry for cross posting but I thought that in the first post noone was willing to reply

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

menu state is like this...but with a lot more options

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

    {ST_MODES,							&MT_MODES,					NULL},
    {0,                                 NULL,                       NULL},

};

You mean I need to read twice with pgm_read_word?

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

Quote:

sorry for cross posting but I thought that in the first post noone was willing to reply

No cross posting just annoys folks. You've now split the discussion. Suppose I suggest something here then someone else reads the other thread and suggests something similar there. They will be rightly p'd off when they realise they just wasted their time.

Anyway what I'd suggest is that you drop PROGMEM out of the equation all together, get it working with RAM based data. Then a level at a time add back in the support for moving data into flash. First then strings themselves and then the pointers to them - adding levels of pgm_read*() at each stage.

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

ok, I'll try this, one step at a time.

thanks for your help.

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

The missing level of flash dereference is here:

   CopyStringtoLCD(((const unsigned char*)message->line1),0,0);
   CopyStringtoLCD(((const unsigned char*)message->line2),0,1); 

Stefan Ernst

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

so Stefan are you saying that i need extra dereference in CopyStringtoLCD function?
or that CopyStringtoLCD does the extra dereference?

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

LCD_Show_Message gets a pointer to a struct in flash and it wants to pass a part of the content of this structure to another function (CopyStringtoLCD). So you need to read this content from flash.

Stefan Ernst

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

I tried this but doesn't work

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

I also feel that after a few hours with pointers I do not have mind clarity :oops:

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

I have an array of structures in pgmspace

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

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

And also MT_WELCOME is in pgmspace initialised the way sternst implied

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 }; 

So, right now we have a member of a structure that is a pointer to another structure (LCD_MSG) that has two members that correspond to the LCD lines.

I believe I need to pgm_read_word() the structure that points to the LCD_MSG structure

temp = pgm_read_word(&menu_state[i].pText);

So passing this temp pointer to my

void LCD_Show_Message(const LCD_MSG *message) 

function would probably do the job.

But it doesn't!!!
Oh my god, please help!

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

kakarot wrote:
But it doesn't!!!
It will if LCD_Show_Message is properly implemented.

Look:
"menu_state[i]" is a structure in flash. You want to get the member "pText" of this structure (which is a pointer to something else). Your code for this:

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

Now inside of LCD_Show_Message "message" points to what? It points to something which is again a structure in flash. And again you want to get a member of this structure which is again a pointer to something else (to a string). But now your code for this is:

(const unsigned char*)message->line1

Stefan Ernst

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

Like I said, if you don't understand this - don't try to do it all on day one. Use building blocks (some might call it a "modular approach") and just add one layer of PROGMEM and then the next until you have something that works. At each stage you will add something to the data definition to move it from RAM to flash and the other side of this coin is that at the same time you will move the access code from a simple variable access to one using pgm_read*() going indirectly through a pointer to PROGMEM.

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
CopyStringtoLCD(((const unsigned char*)pgm_read_word(&message.line2)),0,1);

I tried this but I get compile error

Quote:
../lcd/lcd_lib.c:305: error: request for member 'line2' in something not a structure or union

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

Well is 'message' a structure (in which case '.' access is used) or is a pointer to struct (in which case '->' access is used).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
CopyStringtoLCD(((const unsigned char*)pgm_read_word(&message->line1)),0,0);

This is better, it compiles and partially the code works.
I'll examine my code and will be back.

Thank you very much, I appreciate your help.

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

kakarot wrote:
... and partially the code works.
Let me guess:
Quote:
The welcoming works perfectly
This is no longer true, right?
It worked in your former version only by accident.

Stefan Ernst

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

Those accidents make our life sweet...
But now everything seems fine.
Thank you.
Some of you can easily be called "senshei"
("Master" in japanese) -- RESPECT --