Jump to content

    

Инструмент для создания меню

Всем привет)
К stm32 прикрутил glcd с разрешением 128*64 и библиотеку u8g2.
Теперь встал вопрос по созданию меню.

Когда-то для строчного экрана писал меню сам, но получилось довольно громоздко.

Поделитесь опытом, кто как делал меню, может посоветуете готовые библиотеки.

Гугление особо ничего не дало, кроме ардуинных решений особо ничего не накопал.

Share this post


Link to post
Share on other sites

menu.h

Spoiler

typedef const struct Menu_Item
{
    const struct Menu_Item *Next;     /**< Pointer to the next menu item of this menu item */
    const struct Menu_Item *Previous; /**< Pointer to the previous menu item of this menu item */
    const struct Menu_Item *Parent;   /**< Pointer to the parent menu item of this menu item */
    const struct Menu_Item *Child;    /**< Pointer to the child menu item of this menu item */
    void (*SelectCallback)(void);     /**< Pointer to the optional menu-specific select callback of this menu item */
    void (*EnterCallback)(void);      /**< Pointer to the optional menu-specific enter callback of this menu item */
    const uint32_t Options;
    const char Text[];                /**< Menu item text to pass to the menu display callback function */
} Menu_Item_t;


#define MENU_ITEM(Name, Next, Previous, Parent, Child, SelectFunc, EnterFunc, Options, Text) \
    extern Menu_Item_t Next;     \
    extern Menu_Item_t Previous; \
    extern Menu_Item_t Parent;   \
    extern Menu_Item_t Child;    \
    Menu_Item_t Name = {&Next, &Previous, &Parent, &Child, SelectFunc, EnterFunc, Options, Text}


//#define MENU_PARENT     (&Menu_GetCurrentMenu()->Parent)
#define MENU_PARENT     (CurrentMenuItem->Parent)

/** Relative navigational menu entry for \ref Menu_Navigate(), to move to the menu child. */
//#define MENU_CHILD      (&Menu_GetCurrentMenu()->Child)
#define MENU_CHILD      (CurrentMenuItem->Child)

/** Relative navigational menu entry for \ref Menu_Navigate(), to move to the next linked menu item. */
//#define MENU_NEXT           (&Menu_GetCurrentMenu()->Next)
#define MENU_NEXT       (CurrentMenuItem->Next)
/** Relative navigational menu entry for \ref Menu_Navigate(), to move to the previous linked menu item. */
//#define MENU_PREVIOUS       (&Menu_GetCurrentMenu()->Previous)
#define MENU_PREVIOUS   (CurrentMenuItem->Previous)

extern Menu_Item_t NULL_MENU;

menu.c

 

Spoiler

//MAIN MENU
//        NAME      NEXT,       PREVIOUS    PARENT,      CHILD       SELECT       ENTER      OPTIONS                          TEXT
MENU_ITEM(m_auto,   m_manual,   m_muxbus,   NULL_MENU,   NULL_MENU,  NULL_FUNC,   Auto,      DIM_ON | TIMEOUT_ON | AUTO_ID,   "AUTO  ");
MENU_ITEM(m_manual, m_fails,    m_auto,     NULL_MENU,   NULL_MENU,  NULL_FUNC,   ManualEnt, DIM_ON | TIMEOUT_ON | MANUAL_ID, "MANUAL");
MENU_ITEM(m_fails,  m_maint,    m_manual,   NULL_MENU,   NULL_MENU,  NULL_FUNC,   Fails,     DIM_ON | TIMEOUT_ON | FAILS_ID,  "FAILS ");
MENU_ITEM(m_maint,  m_muxbus,   m_fails,    NULL_MENU,   NULL_MENU,  NULL_FUNC,   GoToChild, DIM_ON | TIMEOUT_ON | MAINT_ID,  "MAINT ");
MENU_ITEM(m_muxbus, m_auto,     m_maint,    NULL_MENU,   NULL_MENU,  NULL_FUNC,   GoToChild, DIM_ON | TIMEOUT_ON | MUXBUS_ID, "MUXBUS");

void MENU_Navigate(Menu_Item_t* NewMenu)
{
    if ((NewMenu == &NULL_MENU) || (NewMenu == 0))
	return;

    CurrentMenuItem = NewMenu;

    if (CurrentMenuItem->Options & TIMEOUT_ON)
	    menu_timeout = globalSysTimer;

    if (CurrentMenuItem->Options & SEL_ENA)
        select_ena = 1;
    else
    	select_ena = 0;

    enter_idx = 0;

    if (CurrentMenuItem != 0 && CurrentMenuItem != &NULL_MENU)
        write_text((uint8_t *)(CurrentMenuItem->Text));
}


void MENU_Run(uint32_t key_val)
{
    if (key_val > 0)
    {
    	key_pressed = key_val;

        switch(key_val)
		{
			case RIGHT_ARROW:
				MENU_Navigate(MENU_NEXT);
			break;

			case LEFT_ARROW:
				MENU_Navigate(MENU_PREVIOUS);
			break;

			case UP_ARROW:
				MENU_Navigate(MENU_PARENT);
			break;

			case DOWN_ARROW:
				MENU_Navigate(MENU_CHILD);
			break;

			case ENTER_PRE:
                    //ENTER Function - on enter button press
				if (CurrentMenuItem->EnterCallback != NULL_FUNC)
					CurrentMenuItem->EnterCallback();
			 break;
		}
    }

    //SELECT Function runs in background
    if (CurrentMenuItem->SelectCallback != NULL_FUNC)
    {
    	if (select_ena)
    	{
    	    CurrentMenuItem->SelectCallback();
    	}
    }

    
    MENU_Timeout();
}

 

 

оригинал тут. работает отлично. я доволен.

Edited by jenya7

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites
2 minutes ago, Eddy_Em said:

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

у меня около 70 меню в 4-х уровнях. пару часов внимательно посидеть и все оки. :)

Share this post


Link to post
Share on other sites

Спасибо, сейчас буду разбираться

Share this post


Link to post
Share on other sites

Пытаюсь разобраться с micromenu-v2, идет туго.
Никакой документации.

Ни у кого случайно не завалялся любой собираемый проект с меню под IAR/KEIL для любого stm32?

Share this post


Link to post
Share on other sites

На github поиском не имеете пользоваться ?

https://github.com/taburyak/Control_Voltage_Battery

первый в списке

Хотя и разбираться особо нечего в трёх файлах

https://github.com/abcminiuser/micromenu-v2

Share this post


Link to post
Share on other sites
10 minutes ago, x893 said:

На github поиском не имеете пользоваться?

Я действительно никогда не пользовался гитхабовским поиском, даже в голову не приходило....
Огромное спасибо за подсказку и ссылки)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now