micromenu-v2

Обсуждаем контроллеры компании Atmel.
Аватара пользователя
НовыйДень
Потрогал лапой паяльник
Сообщения: 362
Зарегистрирован: Вс апр 03, 2022 07:01:29

Re: micromenu-v2

Сообщение НовыйДень »

Не знаю, я сам делал менюшки на основе набивания собственных шишек и мучений, иногда подглядывая за чужими реализациями.
Можно и без С++ написать. И даже без указателей на функции. Просто это будет громозко и неуниверсально. Но можно. Для каждой кнопки напишите исполняемые функции, вызываемые при детектировании факта нажатия кнопки, и внутри их по переменным текущего состояния и режима уже определяйте, какую исполняемую функцию вызывать в зависимости от режима менюшки. Быть может, так вам будет легче разобраться.
Реклама
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Re: micromenu-v2

Сообщение Dimon456 »

Хмм, в начале темы ENTER есть
Спойлер

Код: Выделить всё

enum ButtonValues
{
    BUTTON_NONE,
    BUTTON_UP,
    BUTTON_DOWN,
    BUTTON_LEFT,
    BUTTON_RIGHT,
    BUTTON_ENTER,
};
теперь его убрали
Спойлер

Код: Выделить всё

extern enum ButtonValues
{
   BUTTON_NONE,
   BUTTON_UP,
   BUTTON_DOWN,
   BUTTON_LEFT,
   BUTTON_RIGHT
};
или, может, обрабатывать ENTER не планируете?
Реклама
Land
Прорезались зубы
Сообщения: 217
Зарегистрирован: Ср янв 11, 2012 11:55:51

Re: micromenu-v2

Сообщение Land »

Demiurg, да, я знаю про конечные автоматы и именно так и пытаюсь реализовать. И хотя много легче на стало, я кажется понимаю, куда надо копать. Я не мог перейти от модуля обработки кнопок к модулю меню. Буду пробовать переработать структуру автоматов.
BOB51, ну вот я раньше все небольшие проектики на ассме делал и все было нормально. А вот с переходом на С есть определенные сложности )
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15563
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: micromenu-v2

Сообщение BOB51 »

На ассемблере можно и весьма крупные проекты делать.
Единственно придется к "многофайловому" варианту оформления/написания переходить.
То же самое и на СИ/С++ - в рамках одного файла не получится чего солидного нашкарябать (чем больше текста - тем сложнее разбираться).
А вот правила "многофайловиков" в сишных проектах заметно сложнее.
8)
Реклама
Эиком - электронные компоненты и радиодетали
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

Re: micromenu-v2

Сообщение Demiurg »

Я начинал с асма, сидел на нем несколько лет. Потом перешёл на си. Нет разницы, на каком языке. Главное в организации программных модулей, их взаимосвязях.
Вечером, если не забуду, попробую выложить пример.
Реклама
Land
Прорезались зубы
Сообщения: 217
Зарегистрирован: Ср янв 11, 2012 11:55:51

Re: micromenu-v2

Сообщение Land »

[uquote="Demiurg",url="/forum/viewtopic.php?p=4209356#p4209356"]Вечером, если не забуду, попробую выложить пример.[/uquote]
вот этот?
Спойлер

Код: Выделить всё

//==================
#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_TEXT}};

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

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

CurrMenuItem = NewMenu;

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

GO_MENU_FUNC (MENU_FUNC);
}
//==================

//==================
void Set_Menu_Item (menu_item __flash *NewMenu)
{
if ((void*)NewMenu == (void*)&NULL_ENTRY)
 return;

CurrMenuItem = NewMenu;

Out_Menu_Items (); // Вывод названия уровня меню и пунктов меню, курсора.

GO_MENU_FUNC (ENTER_FUNC);
}
//==================

//==================
void MenuFunc (FuncPtr* Function)
{
if ((void*) Function == (void*) NULL_FUNC)
 return;

((FuncPtr) Function)();
}
//==================

//==================
bool proc_menu_keys (void)
{
switch (GetKeyCode ())
{
 case KEY_ESC_COD:
	 SET_MENU_LEVEL (PARENT);
	 return true;

 case KEY_ENTER_COD:
	 SET_MENU_LEVEL (CHILD);
	 return true;

 case KEY_NEXT_COD:
	 inc_pos_y_curs ();
	 SET_MENU_ITEM (NEXT);
	 return true;

 case KEY_PREV_COD:
	 dec_pos_y_curs ();
	 SET_MENU_ITEM (PREV);
	 return true;

 default:
	 return false;
}
}
//==================

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

//==================
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)
{
 char __flash *data = temp_menu->Text;

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

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

 u08 a = i;

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

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

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

 Print_Buf (1, i, temp_menu->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, temp_menu->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;

 PrintChar (tmp + 1, 1, ARROW_RIGHT);
}
}
//==================
вот например в этом примере я не могу понять, где используется результат функции bool proc_menu_keys (void). Булевое значение же должно где-то проверяться? Или это совершенно не важно и просто происходит переход по указателю SET_MENU_LEVEL ?
Реклама
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18546
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: micromenu-v2

Сообщение ARV »

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

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

все это описано в документации.

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

Добавлено after 3 minutes 29 seconds:
кстати, я хотел бы получить пояснения на счет "корабля" - если я понял контекст высказывания верно, то вы упоротый укроп и помогать вам нет никакого смысла. разубедите меня.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

Re: micromenu-v2

Сообщение Demiurg »

Давайте будем на этом форуме вне политики. Любой разлад на руку "империи лжи"....
Land
Прорезались зубы
Сообщения: 217
Зарегистрирован: Ср янв 11, 2012 11:55:51

Re: micromenu-v2

Сообщение Land »

Спасибо всем за терпение и объяснения. Запустил.
DimAlt
Вымогатель припоя
Сообщения: 576
Зарегистрирован: Пт май 19, 2006 05:39:11
Контактная информация:

Re: micromenu-v2

Сообщение DimAlt »

Может кому пригодится, переписал свою версию микроменю для ардуино на ESP32. https://disk.yandex.ru/d/fBMnIz8LAprE6Q В папке два проекта, просто использование шрифтов сгенерированных в программе CXFontGenerator_3 и проект микроменю, https://youtube.com/shorts/f47wOlPhV0s. Там внизу цифры, просто для примера вывода их из разных шрифтов. Один шрифт содержит только цифры и вызывается со смещением '0', второй вызывается со смещением 0, и в нем, например, вместо цифр можно хранить свои картинки. В принципе можно оставить только два файла микроменю в папке lib, рисование пунктов сделать через функции библиотеки tft, но мне сильно не хватает вывода с выравниванием по правому краю. Работает немного тормознуто. Но и с родными библиотечными функциями print и т.д. примерно также.
Проект создан в vscode+platformio.
Nunga
Родился
Сообщения: 3
Зарегистрирован: Пт ноя 26, 2021 16:01:57

Re: micromenu-v2

Сообщение Nunga »

познавательная тема, однако.
Sergio_fe
Родился
Сообщения: 5
Зарегистрирован: Пт апр 05, 2024 13:26:12

Re: micromenu-v2

Сообщение Sergio_fe »

Доброго времени суток. Подскажите, как можно выключить вывод меню на экран в этой библиотеке?? Идея банальная, если на кнопку не нажимают более 30 секунд - экран ( подсветка) гаснет (это сделано) , меню не выводится ( с этим бьюсь). спасибо
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

Re: micromenu-v2

Сообщение Demiurg »

Конечные автоматы. Состояния. Пример. Состояние. Ничего не надо выводить. Ждём события, под событиями понимаются все что угодно. В смысле по задаче. Вход сыграл. Таймер сработал. Ну и так далее.
Типа так:

Код: Выделить всё

switch(S)
      {
        case State_nichego_ne_vivodim_gdem_sobitie:
            break;
Аватара пользователя
BOB51
Друг Кота
Сообщения: 15563
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Re: micromenu-v2

Сообщение BOB51 »

Один из вариантов управления для "масштабируемой многофункционалки"
"в рамках адрины":
https://radiokot.ru/forum/viewtopic.php ... 5#p4655815
:roll:
Ответить

Вернуться в «AVR»