/*****************************************************************************
 *
 * MODULE:             JN-AN-1158 (Remote)
 *
 * COMPONENT:          Remote.c
 *
 * AUTHOR:             JMB
 *
 * DESCRIPTION:        Remote
 *
 * $HeadURL $
 *
 * $Revision: 11878 $
 *
 * $LastChangedBy: nxp46755 $
 *
 * $LastChangedDate: 2013-11-14 03:57:27 +0000 (Thu, 14 Nov 2013) $
 *
 * $Id: Remote.c 11878 2013-11-14 03:57:27Z nxp46755 $
 *
 *
 ****************************************************************************
 *
 * This software is owned by NXP B.V. and/or its supplier and is protected
 * under applicable copyright laws. All rights are reserved. We grant You,
 * and any third parties, a license to use this software solely and
 * exclusively on NXP products [NXP Microcontrollers such as JN5148, JN5142,
 * JN5139]. You, and any third parties must reproduce the copyright and
 * warranty notice and any other legend of ownership on each copy or partial
 * copy of the software.
 *
 * 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 HOLDER 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 NXP B.V. 2012. All rights reserved
 *
 ***************************************************************************/

/****************************************************************************/
/***        Include files                                                 ***/
/****************************************************************************/
#include <jendefs.h>
#include <AppHardwareApi.h>
#include <mac_pib.h>
#include "Config.h"
#include "Printf.h"
#include "RF4CE_API.h"
#include "ZRC.h"
#include "ZID.h"
#include <string.h>
#include "Button.h"
#include "LcdDriver.h"
#include "LcdFont.h"
#if (defined JENNIC_CHIP_FAMILY_JN516x)
#include "AppApi_JN516x.h"
#include <PeripheralRegs.h>
#elif (defined JENNIC_CHIP_FAMILY_JN514x)
#include "AppApi_JN514x.h"
#endif
#include "NXPLogo.h"

#ifdef STACK_DUMP
    #include "StackMeasure.h"
#endif

#if defined(EK001)
    #include "app_buttons.h"
#endif
extern void vRF4CE_ImpConfigChan(uint8 u8Channels,   uint8 u8MinChannel,
                                 uint8 u8MidChannel, uint8 u8MaxChannel);
/****************************************************************************/
/***        Macro Definitions                                             ***/
/****************************************************************************/

#define NODE_CAPABILITY_SECURE (RF4CE_NODECAP_TYPE_CONTROLLER    \
                                | RF4CE_NODECAP_PWRSRC_MAINS     \
                                | RF4CE_NODECAP_SECURITY_CAPABLE \
                                | RF4CE_NODECAP_CHANNORM_CAPABLE)

#define NODE_CAPABILITY        (RF4CE_NODECAP_TYPE_CONTROLLER    \
                                | RF4CE_NODECAP_PWRSRC_MAINS     \
                                | RF4CE_NODECAP_CHANNORM_CAPABLE)

#define VENDOR_ID              (0xfff1)
#define DEBOUNCE 32000   /* 1280*(1/32000) = 40ms */

#if defined(EK020)
#define BUTTON_0_MASK         1
#define BUTTON_1_MASK         1
#define BUTTON_2_MASK         1
#define BUTTON_3_MASK         1
#endif

#define MIN_MOUSE_DEBOUNCE  (20000)
/* Key board matrix */
#if defined(EK020)
static char acKeyList[ROWS][COLS]= {{ONE_DIGIT,       TWO_DIGIT,       THREE_DIGIT    },
                                    {FOUR_DIGIT,      FIVE_DIGIT,      SIX_DIGIT    },
                                    {SEVEN_DIGIT,    EIGHT_DIGIT,    NINE_DIGIT    },
                                    {REWIND,         ZERO_DIGIT,     FAST_FORWARD},
                                    {PAUSE,          STOP,              PLAY        },
                                    {UP,              DOWN,              LEFT,        RIGHT,            SELECT},
                                    {VOLUME_UP,        VOLUME_DOWN,      CHANNEL_UP, CHANNEL_DOWN,    POWER}};
#endif
/****************************************************************************/
/***        Type Definitions                                              ***/
/****************************************************************************/

typedef enum
{
    E_PRE_START,
    E_COLD_START,
    E_START_COMPLETE,
    E_WAIT_FOR_KEY,
    E_WAIT_FOR_DISCOVERY,
    E_DISPLAY_DEVICES_FOUND,
    E_WAIT_FOR_PAIR_DIS,
    E_START_PAIRING,
    E_WAIT_FOR_PAIRING,
    E_PAIRED,
    E_DEVICE_SELECT,
    E_TRACK_SELECT,
    E_CONFIGMENU,
    E_RUNNING,
    E_TRANSMITTING
} teState;

/****************************************************************************/
/***        Local Function Prototypes                                     ***/
/****************************************************************************/
PRIVATE uint8 u8Read(uint32 u32Button);
PRIVATE void vSendCommand(uint8 u8KeyPressed);
PRIVATE void vSleep(uint32 u32Duration);

PRIVATE void vIdleLoop(void);
PRIVATE void vTimeBeforeSleep(void);
PRIVATE void vSetUpScreenPos(uint8 u8Posible, uint8 u8Direction);
#if (defined USE_IR)
PRIVATE void vEnableIR(void);
#endif
PUBLIC void vLongToString(char * str, uint32 u32Num);

PRIVATE void vValToDec(char *pcOutString, uint8 u8Value, char *pcLabel);
PRIVATE void vStringCopy(char *pcFrom, char *pcTo);

PRIVATE void vTimerISR(uint32 u32Device, uint32 u32ItemBitmap);

#if defined(EK001)
#define u32Button_Timer()          //null macro
#endif

/****************************************************************************/
/***        Exported Variables                                            ***/
/****************************************************************************/
extern HIDDMouseInputReport MouseReport;
/****************************************************************************/
/***        Local Variables                                               ***/
/****************************************************************************/
PRIVATE teState volatile       eState;
tuRF4CE_NibValue     NibValue;

PRIVATE uint8 u8ReceiverPairingRef;
PRIVATE uint8 gu8ScreenPosition = 0;
PRIVATE uint8 u8UserPairConfirm = 0;
PRIVATE uint8 u8TrackSelected = 0;
PRIVATE uint8 u8DevicePaired;
PRIVATE uint8 u8WarmStart = 0;
PRIVATE uint8 u8SleepCounter = 0;
#if defined(EK001)
PRIVATE uint8 u8Paused = 0;
#endif

PRIVATE struct
{
    tsIeeeAddr sIeeeAddr;
    uint16     u16PanId;
    uint8      u8Channel;
} sDiscovered;

PRIVATE struct
{
    uint8        u8Time;
    bool_t        IREnable;
} sSetup;

#define ZID_MODE    1
#define ZRC_MODE    0
static volatile uint8 App_Mode = ZRC_MODE;

#if (defined STACK_MEASURE)
    tsStackInfo sStackInfo;
    extern uint32 heap_location;
    uint32 u32HeapPointer;
#endif
/****************************************************************************/
/***        Exported Functions                                            ***/
/****************************************************************************/
extern uint8 gMAC_u8MaxBuffers;


/****************************************************************************
 *
 * NAME: AppColdStart
 *
 * DESCRIPTION:
 * Entry point for application from boot loader. Initialises system and runs
 * main loop.
 *
 * RETURNS:
 * Never returns.
 *
 ****************************************************************************/
PUBLIC void AppColdStart(void)
{
    volatile uint32 i;
    gMAC_u8MaxBuffers = 2;

    #ifdef JENNIC_CHIP_FAMILY_JN516x
        /* Turn off debugger */
        *(volatile uint32 *)0x020000a0 = 0;
    #endif

    sSetup.u8Time = 60;
    sSetup.IREnable = FALSE;

    vAHI_SysCtrlRegisterCallback(0);

    /* Initialise tick timer to give periodic interrupt */
    vAHI_TickTimerConfigure(E_AHI_TICK_TIMER_DISABLE);
    vAHI_TickTimerWrite(0);
    vAHI_TickTimerRegisterCallback(vTimerISR);
    /* 10 second tick timer */
    vAHI_TickTimerInterval(0x9896800);
    vAHI_TickTimerConfigure(E_AHI_TICK_TIMER_RESTART);

    (void)u32AHI_Init();
    #ifdef JENNIC_CHIP_FAMILY_JN516x
        bAHI_SetClockRate(3);
        vAHI_OptimiseWaitStates();
        /* Turn on SPI master */
        vREG_SysWrite(REG_SYS_PWR_CTRL,
                  u32REG_SysRead(REG_SYS_PWR_CTRL) | REG_SYSCTRL_PWRCTRL_SPIMEN_MASK);
    #endif

    /* initialisation of the uart for debug */
    vUART_printInit();
    /* Init buttons */

    #if (defined STACK_MEASURE)
        u32HeapPointer = ((uint32 *)&heap_location)[0];
        vInitStackMeasure();
    #endif

    #if defined(EK020)
        vButton_Enable(0x01FFFFFF); /* Enable 25 buttons */
    #endif

    if (bAHI_WatchdogResetEvent())
    {
        vPrintf("APP: Watchdog timer has reset device!\r\n");
    }

    #if defined(EK020)
        /* Check if flash should be erased */
        u32Button_Timer();
        /* Read Key Pressed*/
        if (PLAY == u8Read(u32Button_Read()))
        {
            vPrintf("Destroy settings\n\r");
            vRF4CE_ImpDestroySettings();
        }
        vLcdReset(1,13); //vLcdReset(1, u8CalcContrastLevel());
    #elif defined(EK001)
        vAHI_SpiConfigure(1,FALSE, FALSE, FALSE, 1, FALSE, FALSE);

        if(APP_bButtonInitialise())
        {
            vPrintf("Destroy settings\n\r");
            vRF4CE_ImpDestroySettings();
        }
        vLcdReset(0,12);
    #endif

    /* Initialise and populate the display */
    vLcdClear();
    vLcdWriteBitmap((tsBitmap *)&sNXPLogo, 0, 0);
    vLcdWriteText("      RF4CE Remote        ", 5, 0);
    vLcdWriteText("   Control Application    ", 6, 0);
    vLcdRefreshAll();
    for(i=0;i<3000000;i++);

    #if WATCHDOG_ENABLED
    {
        vAHI_WatchdogStop();
    }
    #endif


    /* Initialise stack (implementation-specific command) */
    if (bRF4CE_ImpInit(NODE_CAPABILITY_SECURE, VENDOR_ID, (uint8 *)"JennicC"))
    {
        u8DevicePaired = 0;
        /* Cold start: reset and clear NIB, then start stack */
        vPrintf("Cold start\n\r");
        eState = E_PRE_START;
        /* Initialise and populate the display */
            vLcdClear();
            vLcdWriteText("    Press OK to scan      ", 2, 0);
            vLcdWriteText("   for devices to join    ", 3, 0);
            #if defined(EK001)
                vLcdWriteText("OK                        ", 7, 0);
            #endif
            vLcdRefreshAll();
            vAHI_TickTimerIntEnable(TRUE);
        /* Stack start is asynchronous so enter idle loop waiting for stack to
           complete start-up sequence */
    }
    else
    {
        /* Warm start: reset without clearing NIB */
        vPrintf("Warm start\n\r");
        vRF4CE_NlmeResetReq(FALSE);
        /* Get info from NIB */
        (void)eRF4CE_NlmeGetReq(E_RF4CE_NIB_ATTR_PAIRING_TABLE, 0, &NibValue);
        if(NibValue.sPairingTableEntry.eState  == E_PAIR_ACTIVE )
        {
            u8WarmStart = 1;
            vRF4CE_NlmeStartReq();
        }
        else
        {
            eState = E_PRE_START;
            /* Initialise and populate the display */
            vLcdClear();
            vLcdWriteText("    Press OK to scan      ", 2, 0);
            vLcdWriteText("   for devices to join    ", 3, 0);
            #if defined(EK001)
                vLcdWriteText("OK                        ", 7, 0);
            #endif
            vLcdRefreshAll();
            vAHI_TickTimerIntEnable(TRUE);
        }
    }
	while(bAHI_Clock32MHzStable() == FALSE);
    /* Go to idle loop */
    vIdleLoop();
}

/****************************************************************************
 *
 * NAME: AppWarmStart
 *
 * DESCRIPTION:
 * Entry point for application from boot loader. Simply jumps to AppColdStart
 * as, in this instance, application will never warm start.
 *
 * RETURNS:
 * Never returns.
 *
 ****************************************************************************/
PUBLIC void AppWarmStart(void)
{
    AppColdStart();
}

/****************************************************************************/
/***        Local Functions                                               ***/
/****************************************************************************/
PUBLIC void vRF4CE_StackEvent(teRF4CE_EventType eEvent,
                              tuRF4CE_EventParam *puParam)
{
    char acString[255];
    uint8    *pu8Payload;
    static uint8 n=0;
    tuRF4CE_NibValue uValue;

    switch (eEvent)
    {
    case E_RF4CE_EV_START_CFM:      /* Use with tsRF4CE_NlmeStartCfm */
        if (E_RF4CE_STATUS_SUCCESS == puParam->sNlmeStartCfm.eStatus)
        {
            if (u8WarmStart == 0)
            {
                /* Now running */
                eState = E_START_COMPLETE;
            }
            else
            {
                (void)eRF4CE_NlmeGetReq(E_RF4CE_NIB_ATTR_PAIRING_TABLE, 0, &NibValue);
                eAppApiPlmeSet(PHY_PIB_ATTR_CURRENT_CHANNEL,NibValue.sPairingTableEntry.u8DestLogicalChan);
                vLcdClear();
                vLcdWriteText("          Main Menu        ", 0, 0);
                vLcdWriteInvertedText("Media Player Option       ", 2, 0);
                vLcdWriteText("Setup Menu                 ", 3, 0);
                #if defined(EK001)
                    vLcdWriteText("Ok     Up       Down     ", 7, 0);
                #endif
                vLcdRefreshAll();
                u8UserPairConfirm = 0;
                u8WarmStart = 0;
                eState = E_DEVICE_SELECT;
                vRF4CE_ImpConfigChan(3, 15, 20, 25);

                memset(uValue.au8UserString, 0, RF4CE_USER_STRING_LEN);
                memcpy(uValue.au8UserString, "Remote", 6);
                (void)eRF4CE_NlmeSetReq(E_RF4CE_NIB_ATTR_USER_STRING, 0, &uValue);

                uValue.u8MaxDiscoveryRepetitions = 4;
                (void)eRF4CE_NlmeSetReq(E_RF4CE_NIB_ATTR_MAX_DISC_REPETITIONS, 0, &uValue);

                /* Get info from NIB */
                (void)eRF4CE_NlmeGetReq(E_RF4CE_NIB_ATTR_BASE_CHANNEL, 0, &uValue);
                vAHI_TickTimerIntEnable(TRUE);
            }
        }
        else
        {
            /* Try scanning again */
            vRF4CE_NlmeStartReq();
        }
        break;

    case E_RF4CE_EV_DISC_CFM:   /* Use with tsRF4CE_NlmeAutoDiscoveryCfm */
        if (E_RF4CE_STATUS_SUCCESS == puParam->sNlmeDiscoveryCfm.eStatus)
        {
            uint8 u8i;
            uint8 u8NumNodes = puParam->sNlmeDiscoveryCfm.u8NumNodes;
            tsRF4CE_NodeDesc *psNodeDesc = puParam->sNlmeDiscoveryCfm.psNodeDescList;

            /* Store details of first match for pairing with later */
            sDiscovered.u8Channel      = psNodeDesc->u8LogicalChannel;
            sDiscovered.u16PanId       = psNodeDesc->u16PanId;
            sDiscovered.sIeeeAddr.u32H = psNodeDesc->sIeeeAddr.u32H;
            sDiscovered.sIeeeAddr.u32L = psNodeDesc->sIeeeAddr.u32L;
            for (u8i = 0; u8i <u8NumNodes; u8i++)
            {
                psNodeDesc = &puParam->sNlmeDiscoveryCfm.psNodeDescList[u8i];
            }
            vLcdClear();
            if(psNodeDesc->au8DevTypeList[0] == RF4CE_DEVICE_TYPE_TELEVISION)
            {
                vLcdWriteText("Dev Type: Television ", 2, 0);
            }
            else if(psNodeDesc->au8DevTypeList[0] == RF4CE_DEVICE_TYPE_MEDIA_CENTER)
            {
                vLcdWriteText("Dev Type: Media Player ", 2, 0);
            }
            else
            {
                vLcdWriteText("Dev Type: Unsupported ", 2, 0);
            }
            vValToDec(acString, puParam->sNlmeDiscoveryCfm.u8NumNodes, "  ");
            acString[2]='\0';
            vLcdWriteText("Devices found              ", 0, 0);
            vLcdWriteText(acString, 0, 100);
            vLcdWriteText("Displaying  1  of          ", 3, 0);
            vLcdWriteText(acString, 3, 100);
            vLcdWriteText("MAC: ", 1, 0);
            vLongToString(acString, psNodeDesc->sIeeeAddr.u32H);
            acString[8]='\0';
            vLcdWriteText(acString, 1, 28);
            vLongToString(acString, psNodeDesc->sIeeeAddr.u32L);
            acString[8]='\0';
            vLcdWriteText(acString, 1, 75);
            vLcdWriteInvertedText("Pair to selected device    ", 4, 0);
            vLcdWriteText("Return to discover         ", 5, 0);
            #if defined(EK001)
                vLcdWriteText("Ok     Up       Down     ", 7, 0);
            #endif
            vLcdRefreshAll();
            gu8ScreenPosition = 0;
            eState = E_DISPLAY_DEVICES_FOUND;
        }
        else
        {
            vPrintf("error code %x\r\n",puParam->sNlmeDiscoveryCfm.eStatus);
            eState = E_WAIT_FOR_KEY;
        }
        break;

    case E_RF4CE_EV_PAIR_CFM:       /* Use with tsRF4CE_NlmePairCfm */
        vPrintf("PairCfm:%x:%x:%x:%x",puParam->sNlmePairCfm.eStatus,
                            puParam->sNlmePairCfm.u8PairingRef,
                            puParam->sNlmePairCfm.u16RecVendorId);

        if (E_RF4CE_STATUS_SUCCESS == puParam->sNlmePairCfm.eStatus)
        {
            vPrintf("Paired\r\n");
            eState = E_PAIRED;
            u8ReceiverPairingRef = puParam->sNlmePairCfm.u8PairingRef;
        }
        else
        {
            vPrintf("Not Paired\r\n");
            eState = E_WAIT_FOR_KEY;
        }
        break;

    case E_RF4CE_EV_COMMSTATUS_IND: /* Use with tsRF4CE_NlmeCommStatusInd */
        vPrintf("CommStatusInd:%x:%x:%x:%x:%x:%x", puParam->sNlmeCommStatusInd.u8PairingRef,
                            puParam->sNlmeCommStatusInd.u16DstPanId,
                            puParam->sNlmeCommStatusInd.u8DstAddrMode,
                            puParam->sNlmeCommStatusInd.uDstAddr.sIeeeAddr.u32H,
                            puParam->sNlmeCommStatusInd.uDstAddr.sIeeeAddr.u32L,
                            puParam->sNlmeCommStatusInd.eStatus);
        break;

    case E_RF4CE_EV_NLDE_CFM:       /* Use with tsRF4CE_NldeDataCfm */
        if(puParam->sNldeDataCfm.eStatus == E_RF4CE_STATUS_SUCCESS)
        {
            if (E_TRANSMITTING == eState)
            {
                if (u8TrackSelected == 0)
                {
                    vPrintf("data1\r\n");
                    eState = E_TRACK_SELECT;
                }
                else
                {
                    vPrintf("Data2\r\n");
                    eState = E_RUNNING;
                }
            }
            else
            {
                vPrintf("data3\r\n");
            }
        }
        else
        {
            vLcdClear();
            vLcdWriteText("  No response from Media  ", 2, 0);
            vLcdWriteText("   Player please check    ", 3, 0);
            vLcdWriteText("   software is running.   ", 4, 0);
            vLcdWriteText("    Press OK to return    ", 6, 0);
            vLcdRefreshAll();
            /* which key pressed */
            while(SELECT != u8Read(u32Button_Read()))
            {
                u32Button_Timer();
            }
            while(SELECT == u8Read(u32Button_Read()))
            {
                u32Button_Timer();
            }
            eState = E_DEVICE_SELECT;
            gu8ScreenPosition = 0;
            vLcdClear();
            vLcdWriteText("          Main Menu        ", 0, 0);
            vLcdWriteInvertedText("Media Player Option       ", 2, 0);
            vLcdWriteText("Setup Menu                 ", 3, 0);
            #if defined(EK001)
                vLcdWriteText("Ok     Up       Down     ", 7, 0);
            #endif
            vLcdRefreshAll();
        }
        break;

    case E_RF4CE_EV_UNPAIR_IND:
        vPrintf("UNPAIR_IND\r\n");
        u8DevicePaired = 0;
        #if 0
            vRF4CE_ImpSaveSettings(E_SAVE_MODE_FULL);
            vLcdClear();
            vLcdWriteText("    Press OK to scan      ", 2, 0);
            vLcdWriteText("   for devices to join    ", 3, 0);
            vLcdRefreshAll();
            eState = E_WAIT_FOR_KEY;
        #endif
        // After un-pair destroying settings and doing sw reset.
        vPrintf("Destroy settings\n\r");
        vRF4CE_ImpDestroySettings();
        vAHI_SwReset();
        break;

    case E_RF4CE_EV_NLDE_IND:
        if(App_Mode == ZID_MODE){
            /* To make sure, while in ZID_MODE, app behaves properly.*/
            break ;
        }
        if((eState == E_PAIRED) && (puParam->sNldeDataInd.pu8Nsdu[0] == 0x7A))
        {
            u8UserPairConfirm = 1;
            u8DevicePaired = 1;
            vPrintf("u8DevicePaired %x\n\r",u8DevicePaired);
        }
        else if(puParam->sNldeDataInd.pu8Nsdu[0] == 0x79)
        {
            vPrintf("Sleep 0x79 \n\r");
            vLcdPowerOff();
            vSleep(0);
        }
        else if((eState == E_TRACK_SELECT) ||(eState == E_RUNNING) ||(eState == E_DEVICE_SELECT))
        {
            pu8Payload = &puParam->sNldeDataInd.pu8Nsdu[0];
            pu8Payload[puParam->sNldeDataInd.u8NsduLength] = '\0';
            if(n == 0)
            {
                vLcdClear();
                vLcdWriteText("Track selected:", 0, 0);
                vLcdWriteText((char *)pu8Payload, 1, 0);
                #if (defined EK020)
                    vLcdWriteInvertedText("Select another track       ", 6, 0);
                    vLcdWriteText("Return to Main Menu        ", 7, 0);
                #endif
                vLcdRefreshAll();
                n=1;
                vSendCommand(0x08);
            }
            else
            {
                vLcdWriteText("Artist:", 2, 0);
                vLcdWriteText((char *)pu8Payload, 3, 0);
                #if (defined EK020)
                    vLcdWriteInvertedText("Select another track       ", 6, 0);
                    vLcdWriteText("Return to Main Menu        ", 7, 0);
                #elif (defined EK001)
                    vLcdWriteText("        Vol     Vol ", 6, 0);
                    vLcdWriteText("Pause ",7,0);
                    vLcdWriteText("Up     Down   Back ", 7, 33);
                #endif
                vLcdRefreshAll();
                n=0;
                u8TrackSelected = 1;
                eState = E_RUNNING;
            }
        }
        else
        {
            vPrintf("Data ind!!\n\r");
        }
        break;

    case E_RF4CE_EV_UNPAIR_CFM:     /* Use with tsRF4CE_NlmeUnpairCfm */

        if(puParam->sNlmeUnpairCfm.eStatus == E_RF4CE_STATUS_SUCCESS)
        {
            vPrintf("UNPAIR_CFM\r\n");
            u8DevicePaired = 0;
            vRF4CE_ImpSaveSettings(E_SAVE_MODE_FULL);
            //vLcdReset(1, u8CalcContrastLevel());(1,12);
            vLcdClear();
            vLcdWriteText("    Press OK to scan      ", 2, 0);
            vLcdWriteText("   For devices to join    ", 3, 0);
            #if defined(EK001)
                vLcdWriteText("OK                        ", 7, 0);
            #endif
            vLcdRefreshAll();
            eState = E_WAIT_FOR_KEY;
        }
        else
        {
            vLcdClear();
            vLcdWriteText("       Unpair failed      ", 2, 0);
            vLcdWriteText("     press OK to return   ", 3, 0);
            vLcdWriteText("        to Main Menu      ", 4, 0);
            vLcdRefreshAll();
            u32Button_Timer();
            /* which key pressed */
            while(SELECT != u8Read(u32Button_Read()))
            {
                u32Button_Timer();
            }
            while(SELECT == u8Read(u32Button_Read()))
            {
                u32Button_Timer();
            }
            eState = E_DEVICE_SELECT;
            gu8ScreenPosition = 0;
            vLcdClear();
            vLcdWriteText("          Main Menu        ", 0, 0);
            vLcdWriteInvertedText("Media Player Option       ", 2, 0);
            vLcdWriteText("Setup Menu                 ", 3, 0);
            #if defined(EK001)
                vLcdWriteText("Ok     Up       Down     ", 7, 0);
            #endif
            vLcdRefreshAll();
        }
        break;

    case E_RF4CE_EV_PAIR_IND:       /* Use with tsRF4CE_NlmePairInd */
    case E_RF4CE_EV_DISC_IND:       /* Use with tsRF4CE_NlmeDiscoveryInd */
    case E_RF4CE_EV_AUTODISC_CFM:   /* Use with tsRF4CE_NlmeDiscoveryCfm */
    default:
        vPrintf("Unhandled!\n\r");
        break;
    }
}
/****************************************************************************
 *
 * NAME:

 * DESCRIPTION:
 *
 *
 * PARAMETERS:      Name            RW  Usage
 *
 *
 * RETURNS:
 *
 *
 * NOTES:
 *
 ****************************************************************************/
PRIVATE void vIdleLoop(void)
{
    tuRF4CE_NibValue uValue;
    tsRF4CE_AppCap   sAppCap             = {1, 1, 0, 1, 0};
    uint8            au8DevTypeList[1]   = {RF4CE_DEVICE_TYPE_REMOTE_CONTROL};
    uint8            au8ProfileIdList[1] = {ZRC_PROFILE_ID};
    uint8 u8Key;
    static uint8 u8LastKey=0;
    static volatile uint32 u32Debounce=0;
    static volatile uint32 u32StaticDebounce=MIN_MOUSE_DEBOUNCE;


    #if(defined TRACE_ZRC_COMMADS)
        uint8 au8Data[32] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
    #endif

    while (1)
    {
        switch (eState)
        {
        case E_PRE_START:
            vRF4CE_ImpConfigChan(3, 15, 20, 25);
            vRF4CE_NlmeResetReq(TRUE);
            eState = E_COLD_START;
            vRF4CE_NlmeStartReq();
            break;

        case E_COLD_START:
            /* Waiting for start to complete */
            break;

        case E_START_COMPLETE:
            /* Now running */
            vPrintf("Started\n\r");
            /* Set info in NIB */
            memset(uValue.au8UserString, 0, RF4CE_USER_STRING_LEN);
            memcpy(uValue.au8UserString, "Remote", 6);
            (void)eRF4CE_NlmeSetReq(E_RF4CE_NIB_ATTR_USER_STRING, 0, &uValue);

            uValue.u8MaxDiscoveryRepetitions = 4;
            (void)eRF4CE_NlmeSetReq(E_RF4CE_NIB_ATTR_MAX_DISC_REPETITIONS, 0, &uValue);

            /* Get info from NIB */
            (void)eRF4CE_NlmeGetReq(E_RF4CE_NIB_ATTR_BASE_CHANNEL, 0, &uValue);
            vPrintf("Started WITH CNANNEL %d\n",uValue.u8BaseChannel);
            eState = E_WAIT_FOR_KEY;

            break;

        case E_WAIT_FOR_KEY:
            /* Read Key press */
            u32Button_Timer();
            /* which key pressed */
            u8Key = u8Read(u32Button_Read());

            if (u8Key == SELECT)
            {
                while(SELECT == u8Read(u32Button_Read()))
                {
                    u32Button_Timer();
                }
                vAHI_TickTimerWrite(0);
                u8SleepCounter = 0;
                vRF4CE_ImpConfigChan(3, 15, 20, 25);
                tsRF4CE_AppCap   sAppCap             = {1, 1, 0, 1, 0};
                uint8            au8DevTypeList[1]   = {RF4CE_DEVICE_TYPE_REMOTE_CONTROL};
                uint8            au8ProfileIdList[1] = {ZRC_PROFILE_ID};
                /* Request auto-discovery */
                vPrintf("Trying auto-discovery\n\r");
                eState = E_WAIT_FOR_DISCOVERY;
                vRF4CE_NlmeDiscoveryReq(0xffff, 0xffff, &sAppCap, au8DevTypeList,
                                        au8ProfileIdList, RF4CE_DEVICE_TYPE_MEDIA_CENTER, 1,
                                        au8ProfileIdList, 6250);
            }
            if (u8Key == POWER)
            {
                while(POWER == u8Read(u32Button_Read()))
                {
                    u32Button_Timer();
                }
                vLcdPowerOff();
                vSleep(0);
            }
            break;
        case E_WAIT_FOR_DISCOVERY:
            /* Waiting for discovery to complete */
            break;

        case E_DISPLAY_DEVICES_FOUND:
            /* Read Key press */
            u32Button_Timer();
            u8Key = u8Read(u32Button_Read());
            while (u32Debounce < CONFIGDEBOUNCE){
                u32Debounce++;
                u8Key = u8Read(u32Button_Read());
            }
            /* which key pressed */
            if (DOWN == u8Key && gu8ScreenPosition !=1)
            {
                gu8ScreenPosition++;
                vLcdWriteText("Pair to selected device    ", 4, 0);
                vLcdWriteInvertedText("Return to discover menu", 5, 0);
                vLcdRefreshAll();
                vAHI_TickTimerWrite(0);
                u8SleepCounter = 0;
            }
            if (UP == u8Key && gu8ScreenPosition !=0)
            {
                gu8ScreenPosition--;
                vLcdWriteInvertedText("Pair to selected device    ", 4, 0);
                vLcdWriteText("Return to discover menu", 5, 0);
                vLcdRefreshAll();
                vAHI_TickTimerWrite(0);
                u8SleepCounter = 0;
            }
            if (SELECT == u8Key)
            {
                vAHI_TickTimerWrite(0);
                u8SleepCounter = 0;
                if(gu8ScreenPosition == 1)
                {
                    vLcdClear();
                    vLcdWriteText("    Press OK to scan      ", 2, 0);
                    vLcdWriteText("   for devices to join    ", 3, 0);
                    #if defined(EK001)
                        vLcdWriteText("OK                        ", 7, 0);
                    #endif
                    vLcdRefreshAll();
                    eState = E_WAIT_FOR_KEY;
                }
                else
                {
                    vLcdClear();
                    vLcdWriteText("    Pairing requested     ", 2, 0);
                    vLcdWriteText("       Please wait        ", 3, 0);
                    vLcdRefreshAll();
                    eState = E_START_PAIRING;
                }
            }

             break;

        case E_WAIT_FOR_PAIR_DIS:
            /* Waiting for discovery to complete */
            break;

        case E_START_PAIRING:
            vRF4CE_NlmePairReq(sDiscovered.u8Channel, sDiscovered.u16PanId,
                               &sDiscovered.sIeeeAddr, &sAppCap,
                               au8DevTypeList, au8ProfileIdList, 5);
            eState = E_WAIT_FOR_PAIRING;
            vAHI_TickTimerWrite(0);
            u8SleepCounter = 0;
            break;

        case E_WAIT_FOR_PAIRING:
            /* Waiting for pairing to complete */
            break;

        case E_PAIRED:
            if (u8UserPairConfirm ==  1)
            {
                /* Paired, so can save state */
                vRF4CE_ImpSaveSettings(E_SAVE_MODE_FULL);
                vPrintf("Saved\r\n");
                eState = E_DEVICE_SELECT;
                vLcdClear();
                vLcdWriteText("          Main Menu        ", 0, 0);
                vLcdWriteInvertedText("Media Player Option       ", 2, 0);
                vLcdWriteText("Setup Menu                 ", 3, 0);
                #if defined(EK001)
                    vLcdWriteText("Ok     Up       Down     ", 7, 0);
                #endif
                vLcdRefreshAll();
                u8UserPairConfirm = 0;
                vAHI_TickTimerWrite(0);
                u8SleepCounter = 0;
            }
            break;

        case E_DEVICE_SELECT:

            /* Read Key press */
            u32Button_Timer();
            u8Key = u8Read(u32Button_Read());

            // Switching mode between ZRC and ZID
            if(u8Key == ONE_DIGIT)
            {
                while (u32Debounce < CONFIGDEBOUNCE)
                {
                    u32Debounce++;
                    u8Key = u8Read(u32Button_Read());
                }
                u32Debounce = 0;

                if(App_Mode == ZRC_MODE)
                {
                    App_Mode = ZID_MODE;
                    gu8ScreenPosition = 0;
                    vLcdClear();
                    vLcdWriteText("                          ", 0, 0);
                    vLcdWriteText("Mode -> ZID               ", 3, 0);
                    vLcdWriteText("    Move mouse using -    ", 4, 0);
                    vLcdWriteText("    Up Down Left Right Ok ", 5, 0);
                    vLcdWriteText("         Press 1 for Menu ", 6, 0);
                    vLcdRefreshAll();
                    vPrintf("ZID_MODE\r\n");
                }
                else
                {
                    App_Mode = ZRC_MODE;
                    gu8ScreenPosition = 0;
                    vLcdClear();
                    vLcdWriteText("          Main Menu        ", 0, 0);
                    vLcdWriteInvertedText("Media Player Option       ", 2, 0);
                    vLcdWriteText("Setup Menu                 ", 3, 0);
                    #if defined(EK001)
                        vLcdWriteText("Ok     Up       Down     ", 7, 0);
                    #endif
                    vLcdRefreshAll();
                    vPrintf("ZRC_MODE\r\n");
                }
            }


            if(App_Mode == ZRC_MODE)
            {
                while (u32Debounce < CONFIGDEBOUNCE)
                {
                    u32Debounce++;
                    u8Key = u8Read(u32Button_Read());
                }
                u32Debounce = 0;

                /* which key pressed */
                if (DOWN == u8Key && gu8ScreenPosition !=1)
                {
                    gu8ScreenPosition++;
                    vLcdWriteText("Media Player Option       ", 2, 0);
                    vLcdWriteInvertedText("Setup Menu                 ", 3, 0);
                    vLcdRefreshAll();
                    vAHI_TickTimerWrite(0);
                    u8SleepCounter = 0;
                }
                if (UP == u8Key && gu8ScreenPosition !=0)
                {
                    gu8ScreenPosition--;
                    vLcdWriteInvertedText("Media Player Option       ", 2, 0);
                    vLcdWriteText("Setup Menu                 ", 3, 0);
                    vLcdRefreshAll();
                    vAHI_TickTimerWrite(0);
                    u8SleepCounter = 0;
                }
                if (POWER == u8Key)
                {
                    vSendCommand(POWER);
                    while(POWER == u8Read(u32Button_Read()))
                    {
                        u32Button_Timer();
                    }
                    vLcdPowerOff();
                    vSleep(0);
                }
                if (SELECT == u8Key)
                {
                    while(SELECT == u8Read(u32Button_Read()))
                    {
                        u32Button_Timer();
                    }
                    if(gu8ScreenPosition == 1)
                    {
                        gu8ScreenPosition = 0;
                        vLcdClear();
                        vLcdWriteText("      Setup Menu           ", 0, 0);
                        vLcdWriteInvertedText("Return to Main Menu      ", 2, 0);
                        if (sSetup.u8Time ==  20)
                            vLcdWriteText("Time Before Sleep    20S ", 3, 0);
                        else if (sSetup.u8Time ==  40)
                            vLcdWriteText("Time Before Sleep    40S ", 3, 0);
                        else if (sSetup.u8Time ==  60)
                            vLcdWriteText("Time Before Sleep    60S ", 3, 0);
                        vLcdWriteText("Scan for devices          ", 4, 0);
                        vLcdWriteText("Unpair remote              ", 5, 0);
                        #if defined(EK001)
                            vLcdWriteText("Ok     Up       Down     ", 7, 0);
                        #endif
                        eState = E_CONFIGMENU;
                        vLcdRefreshAll();
                        vAHI_TickTimerWrite(0);
                        u8SleepCounter = 0;
                    }
                    else
                    {
                        vLcdClear();
                        vLcdWriteText("      Select track         ", 2, 0);
                        #if defined(EK001)
                            vLcdWriteText("Ok     Up       Down   Tab", 7, 0);
                        #endif
                        u8TrackSelected = 0;
                        vPrintf("E_TRACK_SELECT\r\n");
                        eState = E_TRACK_SELECT;
                        vSendCommand(SELECT);
                        vLcdRefreshAll();
                        vAHI_TickTimerWrite(0);
                        u8SleepCounter = 0;
                    }
                }
            }
            else // ZID_MODE
            {

                if((u8Key == u8LastKey) && ((u8Key == LEFT) || (u8Key == RIGHT) || (u8Key == UP) || (u8Key == DOWN)))
                {
                    if(u32StaticDebounce < (3*CONFIGDEBOUNCE/4)){
                            u32StaticDebounce += MIN_MOUSE_DEBOUNCE;
                    }
                    u32Debounce = u32StaticDebounce;
                }else{
                    u32Debounce = 0;
                    u32StaticDebounce = MIN_MOUSE_DEBOUNCE;
                }
                u8LastKey = u8Key;

                while (u32Debounce < CONFIGDEBOUNCE)
                {
                    u32Debounce++;
                    u8Key = u8Read(u32Button_Read());
                }

                switch(u8Key)
                {
                    case DOWN:
                        MouseReport.bX = 0;
                        MouseReport.bY = (int8)-1*(u32StaticDebounce/MIN_MOUSE_DEBOUNCE);
                        MouseReport.bmButtons = 0;
                        //eState = E_TRANSMITTING;
                        vZID_SendReportData(u8ReceiverPairingRef,0, E_ZID_ReportType_INPUT,\
                                            E_ZID_ReportId_MOUSE, E_ZID_ReportData_MOUSE);
                        u8SleepCounter = 0;
                        break;

                    case UP:
                        MouseReport.bX = 0;
                        MouseReport.bY = (int8) (u32StaticDebounce/MIN_MOUSE_DEBOUNCE);
                        MouseReport.bmButtons = 0;
                        //eState = E_TRANSMITTING;
                        vZID_SendReportData(u8ReceiverPairingRef,0, E_ZID_ReportType_INPUT,\
                                            E_ZID_ReportId_MOUSE, E_ZID_ReportData_MOUSE);
                        u8SleepCounter = 0;
                        break;

                    case LEFT:
                        MouseReport.bX = (int8) -1*(u32StaticDebounce/MIN_MOUSE_DEBOUNCE);
                        MouseReport.bY = 0;
                        MouseReport.bmButtons = 0;
                        //eState = E_TRANSMITTING;
                        vZID_SendReportData(u8ReceiverPairingRef,0, E_ZID_ReportType_INPUT,\
                                            E_ZID_ReportId_MOUSE, E_ZID_ReportData_MOUSE);
                        u8SleepCounter = 0;
                        break;

                    case RIGHT:
                        MouseReport.bX = (int8) (u32StaticDebounce/MIN_MOUSE_DEBOUNCE);
                        MouseReport.bY = 0;
                        MouseReport.bmButtons = 0;
                        //eState = E_TRANSMITTING;
                        vZID_SendReportData(u8ReceiverPairingRef,0, E_ZID_ReportType_INPUT,\
                                            E_ZID_ReportId_MOUSE, E_ZID_ReportData_MOUSE);
                        u8SleepCounter = 0;
                        break;

                    case SELECT:
                        MouseReport.bX = 0;
                        MouseReport.bY = 0;
                        MouseReport.bmButtons = MOUSE_BTN_LEFT;
                        //eState = E_TRANSMITTING;
                        vZID_SendReportData(u8ReceiverPairingRef,0, E_ZID_ReportType_INPUT,\
                                            E_ZID_ReportId_MOUSE, E_ZID_ReportData_MOUSE);
                        u8SleepCounter = 0;
                        break;

                    default:
                        break;
                }
            }
            break;

        case E_TRACK_SELECT:
            u32Button_Timer();
            u8Key = u8Read(u32Button_Read());
            if (u8Key != ERR)
            {
                u32Debounce=0;

                while (u32Debounce < CONFIGDEBOUNCE)
                {
                    u32Debounce++;
                    u8Key = u8Read(u32Button_Read());
                }


                vAHI_TickTimerWrite(0);
                u8SleepCounter = 0;

                if (DOWN == u8Key)
                {
                    vAHI_TickTimerWrite(0);
                    vSendCommand(DOWN);
                }
                if (UP == u8Key)
                {
                    vAHI_TickTimerWrite(0);
                    vSendCommand(UP);
                }
                if (SELECT == u8Key)
                {
                    vAHI_TickTimerWrite(0);
                    vSendCommand(SELECT);
                }
                if (LEFT == u8Key)
                {
                    vAHI_TickTimerWrite(0);
                    vSendCommand(LEFT);
                }
                if (RIGHT == u8Key)
                {
                    vAHI_TickTimerWrite(0);
                    vSendCommand(RIGHT);
                }
                u8LastKey = u8Key;
                u32Debounce=0;
            }
            break;

        case E_RUNNING:
            /* Read buttons */
            u32Button_Timer();
            u8Key = u8Read(u32Button_Read());

            if (u8Key != ERR)
            {
                u32Debounce = 0;

                while (u32Debounce < CONFIGDEBOUNCE){
                    u32Debounce++;
                    u8Key = u8Read(u32Button_Read());
                }

                vAHI_TickTimerWrite(0);
                u8SleepCounter = 0;

                switch (u8Key)
                {
                    case TWO_DIGIT: // For Stack Measurement
                        #if ((defined STACK_MEASURE) && (defined DBG_ENABLE))
                            vGetStackMeasure(&sStackInfo);
                            vPrintf("\nStack Usage");
                            vPrintf("\n TotalSize      : %x",sStackInfo.u32TotalSize);
                            vPrintf("\n CurrentMeasure : %x",sStackInfo.u32CurrentMeasure);
                            vPrintf("\n PeakMeasure    : %x",sStackInfo.u32PeakMeasure);

                            vPrintf("\nHeap Usage");
                            vPrintf("\n Start   u32HeapPointer=%x\n",u32HeapPointer);
                            u32HeapPointer = ((uint32 *)&heap_location)[0];
                            vPrintf("\n Now     u32HeapPointer=%x\n",u32HeapPointer);
                        #endif
                        break;

                    case THREE_DIGIT:
                        #if(defined TRACE_ZRC_COMMADS)
                            eState = E_TRANSMITTING;
                            vZRC_SendUserControlPressed(u8ReceiverPairingRef,
                                                        ANGLE,
                                                        7,
                                                        au8Data);
                        #endif
                        break;

                    case FOUR_DIGIT:
                        #if (defined TRACE_ZRC_COMMADS)
                            eState = E_TRANSMITTING;
                            vZRC_SendUserControlRepeated(u8ReceiverPairingRef,
                                                         ANGLE,
                                                         9,
                                                         au8Data);
                        #endif
                        break;

                    case FIVE_DIGIT:
                        #if (defined TRACE_ZRC_COMMADS)
                            eState = E_TRANSMITTING;
                            vZRC_SendUserControlReleased(u8ReceiverPairingRef,
                                                         ANGLE);
                        #endif
                        break;

                    case SIX_DIGIT:
                        #if (defined TRACE_ZRC_COMMADS)
                            eState = E_TRANSMITTING;
                            vZRC_SendCmdDiscRequest(u8ReceiverPairingRef);
                        #endif
                        break;

                    case SEVEN_DIGIT:
                        #if (defined TRACE_ZRC_COMMADS)
                            eState = E_TRANSMITTING;
                            vZRC_SendCmdDiscResponse(u8ReceiverPairingRef,au8Data);
                        #endif
                        break;

                    case PLAY:
                        vSendCommand(PLAY);
                        #if (defined EK001)
                        vLcdWriteText("Pause ",7,0);
                        vLcdWriteText("Up     Down   Back ", 7, 33);
                            vLcdRefreshAll();
                        #endif
                        break;
                    case STOP:
                        vSendCommand(STOP);
                        break;
                    case VOLUME_UP:
                        vSendCommand(VOLUME_UP);
                        break;
                    case VOLUME_DOWN:
                        vSendCommand(VOLUME_DOWN);
                        break;
                    case PAUSE:
                        vSendCommand(PAUSE);
                        #if (defined EK001)
                            vLcdWriteText("Play   ",7,0);
                            vLcdWriteText("Up     Down   Back ", 7, 33);
                            vLcdRefreshAll();
                        #endif
                        break;
                    case REWIND:
                        vSendCommand(REWIND);
                        break;
                    case FAST_FORWARD:
                        vSendCommand(FAST_FORWARD);
                        break;
                    case MUTE:
                        vSendCommand(MUTE);
                        break;
                    case POWER:
                        vSendCommand(POWER);
                        /* Delay to make sure that the command is sent before sleep */
                        for(u32Debounce=0;u32Debounce<32000;u32Debounce++);
                        vLcdPowerOff();
                        vSleep(0);
                        break;
                    case DOWN:
                        vAHI_TickTimerWrite(0);
                        if(gu8ScreenPosition !=1)
                        {
                            gu8ScreenPosition++;
                            vLcdWriteText("Select another track       ", 6, 0);
                            vLcdWriteInvertedText("Return to Main Menu        ", 7, 0);
                            vLcdRefreshAll();
                        }

                        break;
                    case UP:
                        if(gu8ScreenPosition !=0)
                        {
                            gu8ScreenPosition--;
                            vLcdWriteInvertedText("Select another track       ", 6, 0);
                            vLcdWriteText("Return to Main Menu        ", 7, 0);
                            vLcdRefreshAll();
                        }
                        break;
                    case LEFT:
                        break;
                    case RIGHT:
                        break;
                    case SELECT:
                        #if (defined EK020)
                            if(gu8ScreenPosition == 0)
                            {
                                vSendCommand(SELECT);
                                vLcdClear();
                                vLcdWriteText("      Select track         ", 2, 0);
                                vLcdRefreshAll();
                                u8TrackSelected = 0;
                                eState = E_TRACK_SELECT;
                                vPrintf("E_TRACK_SELECT\r\n");
                            }
                            else
                            {
                                vSendCommand(STOP);
                                vLcdClear();
                                vLcdWriteText("          Main Menu        ", 0, 0);
                                vLcdWriteInvertedText("Media Player Option       ", 2, 0);
                                vLcdWriteText("Setup Menu                 ", 3, 0);
                                vLcdRefreshAll();
                                gu8ScreenPosition = 0;
                                u8TrackSelected = 0;
                                eState = E_DEVICE_SELECT;
                                vPrintf("E_DEVICE_SELECT\r\n");
                            }
                        #elif (defined EK001)
                            vSendCommand(STOP);
                            vLcdClear();
                            vLcdWriteText("          Main Menu        ", 0, 0);
                            vLcdWriteInvertedText("Media Player Option       ", 2, 0);
                            vLcdWriteText("Setup Menu                 ", 3, 0);
                            vLcdWriteText("Ok     Up       Down     ", 7, 0);
                            vLcdRefreshAll();
                            gu8ScreenPosition = 0;
                            u8TrackSelected = 0;
                            eState = E_DEVICE_SELECT;
                            vPrintf("E_DEVICE_SELECT\r\n");
                        #endif
                        break;

                    default:
                        break;
                }
            }
            break;

        case E_CONFIGMENU:
            /* Read buttons */
            u32Button_Timer();
            u8Key = u8Read(u32Button_Read());

            while (u32Debounce < CONFIGDEBOUNCE){
                u32Debounce++;
                u8Key = u8Read(u32Button_Read());
            }
            switch (u8Key)
            {
                case SELECT:
                    vAHI_TickTimerWrite(0);
                    u8SleepCounter = 0;
                    while(SELECT == u8Read(u32Button_Read()))
                    {
                        u32Button_Timer();
                    }
                    if(gu8ScreenPosition == 0)
                    {
                        vLcdClear();
                        vLcdWriteText("          Main Menu        ", 0, 0);
                        vLcdWriteInvertedText("Media Player Option       ", 2, 0);
                        vLcdWriteText("Setup Menu                 ", 3, 0);
                        #if defined(EK001)
                            vLcdWriteText("Ok     Up       Down     ", 7, 0);
                        #endif
                        vLcdRefreshAll();
                        gu8ScreenPosition = 0;
                        eState = E_DEVICE_SELECT;
                        vPrintf("E_DEVICE_SELECT\r\n");
                    }
                    else if(gu8ScreenPosition == 1)
                        vTimeBeforeSleep();
                    else if(gu8ScreenPosition == 2)
                        (void)vRF4CE_NlmeUnpairReq(0);
                    else if(gu8ScreenPosition == 3)
                        (void)vRF4CE_NlmeUnpairReq(0);
                    break;
                case DOWN:
                    vSetUpScreenPos(SETUP_SCREEN, DIRECTION_DOWN);
                    break;
                case UP:
                    vSetUpScreenPos(SETUP_SCREEN, DIRECTION_UP);
                    break;
                default:
                    break;
            }
            break;
        case E_TRANSMITTING:
            vAHI_TickTimerWrite(0);
            u8SleepCounter = 0;
            /* Waiting for transmit to complete */
            break;

        default:
            break;
        }

        if (   (eState != E_PRE_START)
            && (eState != E_WAIT_FOR_KEY)
            && (eState != E_RUNNING))
        {
         //   vAHI_CpuDoze();
        }
    }
}


/****************************************************************************
 *
 * NAME: u8Read
 *
 * DESCRIPTION:
 * Reads either row DIO pins or column pins to determine which DIOs are
 * connected when a key is pressed
 *
 * PARAMETERS:      Name            RW  Usage
 * Sleep Duration  u32Duration      Read
 *
 * RETURNS:
 * The bit position of the DIO or 0xFF if no/multiple key pressed
 *
 * NOTES:
 *
 ****************************************************************************/
#if defined(EK020)
PRIVATE uint8 u8Read(uint32 u32Button)
{
    uint8 u8Xpos, u8Ypos;
    switch (u32Button)
        {
            case 0x01 : u8Xpos = 0, u8Ypos = 0;   break;
            case 0x02 : u8Xpos = 0, u8Ypos = 1;   break;
            case 0x04 : u8Xpos = 0, u8Ypos = 2;   break;
            case 0x08 : u8Xpos = 1, u8Ypos = 0;   break;
            case 0x10 : u8Xpos = 1, u8Ypos = 1;   break;
            case 0x20 : u8Xpos = 1, u8Ypos = 2;   break;
            case 0x40 : u8Xpos = 2, u8Ypos = 0;   break;
            case 0x80 : u8Xpos = 2, u8Ypos = 1;   break;
            case 0x100 : u8Xpos = 2, u8Ypos = 2;   break;
            case 0x200 : u8Xpos = 3, u8Ypos = 0;   break;
            case 0x400 : u8Xpos = 3, u8Ypos = 1;   break;
            case 0x800 : u8Xpos = 3, u8Ypos = 2;   break;
            case 0x1000 : u8Xpos = 4, u8Ypos = 0;   break;
            case 0x2000 : u8Xpos = 4, u8Ypos = 1;   break;
            case 0x4000 : u8Xpos = 4, u8Ypos = 2;   break;
            case 0x200000 : u8Xpos = 5, u8Ypos = 0;   break;
            case 0x100000 : u8Xpos = 5, u8Ypos = 1;   break;
            case 0x400000 : u8Xpos = 5, u8Ypos = 2;   break;
            case 0x1000000 : u8Xpos = 5, u8Ypos = 3;   break;
            case 0x800000 : u8Xpos = 5, u8Ypos = 4;   break;
            case 0x80000 : u8Xpos = 6, u8Ypos = 0;   break;
            case 0x40000 : u8Xpos = 6, u8Ypos = 1;   break;
            case 0x8000 : u8Xpos = 6, u8Ypos = 2;   break;
            case 0x10000 : u8Xpos = 6, u8Ypos = 3;   break;
            case 0x20000 : u8Xpos = 6, u8Ypos = 4;   break;
            default   : u8Xpos = ERR, u8Ypos = ERR; break;
        }

        /* Is the key pressed valid */
        if ((u8Xpos < ROWS) && (u8Ypos < COLS))
            /* Return the key from the lookup Keyboard in Config.h */
            return acKeyList[u8Xpos][u8Ypos];
        else if (u32Button == PAIR_BUTTONS)
            return (PAIR);
        else
            /* Invalid Key return 0xFF */
            return (ERR);

}
#endif

#if defined(EK001)
PRIVATE uint8 u8Read(uint32 u32Button)
{
    switch (u32Button)
    {
        case APP_BUTTONS_BUTTON_1_MASK:
            if(E_RUNNING == eState){
                if((++u8Paused % 2) == 1)
                    return (PAUSE);
                else
                    return (PLAY);
            }
            else
                return (SELECT);
            break;
        case APP_BUTTONS_BUTTON_2_MASK:
            if(E_RUNNING == eState)
                return (VOLUME_UP);
            else
                return (UP);
            break;
        case APP_BUTTONS_BUTTON_3_MASK:
            if(E_RUNNING == eState)
                return (VOLUME_DOWN);
            else
                return (DOWN);
            break;
        case APP_BUTTONS_BUTTON_4_MASK:
            if(E_TRACK_SELECT == eState)
                return (LEFT);
            else if (E_RUNNING == eState)
                return (SELECT);
            break;
        case APP_BUTTONS_BUTTON_DIO8_MASK:
                return (TWO_DIGIT);
            break;
        default :
            return (ERR);
            break;
    }
    return (ERR);
}
#endif
/****************************************************************************
 *
 * NAME: vSendCommand
 *
 * DESCRIPTION:
 * Send key pressed data
 *
 * PARAMETERS:        Name       RW  Usage
 * key press
 *
 * RETURNS:
 *
 * NOTES:
 *
 ****************************************************************************/
PRIVATE void vSendCommand(uint8 u8KeyPressed)
{
    uint8 au8Nsdu[10];
    uint8 u8DataLen;
    uint8 u8TxOptions;

    /* Create CERC 'key pressed' command frame */
    au8Nsdu[0] = E_ZRC_USER_CONTROL_PRESSED;
    au8Nsdu[1] = u8KeyPressed;
    u8DataLen = 2;
    vPrintf("Data %x\r\n",au8Nsdu[1]);
    eState = E_TRANSMITTING;

    u8TxOptions = RF4CE_TX_OPT_ACKNOWLEDGE | RF4CE_TX_OPT_SINGLE_CHAN;

    /* Setting min backoff exponent to 0 */
    MAC_vPibSetMinBe(pvAppApiGetMacHandle(), 0);
    /* Spinlock to make sure that transition to 32MHz happened. */

    while(bAHI_Clock32MHzStable() == FALSE);

    vRF4CE_NldeDataReq(u8ReceiverPairingRef, ZRC_PROFILE_ID, 0x0000,
                       u8DataLen, au8Nsdu, u8TxOptions);
}

/****************************************************************************
 *
 * NAME: vValToDec
 *
 * DESCRIPTION:
 * Converts an 8-bit value to a string of the textual decimal representation.
 * Adds a text string after the text.
 *
 * PARAMETERS:      Name            RW  Usage
 *                  pcOutString     R   Location for new string
 *                  u8Value         R   Value to convert
 *                  pcLabel         R   Label to append to string
 *
 * RETURNS:
 * void
 *
 ****************************************************************************/
PRIVATE void vValToDec(char *pcOutString, uint8 u8Value, char *pcLabel)
{
    static const uint8 au8Digits[3] = {100, 10, 1};
    uint8 u8Digit;
    uint8 u8DigitIndex;
    uint8 u8Count;
    bool_t boPreviousDigitPrinted = FALSE;

    for (u8DigitIndex = 0; u8DigitIndex < 3; u8DigitIndex++)
    {
        u8Count = 0;
        u8Digit = au8Digits[u8DigitIndex];
        while (u8Value >= u8Digit)
        {
            u8Value -= u8Digit;
            u8Count++;
        }

        if ((u8Count != 0) || (boPreviousDigitPrinted == TRUE)
            || (u8DigitIndex == 2))
        {
            *pcOutString = '0' + u8Count;
            boPreviousDigitPrinted = TRUE;
            pcOutString++;
        }
    }

    vStringCopy(pcLabel, pcOutString);
}
/****************************************************************************
 *
 * NAME: vStringCopy
 *
 * DESCRIPTION:
 * Simple string copy as standard libraries not available.
 *
 * PARAMETERS:      Name    RW  Usage
 *                  pcFrom  R   Pointer to string to copy
 *                  pcTo    W   Pointer to store for new string
 *
 * RETURNS:
 * void
 *
 ****************************************************************************/
PRIVATE void vStringCopy(char *pcFrom, char *pcTo)
{
    while (*pcFrom != '\0')
    {
        *pcTo = *pcFrom;
        pcTo++;
        pcFrom++;
    }
    *pcTo = '\0';
}
/****************************************************************************
 *
 * NAME: Time Before Sleep called
 *
 * DESCRIPTION:
 *
 *
 * PARAMETERS:      Name    RW  Usage
 *
 *
 * RETURNS:
 * void
 *
 ****************************************************************************/
PRIVATE void vTimeBeforeSleep(void)
{
    if(sSetup.u8Time == 20)
    {
        sSetup.u8Time = 40;
        vLcdWriteInvertedText("Time Before Sleep    40S ", 3, 0);
        vLcdRefreshAll();
    }
    else if(sSetup.u8Time == 40)
    {
        sSetup.u8Time = 60;
        vLcdWriteInvertedText("Time Before Sleep    60S ", 3, 0);
        vLcdRefreshAll();
    }
    else if(sSetup.u8Time == 60)
    {
        sSetup.u8Time = 20;
        vLcdWriteInvertedText("Time Before Sleep    20S ", 3, 0);
        vLcdRefreshAll();
    }
}

/****************************************************************************
 *
 * NAME: Screen Position
 *
 * DESCRIPTION:
 *
 *
 * PARAMETERS:      Name    RW  Usage
 *
 *
 * RETURNS:
 * void
 *
 ****************************************************************************/
PRIVATE void vSetUpScreenPos(uint8 u8Posible, uint8 u8Direction)
{
    volatile uint32 i;
    // Following delay for 32MHz
    for(i=0;i<300000;i++);
    u8SleepCounter = 0;

    if (u8Direction == DIRECTION_DOWN)
    {
        if(gu8ScreenPosition == 0)
        {
            vLcdWriteText("Return to Main Menu      ", 2, 0);

            if (sSetup.u8Time ==  20)
                vLcdWriteInvertedText("Time Before Sleep    20S ", 3, 0);
            else if (sSetup.u8Time ==  40)
                vLcdWriteInvertedText("Time Before Sleep    40S ", 3, 0);
            else if (sSetup.u8Time ==  60)
                vLcdWriteInvertedText("Time Before Sleep    60S ", 3, 0);

            vLcdRefreshAll();
            gu8ScreenPosition++;
        }

        else if(gu8ScreenPosition == 1)
        {

            if (sSetup.u8Time ==  20)
                vLcdWriteText("Time Before Sleep    20S ", 3, 0);
            else if (sSetup.u8Time ==  40)
                vLcdWriteText("Time Before Sleep    40S ", 3, 0);
            else if (sSetup.u8Time ==  60)
                vLcdWriteText("Time Before Sleep    60S ", 3, 0);

            vLcdWriteInvertedText("Scan for devices          ", 4, 0);

            vLcdRefreshAll();
            gu8ScreenPosition++;
        }
        else if(gu8ScreenPosition == 2)
        {
            vLcdWriteText("Scan for devices          ", 4, 0);
            vLcdWriteInvertedText("Unpair remote              ", 5, 0);

            vLcdRefreshAll();
            gu8ScreenPosition++;
        }
    }
    if (u8Direction == DIRECTION_UP)
        {
            if(gu8ScreenPosition == 1)
            {
                if (sSetup.u8Time ==  20)
                    vLcdWriteText("Time Before Sleep    20S ", 3, 0);
                else if (sSetup.u8Time ==  40)
                    vLcdWriteText("Time Before Sleep    40S ", 3, 0);
                else if (sSetup.u8Time ==  60)
                    vLcdWriteText("Time Before Sleep    60S ", 3, 0);

                vLcdWriteInvertedText("Return to Main Menu      ", 2, 0);
                gu8ScreenPosition--;
                vLcdRefreshAll();
            }
            else if(gu8ScreenPosition == 2)
            {

                if (sSetup.u8Time ==  20)
                    vLcdWriteInvertedText("Time Before Sleep    20S ", 3, 0);
                else if (sSetup.u8Time ==  40)
                    vLcdWriteInvertedText("Time Before Sleep    40S ", 3, 0);
                else if (sSetup.u8Time ==  60)
                    vLcdWriteInvertedText("Time Before Sleep    60S ", 3, 0);

                vLcdWriteText("Scan for devices          ", 4, 0);

                vLcdRefreshAll();
                gu8ScreenPosition--;
            }
            else if(gu8ScreenPosition == 3)
            {
                vLcdWriteInvertedText("Scan for devices          ", 4, 0);
                vLcdWriteText("Unpair remote              ", 5, 0);
                vLcdRefreshAll();
                gu8ScreenPosition--;
            }
        }
}

#if (defined USE_IR)
/****************************************************************************
 *
 * NAME: EnableIR
 *
 * DESCRIPTION:
 *
 *
 * PARAMETERS:      Name    RW  Usage
 *
 *
 * RETURNS:
 * void
 *
 ****************************************************************************/
PRIVATE void vEnableIR(void)
{
    if(sSetup.IREnable == FALSE)
    {
        sSetup.IREnable = TRUE;
        vLcdWriteInvertedText("IR Enable            True ", 3, 0);
        vLcdRefreshAll();
    }
    else if(sSetup.IREnable == TRUE)
    {
        sSetup.IREnable = FALSE;
        vLcdWriteInvertedText("IR Enable           False ", 3, 0);
        vLcdRefreshAll();
    }
}
#endif

/****************************************************************************
 *
 * NAME: vValToDec
 *
 * DESCRIPTION:
 * Converts an 16-bit value to a string of the textual decimal representation.
 * Adds a text string after the text.
 *
 * PARAMETERS:      Name            RW  Usage
 *                  pcOutString     R   Location for new string
 *                  u16Num         R   Value to convert
 *
 * RETURNS:
 * void
 *
 ****************************************************************************/
PUBLIC void vLongToString(char * str, uint32 u32Num)
{
    uint8 u8Nybble;
    int i;
    for (i = 28; i >= 0; i -= 4)
    {
        u8Nybble = (uint8)((u32Num >> i) & 0x0f);
        u8Nybble += 0x30;
        if (u8Nybble > 0x39)
            u8Nybble += 7;

        *str = u8Nybble;
        str++;
    }
}
/****************************************************************************
 *
 * NAME: vSleep
 *
 * DESCRIPTION:
 * Sends the device into either a deep sleep until a key is pressed
 * or a light sleep for a specified duration
 *
 * PARAMETERS:      Name            RW  Usage
 * Sleep Duration  u32Duration      Read
 *
 * RETURNS:
 * None: NOTE THIS FUNCTION DOES NOT RETURN AT ALL
 *       PROGRAM RESTARTS at appColdStart of appWarmStart
 * NOTES:
 * Setting the duration to 0 causes deep sleep otherwise the sleep
 * delay is u32Duration*(1/32000)  ie 32=1ms
 ****************************************************************************/
PRIVATE void vSleep(uint32 u32Duration)
{
    volatile uint16 u16i;
    uint32 u32DioStatus;

    vPrintf("Sleep\r\n");
    (void)u8AHI_WakeTimerFiredStatus();  /* clear any pending wake timers before sleeping */
    /* Read wake status of IO lines to clear bits and prevent multiple interrupts */
    u32DioStatus = u32AHI_DioInterruptStatus();

    for (u16i=0;u16i<1000;u16i++);
    if (u32Duration > 0)
    {
        vAHI_WakeTimerEnable(E_AHI_WAKE_TIMER_0,TRUE);
        vAHI_WakeTimerStart(E_AHI_WAKE_TIMER_0,u32Duration);
        vRF4CE_ImpSaveSettings(E_SAVE_MODE_MINIMAL);
        vAHI_Sleep(E_AHI_SLEEP_OSCON_RAMON);   /* sleep with memory held */
    }
    else /* awakes to APP_COLD START" */
    {
        #if defined(EK020)
            // following defines to make PWR btn as wakeup source
            #define COL_WAKEUP 0x00400
            #define ROW_WAKEUP 0x20000

            vAHI_UartDisable(E_AHI_UART_0);   //Disabling UART for 6x.

            /* Read wake status of IO lines to clear bits and prevent multiple interrupts */
            u32DioStatus = u32AHI_DioInterruptStatus();

            vAHI_DioSetPullup(COL_WAKEUP, 0);            // SetPullup(on, off)
            vAHI_DioSetDirection(COL_WAKEUP,ROW_WAKEUP); // SetDirection(input, output) ,
            vAHI_DioSetOutput(0, ROW_WAKEUP);            // vAHI_DioSetOutput(high, low)
            vAHI_DioWakeEdge(0, COL_WAKEUP);             // WakeEdge(rising, falling)
            vAHI_DioWakeEnable(COL_WAKEUP, 0);           // WakeEnable(enable, disable)
        #elif defined(EK001)
            vAHI_DioWakeEnable(0, APP_BUTTONS_BUTTON_1_MASK);  // WakeEnable(enable, disable)
        #endif

        vRF4CE_ImpSaveSettings(E_SAVE_MODE_MINIMAL);
        for (u16i=0;u16i<1000;u16i++);
        /* Sleep selected */
        vAHI_Sleep(E_AHI_SLEEP_OSCON_RAMOFF);
    }
}

/****************************************************************************
 *
 * NAME: vTime_TimerISR
 *
 * DESCRIPTION:
 *
 *
 * RETURNS:
 * None.
 *
 * NOTES:
 * None.
 ****************************************************************************/
PRIVATE void vTimerISR(uint32 u32Device, uint32 u32ItemBitmap)
{
    u8SleepCounter++;

    if ((sSetup.u8Time ==  20) && u8SleepCounter == 2)
    {
        u8SleepCounter = 0;
        vLcdPowerOff();
        vSleep(0);
    }
    else if ((sSetup.u8Time ==  40) && u8SleepCounter == 4)
    {
        u8SleepCounter = 0;
        vLcdPowerOff();
        vSleep(0);
    }
    else if ((sSetup.u8Time ==  60) && u8SleepCounter == 6)
    {
        u8SleepCounter = 0;
        vLcdPowerOff();
        vSleep(0);
    }
}

/****************************************************************************/
/***        END OF FILE                                                   ***/
/****************************************************************************/
