/* --COPYRIGHT--,BSD
 * Copyright (c) 2012, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * --/COPYRIGHT--*/
//
// Include files
//
#include "deviceSpecifics.h"
#include "MSP-EXP430F5438 HAL\hal_MSP-EXP430F5438.h"
#include "UserExperienceGraphics.h"
#include "i2cbslUserInterface.h"


//
// Local variables
//
static volatile uint8_t buttonsPressed = 0; /*! Stores pressed buttons */
static volatile uint8_t buttonDebounce = 1; /*! Used to debounce buttons */
static uint8_t menuPos = 0;                 /*! Stores current menu position */

//
// Local function prototypes
//
static void menuUpdate(char *, uint8_t *, uint8_t , uint8_t );
static uint8_t menuMode(char *, uint8_t , uint8_t );
static void startWDT(void);

/******************************************************************************
 * @brief   Initializes the LCD and buttons
 *
 * @return none
 *****************************************************************************/
void initUserInterface(void)
{
    halBoardStartXT1();
    halBoardSetSystemClock(SYSCLK_16MHZ);
    halLcdInit();
    halLcdBackLightInit();
    halLcdSetBackLight(8);      // Adjust Backlight as needed
    halLcdSetContrast(100);      // Adjust contrast as needed
    halLcdClearScreen();
    buttonDebounce = 1;
    halButtonsInit( BUTTON_ALL );
    halButtonsInterruptEnable( BUTTON_ALL );
}

/******************************************************************************
 * @brief   Updates the displayed menu based on selection
 *
 * @param menuText Pointer to current menu 
 * @param menuPos  Current menu position (updated after this function)
 * @param change   0: Get previous, 1:Get Next
 * @param menuNum  Number of members in Menu
 *
 * @return none
 *****************************************************************************/
static void menuUpdate(char *menuText, uint8_t *menuPos, uint8_t change, uint8_t menuNum)
{
    halLcdPrintLine(&menuText[*menuPos*MENU_ITEM_WIDTH+17],
                  (*menuPos)+1,  OVERWRITE_TEXT );

    if (change == 0)                          //Subtract
    {
        if ( *menuPos > 0 )
            (*menuPos)--;
        else
            *menuPos = (menuNum - 1);
    }
    else
    {
        if ( (*menuPos) < menuNum - 1 )
            (*menuPos)++;
        else
            *menuPos = 0;
    }

    halLcdPrintLine(&menuText[*menuPos*MENU_ITEM_WIDTH+17],
                   (*menuPos)+1, INVERT_TEXT | OVERWRITE_TEXT );
}

/******************************************************************************
 * @brief   Displays a menu and waits for selection of an item 
 *
 * @param menuText Pointer to menu being displayed
 * @param menuNum  Number of items in menu
 * @param menuStartPosition  Start position of menu
 *
 * @return uint8_t Position selected by user  
 *         0xFF    User cancelled menu
 *****************************************************************************/
uint8_t menuMode(char *menuText, uint8_t menuNum, uint8_t menuStartPosition)
{
    uint8_t menuPosition, quit = 0, selectionMade = 0;
    uint16_t i;

    halButtonsInterruptEnable( BUTTON_ALL );

    halLcdClearScreen();
    halLcdImage(TI_TINY_BUG, 4, 32, 104, 12 );
    menuPosition = 0;
    //Print menu title
    halLcdPrintLine(menuText, 0, 0 );

    //Print menu items
    for (i=0;i<menuNum;i++)
    halLcdPrintLine(&menuText[i*MENU_ITEM_WIDTH+17], i+1,  OVERWRITE_TEXT );
    //First line is inverted text, automatic selection
    menuPosition = menuStartPosition;
    halLcdPrintLine(&menuText[menuPosition*MENU_ITEM_WIDTH+17],  menuPosition+1,     \
                  INVERT_TEXT | OVERWRITE_TEXT );
    buttonsPressed = 0;
    while (quit == 0 && selectionMade == 0)
    {
        TA0CTL &= ~TAIFG;

        __bis_SR_register(LPM3_bits + GIE);     //Returns if button pressed or clock ticks
        __no_operation();                       // For debugger only

        if (buttonsPressed)
        {
            switch (buttonsPressed)
            {
                case BUTTON_UP:       
                    menuUpdate(menuText, &menuPosition, 0, menuNum); 
                    break;
                case BUTTON_DOWN:     
                    menuUpdate(menuText, &menuPosition, 1, menuNum); 
                    break;
                case BUTTON_SELECT:   
                    selectionMade = 1; 
                    break;
                case BUTTON_S2:       
                    selectionMade = 1; 
                    break;
                case BUTTON_S1:       
                    quit = 1; 
                    menuPosition=0xFF; 
                    break;
                default: 
                    break;
            }
        }
        buttonsPressed  = 0;
    }

    halButtonsInterruptDisable( BUTTON_ALL );
    halLcdClearScreen();
    return menuPosition;
}


/******************************************************************************
 * @brief   Displays the Manu menu, waits for a selection in SubMenu 
 *
 * @param menuText      Main Menu
 * @param submenulist   List of sub-menus
 *
 * @return uint8_t Position selected by user  
 *****************************************************************************/
uint8_t menuSelection(char menuText[], submenu_list_t * submenulist)
{
    uint8_t  procedureSelected = 0;
    static uint8_t submenusel =0;

    while (!procedureSelected)
    {
        menuPos = menuMode(menuText, MAIN_MENU_MAX, menuPos);
        if (menuPos != 0xFF)
        {
            submenusel = menuMode(submenulist[menuPos].menu_ptr, submenulist[menuPos].num_menu, 0);
            if (submenusel != 0xFF)
                procedureSelected = 1;
        }
    }
    return ((menuPos*7) + submenusel);
}


/******************************************************************************
 * @brief   Start WDT as Interval counter
 *
 * @return none
 *****************************************************************************/
static void startWDT(void)
{
    //WDT as 250ms interval counter
    SFRIFG1 &= ~WDTIFG;
    WDTCTL = WDTPW + WDTSSEL_1 + WDTTMSEL + WDTCNTCL + WDTIS_5;
    SFRIE1 |= WDTIE;
}


/******************************************************************************
 * @brief   Convert an 8-bit number to a string with its hexadecimal value 
 *
 * @param hex   8-bit value
 * @param text  Text with output value ("0xHH")
 *
 * @return none
 *****************************************************************************/
void hex2text(uint8_t hex, char* text)
{
    text[0] = '0';
    text[1] = 'x';
    text[2] = (hex >> 4);
    if (text[2] < 0x0A)
        text[2] += '0';
    else
        text[2] += 'A' - 0x0A;
    
    text[3] = (hex & 0x0F);
    
    if (text[3] < 0x0A)
        text[3] += '0';
    else
        text[3] += 'A' - 0x0A;

}

/******************************************************************************
 * @brief   Watchdog Timer Interrupt Service Routine
 *
 * @return none
 *****************************************************************************/
#pragma vector=WDT_VECTOR
__interrupt void WDT_ISR(void)
{
    if (buttonDebounce == 2)
    {
        buttonDebounce = 1;
        SFRIFG1 &= ~WDTIFG;
        SFRIE1 &= ~WDTIE;
        WDTCTL = WDTPW + WDTHOLD;
    }
}

/******************************************************************************
 * @brief   Port 2 Interrupt Service Routine
 *
 * @return none
 *****************************************************************************/
#pragma vector=PORT2_VECTOR
__interrupt void Port2_ISR(void)
{
    if (buttonDebounce == 1)
    {
        buttonsPressed = P2IFG;
        buttonDebounce = 2;
        startWDT();
        __bic_SR_register_on_exit(LPM3_bits);
    }
    else if (0 == buttonDebounce)
    {
        buttonsPressed = P2IFG;
        __bic_SR_register_on_exit(LPM4_bits);
    }

    P2IFG = 0;
}
