Например TDA7294

Форум РадиоКот • Просмотр темы - FlexMenu - решение вопросов меню. Зацените.
Форум РадиоКот
Здесь можно немножко помяукать :)





Текущее время: Вт апр 16, 2024 10:37:20

Часовой пояс: UTC + 3 часа


ПРЯМО СЕЙЧАС:



Начать новую тему Ответить на тему  [ Сообщений: 78 ]  1, , ,  
Автор Сообщение
Не в сети
 Заголовок сообщения: FlexMenu - решение вопросов меню. Зацените.
СообщениеДобавлено: Сб май 02, 2020 10:33:54 
Ум, честь и совесть. И скромность.
Аватар пользователя

Карма: 97
Рейтинг сообщений: 2058
Зарегистрирован: Чт дек 28, 2006 08:19:56
Сообщений: 18030
Откуда: Новочеркасск
Рейтинг сообщения: 5
Медали: 2
Получил миской по аватаре (1) Мявтор 3-й степени (1)
Досамоизолировался я до изобретения велосипеда меню... В том или ином виде все это в моих проектах было и ранее, но теперь все объединил в одно целое.
Вот как-то так оно работает

На видео показаны основные фишки моего варианта:

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

Кто работал с MicroMenu, тому подобный способ описания структуры меню будет знаком. Как видите, главное отличие в том, что пункты имеют разный размер, т.е. количество полей разное. Это позволяет экономить память в некоторых случаях. С другой стороны, добавилась возможность добавить новое поле, которое я назвал по-русски свойством, а по-английски property. Пункты меню, имеющие такое поле, позоляют видеть значение свойства и менять его интерактивно - на видео вы это видели.

Меню с видео описывается в коде так:
Код:
// главное меню
//     id         name            parent   prev   next   func|subm   property
MENU_CMD( mm_1,   "BEEP",         NONE,   NONE,   mm_2,   beep);
MENU_PROP(mm_2,   "TEST",         NONE,   mm_1,   mm_3,   NULL,      PROP_U8(u8, NOSTORE, 0, 12));
MENU_PROP(mm_3,   "MOTOR",         NONE,   mm_2,   mm_4,   motor,      PROP_BOOL(motor_state, NOSTORE, sf("STOP"), sf("RUN")));
MENU_SUB( mm_4,   "SUBMENU",      NONE,   mm_3,   mm_5,   sm_1);
MENU_PROP(mm_5,   "TEMPERATURE",   NONE,   mm_4,   mm_6,   NULL,      PROP_I16(vfr, NOSTORE, -20, 20));
MENU_CMD( mm_6,   "LOAD",         NONE,   mm_5,   mm_7,   load);
MENU_CMD( mm_7,   "SAVE & EXIT",   NONE,   mm_6,   NONE,   save);

// субменю
MENU_CMD( sm_1, "STOP DEMO 1",      mm_4,   NONE,   sm_2,   done);
MENU_CMD( sm_2, "STOP DEMO 2",      mm_4,   sm_1,   sm_3,   done);
MENU_SUB( sm_3, "STOP SUB",         mm_4,   sm_2,   NONE,   ssm_1);

// субменю 2
MENU_CMD(ssm_1, "SUB STOP DEMO 1",   sm_3,   NONE,   ssm_2,   done);
MENU_CMD(ssm_2, "SUB STOP DEMO 2",   sm_3,   ssm_1,   ssm_3,   done);
MENU_CMD(ssm_3, "SUB STOP DEMO 3",   sm_3,   ssm_2,   NONE,   done);

Реализована поддержка следующих свойств:
    - целое число (со знаком и без оного, 8 и 16 бит), причем число можно выводить в десятичной или шестнадцатеричной форме;
    - булево значение (т.е. логическое) - оно отображается парой соответствующих строк текста;
    - выбор одного варианта из нескольких - каждый вариант так же представляется соответствующим текстом.

Относительно просто добавить поддержку и 32-битных чисел... Но надо ли? Вводить их значение при помощи кнопок "навигации" - это удовольствие не из приятных... При желании это можно реализовать по-старинке - написав свою функцию и назначив её нужному пункту меню...

Таким образом, моя система меню сразу позволяет решить следующие задачи, практически всегда присутствующие в проектах на МК с ЖКИ:
    - организовать процесс "настройки" всех параметров при помощи интуитивного меню;
    - сохранять автоматически в EEPROM все свойства, используемые в меню, и загружать их оттуда.

То есть теперь достаточно описать пункты меню вместе с соответствующими свойствами, выделить место под переменные для этих свойств (эти переменные затем использовать по назначению в программе), выделить место в EEPROM для сохранени значений этих свойств (все это указывается при создании свойства в пункте меню), и в нужный момент вызвать созданное меню на дисплей - все остальные заботы я уже решил!

Думаю, многие знают, что не всегда просто решить, напрмер, интерактивную регулировку яркости подсветки дисплея. Часто делают так: в меню выбирают пункт, по активации которого выводится редактор яркости (то ли шкала, то ли число), а потом, когда ввод нового значения яркости завершен, работа с меню завершается, и задается новое значение яркости. Так вот, в моей системе яркость может меняться одновременно с изменением соответствующего свойства! На видео вы могли видеть, как включается и выключается "моторчик" - точно так же можно выполнять какую-то функцию при каждом изменении числа. То есть реализован полностью интерактивный способ изменения всех свойств! И прощайте странные цифры, обозначающие включение или отключение каких-то режимов - здравствуйте понятные слова!

_________________
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: FlexMenu - решение вопросов меню. Зацените.
СообщениеДобавлено: Сб май 02, 2020 13:47:40 
Друг Кота
Аватар пользователя

Карма: 86
Рейтинг сообщений: 1018
Зарегистрирован: Чт апр 11, 2013 11:19:59
Сообщений: 4875
Откуда: Минск
Рейтинг сообщения: 0
Да. тема реализации хорошего и универсального меню, похоже, вечная и велосипедистая.

Для своего проекта тоже реализовывал что-то похожее (смотреть с момента 2:32).

Тут можно глянуть на идеи реализации: menu.h и menu.c

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

Самое муторное - это "красивый" вывод типа enum текстом, а не просто числами. В функциях ниже видно, как эти вещи "некрасиво" обрабатываются через switch ... case.

Можно было бы усложнить структуру MenuItem, и вынести все эти min/max туда, но было уже лениво, да и свои ограничения в этом тоже есть.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: FlexMenu - решение вопросов меню. Зацените.
СообщениеДобавлено: Сб май 02, 2020 14:18:16 
Ум, честь и совесть. И скромность.
Аватар пользователя

Карма: 97
Рейтинг сообщений: 2058
Зарегистрирован: Чт дек 28, 2006 08:19:56
Сообщений: 18030
Откуда: Новочеркасск
Рейтинг сообщения: 0
Медали: 2
Получил миской по аватаре (1) Мявтор 3-й степени (1)
Ну, в принципе, у меня тот же подход, разве что от массива перешёл к связному списку. Хотя, мог бы и массивом... раньше, кстати, именно массивом делал.
Главное, у меня все эти массивы и списки хранятся в памяти программ, что для AVR очень актуально. И более-менее возможным это стало с появлением полноценной поддержки указателей на память программ.

_________________
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!


Вернуться наверх
 
PCBWay - всего $5 за 10 печатных плат, первый заказ для новых клиентов БЕСПЛАТЕН

Сборка печатных плат от $30 + БЕСПЛАТНАЯ доставка по всему миру + трафарет

Онлайн просмотровщик Gerber-файлов от PCBWay + Услуги 3D печати
Не в сети
 Заголовок сообщения: Re: FlexMenu - решение вопросов меню. Зацените.
СообщениеДобавлено: Сб май 02, 2020 14:36:42 
Друг Кота
Аватар пользователя

Карма: 86
Рейтинг сообщений: 1018
Зарегистрирован: Чт апр 11, 2013 11:19:59
Сообщений: 4875
Откуда: Минск
Рейтинг сообщения: 0
А что эта за новость про полноценные указатели на flash в AVR? А то я как-то последние пару лет AVR подзабросил и STM32 осваиваю.

Раньше приходилось pgm_read_*() функциями пользоваться, а сейчас что-то изменилось?


Вернуться наверх
 
Организация питания на основе надежных литиевых аккумуляторов EVE и микросхем азиатского производства

Качественное и безопасное устройство, работающее от аккумулятора, должно учитывать его физические и химические свойства, профили заряда и разряда, их изменение во времени и под влиянием различных условий, таких как температура и ток нагрузки. Мы расскажем о литий-ионных аккумуляторных батареях EVE и нескольких решениях от различных китайских компаний, рекомендуемых для разработок приложений с использованием этих АКБ. Представленные в статье китайские аналоги помогут заменить продукцию западных брендов с оптимизацией цены без потери качества.

Подробнее>>
Не в сети
 Заголовок сообщения: Re: FlexMenu - решение вопросов меню. Зацените.
СообщениеДобавлено: Сб май 02, 2020 17:26:37 
Ум, честь и совесть. И скромность.
Аватар пользователя

Карма: 97
Рейтинг сообщений: 2058
Зарегистрирован: Чт дек 28, 2006 08:19:56
Сообщений: 18030
Откуда: Новочеркасск
Рейтинг сообщения: 0
Медали: 2
Получил миской по аватаре (1) Мявтор 3-й степени (1)
Вот именно что изменилось! Теперь можно сделать const __flash uint32_t *ptr; и потом спокойно разыменовывать его для чтения. Так что все эти pgm_read_xxxx можно, слава богу, забыть, как страшный сон.

_________________
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!


Вернуться наверх
 
Новый аккумулятор EVE серии PLM для GSM-трекеров, работающих в жёстких условиях (до -40°С)

Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре. Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.

Подробнее>>
Не в сети
 Заголовок сообщения: Re: FlexMenu - решение вопросов меню. Зацените.
СообщениеДобавлено: Сб май 02, 2020 18:27:18 
Поставщик валерьянки для Кота

Карма: 12
Рейтинг сообщений: 532
Зарегистрирован: Ср июл 17, 2013 13:55:57
Сообщений: 1978
Рейтинг сообщения: 0
https://gcc.gnu.org/onlinedocs/gcc/Name ... paces.html
Ну только это не пару лет назад изменилось, а лет 5-7 наверное назад. Но мало кто об этом слышал тогда. Один хрень остались нюансы. Функции stdlib'а (тот же printf) надо всё-равно вызывать отдельные, ибо они не из исходников берутся, а скомпилены с жесткой адресацией и соотв. для флэша копии инструкций есть с _P в названии. Но вот без pgmspace.h в основной программе уже можно обойтись, да.


Вернуться наверх
 
В сети
 Заголовок сообщения: Re: FlexMenu - решение вопросов меню. Зацените.
СообщениеДобавлено: Вт май 05, 2020 13:07:22 
Это не хвост, это антенна

Карма: 4
Рейтинг сообщений: 141
Зарегистрирован: Ср июн 25, 2008 15:19:44
Сообщений: 1383
Рейтинг сообщения: 0
Я уже сам хотел создать отдельную тему. Итак, я тоже использую концепцию MicroMenu. Но мне не понравилось ни так как это сделано в статье easyelectronics (хотя и взял оттуда наименования, Parent, Child), ни в оригинале на AVRFreaks.
Уже не важно, кто и как реализовал саму структуру. У каждого свой подход, свои потребности.
Я остановился на такой реализации для символьного дисплея:
menu.h
Спойлер
Код:
//==================
#ifndef MENU_H

#define MENU_H

#include "menu.h"

#include "main_def_func.h"
//==================

//==================
// Typedefs:
typedef void (*FuncPtr)(void);
//==================

//==================
typedef struct menu_item
{
   void         *Parent;
   void         *Child;
   void         *Next;
   void         *Prev;
   FuncPtr       EnterFunc;
   FuncPtr       PlusFunc;
   FuncPtr       MinusFunc;
   FuncPtr       MenuInitFunc;
   char __flash  *Rus_Text;
   char __flash  *Angl_Text;
} menu_item;
//==================

// Externs:
//==================
extern menu_item __flash *CurrMenuItem; // Текущий пункт меню.

extern menu_item __flash Null_Menu;
//==================

// Defines and Macros:
//==================
#define NULL_ENTRY Null_Menu
#define NULL_FUNC  (void*)0
#define NULL_TEXT  ""
#define PAGE_MENU  3
//==================

//==================
#define MAKE_MENU(Name, Parent, Child, Next, Prev, EnterFunc, PlusFunc, MinusFunc, MenuInitFunc, Rus_Text, Angl_Text) \
extern menu_item __flash Parent;                                                                                      \
extern menu_item __flash Child;                                                                                       \
extern menu_item __flash Next;                                                                                        \
extern menu_item __flash Prev;                                                                                        \
       menu_item __flash Name =                                                                                       \
{                                                                                                                     \
      (menu_item*)      &Parent,                                                                                      \
      (menu_item*)      &Child,                                                                                       \
      (menu_item*)      &Next,                                                                                        \
      (menu_item*)      &Prev,                                                                                        \
                         EnterFunc,                                                                                   \
                         PlusFunc,                                                                                    \
                         MinusFunc,                                                                                   \
                         MenuInitFunc,                                                                                \
                        {Rus_Text},                                                                                   \
                        {Angl_Text}                                                                                   \
}
//==================

//==================
#define PARENT          *((menu_item __flash*) (CurrMenuItem->Parent))
#define CHILD           *((menu_item __flash*) (CurrMenuItem->Child))
#define NEXT            *((menu_item __flash*) (CurrMenuItem->Next))
#define PREV            *((menu_item __flash*) (CurrMenuItem->Prev))
#define ENTER_FUNC      *((FuncPtr)            (CurrMenuItem->EnterFunc))
#define MENU_PLUS_FUNC  *((FuncPtr)            (CurrMenuItem->PlusFunc))
#define MENU_MINUS_FUNC *((FuncPtr)            (CurrMenuItem->MinusFunc))
#define MENU_INIT_FUNC  *((FuncPtr)            (CurrMenuItem->MenuInitFunc))
//==================

//==================
#define SET_MENU_LEVEL(x) \
   Set_Menu_Level(&x)

#define SET_MENU_ITEM(x) \
   Set_Menu_Item(&x)
   
#define GO_MENU_FUNC(x)  \
   MenuFunc((FuncPtr*)&x)
   
#define EXTERN_MENU(Name) \
    extern menu_item __flash Name;

#define CHK_CHANGE_MENU(x) \
   chk_change_menu(&x)
//==================

//==================
enum
{
   SET_LEVEL = 0,
   SET_NEXT,
   SET_PREV,
};
//==================

// Prototypes:
//==================
bool Set_Menu_Level (menu_item __flash *NewMenu);
bool MenuFunc(FuncPtr* Function);
bool chk_change_menu (menu_item __flash *NewMenu);
//==================

//==================
bool proc_menu_keys (void);
//==================

//==================
void Out_Menu_Items_Init (void);
void Out_Menu_Items (void);
//==================

//==================
void out_name_level (void);
u08 count_chars (char __flash *data);
void make_page_menu (void);
void inc_pos_y_curs (void);
void dec_pos_y_curs (void);
void set_pos_curs (void);
//==================

//==================
char __flash * Get_Addr_Lang_Text (void);
//==================

#endif


menu.c
Спойлер
Код:
//==================
#include "menu.h"
//==================

//==================
static u08 quant_items;
static u08 pos_y_curs;
//==================

//================
menu_item __flash *CurrMenuItem; // Текущий пункт меню.

menu_item __flash *BeginCurrMenuLevel; // Начало массива текущего уровня меню.

menu_item __flash *temp_menu;

menu_item __flash  Null_Menu = {(void*)0, (void*)0, (void*)0, (void*)0, NULL_FUNC, NULL_FUNC, NULL_FUNC, NULL_FUNC, NULL_TEXT, NULL_TEXT};
//================

//==================
bool Set_Menu_Level (menu_item __flash *NewMenu)
{
   if ((void*)NewMenu == (void*)&NULL_ENTRY)
      return false;
   else
   {
      CurrMenuItem = NewMenu;

      Out_Menu_Items_Init (); // Так как новый уровень, инициализация переменных.
      Out_Menu_Items (); // Вывод названия уровня меню и пунктов меню, курсора.

      GO_MENU_FUNC (MENU_INIT_FUNC);
      return true;
   }
}
//==================

//==================
bool MenuFunc (FuncPtr* Function)
{
   if ((void*) Function == (void*) NULL_FUNC)
      return false;
   else
   {
      ((FuncPtr) Function)();
      return true;
   }
}
//==================

/*
Уровни, пункты, текст - все выводится автоматом.
Так как все переходы по меню расписаны в структуре, то отпадает надобность в запоминании перемещений по меню.
*/

//==================
void Out_Menu_Items_Init (void)
{
   quant_items = 1;
   pos_y_curs = 1;

// Получение адреса начала массива уровня меню.
   BeginCurrMenuLevel = CurrMenuItem;
   temp_menu = (menu_item __flash *)(CurrMenuItem->Prev);

   while (1)
   {
      if ((void*)temp_menu == (void*)&NULL_ENTRY)
      {
         break;
      }
      else
      {
         BeginCurrMenuLevel = temp_menu;
         temp_menu = (menu_item __flash *)(temp_menu->Prev);
      }
   }

// Получение количества пунктов меню.
   temp_menu = (menu_item __flash *)(BeginCurrMenuLevel->Next);

   while (1)
   {
      if ((void*)temp_menu == (void*)&NULL_ENTRY)
      {
         break;
      }

      temp_menu = (menu_item __flash *)(temp_menu->Next);
      quant_items++;
   }

// Позиция курсора.
   if (quant_items > 1)
   {
      temp_menu = BeginCurrMenuLevel;

      while (1)
      {
         if ((void*)temp_menu == (void*)&NULL_ENTRY)
            return;

         if (temp_menu == CurrMenuItem)
            return;
         else
            pos_y_curs++;

         temp_menu = (menu_item __flash *)(temp_menu->Next);
      }
   }
}

void Out_Menu_Items (void)
{
   clr_dsp_buf ();

   out_name_level (); // Вывод названия уровня меню.

   make_page_menu (); // Вывод пунктов меню.

   set_pos_curs ();   // Установка позиции и вывод курсора.
}
//==================

//==================
// Вывод названия уровня меню.
void out_name_level (void)
{
   temp_menu = (menu_item __flash *)(CurrMenuItem->Parent); // Считывание названия уровня меню из пункта меню в верхнем уровне.

   if ((void*)temp_menu != (void*)&NULL_ENTRY)
   {
      u08 i = count_chars (Get_Addr_Lang_Text ()); // Подсчет кол-ва символов в строке.

// Выравнивание текста посередине строки дисплея.

      u08 a = i;

      i = (20 - i); // Дисплей 20x4. Отнимаем от 20 число символов.

      i >>= 1; // Делим остаток на 2.

      if (a & (1<<0))
         i += 2; // Если число нечетное.
      else
         i++; // Если число четное.

      Print_Buf (1, i, Get_Addr_Lang_Text ());
   }
}
//==================

//==================
// Подсчет кол-ва символов в строке.
u08 count_chars (char __flash *data)
{
   u08 i = 0;

   while (data [i])
   {
      i++;
   }
   return i;
}
//==================

//==================
void make_page_menu (void)
{
   signed char tmp_pos_y_curs;
   u08 i; // Счетчик страниц.
   u08 j; // Страница меню.

   if (quant_items > 1) // Если пунктов меню больше 1, значит есть что выводить.
   {
      temp_menu = BeginCurrMenuLevel;

      if (pos_y_curs > PAGE_MENU)
      {
         tmp_pos_y_curs = pos_y_curs;

         i = 0; // Счетчик страниц.

         while (tmp_pos_y_curs > 0)
         {
            tmp_pos_y_curs -= PAGE_MENU;
            i++;
         }
         tmp_pos_y_curs += PAGE_MENU;

         j = PAGE_MENU; // Страница меню.

         while (i-- > 1)
         {
            while (j--)
            {
               temp_menu = (menu_item __flash *)(temp_menu->Next); // Следующий пункт меню.
            }
            j = PAGE_MENU; // Страница меню.
         }
      }

      u08 pos_y_text_item = 2; //
      j = PAGE_MENU; // Страница меню.

      while (j--)
      {
         Print_Buf (pos_y_text_item, 2, Get_Addr_Lang_Text ()); // вывод названия пункта меню.

         temp_menu = (menu_item __flash *)(temp_menu->Next); // Следующий пункт меню.

         if ((void*)temp_menu == (void*)&NULL_ENTRY) // Если элемент Next
            return;                                  // пустой, то выход.
         else
            pos_y_text_item++;
      }
   }
}
//==================

//==================
void inc_pos_y_curs (void)
{
   if (quant_items > 1)
   {
      if (pos_y_curs < quant_items) pos_y_curs++;
   }
}

void dec_pos_y_curs (void)
{
   if (quant_items > 1)
   {
      if (pos_y_curs > 1) pos_y_curs--;
   }
}
//==================

//==================
void set_pos_curs (void)
{
   if (quant_items > 1)
   {
      signed char tmp = pos_y_curs;

      while (tmp > 0)
      {
         tmp -= PAGE_MENU;
      }

      if (tmp <= 0) tmp += PAGE_MENU;

      Print_Char (tmp + 1, 1, ARROW_RIGHT);
   }
}
//==================

//==================
bool chk_change_menu (menu_item __flash *NewMenu)
{
   if ((void*)NewMenu == (void*)&NULL_ENTRY)
      return false;
   else
      return true;
}
//==================

//==================
char __flash * Get_Addr_Lang_Text (void)
{
   switch (get_lang ())
   {
      case RUS:
         return temp_menu -> Rus_Text;

      case ANGL:
         return temp_menu -> Angl_Text;

      default:
         return NULL_TEXT;
   }
}
//==================


Это взято из проекта с семисегментниками.
menu.h
Спойлер
Код:
//==================
#ifndef MENU_H

#define MENU_H

#include "menu.h"

#include "main_def_func.h"
//==================

//==================
// Typedefs:
typedef void (*FuncPtr)(void);
//==================

//==================
typedef struct menu_item
{
   void         *Parent;
   void         *Child;
   void         *Next;
   void         *Prev;
   FuncPtr       PlusFunc;
   FuncPtr       MinusFunc;
   FuncPtr       EnterFunc;
   FuncPtr       MenuInitFunc;
   char __flash *Text;
} menu_item;
//==================

// Externs:
//==================
extern menu_item __flash *CurrMenuItem; // Текущий пункт меню.
extern menu_item __flash *BeginCurrMenuLevel; // Начало массива текущего уровня меню.

extern __flash menu_item Null_Menu;

extern char Menu_Str_Buf []; // Буфер для вывода текста.

extern void (*MenuFuncPtr)(void);
//==================

// Defines and Macros:
//==================
#define NULL_ENTRY Null_Menu
#define NULL_FUNC  (void*)0
#define NULL_TEXT  ""
#define PAGE_MENU  3
//==================

//==================
#define MAKE_MENU(Name, Parent, Child, Next, Prev, PlusFunc, MinusFunc, EnterFunc, MenuInitFunc, Text) \
extern menu_item __flash Parent;                                                                       \
extern menu_item __flash Child;                                                                        \
extern menu_item __flash Next;                                                                         \
extern menu_item __flash Prev;                                                                         \
       menu_item __flash Name =                                                                        \
{                                                                                                      \
      (menu_item*)      &Parent,                                                                       \
      (menu_item*)      &Child,                                                                        \
      (menu_item*)      &Next,                                                                         \
      (menu_item*)      &Prev,                                                                         \
                         PlusFunc,                                                                     \
                         MinusFunc,                                                                    \
                         EnterFunc,                                                                    \
                         MenuInitFunc,                                                                 \
                        {Text}                                                                         \
}
//==================

//==================
#define PARENT         *((menu_item __flash*) (CurrMenuItem->Parent))
#define CHILD          *((menu_item __flash*) (CurrMenuItem->Child))
#define NEXT           *((menu_item __flash*) (CurrMenuItem->Next))
#define PREV           *((menu_item __flash*) (CurrMenuItem->Prev))
#define PLUS_FUNC      *((FuncPtr)   (CurrMenuItem->PlusFunc))
#define MINUS_FUNC     *((FuncPtr)   (CurrMenuItem->MinusFunc))
#define ENTER_FUNC     *((FuncPtr)   (CurrMenuItem->EnterFunc))
#define MENU_INIT_FUNC *((FuncPtr)   (CurrMenuItem->MenuInitFunc))
//==================

//==================
#define SET_MENU_LEVEL(x) \
   Set_Menu_Level(&x)

#define GO_MENU_FUNC(x)  \
   MenuFunc((FuncPtr*)&x)

#define EXTERN_MENU(Name) \
    extern menu_item __flash Name;
//==================

//==================
enum
{
   SET_LEVEL = 0,
   SET_NEXT,
   SET_PREV,
};
//==================

// Prototypes:
//==================
bool Set_Menu_Level (menu_item __flash *NewMenu);
bool MenuFunc(FuncPtr* Function);
//==================

//==================
void Out_Menu_Items_Init (void);
void Out_Menu_Items (void);
//==================

//==================
bool proc_menu_keys (void);
//==================

#endif


menu.c
Спойлер
Код:
//==================
#include "menu.h"
//==================

//================
menu_item __flash *CurrMenuItem; // Текущий пункт меню.

menu_item __flash *BeginCurrMenuLevel; // Начало массива текущего уровня меню.

menu_item __flash *temp_menu;

menu_item __flash  Null_Menu = {(void*)0, (void*)0, (void*)0, (void*)0, NULL_FUNC, NULL_FUNC, NULL_FUNC, NULL_FUNC, {NULL_TEXT}};

void (*MenuFuncPtr)(void);
//================

//======================
// Уровни, пункты, текст - все выводится автоматом.
// Так как все переходы по меню расписаны в структуре, то отпадает надобность в запоминании перемещений по меню.
//======================

//==================
bool Set_Menu_Level (menu_item __flash *NewMenu)
{
   if ((void*)NewMenu == (void*)&NULL_ENTRY)
      return false;
   else
   {
      CurrMenuItem = NewMenu;
      clr_dsp_buf ();
      Print_Buf (1, CurrMenuItem->Text); // вывод названия пункта меню.
      GO_MENU_FUNC (MENU_INIT_FUNC);
      return true;
   }
}
//==================

//==================
bool Set_Menu_Item (menu_item __flash *NewMenu)
{
   if ((void*)NewMenu == (void*)&NULL_ENTRY)
      return false;
   else
   {
      CurrMenuItem = NewMenu;
      clr_dsp_buf ();
      Print_Buf (1, CurrMenuItem->Text); // вывод названия пункта меню.
      GO_MENU_FUNC (MENU_INIT_FUNC);
      return true;
   }
}
//==================

//==================
bool MenuFunc (FuncPtr* Function)
{
   if ((void*) Function == (void*) NULL_FUNC)
      return false;
   else
   {
      ((FuncPtr) Function)();
      return true;
   }
}
//==================

//==================
//---------- Навигация по меню. ----------
// Кнопки:
// Esc. Выход из меню. Переход на родительский уровень. Отмена.
// Enter. Вход в меню. Переход на пункт меню. Вход в режим редактирования параметра. Сохранение параметра.
// Plus. Следующий пункт меню. Изменение параметра. Увеличить значение параметра.
// Minus. Предыдущий пункт меню. Изменение параметра. Уменьшить значение параметра.
//----------
// Esc. Parent Level.
// Enter. Child Level. Func.
// Plus. Next Item. Func.
// Minus. Prev Item. Func.
//----------
bool proc_menu_keys (void)
{
   if (Get_Event (EV_ID_KEY_PRESSED))
   {
      switch (Get_Key_Code ())
      {
         case KEY_ESC_COD:
            if (SET_MENU_LEVEL (PARENT))
               return true;
            else
               return false;

         case KEY_ENTER_COD:
            if (CurrMenuItem -> EnterFunc != NULL_FUNC)
               GO_MENU_FUNC (ENTER_FUNC);

            if (SET_MENU_LEVEL (CHILD))
               return true;
            else
               return false;

         case KEY_PLUS_COD:
            if (CurrMenuItem -> PlusFunc != NULL_FUNC)
            {
               GO_MENU_FUNC (PLUS_FUNC);
               return false;
            }

            if (SET_MENU_LEVEL (NEXT))
               return true;
            else
               return false;

         case KEY_MINUS_COD:
            if (CurrMenuItem -> MinusFunc != NULL_FUNC)
            {
               GO_MENU_FUNC (MINUS_FUNC);
               return false;
            }

            if (SET_MENU_LEVEL (PREV))
               return true;
            else
               return false;

         default:
            return false;
      }
   }

   else
      return false;
}
//==================


В последнем примере проект. Дисплей из семисегментных индикаторов. Навигация 3 кнопки. Пришлось как следует помучаться, задать кнопками двойные назначения. Next_Plus, Prev_Minus. Получилось достаточно гибко. Игра не только алгоритмом но и тем, что находится в полях структуры.

С самого начала была сложность с параметрами. Они не для каждого пункта нужны. И потому лишняя информация. И здесь выход - хоть какая-то типизация, если параметров нет, указатель в NULL, если есть, указатель на параметры. Минус - лишний расход памяти.
Если в этом топике кто-нибудь поможет выработать решение с полем параметры, топик можно будет считать успешным.

Задача, написать макрос, который позволит сделать поле Parameters не обязательным. Как пример.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: FlexMenu - решение вопросов меню. Зацените.
СообщениеДобавлено: Вт май 05, 2020 15:19:10 
Ум, честь и совесть. И скромность.
Аватар пользователя

Карма: 97
Рейтинг сообщений: 2058
Зарегистрирован: Чт дек 28, 2006 08:19:56
Сообщений: 18030
Откуда: Новочеркасск
Рейтинг сообщения: 0
Медали: 2
Получил миской по аватаре (1) Мявтор 3-й степени (1)
Demiurg писал(а):
Если в этом топике кто-нибудь поможет выработать решение с полем параметры, топик можно будет считать успешным.

Задача, написать макрос, который позволит сделать поле Parameters не обязательным. Как пример.
именно это я и реализовал, помимо всего прочего, что вы могли бы заметить самии по примеру кода, что я приводил в первом сообщении, если бы не были так самоуверены.

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

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

так же, как я и писал в самом начале, я реализовал концепцию "свойств", т.е. отображаемых и редактируемых при помощи меню параметров программы. сейчас реализована поддержка свойств типа uint8_t, int8_t, uin16_t, int16_t, bool и "enum". поддержка означает, что любое из этих свойств можно:
    - отобразить в тексте пункта меню;
    - изменить на ±1 или ±N, где N<128 (N фиксируется для всей системы меню, но для изменения на N и на 1 применяются разные команды, т.е. можно реализовать обычное и ускоренное изменение свойства);
    - считать из EEPROM автоматически при инициализации меню или в любой момент отдельной функцией;
    - сохранить в EEPROM при помощи отдельной функции.

считывание/сохранение делается имнно для всех свойств, связанных с меню, т.е. автоматически, без необходимости делать это отдельно для каждого.
при отображении свойств типа bool вместо 1 или 0 (или вместо фиксированных строк "true"/"false") выводятся задаваемые пользователем строки, т.е. делается осмысленный вывод значения параметра типа "МОТОР ВКЛ.", "ПОДСВЕТКА ОТКЛ.".
для свойства "enum" подобных строк должно быть определено пользователем столько, сколько элементов перечисления.

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

как-то так вот. на двух приведенных ранее видео все эти возможности показаны.

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

_________________
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!


Вернуться наверх
 
В сети
 Заголовок сообщения: Re: FlexMenu - решение вопросов меню. Зацените.
СообщениеДобавлено: Вт май 05, 2020 15:52:41 
Это не хвост, это антенна

Карма: 4
Рейтинг сообщений: 141
Зарегистрирован: Ср июн 25, 2008 15:19:44
Сообщений: 1383
Рейтинг сообщения: 0
1 - Вспомним наши споры. И вспомним, что мы остановились на том, что остались при своих. Где-то я с вами согласен, но в основном мы разошлись.
2 - Нет никакой самоуверенности. А вот у вас я вижу самовосхваление вашего труда. Без эмоций. Напоминаю.
3 - Вам уже написали, значит другие тоже работали над этой темы (и я в том числе), и вам уже написали, что универсальности не добиться.
4 - Я на примере двух своих проектов показал, что универсальности нет. Разные типы дисплеев. И я не про символьный-графический-семисгментный. Разные количества строк, то сеть пунктов и выводимой на дисплей информации. Разная навигация, разное количество строк. Скроллинг, и все остальное прочее. Это тоже дело вкуса, и у каждого разный подход и предпочтения.

Поэтому, задвигаем в сторону все красивости. И программную реализацию. Смотрим шире. Главную причину я уже указал. Плюс вы еще на одну указали, что есть лишние поля. И я сам знаю о о них.

Нам не нужна на самом деле регулировка яркости дисплея на месте, это я сделал еще в 2013 году. И на самом деле это к меню не относится.

Что мы хотим от проекта? Хороший и удобный инструмент создания и редактирования меню. Итак, вспоминаем правило. Чем больше данных, структур - тем меньше программа. И наоборот. Что мы можем упаковать в структуры? Начинаем классифицировать.

Вы сказали, что поля "Enter", "Plus", "Minus" лишние. Согласен и не согласен. Особенно, если у кнопок альтернативные функции. Next-Plus, Prev_Minus. Для меня это был компромисс. Параметры тоже не в каждом пункте.

Вы написали, что решили эту проблему. Поделитесь. Это мы обсудим. Все остальное красивости. И мне неинтересны. И я уверен, что мою позицию поддержат. Если кто-то из новичков попросит готовое решение, почему бы и нет. Дадим ему тестовый проект для примера. Как это, вообще-то, в статьях по микроконтроллерам и делается. Ведь мы с вами уже знаем, как создавать меню. Не так ли?


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: FlexMenu - решение вопросов меню. Зацените.
СообщениеДобавлено: Вт май 05, 2020 16:06:59 
Ум, честь и совесть. И скромность.
Аватар пользователя

Карма: 97
Рейтинг сообщений: 2058
Зарегистрирован: Чт дек 28, 2006 08:19:56
Сообщений: 18030
Откуда: Новочеркасск
Рейтинг сообщения: 0
Медали: 2
Получил миской по аватаре (1) Мявтор 3-й степени (1)
Demiurg писал(а):
универсальности нет
универсальность есть. например, стандартная библиотека Си - разве она не универсальна? универсальность достигается предоставлением основных решений наиболее характерных задач. а остальное - да, требует усилий.

так вот. MicroMenu решает только одну проблему - составление структуры меню, как вы ранее справедливо заметили - просто фантик для обертки данных. и частично решает проблему навигации по этой структуре. вопрос отображения меню, как и вопрос получения "команд навигации" MicroMenu не решает.

моя версия, которую я назвал FlexMenu, решает еще несколько проблем - редактирование свойств. вопрос отображения структуры так же остается за рамками, как и вопрос получения команд управления.

именно отказом от 100% готовых решений достигается универсальность остальной части: структура меню неизменно создается одним и тем же кодом как для ЖКИ, так и для 7-сегментника, так и для терминала по USART. эта часть универсальна. так же универсальным остается часть, отвечающая за редактирование и сохранение/загрузку свойств - она не зависит от того, как меню отображается и чем управляется.

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

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

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

_________________
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!


Вернуться наверх
 
В сети
 Заголовок сообщения: Re: FlexMenu - решение вопросов меню. Зацените.
СообщениеДобавлено: Вт май 05, 2020 16:34:09 
Это не хвост, это антенна

Карма: 4
Рейтинг сообщений: 141
Зарегистрирован: Ср июн 25, 2008 15:19:44
Сообщений: 1383
Рейтинг сообщения: 0
единственное, что я пока не стал делать (и более того: не очень понимаю, надо ли это делать, а так же как оптимальнее всего это сделать) - это возврат из субменю ровно к тому виду родительского меню, из которого был вход в подменю. на видео вы видели это: вход в субменю осуществлялся из третьей или пятой строки меню, а после возврата из субменю выделенной оказывалась первая строка. если это не проблема (как по мне - так не проблема) - то и ладно, если это надо устранить - придется кумекать...

:) Я вам писал, что вы не поняли сути MicroMenu. Структуры завернутые в красивые фантики. Вся навигация уже намертво прошитая в структурах. Нет проблемы вернуться куда угодно, и зайти куда угодно. Именно возврат ОЧЕНЬ и КРАЙНЕ важен, особенно если меню увесистое. С десятками, сотнями пунктов меню и подменю. Я занимаюсь обслуживанием промышленного оборудования, и были частотники, что-то еще, возврат был на первый пункт. Знаете, как это дико выбешивает, если нужно настроить аппарат, а у него меню на сотни пунктов.
Как я вам уже писал, если ваш проект решит многие известные проблемы с меню, то он будет иметь неплохой успех. Не хуже, чем в статье на easyelectronics. Если же он удобен только для вас и только под ваш компилятор, он не будет иметь никакой практической цены. Кроме вас.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: FlexMenu - решение вопросов меню. Зацените.
СообщениеДобавлено: Вт май 05, 2020 16:43:25 
Ум, честь и совесть. И скромность.
Аватар пользователя

Карма: 97
Рейтинг сообщений: 2058
Зарегистрирован: Чт дек 28, 2006 08:19:56
Сообщений: 18030
Откуда: Новочеркасск
Рейтинг сообщения: 0
Медали: 2
Получил миской по аватаре (1) Мявтор 3-й степени (1)
Demiurg писал(а):
Я вам писал, что вы не поняли сути MicroMenu
я вам писал, что вы слишком самоуверены.
Demiurg писал(а):
Знаете, как это дико выбешивает, если нужно настроить аппарат, а у него меню на сотни пунктов.
не знаю, но представить могу :)
Demiurg писал(а):
если ваш проект решит многие известные проблемы с меню
так вы сформулируйте эти проблемы, потому как я не понимаю, о чем вы говорите, после того, как я расписал и продемонстрировал на видео уже реализованные возможности. что еще не решенным осталось-то?
Demiurg писал(а):
он будет иметь неплохой успех
я за славой не гонюсь :)

_________________
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: FlexMenu - решение вопросов меню. Зацените.
СообщениеДобавлено: Вт май 05, 2020 18:27:24 
Поставщик валерьянки для Кота

Карма: 20
Рейтинг сообщений: 253
Зарегистрирован: Вс июн 19, 2016 09:32:03
Сообщений: 2090
Рейтинг сообщения: 0
С самого начала была сложность с параметрами. Они не для каждого пункта нужны. И потому лишняя информация. И здесь выход - хоть какая-то типизация, если параметров нет, указатель в NULL, если есть, указатель на параметры. Минус - лишний расход памяти.
Если в этом топике кто-нибудь поможет выработать решение с полем параметры, топик можно будет считать успешным.

На C++ меню можно описать в одном виде, а потом на этапе компиляции взять массив и превратить его в нечто совершенно другое. Например, меню из первого поста может выглядеть так:
Спойлер
Код:
constexpr MenuItem menuItems[] =
{
    { 0, "BEEP",  beep },
    { 0, "TEST",  nullptr, PROP_U8(u8, NOSTORE, 0, 12) },
    { 0, "MOTOR", motor,   PROP_BOOL(motor_state, NOSTORE, sf("STOP"), sf("RUN")) },
    { 0, "SUBMENU" },
      { 1, "STOP DEMO 1", done);
      { 1, "STOP DEMO 2", done);
      { 1, "STOP SUB");
         { 2, "SUB STOP DEMO 1", done },
         { 2, "SUB STOP DEMO 2", done },
         { 2, "SUB STOP DEMO 3", done },
    { 0, "TEMPERATURE", nullptr, PROP_I16(vfr, NOSTORE, -20, 20) },
    { 0, "LOAD",        load },
    { 0, "SAVE & EXIT", save }
};

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


Вернуться наверх
 
В сети
 Заголовок сообщения: Re: FlexMenu - решение вопросов меню. Зацените.
СообщениеДобавлено: Вт май 05, 2020 20:05:53 
Это не хвост, это антенна

Карма: 4
Рейтинг сообщений: 141
Зарегистрирован: Ср июн 25, 2008 15:19:44
Сообщений: 1383
Рейтинг сообщения: 0
Нужен костяк, на котором можно уже реализовать все красивости, про которые вы так расписали. Пусть это даже не будет соответствовать вашим запросам, но полностью моим.
Анализируем. Навигация. Есть точка входа в меню. Этих точек может быть несколько. Дальше работает "матрица". Текущий пункт, подпункт, следующий, предыдущий. Закладываем "родительский" пункт. То есть, основа MicroMenu. Parent, Child, Next, Prev. Это ядро "матрицы". В ней у нас прописана вся навигация по меню. По сути отдельный конечный автомат. И текст пунктов меню. Это тоже обязательный элемент структуры. Здесь уже дело вкуса, у кого-то это указатель на текст, но здесь добавляется трудоемкость, придумывание название тексту. Лично мне такой способ не годится, потому прямой текст, и сразу визуально видно пункт меню в проекте и уменьшается количество мест для создания меню. Что остается у нас в итоге:
Код:
// NAME PARENT CHILD NEXT PREV TEXT // Можно так.
// NAME TEXT PARENT CHILD NEXT PREV // Можно так. Кому как нравится.

//===========
//         NAME       PARENT      CHILD       NEXT        PREV        TEXT
//----------

//----------
MAKE_MENU (L_DEFAULT, NULL_ENTRY, L_L1_I1,    NULL_ENTRY, NULL_ENTRY, "ПАРАМЕТРЫ");

MAKE_MENU (L_L1_I1,   L_DEFAULT,  NULL_ENTRY, L_L1_I2,    NULL_ENTRY, "Пункт 1");

Это минимальная структура, которая необходима для всех пунктов. Что делать дальше? Можно сделать поле-указатель (void*). Этим мы получаем свободу в плане, лепим уже где-то там необходимые нам структуры с необходимыми нам вещами, параметры, указатели на функции. Вариант так себе, это еще два байта на каждый пункт меню. А вот если бы написать такой-ие макрос-ы, что позволило бы в случае необходимости добавлять нужные поля. Вот как у Reflector. Но он говорит о плюсах. А я их не знаю.

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


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: FlexMenu - решение вопросов меню. Зацените.
СообщениеДобавлено: Вт май 05, 2020 21:48:02 
Ум, честь и совесть. И скромность.
Аватар пользователя

Карма: 97
Рейтинг сообщений: 2058
Зарегистрирован: Чт дек 28, 2006 08:19:56
Сообщений: 18030
Откуда: Новочеркасск
Рейтинг сообщения: 0
Медали: 2
Получил миской по аватаре (1) Мявтор 3-й степени (1)
Demiurg писал(а):
Есть подозрение, что это и есть те два байта о которых я писал чуток выше. То есть спрятано в программе, но не во Flash
не те два байта, а разное количество байт, в зависимости от того, какие именно поля в структуре присутствуют, а какие отсутствуют. вся структура меню размещается во flash.

только что закончил "тестирование" размещения всего этого безобразия и в ОЗУ - для так любимой вами "кроссплатформенности". теперь можно или в ОЗУ все структуры строить, или во flash.

Добавлено after 1 hour 10 minutes 18 seconds:
подготовил DOXYGEN-документацию, прилагаю.
там есть ссылки почти на все исходники для ознакомления с их содержимым, все исходники "интерактивные", т.е. при наведении на все документированные штучки всплывает подсказка, а по клику происходит переход к описанию этой штуки.


Вложения:
FlexMenu.zip [254.19 KiB]
Скачиваний: 227

_________________
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: FlexMenu - решение вопросов меню. Зацените.
СообщениеДобавлено: Ср май 06, 2020 13:48:12 
Ум, честь и совесть. И скромность.
Аватар пользователя

Карма: 97
Рейтинг сообщений: 2058
Зарегистрирован: Чт дек 28, 2006 08:19:56
Сообщений: 18030
Откуда: Новочеркасск
Рейтинг сообщения: 0
Медали: 2
Получил миской по аватаре (1) Мявтор 3-й степени (1)
полный набор файлов FlexMenu вместе с демо-проектами и проектом протеуса доступны по ссылке: https://cloud.mail.ru/public/7eFh%2Fo9BnSJE3g

_________________
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: FlexMenu - решение вопросов меню. Зацените.
СообщениеДобавлено: Ср май 06, 2020 14:08:07 
Друг Кота
Аватар пользователя

Карма: 86
Рейтинг сообщений: 1018
Зарегистрирован: Чт апр 11, 2013 11:19:59
Сообщений: 4875
Откуда: Минск
Рейтинг сообщения: 0
В целом, красиво сделано.

Что мне не очень нравится, так это то, что у пункта меню есть поля .prev и .next. Я когда свою имплементацию делал, пытался от этого избавиться.

Ведь технически, эти поля - лишние. Плюс они требуют ручных изменений в структуре меню, если какой-то пункт хочется перенести в другое место - на том же уровне или подменю. Ну.. как бы схлопнуть разорванный двусвязный список и вставить пункт в другой.

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

В данной реализации последовательность объявления пунктов меню роли не играет. Она такая чисто для удобства чтения. Но вот в моём случае всё же приходится пользоваться общим массивом пунктов мееню (констатнтым, во flash), и тогда порядок описания пунктов меню уже сам по себе решает эту задачу.

Но как я писал раньше, свою реализацию я так до конца и не вылизал ещё. Поэтому сюда это в виде идеи подаю.


Вернуться наверх
 
В сети
 Заголовок сообщения: Re: FlexMenu - решение вопросов меню. Зацените.
СообщениеДобавлено: Ср май 06, 2020 14:28:43 
Это не хвост, это антенна

Карма: 4
Рейтинг сообщений: 141
Зарегистрирован: Ср июн 25, 2008 15:19:44
Сообщений: 1383
Рейтинг сообщения: 0
...

Будь другом, покажи здесь одну вещь, как ты реализовал необязательный параметр. Либо в личку. По сути, со времен MicroMenu, это у меня единственная заморочка. Помню пробовал, не получилось, плюнул, пошел дальше.

Добавлено after 15 minutes 24 seconds:
Я уже писал, чтобы была полноценная реализация навигации по меню, а тем более, чтобы возвращаться как в родительский так и в подпункты, нужно 4 поля. Parent, Child, Next, Prev. Нам нужно запомнить начало уровня и номер текущего пункта меню. Все. Выше я выкладывал примеры меню. Также у меня реализован вывод какого угодно числа пунктов. При символьном дисплее 20х4.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: FlexMenu - решение вопросов меню. Зацените.
СообщениеДобавлено: Ср май 06, 2020 15:11:19 
Ум, честь и совесть. И скромность.
Аватар пользователя

Карма: 97
Рейтинг сообщений: 2058
Зарегистрирован: Чт дек 28, 2006 08:19:56
Сообщений: 18030
Откуда: Новочеркасск
Рейтинг сообщения: 0
Медали: 2
Получил миской по аватаре (1) Мявтор 3-й степени (1)
WiseLord писал(а):
Ведь технически, эти поля - лишние.
проблема лично для меня в том, что я пока не смог написать макрос, который бы позволял создавать массив указателей на структуры переменной длины прямо в инициализации самого массива. для списка взял идею из MicroMenu, а вот для массива не выходит - ругается компилятор на неопределенный размер структуры... или я чего-то не понимаю, или это невозможно в принципе.

поэтому пришлось делать список.

раньше тоже делал меню массивами. но все структуры были фиксированного размера - снова лишние поля...
Demiurg писал(а):
нужно 4 поля. Parent, Child, Next, Prev.
я сделал на трех. проблему с возвратом из субменю к первому пункту решил - она решаема для любого количества пунктов любых реализаций, и в примерах проектов, которые я выложил вместе с исходниками, это демонстрируется: возврат из субменю происходит к выделению "входного" пункта.
Demiurg писал(а):
как ты реализовал необязательный параметр.
анонимный union: для пункта "команда" не нужно поле "субменю", но нужно поле "функция", для пункта "субменю" не нужно поле "функция", но нужно поле "субменю" - если сделать оба поля в union-е, то вместо двух полей будет фактически одно... так можно и для трех, и для четырех сделать - было бы желание.

Добавлено after 3 minutes 29 seconds:
WiseLord, я старался сделать так, чтобы можно было максимально абстрагироваться от патформы... можете собрать демо-проект под свой ARM - получилось у меня или нет? в fmenu_config.h надо заремарить PLACE_CONST_IN_FLASH - у ARM памяти много... и должно собраться. с портами и USART, конечно, я не знаю, насколько просто будет выглядеть адаптация демо-проекта...

_________________
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!


Вернуться наверх
 
В сети
 Заголовок сообщения: Re: FlexMenu - решение вопросов меню. Зацените.
СообщениеДобавлено: Ср май 06, 2020 17:40:28 
Это не хвост, это антенна

Карма: 4
Рейтинг сообщений: 141
Зарегистрирован: Ср июн 25, 2008 15:19:44
Сообщений: 1383
Рейтинг сообщения: 0
Пара моментов. Скажу сразу, взглянул на ваш код и у меня "бигуди зашевелились"...
Первый. В статье про MicroMenu честно написано, сколько байтов на пункт меню тратится. В своей переделке я тоже знаю. Вы можете сказать, сколько у вас тратится? В разных вариациях.
Второй момент. Проект MicroMenu хорош, если параметры идут списком. Мне вот интересно, а что если экран примерно такого вида? У меня это визуально реализовано так. Значение нужного параметра мигает. Это означает, что его можно редактировать.
Вложение:
000001.jpg [200.09 KiB]
Скачиваний: 198

Я когда начинал возиться с меню, смотрел в сторону DOS (autoexec.bat, config.sys (у меня где-то до сих пор сохранились книги, распечатки, файлы про MS-Dos, команды (в свое время делал мультизагрузку (один мой рабочий загрузочный диск мой знакомый даже купил)))), Volcov Commander с его vc.mnu. И остановился я в итоге вот на какой концепции. Универсальности нет и не будет. ПЛК, точнее, панель оператора. Это абсолютно самостоятельный модуль, пусть и подчиненный. Работа панели оператора не влияет на работу ПЛК, работа ПЛК не влияет на работу панели. Так вот, меню - это самостоятельный модуль. И состояние другого модуля. Я его назвал info_service. Несколько лет наткнулся на TUI, но этот проект не соответствовал моим запросам. В итоге родилась концепция info_service. Мухи отдельно, котлеты отдельно. Ха, кстати, в одном проекте остался этот рудимент. Название, но не суть. Где-то 2013 год.
Вложение:
000002.jpg [135.25 KiB]
Скачиваний: 191


Вернуться наверх
 
Показать сообщения за:  Сортировать по:  Вернуться наверх
Начать новую тему Ответить на тему  [ Сообщений: 78 ]  1, , ,  

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 28


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
Extended by Karma MOD © 2007—2012 m157y
Extended by Topic Tags MOD © 2012 m157y