/**
  ******************************************************************************
  * @file menu.c
  * @brief This file contains all the functions for the menu demo.
  * @author STMicroelectronics - MCD Application Team
  * @version V1.1.0
  * @date    09/14/2009
  ******************************************************************************
  *
  */

// Includes ------------------------------------------------------------------
#include "menu.h"

// Private typedef -----------------------------------------------------------

// Private define ------------------------------------------------------------
#define MENU_TOP_TEXT        ("  ** MENU **  ")
#define HELP_TEXT            ("HELP - push SEL")
#define PWM_DEMO_TEXT        ("    PWM DEMO")
#define BEEPER_DEMO_TEXT     ("  BEEPER DEMO")
#define MICROSD_DEMO_TEXT    ("  MICROSD DEMO")
#define ABOUT_TEXT           ("     ABOUT")

__CONST MENU_NEXTSTATE_T MENU_NEXTSTATE[] =
    {
        // STATE                     INPUT           NEXT STATE 
        // MENU Level 1          /* Key */
        { HELP,                      LEFT,           ABOUT },
        { HELP,                      RIGHT,          PWM_DEMO },
        { HELP,                      SEL,            EXE_HELP },
        { PWM_DEMO,                  LEFT,           HELP },
        { PWM_DEMO,                  RIGHT,          BEEPER_DEMO },
        { PWM_DEMO,                  SEL,            EXE_PWM_DEMO },
        { BEEPER_DEMO,               LEFT,           PWM_DEMO },
        { BEEPER_DEMO,               RIGHT,          MICROSD_DEMO },
        { BEEPER_DEMO,               SEL,            EXE_BEEPER_DEMO },
        { MICROSD_DEMO,              LEFT,           BEEPER_DEMO },
        { MICROSD_DEMO,              RIGHT,          ABOUT },
        { MICROSD_DEMO,              SEL,            EXE_MICROSD_DEMO },
        { ABOUT,                     LEFT,           MICROSD_DEMO },
        { ABOUT,                     RIGHT,          HELP },
        { ABOUT,                     SEL,            EXE_ABOUT },

        // EXE menu 
        { EXE_ABOUT,                 UP,             ABOUT },
        { EXE_HELP,                  UP,             HELP },
        { EXE_PWM_DEMO,              UP,             PWM_DEMO },
        { EXE_BEEPER_DEMO,           UP,             BEEPER_DEMO },
        { EXE_MICROSD_DEMO,          UP,             MICROSD_DEMO },
        // End of table 
        { 0,                         0,              0, }
    };

__CONST MENU_STATE_T MENU_STATE[] =
    {
        // STATE                     STATE TEXT            FUNCTION 
        // MENU Level 1 
        { HELP,                      HELP_TEXT,            0 },
        { PWM_DEMO,                  PWM_DEMO_TEXT,        0 },
        { BEEPER_DEMO,               BEEPER_DEMO_TEXT,     BEEPERDEMO_Reset },
        { MICROSD_DEMO,              MICROSD_DEMO_TEXT,    MICROSDDEMO_Reset },
        { ABOUT,                     ABOUT_TEXT,           0 },
        // EXE menu 
        { EXE_HELP,                  0,                    HELP_Exec },
        { EXE_ABOUT,                 0,                    ABOUT_Exec },
        { EXE_PWM_DEMO,              0,                    PWMDEMO_Exec },
        { EXE_BEEPER_DEMO,           0,                    BEEPERDEMO_Exec },
        { EXE_MICROSD_DEMO,          0,                    MICROSDDEMO_Exec },
        // End of table 
        { 0,                         0,                    0 }
    };

// Private macro -------------------------------------------------------------
// Private variables ---------------------------------------------------------
STATE_ID_T PreviousTopState, State;
void (*pStateFunc)(void);

// Private function prototypes -----------------------------------------------
// Private functions ---------------------------------------------------------
/** Initialize the menu variables. Must be called by application Init function.
  * @param[in] None
  * @return None
  **/
void MenuInit(void)
{
    PreviousTopState = 0;
    State = HELP;
    pStateFunc = 0;
}

/** This function updates the menu states and display the new menu on the LCD.
  * @param[in] ujoystick is the new joystick state
  * @return None
  **/
void MenuUpdate(JOYSTICK_ID_T ujoystick)
{
    uint8_t i;
    STATE_ID_T NextState;

    NextState = 0;

    // Search if the next menu state exists 
    for (i = 0; MENU_NEXTSTATE[i].State; i++)
    {
        if (MENU_NEXTSTATE[i].State == State && MENU_NEXTSTATE[i].Key == ujoystick)
        {
            NextState = MENU_NEXTSTATE[i].NextState;
            break;
        }
    }

    // if next state exists 
    if (NextState)
    {
        // Update the previous top state 
        switch (ujoystick)
        {
        case UP:
            PreviousTopState = 0;
            for (i = 0; MENU_NEXTSTATE[i].State; i++)
            {
                if ((MENU_NEXTSTATE[i].State == NextState) && (MENU_NEXTSTATE[i].Key == UP))
                {
                    PreviousTopState = MENU_NEXTSTATE[i].NextState;
                    break;
                }
            }
            break;

        case SEL:
            // If a sub-menu is entered, the PreviousTopState is the current state 
            PreviousTopState = State;
            break;

        default:
            break;
        }
        State = NextState; /* Update current state */

        MenuDisplay(); /* Display the new menu on LCD */

        // Execute the function of state if there is one
        for (i = 0; MENU_STATE[i].State; i++)
        {
            if (MENU_STATE[i].State == State)
            {
                pStateFunc = MENU_STATE[i].pFunc;
                if (pStateFunc) /* Check if there is a state function to be executed */
                {
                    pStateFunc(); /* Execute the state function */
                    pStateFunc = 0;
                }
            }
        }
    }
}

/** This function displays the current menu level on the LCD
  * @param[in] None
  * @return None
  **/
void MenuDisplay(void)
{

    uint8_t i;
    LCD_Clear();
		WaitDelay(20);
    // Display menu line 1 
    if (PreviousTopState)
    {
        for (i = 0; MENU_STATE[i].State; i++)
        {
            if (MENU_STATE[i].State == PreviousTopState)
            {
                if (MENU_STATE[i].pText)
                {
                    LCD_PrintString(LCD_LINE1, ENABLE, DISABLE, MENU_STATE[i].pText);
                }
                break;
            }
        }
    }
    else
    {
        // Menu top level reached 
        LCD_PrintString(LCD_LINE1, ENABLE, DISABLE, MENU_TOP_TEXT);
    }

    // Display menu line 2 
    for (i = 0; MENU_STATE[i].State; i++)
    {
        if (MENU_STATE[i].State == State)
        {
            if (MENU_STATE[i].pText)
            {
                LCD_PrintString(LCD_LINE2, ENABLE, DISABLE, MENU_STATE[i].pText);
            }
            break;
        }
    }
}

