Что за хрень у меня с PROGMEM?

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Вот такой несложный примерчик:

char buf[30] = {};

typedef const struct PROGMEM MENU1 {
  const struct MENU1 *Next; 
  const struct MENU1 *Previous;
  const struct MENU1 *Parent;
  const struct MENU1 *Child;
  void (*handler)(void);
  const char Name[21];
} MENU;

MENU *curr = NULL;

MENU Menu[]={

{&Menu[1],&Menu[2],&Menu[0],&Menu[3],0,"Menu1"},  //
{&Menu[2],&Menu[0],&Menu[1],&Menu[1],0,"Menu2"},  //  
{&Menu[0],&Menu[1],&Menu[2],&Menu[2],0,"Menu3"},  //

{&Menu[4],&Menu[5],&Menu[0],&Menu[6],0,"SUB_Menu1  "},  //
{&Menu[5],&Menu[3],&Menu[1],&Menu[4],0,"SUB_Menu2  "},  // 
{&Menu[3],&Menu[4],&Menu[2],&Menu[5],0,"SUB_Menu3  "}
};

void setup() {
  Serial.begin(115200);

  for (int i=0; i<6;i++)
  {
     curr = (MENU*)pgm_read_byte(&Menu[i]);
     sprintf_P(buf, PSTR("%S"), (char*)curr->Name);
     Serial.println(buf);
  }
}

void loop() {

}

А на выходе: 

Menu2
Menu3
Menu1
SUB_Menu2  
SUB_Menu1 
 
Это как так получается?
 
asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Atmega328. Компилятор предупреждений не дает даже с -Wall

rkit
Онлайн
Зарегистрирован: 23.11.2016

pgm_read_byte

Ну и указатели на память из progmem-структуры - шикардос

b707
Offline
Зарегистрирован: 26.05.2017

хм, я бы тоже спросил "что за хрень"?

MENU Menu[]={

{&Menu[1],&Menu[2],&Menu[0],&Menu[3],0,"Menu1"},  //
{&Menu[2],&Menu[0],&Menu[1],&Menu[1],0,"Menu2"},  //  
{&Menu[0],&Menu[1],&Menu[2],&Menu[2],0,"Menu3"},  //

{&Menu[4],&Menu[5],&Menu[0],&Menu[6],0,"SUB_Menu1  "},  //
{&Menu[5],&Menu[3],&Menu[1],&Menu[4],0,"SUB_Menu2  "},  // 
{&Menu[3],&Menu[4],&Menu[2],&Menu[5],0,"SUB_Menu3  "}
};

указатели сами на себя? - ну допустим... 

а ничего, что в момент инициализации первой строки еще не существует Menu[1] Menu[2] и Menu[3] - а ссылки на них уже используются? - или компилятор разберется?

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

rkit пишет:

pgm_read_byte 

Замена на pgm_read_word  в данном случае ничего не меняет, хотя да, байт это косяк.

 

Цитата:
Ну и указатели на память из progmem-структуры - шикардос

Ну и как надо? 

 

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

b707 пишет:

хм, я бы тоже спросил "что за хрень"?

MENU Menu[]={

{&Menu[1],&Menu[2],&Menu[0],&Menu[3],0,"Menu1"},  //
{&Menu[2],&Menu[0],&Menu[1],&Menu[1],0,"Menu2"},  //  
{&Menu[0],&Menu[1],&Menu[2],&Menu[2],0,"Menu3"},  //

{&Menu[4],&Menu[5],&Menu[0],&Menu[6],0,"SUB_Menu1  "},  //
{&Menu[5],&Menu[3],&Menu[1],&Menu[4],0,"SUB_Menu2  "},  // 
{&Menu[3],&Menu[4],&Menu[2],&Menu[5],0,"SUB_Menu3  "}
};

указатели сами на себя? - ну допустим... 

а ничего, что в момент инициализации первой строки еще не существует Menu[1] Menu[2] и Menu[3] - а ссылки на них уже используются? - или компилятор разберется?

Да бог с ними с указателями, я же ими не пользуюсь. Просто взял пример с просторов. Хотя по 

curr = (MENU*)pgm_read_byte(&curr->Next);  

Переходит, вроде, правильно.

А начал с того что пытался прикрутить https://github.com/abcminiuser/micromenu-v2 

Нихрена не заработало. Решил протестировать на чем попроще.

b707
Offline
Зарегистрирован: 26.05.2017

а если сначала создать массив, а потом уже заполнить ссылками? я понимаю, что некрасиво - но если глюки пропадут. будет ясно. что дело в инициализации

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Заработало после того как добавил  указатель на самого себя

char buf[30] = {};

typedef const struct PROGMEM MENU1 {
  const struct MENU1 *Self; 
  const struct MENU1 *Next; 
  const struct MENU1 *Previous;
  const struct MENU1 *Parent;
  const struct MENU1 *Child;
  void (*handler)(void);
  const char Name[21];
} MENU;

MENU *curr = NULL;

MENU Menu[]={

{&Menu[0],&Menu[1],&Menu[2],&Menu[0],&Menu[3],0,"Menu1"},  //
{&Menu[1],&Menu[2],&Menu[0],&Menu[1],&Menu[1],0,"Menu2"},  //  
{&Menu[2],&Menu[0],&Menu[1],&Menu[2],&Menu[2],0,"Menu3"},  //

{&Menu[3],&Menu[4],&Menu[5],&Menu[0],&Menu[6],0,"SUB_Menu1  "},  //
{&Menu[4],&Menu[5],&Menu[3],&Menu[1],&Menu[4],0,"SUB_Menu2  "},  // 
{&Menu[5],&Menu[3],&Menu[4],&Menu[2],&Menu[5],0,"SUB_Menu3  "}
};


void setup() {
  Serial.begin(115200);

  for (int i=0; i<6;i++)
  {
     curr = (MENU*)pgm_read_word(&Menu[i]);
     sprintf_P(buf, PSTR("%S"), (char*)curr->Name);
     Serial.println(buf);
  }
  curr = (MENU*)pgm_read_word(&curr->Next);
  sprintf_P(buf, PSTR("%S"), (char*)curr->Name);
  Serial.println("Next");
  Serial.println(buf);
  curr = (MENU*)pgm_read_word(&curr->Parent);
  sprintf_P(buf, PSTR("%S"), (char*)curr->Name);
  Serial.println("Parent");
  Serial.println(buf);

  
}
Menu1
Menu2
Menu3
SUB_Menu1  
SUB_Menu2  
SUB_Menu3  
Next
SUB_Menu1  
Parent
Menu1
 
sadman41
Offline
Зарегистрирован: 19.10.2016

asam, могу тебе подправленное микроменю2 выдать. У меня тоже с ходу не завелось, пришлось подебажить.

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

sadman41 пишет:

asam, могу тебе подправленное микроменю2 выдать. У меня тоже с ходу не завелось, пришлось подебажить.

О, буду очснь признателен.

sadman41
Offline
Зарегистрирован: 19.10.2016

давай мыло или сам напиши на wrk.sadman@gmail.com

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

sadman41 пишет:

давай мыло или сам напиши на wrk.sadman@gmail.com

Написал, но, на всякий случай продублирую здесь - automation248@hotmail.com

b707
Offline
Зарегистрирован: 26.05.2017

sadman41 пишет:

asam, могу тебе подправленное микроменю2 выдать. У меня тоже с ходу не завелось, пришлось подебажить.

а мне что-то оно вообще не понравилось, все эти ссылки совершенно левые :)

Слепил свое, упрощенное, в нет никаких Парентов и Некстов :), а просто каждая строчка может быть либо переходом в другое меню(дочернее, родительское - не важно), либо функцией.

Я его тут на форуме публиковал, надо поискать ссылку

sadman41
Offline
Зарегистрирован: 19.10.2016

b707 пишет:

sadman41 пишет:

asam, могу тебе подправленное микроменю2 выдать. У меня тоже с ходу не завелось, пришлось подебажить.

а мне что-то оно вообще не понравилось, все эти ссылки совершенно левые :)

А мне лень было лепить своё, я там подправил в трёх местах... наверное можно было и в двух, ну да ладно )

Вполне себе работает. Разве что удобно интегрируется на однострочники... с остальным всё равно приходится башку ломать.

b707
Offline
Зарегистрирован: 26.05.2017

во, нашел примерчик своего

http://arduino.ru/forum/pesochnitsa-razdel-dlya-novichkov/sozdanie-mnogourovnevogo-graficheskogo-menyu#comment-530028

Кстати, вспомнил главное достоинство моего варианта (ну с моей иочки зрения) - в моей структуре можно в любое место добавить дополнительные пункты, не меняя ссылок соседних элементов. А удалять - просто комментируя строчки меню в коде, структура меню подстроится под изменения сама.

 

да, там вся ветка интересная, много других примеров кода

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

1 Я вообще против организации меню на структурах. Конечно организация отображение информации на экране решается хорошо. Вот со сменой обработчиков кнопок выходит не очень. И при кнопках подключенных на отдельные выводы, что сенсорные кнопки на экране.

2 Вторая тюфтень. Что это за позиции 0,1,2,3  и так далее. Да это удобно для компьютера, Для человека это первый источник поймать косяк. Так что здесь сразу объявлять костанты page0,page1,page2, и разумеется делать их подразделы page0_0,page0_1,page1_0,page1_1,page2_0,page2_1. Перечисляемый тип это оно.

3 Переходить из одного пункта меню лучше по отдельной специальной функции goPage(page0_1);

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

qwone пишет:

1 Я вообще против организации меню на структурах. Конечно организация отображение информации на экране решается хорошо. Вот со сменой обработчиков кнопок выходит не очень. И при кнопках подключенных на отдельные выводы, что сенсорные кнопки на экране.

Это интересная тема которую, возможно, стоит обсудить в отдельном топике про организацию меню.

Цитата:
2 Вторая тюфтень. Что это за позиции 0,1,2,3  и так далее. Да это удобно для компьютера, Для человека это первый источник поймать косяк. ...

Еще раз повторю для тех кто не читает весь топик - Я не пытаюсь организовать меню именно таким образом. Я пытаюсь разобраться как адресовать структуры и их поля из PROGMEM и просто взял готовый пример.

И мне так до конца и не понятно почему если засунуть в начало структуры указатель на свой экземпляр, то все начинает работать, как ожидалось, а без этого нет. Если есть что по этому поводу сказать, то с удовольствием выслушаю. А про меню, давайте в другой топик.