/*****************************************************************************
 *
 * MODULE:             JN-AN-1200-ZigBee-RF4CE-Application-Template
 *
 * COMPONENT:          Remote.c
 *
 * DESCRIPTION:        Remote Implementation
 *
 * $HeadURL $
 *
 * $Revision: 12054 $
 *
 * $LastChangedBy: nxp57621 $
 *
 * $LastChangedDate: 2013-12-06 12:03:00 +0530 (Fri, 06 Dec 2013) $
 *
 * $Id: Remote.c 12054 2013-12-06 06:33:00Z nxp57621 $
 *
 ****************************************************************************
 *
 * 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 JN516x, JN514x,
 * JN513x].
 * 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. 2014. All rights reserved
 *
 ***************************************************************************/

/****************************************************************************/
/***        Include files                                                 ***/
/****************************************************************************/
#include <jendefs.h>
#include <PeripheralRegs.h>
#include <string.h>
#include "RF4CE_API.h"
#include "Config.h"
#include "Printf.h"
#include "dbg.h"
#if defined (EKx)
#include "MatrixButton.h"
#else
#include "app_buttons.h"
#include "LcdDriver.h"
#endif


/****************************************************************************/
/***        Macro Definitions                                             ***/
/****************************************************************************/

//#define POWERSAVING
#ifdef DEBUG_APP
    #define TRACE_APP   TRUE
#else
    #define TRACE_APP   FALSE
#endif

//#define vPrintf DBG_vPrintf

/****************************************************************************/
/***        Type Definitions                                              ***/
/****************************************************************************/
typedef enum
{
    E_COLD_START,
    E_WARM_START,
    E_WAIT_FOR_EV_START_CFM,
    E_WAIT_FOR_KEY,
    E_START_DISCOVERY,
    E_WAIT_FOR_EV_DISC_DONE,
    E_START_PAIRING,
    E_WAIT_FOR_EV_PAIR_CFM,
    E_PAIRED,
    E_PAIRING_FAILURE_PAIRED,
    E_PAIRING_FAILURE_UNPAIRED,
    E_PRE_RUNNING,
    E_RUNNING,
    E_TRANSMITTING,
    E_TRANSMIT_FAILED,
    E_UNPAIRED
} teState;

typedef struct
{
    tsIeeeAddr sIeeeAddr;
    uint16     u16PanId;
    uint8      u8Channel;
} tsDiscovered;


/****************************************************************************/
/***        Local Function Prototypes                                     ***/
/****************************************************************************/
PRIVATE void vInitSystem(void);
PRIVATE void vIdleLoop(void);
PRIVATE void vBlinkLED(uint8 u8NumBlink, uint8 u8t100ms);
PRIVATE uint8 u8Read(volatile tsButtonDesc* Buttons);
PRIVATE void vSendCommand(uint8 u8KeyPressed);
PRIVATE void vSleep(void);
PRIVATE void vTimerISR(uint32 u32Device, uint32 u32ItemBitmap);
PRIVATE bool_t bGetNextActivePairingEntry(uint8 *u8CurrentPairingEntry);
PRIVATE uint8 u8NumOfActivePairingEntries(void);
PRIVATE void vDelayIn100ms(uint8 u8DelayIn100ms);
PRIVATE uint8 u8ButtonReadWithSWDebounce(volatile tsButtonDesc* ButtonList);
#ifdef POWERSAVING
PRIVATE void vSystemControl_ISR(uint32 u32DeviceId, uint32 u32ItemBitmap);
#endif


/****************************************************************************/
/***        Exported Variables                                            ***/
/****************************************************************************/
extern uint8 gMAC_u8MaxBuffers;
#if !defined (EKx)
extern uint8 u8WakeUpButton;
#endif

/****************************************************************************/
/***        Local Variables                                               ***/
/****************************************************************************/
PRIVATE volatile teState eState;
PRIVATE tuRF4CE_NibValue uNibValue;
PRIVATE uint8 u8CurrentPairingEntry = 0xFF;
PRIVATE volatile bool_t bUnPaired = FALSE;
PRIVATE volatile uint32 u32SleepCounter = 0;
PRIVATE volatile uint32 u32DelayCounter = 0;
PRIVATE tsDiscovered sDiscovered;
PRIVATE uint8 KeyAtInit = ERR;
PRIVATE bool SettingDestroyed = FALSE;
PRIVATE uint32 bWakeKeyPressed = 0;

tsRF4CE_AppCap sOrgAppCap = {USER_STRING_SPECIFIED,
                             NUM_OF_SUPPORTED_DEVICE_TYPES,
                             RESERVED,
                             NUM_OF_SUPPORTED_PROFILES,
                             RESERVED};
PRIVATE uint8 au8OrgDevTypeList[NUM_OF_SUPPORTED_DEVICE_TYPES] = \
                                        {RF4CE_DEVICE_TYPE_REMOTE_CONTROL};
PRIVATE uint8 au8OrgProfileIdList[NUM_OF_SUPPORTED_PROFILES] = {ZRC_PROFILE_ID};
PRIVATE uint8 au8OrgDiscProfileIdList[NUM_OF_DISCOVERABLE_PROFILES] = \
                                                            {ZRC_PROFILE_ID};

#ifdef LED_DO
#define LED_ON vAHI_DoSetDataOut(0x00, LED_DO)
#define LED_OFF vAHI_DoSetDataOut(LED_DO, 0x00)
#else
#define LED_ON  vAHI_DioSetOutput(0x00000000, LED_DIO)
#define LED_OFF vAHI_DioSetOutput(LED_DIO, 0x00000000)
#endif

#ifdef MATRIX_UPDATE_USE_TICKS
PRIVATE bool_t bUpdateMatrix = FALSE;
volatile tsButtonDesc* CurrentButtonList;
#endif

#if defined (DR1218)
//									  code						lp_code						type		press tp tr	bk line
volatile tsButtonDesc tsButton[NUM_BUTTONS]= {
									{ S1, 						DESTROY, 					eOneShot, 	FALSE, 0, 0, 4, 0x200},
									{ PAIR, 					PAIR, 						eOneShot, 	FALSE, 0, 0, 1, 0x200},
									{ S3, 						S3, 						eOneShot, 	FALSE, 0, 0, 4, 0x20},
									{ S4, 						S4, 						eOneShot, 	FALSE, 0, 0, 4, 0x100},
									{ S5, 						S5, 						eOneShot, 	FALSE, 0, 0, 1, 0x100},
									{ S6, 						S6, 						eOneShot, 	FALSE, 0, 0, 1, 0x20},
									{ S7, 						S7, 						eOneShot, 	FALSE, 0, 0, 4, 0x10},
									{ S8, 						S8, 						eOneShot, 	FALSE, 0, 0, 4, 0x80},
									{ S9, 						S9, 						eOneShot, 	FALSE, 0, 0, 1, 0x80},
									{ S10, 						S10, 						eOneShot, 	FALSE, 0, 0, 1, 0x10},
									{ S11, 						S11, 						eOneShot, 	FALSE, 0, 0, 4, 0x01},
									{ S12, 						S12, 						eOneShot, 	FALSE, 0, 0, 4, 0x40},
									{ S13, 						S13, 						eOneShot, 	FALSE, 0, 0, 1, 0x40},
									{ S14, 						S14, 						eOneShot, 	FALSE, 0, 0, 1, 0x01},
									{ S15, 						S15, 						eOneShot, 	FALSE, 0, 0, 5, 0x200},
									{ S16, 						S16, 						eOneShot, 	FALSE, 0, 0, 3, 0x200},
									{ S17, 						S17, 						eOneShot, 	FALSE, 0, 0, 2, 0x200},
									{ S18, 						S18, 						eOneShot, 	FALSE, 0, 0, 0, 0x200},
									{ S19, 						S19, 						eOneShot, 	FALSE, 0, 0, 5, 0x100},
									{ S20, 						S20, 						eOneShot, 	FALSE, 0, 0, 3, 0x100},
									{ S21, 						S21, 						eOneShot, 	FALSE, 0, 0, 2, 0x100},
									{ S22, 						S22, 						eOneShot, 	FALSE, 0, 0, 0, 0x100},
									{ S23, 						S23, 						eOneShot, 	FALSE, 0, 0, 5, 0x80},
									{ S24, 						S24, 						eOneShot, 	FALSE, 0, 0, 3, 0x80},
									{ S25, 						S25, 						eOneShot, 	FALSE, 0, 0, 2, 0x80},
									{ S26, 						S26, 						eOneShot, 	FALSE, 0, 0, 0, 0x80},
									{ S27, 						S27, 						eOneShot, 	FALSE, 0, 0, 5, 0x40},
									{ S28, 						S28, 						eOneShot, 	FALSE, 0, 0, 3, 0x40},
									{ S29, 						S29, 						eOneShot, 	FALSE, 0, 0, 2, 0x40},
									{ S30, 						S30, 						eOneShot, 	FALSE, 0, 0, 0, 0x40},
									{ S31, 						S31, 						eOneShot, 	FALSE, 0, 0, 5, 0x20},
									{ S32, 						S32, 						eOneShot, 	FALSE, 0, 0, 3, 0x20},
									{ S33, 						S33, 						eOneShot, 	FALSE, 0, 0, 2, 0x20},
									{ S34, 						S34, 						eOneShot, 	FALSE, 0, 0, 0, 0x20},
									{ S35, 						S35, 						eOneShot, 	FALSE, 0, 0, 5, 0x10},
									{ S36, 						S36, 						eOneShot, 	FALSE, 0, 0, 3, 0x10},
									{ S37, 						S37, 						eOneShot, 	FALSE, 0, 0, 2, 0x10},
									{ S38, 						S38, 						eOneShot, 	FALSE, 0, 0, 0, 0x10},
									{ S39, 						S39, 						eOneShot, 	FALSE, 0, 0, 5, 0x01},
									{ S40, 						S40, 						eOneShot, 	FALSE, 0, 0, 3, 0x01},
									{ S41, 						S41, 						eOneShot, 	FALSE, 0, 0, 2, 0x01},
									{ S42, 						S42, 						eOneShot, 	FALSE, 0, 0, 0, 0x01}
									};
#endif // DR1218
#if defined (DR1218_DIV)
//									  code						lp_code						type		press tp tr	bk line
volatile tsButtonDesc tsButton[NUM_BUTTONS]= {
									{ S1, 						DESTROY, 					eOneShot, 	FALSE, 0, 0, 4, 0x200},
									{ PAIR, 					PAIR, 						eOneShot, 	FALSE, 0, 0, 1, 0x200},
									{ S3, 						S3, 						eOneShot, 	FALSE, 0, 0, 4, 0x20},
									{ S4, 						S4, 						eOneShot, 	FALSE, 0, 0, 4, 0x100},
									{ S5, 						S5, 						eOneShot, 	FALSE, 0, 0, 1, 0x100},
									{ S6, 						S6, 						eOneShot, 	FALSE, 0, 0, 1, 0x20},
									{ S7, 						S7, 						eOneShot, 	FALSE, 0, 0, 4, 0x10},
									{ S8, 						S8, 						eOneShot, 	FALSE, 0, 0, 4, 0x80},
									{ S9, 						S9, 						eOneShot, 	FALSE, 0, 0, 1, 0x80},
									{ S10, 						S10, 						eOneShot, 	FALSE, 0, 0, 1, 0x10},
									{ S11, 						S11, 						eOneShot, 	FALSE, 0, 0, 4, 0x01},
									{ S12, 						S12, 						eOneShot, 	FALSE, 0, 0, 4, 0x40},
									{ S13, 						S13, 						eOneShot, 	FALSE, 0, 0, 1, 0x40},
									{ S14, 						S14, 						eOneShot, 	FALSE, 0, 0, 1, 0x01},
									{ S15, 						S15, 						eOneShot, 	FALSE, 0, 0, 5, 0x200},
									{ S16, 						S16, 						eOneShot, 	FALSE, 0, 0, 3, 0x200},
									{ S17, 						S17, 						eOneShot, 	FALSE, 0, 0, 2, 0x200},
									{ S18, 						S18, 						eOneShot, 	FALSE, 0, 0, 0, 0x200},
									{ S19, 						S19, 						eOneShot, 	FALSE, 0, 0, 5, 0x100},
									{ S20, 						S20, 						eOneShot, 	FALSE, 0, 0, 3, 0x100},
									{ S21, 						S21, 						eOneShot, 	FALSE, 0, 0, 2, 0x100},
									{ S22, 						S22, 						eOneShot, 	FALSE, 0, 0, 0, 0x100},
									{ S23, 						S23, 						eOneShot, 	FALSE, 0, 0, 5, 0x80},
									{ S24, 						S24, 						eOneShot, 	FALSE, 0, 0, 3, 0x80},
									{ S25, 						S25, 						eOneShot, 	FALSE, 0, 0, 2, 0x80},
									{ S26, 						S26, 						eOneShot, 	FALSE, 0, 0, 0, 0x80},
									{ S27, 						S27, 						eOneShot, 	FALSE, 0, 0, 5, 0x40},
									{ S28, 						S28, 						eOneShot, 	FALSE, 0, 0, 3, 0x40},
									{ S29, 						S29, 						eOneShot, 	FALSE, 0, 0, 2, 0x40},
									{ S30, 						S30, 						eOneShot, 	FALSE, 0, 0, 0, 0x40},
									{ S31, 						S31, 						eOneShot, 	FALSE, 0, 0, 5, 0x20},
									{ S32, 						S32, 						eOneShot, 	FALSE, 0, 0, 3, 0x20},
									{ S33, 						S33, 						eOneShot, 	FALSE, 0, 0, 2, 0x20},
									{ S34, 						S34, 						eOneShot, 	FALSE, 0, 0, 0, 0x20},
									{ S35, 						S35, 						eOneShot, 	FALSE, 0, 0, 5, 0x10},
									{ S36, 						S36, 						eOneShot, 	FALSE, 0, 0, 3, 0x10},
									{ S37, 						S37, 						eOneShot, 	FALSE, 0, 0, 2, 0x10},
									{ S38, 						S38, 						eOneShot, 	FALSE, 0, 0, 0, 0x10},
									{ S39, 						S39, 						eOneShot, 	FALSE, 0, 0, 5, 0x01},
									{ S40, 						S40, 						eOneShot, 	FALSE, 0, 0, 3, 0x01},
									{ S41, 						S41, 						eOneShot, 	FALSE, 0, 0, 2, 0x01},
									{ S42, 						S42, 						eOneShot, 	FALSE, 0, 0, 0, 0x01}
									};
#endif // DR1218_DIV
#if defined (OM15011)
//									  code						lp_code						type		press tp tr	bk line
volatile tsButtonDesc tsButton[NUM_BUTTONS]= {
									{ CHANNEL_DOWN,				CHANNEL_DOWN,				eDisabled,	FALSE, 0, 0, 0, 0x01}, // K_1 (disabled because layout error)
									{ TWO_DIGIT,				TWO_DIGIT,					eOneShot,	FALSE, 0, 0, 1, 0x01}, //K_2
									{ ONE_DIGIT,				ONE_DIGIT,					eOneShot,	FALSE, 0, 0, 2, 0x01}, //K_3
									{ UP,						UP,							eRepeat,	FALSE, 0, 0, 3, 0x01}, //K_4
									{ ERR,						ERR,						eDisabled,	FALSE, 0, 0, 4, 0x01}, //no key (iso K_5)
									{ ERR,						ERR,						eDisabled,	FALSE, 0, 0, 0, 0x10}, // no key (iso K_7)
									{ ERR,						ERR,						eDisabled,	FALSE, 0, 0, 5, 0x01}, // no key -iso K_6)
									{ CHANNEL_UP,				CHANNEL_UP,					eRepeat,	FALSE, 0, 0, 1, 0x10}, //K_8
									{ ERR,						ERR,						eDisabled,	FALSE, 0, 0, 2, 0x10}, // no key (iso K_9)
									{ PAGE_DOWN,				PAGE_DOWN,					eOneShot,	FALSE, 0, 0, 3, 0x10}, //K_10
									{ ERR,						ERR,						eDisabled,	FALSE, 0, 0, 4, 0x10}, // no key (iso K_11)
									{ ERR,						ERR,						eDisabled,	FALSE, 0, 0, 5, 0x10}, //no key (iso K_12)
									{ ERR,						ERR,						eDisabled,	FALSE, 0, 0, 0, 0x20}, //K_13 (no function printed on key)
									{ ERR,						ERR,						eDisabled,	FALSE, 0, 0, 1, 0x20}, //K_14 (no function printed on key)
									{ ERR,						ERR,						eDisabled,	FALSE, 0, 0, 2, 0x20}, //K_15 (no function for 'envelope' symbol in CEC)
									{ ZERO_DIGIT,				ZERO_DIGIT,					eOneShot, 	FALSE, 0, 0, 3, 0x20}, //K_16
									{ PAIR,						PAIR,						eOneShot,	FALSE, 0, 0, 4, 0x20}, //K_17
									{ ERR,						ERR,						eDisabled,	FALSE, 0, 0, 5, 0x20}, //K_18 (no function printed on key)
									{ ERR,						ERR,						eDisabled,	FALSE, 0, 0, 0, 0x40}, //K_19 (no function printed on key)
									{ NINE_DIGIT,				NINE_DIGIT,					eOneShot, 	FALSE, 0, 0, 1, 0x40}, //K_20
									{ ERR,						ERR,						eDisabled,	FALSE, 0, 0, 2, 0x40}, //K_21 (no function printed on key)
									{ SEVEN_DIGIT,				SEVEN_DIGIT,				eOneShot,	FALSE, 0, 0, 3, 0x40}, //K_22
									{ ERR,						ERR,						eDisabled,	FALSE, 0, 0, 4, 0x40}, //K_23 (no function printed on key)
									{ F4_YELLOW,				F4_YELLOW,					eOneShot,	FALSE, 0, 0, 5, 0x40}, //K_24
									{ F1_BLUE,					F1_BLUE,					eOneShot,	FALSE, 0, 0, 0, 0x80}, //K_25
									{ SIX_DIGIT,				SIX_DIGIT,					eOneShot,	FALSE, 0, 0, 1, 0x80}, //K_26
									{ F2_RED,					F2_RED,						eOneShot,	FALSE, 0, 0, 2, 0x80}, // K_27
									{ PAGE_UP,					PAGE_UP,					eOneShot,	FALSE, 0, 0, 3, 0x80}, // K_28
									{ F3_GREEN,					F3_GREEN,					eOneShot,	FALSE, 0, 0, 4, 0x80}, //K_29
									{ LEFT,						LEFT,						eRepeat,	FALSE, 0, 0, 5, 0x80}, //K_30
									{ S22,						S22,						eOneShot,	FALSE, 0, 0, 0, 0x100}, //K_31
									{ FIVE_DIGIT,				FIVE_DIGIT,					eOneShot,	FALSE, 0, 0, 1, 0x100}, //K_32
									{ DOWN,						DOWN,						eRepeat,	FALSE, 0, 0, 2, 0x100}, //K_33
									{ EIGHT_DIGIT,				EIGHT_DIGIT,				eOneShot,	FALSE, 0, 0, 3, 0x100}, //K_34
									{ VOLUME_DOWN,				VOLUME_DOWN,				eRepeat,	FALSE, 0, 0, 4, 0x100}, //K_35
									{ F5,						F5,							eOneShot,	FALSE, 0, 0, 5, 0x100}, //K_36
									{ RIGHT,					RIGHT,						eRepeat,	FALSE, 0, 0, 0, 0x200}, //K_37
									{ FOUR_DIGIT,				FOUR_DIGIT,					eOneShot,	FALSE, 0, 0, 1, 0x200}, //K_38
									{ SELECT,					DESTROY,					eOneShot,	FALSE, 0, 0, 2, 0x200}, //K_39
									{ ERR,						ERR,						eDisabled,	FALSE, 0, 0, 3, 0x200}, //K_40 (no function printed on key)
									{ VOLUME_UP,				VOLUME_UP,					eRepeat,	FALSE, 0, 0, 4, 0x200}, //K_41
									{ ERR,						ERR,						eDisabled, 	FALSE, 0, 0, 5, 0x200} // K_42 (no function printed on key)
									};
#endif // OM15011
#if defined (OM15012)
//									  code						lp_code						type		press tp tr	bk line
volatile tsButtonDesc tsButton[NUM_BUTTONS]= {
									{ SOUND_SELECT,				SOUND_SELECT,				eOneShot,	FALSE, 0, 0, 0, 0x01}, //K_1
									{ CHANNEL_UP,				CHANNEL_UP,					eRepeat,	FALSE, 0, 0, 0, 0x02}, //K_2
									{ PROGRAM_GUIDE,			PROGRAM_GUIDE,				eOneShot,	FALSE, 0, 0, 0, 0x04}, //K_3
									{ VOLUME_UP,				VOLUME_UP,					eRepeat,	FALSE, 0, 0, 0, 0x08}, //K_4
									{ MUTE,						MUTE,						eOneShot,	FALSE, 0, 0, 0, 0x10}, //K_5
									{ SELECT_AV_INPUT_FUNCTION,	SELECT_AV_INPUT_FUNCTION,	eOneShot,	FALSE, 0, 0, 0, 0x20}, //K_6
									{ FORWARD, 					FORWARD,					eOneShot,	FALSE, 0, 0, 1, 0x01}, //K_7
									{ CLEAR,					CLEAR,						eOneShot,	FALSE, 0, 0, 1, 0x02}, //K_8
									{ BACKWARD,					BACKWARD,					eOneShot,	FALSE, 0, 0, 1, 0x04}, //K_9
									{ SETUP_MENU,				SELECT_MEDIA_FUNCTION,		eOneShot,	FALSE, 0, 0, 1, 0x08}, //K_10
									{ INPUT_SELECT,				INPUT_SELECT,				eOneShot,	FALSE, 0, 0, 1, 0x10}, //K_11
									{ F5,						F5,							eOneShot,	FALSE, 0, 0, 1, 0x20}, //K_12
									{ PAUSE_PLAY_FUNCTION,		PAUSE_PLAY_FUNCTION,		eOneShot,	FALSE, 0, 0, 2, 0x01}, //K_13
									{ ZERO_DIGIT,				ZERO_DIGIT,					eOneShot,	FALSE, 0, 0, 2, 0x02}, //K_14
									{ REWIND,					REWIND,						eOneShot,	FALSE, 0, 0, 2, 0x04}, //K_15
									{ SEVEN_DIGIT,				SEVEN_DIGIT,				eOneShot,	FALSE, 0, 0, 2, 0x08}, //K_16
									{ FAST_FORWARD,				FAST_FORWARD,				eOneShot,	FALSE, 0, 0, 2, 0x10}, //K_17
									{ STOP,						STOP,						eOneShot,	FALSE, 0, 0, 2, 0x20}, //K_18
									{ DOWN, 					DOWN, 						eRepeat,	FALSE, 0, 0, 3, 0x01}, //K_19
									{ EIGHT_DIGIT,				EIGHT_DIGIT,				eOneShot,	FALSE, 0, 0, 3, 0x02}, //K_20
									{ ROOT_MENU, 				PAIR,						eOneShot,	FALSE, 0, 0, 3, 0x04}, //K_21
									{ FOUR_DIGIT, 				FOUR_DIGIT,					eOneShot,	FALSE, 0, 0, 3, 0x08}, //K_22
									{ NINE_DIGIT,				NINE_DIGIT,					eOneShot,	FALSE, 0, 0, 3, 0x010},//K_23
									{ DISPLAY_INFO,				DISPLAY_INFO,				eOneShot,	FALSE, 0, 0, 3, 0x20}, //K_24
									{ SELECT,					DESTROY,					eOneShot,	FALSE, 0, 0, 4, 0x01}, //K_25
									{ FIVE_DIGIT,				FIVE_DIGIT,					eOneShot,	FALSE, 0, 0, 4, 0x02}, //K_26
									{ LEFT,						LEFT,						eRepeat,	FALSE, 0, 0, 4, 0x04}, //K_27
									{ ONE_DIGIT,				ONE_DIGIT,					eOneShot,	FALSE, 0, 0, 4, 0x08}, //K_28
									{ SIX_DIGIT,				SIX_DIGIT,					eOneShot,	FALSE, 0, 0, 4, 0x10}, //K_29
									{ RIGHT,					RIGHT,						eRepeat,	FALSE, 0, 0, 4, 0x20}, //K_30
									{ UP,						UP,							eRepeat,	FALSE, 0, 0, 5, 0x01}, //K_31
									{ TWO_DIGIT,				TWO_DIGIT,					eOneShot,	FALSE, 0, 0, 5, 0x02}, //K_32
									{ VOLUME_DOWN,				VOLUME_DOWN,				eRepeat,	FALSE, 0, 0, 5, 0x04}, //K_33
									{ POWER,					POWER,						eOneShot, 	FALSE, 0, 0, 5, 0x08}, //K_34
									{ THREE_DIGIT,				THREE_DIGIT,				eOneShot, 	FALSE, 0, 0, 5, 0x010},//K_35
									{ CHANNEL_DOWN,				CHANNEL_DOWN,				eRepeat, 	FALSE, 0, 0, 5, 0x20}  //K_36
									};
#endif // OM15012
#if defined (OM15013)
//									  code						lp_code						type		press tp tr	bk line
volatile tsButtonDesc tsButton[NUM_BUTTONS]= {
									{ ONE_DIGIT,				ONE_DIGIT,					eOneShot, 	FALSE, 0, 0, 0, 0x02}, // K_1
									{ TWO_DIGIT,				TWO_DIGIT,					eOneShot, 	FALSE, 0, 0, 1, 0x01}, //K_2
									{ THREE_DIGIT,				THREE_DIGIT,				eOneShot, 	FALSE, 0, 0, 2, 0x02}, //K_3
									{ FOUR_DIGIT,				FOUR_DIGIT,					eOneShot, 	FALSE, 0, 0, 0, 0x04}, //K_4
									{ FIVE_DIGIT,				FIVE_DIGIT,					eOneShot,	FALSE, 0, 0, 1, 0x02}, //K5
									{ SIX_DIGIT,				SIX_DIGIT,					eOneShot,	FALSE, 0, 0, 2, 0x04}, // K6
									{ SEVEN_DIGIT,				SEVEN_DIGIT,				eOneShot,	FALSE, 0, 0, 0, 0x08}, // K7
									{ EIGHT_DIGIT,				EIGHT_DIGIT,				eOneShot, 	FALSE, 0, 0, 1, 0x04}, //K_8
									{ NINE_DIGIT,				NINE_DIGIT,					eOneShot, 	FALSE, 0, 0, 2, 0x08}, // K9
									{ ZERO_DIGIT,				ZERO_DIGIT,					eOneShot, 	FALSE, 0, 0, 1, 0x08}, //K_10
									{ POWER,					POWER,						eOneShot,	FALSE, 0, 0, 0, 0x01}, // K11
									{ MUTE,						MUTE,						eOneShot, 	FALSE, 0, 0, 2, 0x01}, //K12
									{ VOLUME_UP,				VOLUME_UP,					eRepeat,	FALSE, 0, 0, 0, 0x1000}, //K_13
									{ SETUP_MENU,				SETUP_MENU,					eOneShot, 	FALSE, 0, 0, 1, 0x100}, //K_14
									{ CHANNEL_UP,				CHANNEL_UP,					eRepeat,	FALSE, 0, 0, 2, 0x1000}, //K_15
									{ VOLUME_DOWN,				VOLUME_DOWN,				eRepeat, 	FALSE, 0, 0, 3, 0x01}, //K_16
									{ SETUP_MENU,				SETUP_MENU,					eOneShot, 	FALSE, 0, 0, 1, 0x1000}, //K_17
									{ CHANNEL_DOWN,				CHANNEL_DOWN,				eRepeat, 	FALSE, 0, 0, 5, 0x01}, //K_18
									{ UP,						UP,							eRepeat, 	FALSE, 0, 0, 3, 0x02}, //K_19
									{ LEFT,						LEFT,						eRepeat, 	FALSE, 0, 0, 3, 0x04}, //K_20
									{ SELECT,					DESTROY,					eOneShot, 	FALSE, 0, 0, 4, 0x01}, //K_21
									{ RIGHT,					RIGHT,						eRepeat,	FALSE, 0, 0, 5, 0x02}, //K_22
									{ DOWN,						DOWN,						eRepeat, 	FALSE, 0, 0, 4, 0x02}, //K_23
									{ CONTENTS_MENU,			CONTENTS_MENU,				eOneShot, 	FALSE, 0, 0, 3, 0x08}, //K_24
									{ EXIT,						EXIT,						eOneShot, 	FALSE, 0, 0, 5, 0x04}, //K_25
									{ F2_RED,					F2_RED,						eOneShot, 	FALSE, 0, 0, 3, 0x100}, //K_26
									{ F3_GREEN,					F3_GREEN,					eOneShot, 	FALSE, 0, 0, 4, 0x04}, // K_27
									{ F4_YELLOW,				PAIR,						eOneShot, 	FALSE, 0, 0, 4, 0x08}, // K_28
									{ F1_BLUE,					F1_BLUE,					eOneShot, 	FALSE, 0, 0, 5, 0x08}, //K_29
									{ BACKWARD,					BACKWARD,					eOneShot, 	FALSE, 0, 0, 3, 0x1000}, //K_30
									{ PLAY,						PLAY,						eOneShot, 	FALSE, 0, 0, 4, 0x100}, //K_31
									{ PAUSE,					PAUSE,						eOneShot, 	FALSE, 0, 0, 4, 0x1000}, //K_32
									{ FORWARD,					FORWARD,					eOneShot, 	FALSE, 0, 0, 5, 0x100}, //K_33
									{ DISPLAY_INFO,				DISPLAY_INFO,				eOneShot, 	FALSE, 0, 0, 0, 0x100}, //K_34
									{ SELECT_AV_INPUT_FUNCTION,	SELECT_AV_INPUT_FUNCTION,	eOneShot, 	FALSE, 0, 0, 2, 0x100}, //K_35
									{ ERR,						ERR,						eDisabled, 	FALSE, 0, 0, 0, 0} //K_36 not used
									};
#endif // OM15013



/****************************************************************************/
/***        Exported Functions                                            ***/
/****************************************************************************/


/****************************************************************************/
/***        Local Functions                                               ***/
/****************************************************************************/

/****************************************************************************
 *
 * NAME: AppColdStart
 *
 * DESCRIPTION:
 * Entry point for application from boot loader. Initializes system and runs
 * main loop.
 *
 * RETURNS:
 * Never returns.
 *
 ****************************************************************************/
PUBLIC void AppColdStart(void)
{
#ifdef MATRIX_UPDATE_USE_TICKS
	uint8 i;
#endif



    gMAC_u8MaxBuffers = 2;

    vAHI_WatchdogStop();

    /* General initialisation */
    vInitSystem();

    vPrintf("\nStarting");

#if !defined (MATRIX_UPDATE_USE_TICKS)
   /* Initialise stack (implementation-specific command) */
    if (bRF4CE_ImpInit(NODE_CAPABILITY, VENDOR_ID,(uint8 *)VENDOR_STRING))
    {
        vPrintf("\nColdStart");
        eState = E_COLD_START;
    }
    else
    {
        vPrintf("\nWarmStart");
        eState = E_WARM_START;
    }
#endif

    vAHI_TickTimerIntEnable(TRUE);

#ifdef MATRIX_UPDATE_USE_TICKS
        /* Enable buttons */
    vMatrixButton_Configure(NUM_BUTTONS, BUTTON_BANKS_DIO_MASK, BUTTON_LINES_DIO_MASK);

    /* reset KeyAtInit */
    KeyAtInit = ERR;

    /* Check if flash should be erased (DESTROY button pressed at power on but not when wakeup by key pressed in bound state)*/
	KeyAtInit = u8ButtonReadWithSWDebounce(tsButton);

	/* remove DESTROY from tsButton lp_code list and replace it by the short code */
	for (i=0;i<NUM_BUTTONS;i++)
	{
		if (tsButton[i].lp_code == DESTROY)
			{
			tsButton[i].lp_code = tsButton[i].code;
			break;
			}
	}

	if (KeyAtInit == DESTROY)
	{
		if (bWakeKeyPressed == 0)
		{
			vPrintf("Destroy settings\n");
			vRF4CE_ImpDestroySettings();
			SettingDestroyed = TRUE;
		}
	    KeyAtInit = tsButton[i].code;
	}

    /* Initialise stack (implementation-specific command) */
    if (bRF4CE_ImpInit(NODE_CAPABILITY, VENDOR_ID,(uint8 *)VENDOR_STRING))
    {
        vPrintf("\nColdStart");
        eState = E_COLD_START;
    }
    else
    {
        vPrintf("\nWarmStart");
        eState = E_WARM_START;
    }

#endif

    if (SettingDestroyed)
    	{
    	vBlinkLED (4, 5);
    	SettingDestroyed = FALSE;
    	}
    /* Go to idle loop */
    vIdleLoop();
}

/****************************************************************************
 *
 * NAME: AppWarmStart
 *
 * DESCRIPTION:
 * Entry point for a wake from sleep mode with the memory contents held.
 *
 * RETURNS:
 * void
 *
 ****************************************************************************/
PUBLIC void AppWarmStart(void)
{
    AppColdStart();
}

/****************************************************************************
 *
 * NAME: vInitSystem
 *
 * DESCRIPTION:
 * Initialises stack and hardware.
 *
 * RETURNS:
 * void
 *
 ****************************************************************************/
PRIVATE void vInitSystem(void)
{
#if !defined (MATRIX_UPDATE_USE_TICKS)
	uint8 i;
#endif

   /* Initialise stack and hardware interfaces. */
    (void)u32AHI_Init();

	//set DIOs as input
	vAHI_DioSetDirection(0xFFFFFFFF, 0x00000000);

#ifdef LED_DO
	// enable DO as general purpose outputs
	bAHI_DoEnableOutputs(TRUE);
	//switch LED on
	LED_ON;
#else
	// set LED DIO as output
	vAHI_DioSetDirection(0x00000000, LED_DIO);
	//switch LED on
	LED_ON;
#endif // LED_DO

	//Disable pullup
	//vAHI_DioSetPullup(0x00000000, 0xFFFFFF3F);
	vAHI_DioSetPullup(0x00000000, 0xFFFFFFFF);

#ifdef POWERSAVING
	/* Configure brown-out to give interrupt when voltage falls below threshold */
	vAHI_BrownOutConfigure(E_AHI_VBOREF_1V95,	/* Threshold */
						   FALSE,				/* Do not reset on event detection */
						   //TRUE,				/* Reset on event detection */
						   TRUE,				/* Enable brownout detection */
						   //FALSE,				/* Disable brownout detection */
						   FALSE,				/* Disable interrupt on exiting condition */
						   TRUE);				/* Enable interrupt on entering condition */

	/* Register interrupt handler that will be called when a system control
	   event (i.e. brown-out etc) occurs */
    vAHI_SysCtrlRegisterCallback(vSystemControl_ISR);

#endif




	/* Determine whether the switch to crystal oscillator has taken place*/
    while(bAHI_GetClkSource() == TRUE);
    /* Set clock to CPU_FREQUENCY_MHz and OptimiseWaitState */
    bAHI_SetClockRate((CPU_FREQUENCY_MHz == 32)? 3 : 2);
    vAHI_OptimiseWaitStates();

    while(bAHI_Clock32MHzStable() == FALSE);

    /* Initialise tick timer to give periodic interrupt */
    vAHI_TickTimerConfigure(E_AHI_TICK_TIMER_DISABLE);
    vAHI_TickTimerWrite(0);
    vAHI_TickTimerRegisterCallback(vTimerISR);
    vAHI_TickTimerInterval(16 * 100000); /* 100ms tick from 16MHz Clock source */
//    vAHI_TickTimerInterval(16 * 10000); /* 10ms tick from 16MHz Clock source */
    vAHI_TickTimerConfigure(E_AHI_TICK_TIMER_RESTART);

    /* Initialise UART for debug */
    vUART_printInit();

#if !defined (MATRIX_UPDATE_USE_TICKS)

        /* Enable buttons */
    vMatrixButton_Configure(NUM_BUTTONS, BUTTON_BANKS_DIO_MASK, BUTTON_LINES_DIO_MASK);

    /* reset KeyAtInit */
    KeyAtInit = ERR;

    /* Check if flash should be erased (DESTROY button pressed at power on but not when wakeup by key pressed in bound state)*/
	KeyAtInit = u8ButtonReadWithSWDebounce(tsButton);

	/* remove DESTROY from tsButton lp_code list and replace it by the short code */
	for (i=0;i<NUM_BUTTONS;i++)
	{
		if (tsButton[i].lp_code == DESTROY)
			{
			tsButton[i].lp_code = tsButton[i].code;
			break;
			}
	}

	if (KeyAtInit == DESTROY)
	{
		if (bWakeKeyPressed == 0)
		{
			vPrintf("Destroy settings\n");
			vRF4CE_ImpDestroySettings();
			SettingDestroyed = TRUE;
		}
	    KeyAtInit = tsButton[i].code;
	}
#endif

}

/****************************************************************************
 *
 * NAME: vIdleLoop
 *
 * DESCRIPTION: Application state machine
 *
 * RETURNS:
 * void
 *
 ****************************************************************************/
PRIVATE void vIdleLoop(void)
{
    uint8 u8Key = ERR;
    bool_t bPerformAction = FALSE;
    volatile uint32 u32i;

    while (1)
    {
        switch (eState)
        {
            case E_COLD_START:
                /* Cold start: reset stack and clear NIB; then start stack */
                vRF4CE_NlmeResetReq(TRUE);
                /* Stack start is asynchronous; wait for start confirmation.*/
                eState = E_WAIT_FOR_EV_START_CFM;
                vRF4CE_NlmeStartReq();

//                /* Initialise tick timer to give periodic interrupt */
//                vAHI_TickTimerConfigure(E_AHI_TICK_TIMER_DISABLE);
//                vAHI_TickTimerWrite(0);
//                vAHI_TickTimerRegisterCallback(vTimerISR);
//            //    vAHI_TickTimerInterval(16 * 100000); /* 100ms tick from 16MHz Clock source */
//                vAHI_TickTimerInterval(16 * 10000); /* 10ms tick from 16MHz Clock source */
//                vAHI_TickTimerConfigure(E_AHI_TICK_TIMER_RESTART);
//                vAHI_TickTimerIntEnable(TRUE);
            	//switch LED off
                LED_OFF;
                break;

            case E_WAIT_FOR_EV_START_CFM:
                break;

            case E_WARM_START:
                /* Warm start: reset without clearing NIB */
                vRF4CE_NlmeResetReq(FALSE);

                if(bGetNextActivePairingEntry(&u8CurrentPairingEntry))
                {
                    /* Start as pairing table is non empty */
                    eState = E_PRE_RUNNING;
                }
                else
                {
                    /* Cold Start again as pairing table is empty */
                    eState = E_COLD_START;
                }

//                /* Initialise tick timer to give periodic interrupt */
//                vAHI_TickTimerConfigure(E_AHI_TICK_TIMER_DISABLE);
//                vAHI_TickTimerWrite(0);
//                vAHI_TickTimerRegisterCallback(vTimerISR);
//            //    vAHI_TickTimerInterval(16 * 100000); /* 100ms tick from 16MHz Clock source */
//                vAHI_TickTimerInterval(16 * 10000); /* 10ms tick from 16MHz Clock source */
//                vAHI_TickTimerConfigure(E_AHI_TICK_TIMER_RESTART);
//                vAHI_TickTimerIntEnable(TRUE);
            	//switch LED off
                LED_OFF;
                break;

            case E_WAIT_FOR_KEY:
				/* Check if button was pressed at init*/
            	if (KeyAtInit != ERR)
            	{
            		u8Key= KeyAtInit;
            		KeyAtInit = ERR;
            	}
            	else
            	{
            		u8Key= u8ButtonReadWithSWDebounce(tsButton);
            	}
				/* Wait PAIR key to be pressed */
				if (u8Key == PAIR)
				{
					vPrintf("\nPAIR Button pressed\n");
					eState = E_START_DISCOVERY;
				}
                break;

            case E_START_DISCOVERY:
                u32SleepCounter = 0;

                /* Set info in NIB */
                memset(uNibValue.au8UserString, 0, RF4CE_USER_STRING_LEN);
                memcpy(uNibValue.au8UserString, USER_STRING, USER_STRING_LEN);
                (void)eRF4CE_NlmeSetReq(E_RF4CE_NIB_ATTR_USER_STRING, 0, &uNibValue);

                uNibValue.u8MaxDiscoveryRepetitions = MAX_DISCOVERY_REPETITIONS;
                (void)eRF4CE_NlmeSetReq(E_RF4CE_NIB_ATTR_MAX_DISC_REPETITIONS,
                                        0, &uNibValue);

                /* Get info from NIB */
                (void)eRF4CE_NlmeGetReq(E_RF4CE_NIB_ATTR_BASE_CHANNEL, 0, &uNibValue);
                vPrintf("\nStarted with Channel %d",uNibValue.u8BaseChannel);

                /* Request discovery */
                vPrintf("\nTrying discovery");


                eState = E_WAIT_FOR_EV_DISC_DONE;

                vRF4CE_NlmeDiscoveryReq(0xffff, 0xffff,
                                        &sOrgAppCap, au8OrgDevTypeList,
                                        au8OrgProfileIdList,
                                        RF4CE_DEVICE_TYPE_MEDIA_CENTER,
                                        NUM_OF_DISCOVERABLE_PROFILES,
                                        au8OrgDiscProfileIdList,
                                        MAX_DISCOVERY_DURATION);
                break;

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

            case E_START_PAIRING:
                vPrintf("\nPairing");
                vRF4CE_NlmePairReq(sDiscovered.u8Channel, sDiscovered.u16PanId,
                                   &sDiscovered.sIeeeAddr, &sOrgAppCap,
                                   au8OrgDevTypeList, au8OrgProfileIdList,
                                   KEY_EXCHANGE_TRANSFER_COUNT);
                eState = E_WAIT_FOR_EV_PAIR_CFM;
                break;

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

            case E_PAIRED:
                /* As paired save the settings and get into running mode */
                vRF4CE_ImpSaveSettings(E_SAVE_MODE_FULL);
                vPrintf("\nSaved");
            	vBlinkLED (1, 10);
                eState = E_PRE_RUNNING;
                break;

            case E_PAIRING_FAILURE_PAIRED:
            	vBlinkLED (5, 30);
                eState = E_PRE_RUNNING;
                break;

            case E_PAIRING_FAILURE_UNPAIRED:
            	vBlinkLED (5, 3);
                eState = E_WAIT_FOR_KEY;
                break;

            case E_PRE_RUNNING:
                eState = E_RUNNING;
                break;

            case E_RUNNING:
            	if (KeyAtInit != ERR)
            	{
            		u8Key= KeyAtInit;
            		KeyAtInit = ERR;
            	}
            	else
            	{
            		u8Key= u8ButtonReadWithSWDebounce(tsButton);
            	}

                if((u8Key != ERR) && (u8Key != PAIR) && (u8Key != DESTROY))
                {
                    bPerformAction = TRUE;
                }
                if(bPerformAction)
                {
                    bPerformAction = FALSE;
                    switch(u8Key)
                    {
                        case PAIR:
                            if(u8NumOfActivePairingEntries() < RF4CE_NWKC_MAX_PAIRING_TABLE_ENTRIES)
                            {
                                eState = E_START_DISCOVERY;
                            }
                            break;
                        default:
                            vSendCommand(u8Key);
                            break;
                    }
                }


                break;

            case E_TRANSMITTING:
                /* Waiting for transmit to complete */
                break;

            case E_TRANSMIT_FAILED:
                for(u32i=0;u32i<3000000;u32i++);
                eState = E_PRE_RUNNING;
                break;

            default:
                break;
        }
    }
}

/****************************************************************************
 *
 * NAME: vRF4CE_StackEvent
 *
 * DESCRIPTION:
 * Handle the generated stack event
 *
 * PARAMETERS:          Name            RW  Usage
 *                      eEvent          R   RF4CE Stack event type
 *                      puParam         R   Pointer to parameter of RF4CE event
 *
 * RETURNS:
 * None.
 *
 ****************************************************************************/
PUBLIC void vRF4CE_StackEvent(teRF4CE_EventType eEvent,
                              tuRF4CE_EventParam *puParam)
{
    switch (eEvent)
    {
    case E_RF4CE_EV_START_CFM:      /* Use with tsRF4CE_NlmeStartCfm */
        if (E_RF4CE_STATUS_SUCCESS == puParam->sNlmeStartCfm.eStatus)
        {
            eState = E_WAIT_FOR_KEY;
        }
        else
        {
            /* Try scanning again till successful start confirm comes*/
            vRF4CE_NlmeStartReq();
        }
        break;

    case E_RF4CE_EV_DISC_CFM:   /* Use with tsRF4CE_NlmeDiscoveryCfm */
        if (E_RF4CE_STATUS_SUCCESS == puParam->sNlmeDiscoveryCfm.eStatus)
        {
            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;
            eState = E_START_PAIRING;
        }
        else
        {
            vPrintf("\nDisc Cfm! Error code %x",puParam->sNlmeDiscoveryCfm.eStatus);

            if(u8NumOfActivePairingEntries())
            {
                eState = E_PAIRING_FAILURE_PAIRED;
            }
            else
            {
                eState = E_PAIRING_FAILURE_UNPAIRED;
            }
        }
        break;

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

        if (E_RF4CE_STATUS_SUCCESS == puParam->sNlmePairCfm.eStatus)
        {
            vPrintf("\nPaired");
            u8CurrentPairingEntry = puParam->sNlmePairCfm.u8PairingRef;
            eState = E_PAIRED;
        }
        else
        {
            vPrintf("\nNot Paired");
            if(u8NumOfActivePairingEntries())
            {
                eState = E_PAIRING_FAILURE_PAIRED;
            }
            else
            {
                eState = E_PAIRING_FAILURE_UNPAIRED;
            }
        }
        break;

    case E_RF4CE_EV_COMMSTATUS_IND: /* Use with tsRF4CE_NlmeCommStatusInd */
        break;

    case E_RF4CE_EV_NLDE_CFM:       /* Use with tsRF4CE_NldeDataCfm */
        if(puParam->sNldeDataCfm.eStatus == E_RF4CE_STATUS_SUCCESS)
        {
            eState = E_RUNNING;
        }
        else
        {
            eState = E_TRANSMIT_FAILED;
        }
        break;

    case E_RF4CE_EV_UNPAIR_IND:
        vRF4CE_NlmeUnpairResp(puParam->sNlmeUnpairInd.u8PairingRef);
        vRF4CE_ImpSaveSettings(E_SAVE_MODE_FULL);
        bUnPaired = TRUE;
        break;

    case E_RF4CE_EV_NLDE_IND:
        vPrintf("\nData Ind");
        break;

    case E_RF4CE_EV_UNPAIR_CFM:     /* Use with tsRF4CE_NlmeUnpairCfm */
        vPrintf("\nUnpair Cfm");
        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("\nUnhandled!");
        break;
    }
}



/****************************************************************************
 *
 * NAME: u8ButtonReadWithSWDebounce
 *
 * DESCRIPTION:
 * Reads button DIO pressed with software debounce of 100ms.
 *
 * RETURNS:
 * u8Key    DIO button number of pressed key
 *
 ****************************************************************************/
PRIVATE uint8 u8ButtonReadWithSWDebounce(volatile tsButtonDesc* ButtonList)
{

    uint8 u8Key, u8Button= ERR;
    uint16 u16Timepressed;
#ifdef MULTITOUCH
    uint8 i;
#endif
    static bool_t repeat_on =FALSE;
    uint16 repeat_threshold;


    u16Timepressed = 0;

	u8Key = u8Read(tsMatrixButton_Update(ButtonList));
	if(u8Key != ERR)
	{
#ifdef MATRIX_UPDATE_USE_TICKS
		CurrentButtonList = ButtonList;
		bUpdateMatrix = TRUE;
		u32SleepCounter = 0;
#endif

		if (ButtonList[u8Key].type == eOneShot)
		{
#ifdef MULTITOUCH
			/* RAZ all time_pressed */
			for (i=0;i<NUM_BUTTONS; i++)
			{
				ButtonList[i].time_pressed = 0;
			}
#endif
			// reset repeat_on
			repeat_on =FALSE;
			//switch LED on
			LED_ON;
			/* wait for button release for MIN_RELESAED*/
			do
			{
#if !defined (MATRIX_UPDATE_USE_TICKS)
				tsMatrixButton_Update(ButtonList);
#endif
				if (ButtonList[u8Key].time_pressed > u16Timepressed) u16Timepressed = ButtonList[u8Key].time_pressed;
				u32SleepCounter = 0;
			}
			while ((ButtonList[u8Key].pressed) || (ButtonList[u8Key].time_released < CONFIGDEBOUNCE_MIN_RELEASED)) ;

			if (u16Timepressed>=CONFIGDEBOUNCE_LONG_PRESSED)
			{
				u8Button= ButtonList[u8Key].lp_code;
				vPrintf("Button Long Pressed (p %d r%d) CEC_Cmd %x\n", u16Timepressed, ButtonList[u8Key].time_released, u8Button);
				vPrintf("Button Long Pressed CEC_Cmd %x\n", u8Button);
			}
			else
			{
				u8Button= ButtonList[u8Key].code;
				vPrintf("Button Short Pressed (p %d r%d) CEC_Cmd %x\n", u16Timepressed, ButtonList[u8Key].time_released, u8Button);
				vPrintf("Button CEC_Cmd %x\n", u8Button);
			}
#ifdef MULTITOUCH
			/* check here if another button has been pressed by checking all time_pressed for the buttons that can be involved in multitouch */
			/* manage touch combination and change u8Key value in accordance */
			/* For example, if ButtonList[8] can be involved in multitouch, then check if ButtonList[8].time_pressed !=0 */
			/* In that case evaluate if ButtonList[8]+ButtonList[u8Key] has a function that overrides the function of ButtonList[u8Key] */
			/* and replace u8Button value in that case */
#endif

				//switch LED off
			LED_OFF;
		}
		else if (ButtonList[u8Key].type == eRepeat)
		{
			//switch LED on
			LED_ON;
			// choose repeat_threshold depending on repeat_on
			if (repeat_on)
			{
				repeat_threshold= CONFIGDEBOUNCE_CONTINUE_REPEAT;
			}
			else
			{
				repeat_threshold= CONFIGDEBOUNCE_START_REPEAT;
			}

			/* wait for button release for MIN_RELESAED*/
			do
			{
#if !defined (MATRIX_UPDATE_USE_TICKS)
				tsMatrixButton_Update(ButtonList);
#endif
				if (ButtonList[u8Key].time_pressed > u16Timepressed) u16Timepressed = ButtonList[u8Key].time_pressed;
				u32SleepCounter = 0;
			}
			while ( ((ButtonList[u8Key].pressed) && (u16Timepressed < repeat_threshold)) ||
					((ButtonList[u8Key].time_released < CONFIGDEBOUNCE_MIN_RELEASED) &&
							(!(ButtonList[u8Key].pressed) || (u16Timepressed < repeat_threshold))) );


			if (u16Timepressed >= repeat_threshold)
			{
				repeat_on = TRUE;
				ButtonList[u8Key].time_pressed = 0;
				u8Button= ButtonList[u8Key].code;
				vPrintf("Button CEC_Cmd (repeat)%x\n", u8Button);
				//switch LED off
				LED_OFF;
			}
			else
			{
				repeat_on = FALSE;
				u8Button= ButtonList[u8Key].code;
				vPrintf("Button CEC_Cmd %x\n", u8Button);
				//switch LED off
				LED_OFF;
			}
		}

#ifdef MATRIX_UPDATE_USE_TICKS
		bUpdateMatrix = FALSE;
#endif

	}
	else
	{
		repeat_on = FALSE;
		u8Button = ERR;
	}


	return (u8Button);
}

/****************************************************************************
 *
 * NAME: vDelayIn100ms
 *
 * DESCRIPTION:
 * Delay in multiple of 100ms. This function utilizes tick timer.
 *
 * PARAMETERS:
 * u8DelayIn100ms   Delay in multiple of 100ms
 *
 * RETURNS:
 * void
 *
 ****************************************************************************/
void vDelayIn100ms(uint8 u8DelayIn100ms)
{
    u32DelayCounter = 0;
    while(u32DelayCounter < u8DelayIn100ms) vAHI_CpuDoze();
}


/****************************************************************************
 *
 * NAME: u8Read
 *
 * DESCRIPTION:
 * Reads either which DIO pins to determine which DIO is
 * connected when a key is pressed
 *
 * PARAMETERS:      Name            RW  Usage
 * uint32           u32Button       Button Presses
 *
 * RETURNS:
 * The bit position of the DIO or 0xFF if no/multiple key pressed
 *
 * NOTES:
 *
 ****************************************************************************/
PRIVATE uint8 u8Read(volatile tsButtonDesc* Buttons)
{

	uint8 Button = ERR;
	uint8 i;

	for (i=0;i<NUM_BUTTONS; i++)
	{
		if ((Buttons[i].pressed) && (Buttons[i].type != eModifier) && (Buttons[i].type != eDisabled))
			{
				Button = i;
				break;
			}
	}

	return (Button);
 }

/****************************************************************************
 *
 * NAME: vBlinkLED
 *
 * DESCRIPTION:
 * Blink LED n times with x ms ON/OF time
 *
 * PARAMETERS:      Name            RW  Usage
 * uint8           u8NumBlink       no	Number blinks
 * uint8           u8t100ms       	no	On and OFF time in 100ms
 *
 * RETURNS:
 * none
 *
 * NOTES:
 *
 ****************************************************************************/
PRIVATE void vBlinkLED(uint8 u8NumBlink, uint8 u8t100ms)
{
	uint8 i;

	/* Ensure starting with Led off */
	LED_OFF;
	// delay 100ms
	vDelayIn100ms(u8t100ms);


	for (i=0;i<u8NumBlink;i++)
	{
		/* blink LED 5 times */
		//switch LED on
		LED_ON;
		// delay 100ms
		vDelayIn100ms(u8t100ms);
		//switch LED off
		LED_OFF;
		// delay 100ms
		vDelayIn100ms(u8t100ms);
	}
}


/****************************************************************************
 *
 * NAME: vSendCommand
 *
 * DESCRIPTION:
 * Send key pressed data
 *
 * RETURNS:
 * void
 *
 ****************************************************************************/
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 = CERC_CONTROL_PRESSED_CMD_LENGTH;
    vPrintf("\nData %x\n\n",au8Nsdu[1]);
    eState = E_TRANSMITTING;

    u8TxOptions = RF4CE_TX_OPT_ACKNOWLEDGE|RF4CE_TX_OPT_SECURITY;

    /* Spinlock to make sure that transition to 32MHz happened. */
    while(bAHI_Clock32MHzStable() == FALSE);

    vRF4CE_NldeDataReq(u8CurrentPairingEntry/*au8ReceiverPairingRef[u8CurrentTarget]*/,
                        ZRC_PROFILE_ID, VENDOR_ID,
                       u8DataLen, au8Nsdu, u8TxOptions);
}

/****************************************************************************
 *
 * NAME: vSleep
 *
 * DESCRIPTION:
 * Sends the device into E_AHI_SLEEP_OSCOFF_RAMON sleep mode.
 *
 * RETURNS:
 * None
 *
 * NOTES:
 * This function does not return at all; Program restarts at appColdStart of
 * appWarmStart.
 ****************************************************************************/
PRIVATE void vSleep()
{
    volatile uint16 u16i;
    uint32 u32DioStatus;

    vPrintf("\nZzz");

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

    // following defines to make S1 btn as wakeup source
//	#define COL_WAKEUP 0x00010
//    #define COL_WAKEUP 0x00008
//    #define ROW_WAKEUP 0x80000
	#define COL_WAKEUP 0x0003F
	#define ROW_WAKEUP 0xFC400

    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)
    vAHI_DioSetPullup(COL_WAKEUP, ~COL_WAKEUP);            // 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)

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

    vAHI_DioWakeEnable(COL_WAKEUP, ~COL_WAKEUP);           // WakeEnable(enable, disable)

    vRF4CE_ImpSaveSettings(E_SAVE_MODE_MINIMAL);
    for (u16i=0;u16i<1000;u16i++);

    /* disable tick timer*/
    //vAHI_TickTimerConfigure(E_AHI_TICK_TIMER_DISABLE);

    /* Sleep selected */
#ifdef POWERSAVING
    vAHI_Sleep(E_AHI_SLEEP_OSCOFF_RAMON);
#else
    vAHI_Sleep(E_AHI_SLEEP_OSCOFF_RAMON);
#endif
}

/****************************************************************************
 *
 * NAME: vTimerISR
 *
 * DESCRIPTION:
 * Tick timer interrupt service routine.
 * Configured to occur at every 100ms in vInitSystem() funciton.
 *
 * RETURNS:
 * void
 *
 ****************************************************************************/
PRIVATE void vTimerISR(uint32 u32Device, uint32 u32ItemBitmap)
{
    u32SleepCounter++;
    u32DelayCounter++;

    //if ((u32SleepCounter % 100)==0) vPrintf("\n%d\n", u32DelayCounter);

    //vIdleLoop();

    if(u32SleepCounter >= (TIME_BEFORE_SLEEP_IN_100MS))
    {
        u32SleepCounter = 0;
        vSleep();
    }
#ifdef MATRIX_UPDATE_USE_TICKS
    if (bUpdateMatrix == TRUE) tsMatrixButton_Update(CurrentButtonList);
#endif
}

/****************************************************************************
 *
 * NAME: bGetNextActivePairingEntry
 *
 * DESCRIPTION:
 * Finds the active pair entry. If passed argument points to the value which is
 * larger than RF4CE_NWKC_MAX_PAIRING_TABLE_ENTRIES, search begins from first
 * pairing entry.
 *
 * RETURNS:
 * bool_t   Returns TRUE if any active pairing entry found; FALSE otherwise.
 *
 ****************************************************************************/
PRIVATE bool_t bGetNextActivePairingEntry(uint8 *u8CurrentPairingEntry)
{
    uint8 u8i,u8StartIndex;

    if((*u8CurrentPairingEntry) >= RF4CE_NWKC_MAX_PAIRING_TABLE_ENTRIES)
    {
        u8StartIndex = 0x00;
    }
    else
    {
        u8StartIndex = (((*u8CurrentPairingEntry)+1)%RF4CE_NWKC_MAX_PAIRING_TABLE_ENTRIES);
    }

    for(u8i=u8StartIndex; u8i<(RF4CE_NWKC_MAX_PAIRING_TABLE_ENTRIES+u8StartIndex);u8i++)
    {
        (void)eRF4CE_NlmeGetReq(E_RF4CE_NIB_ATTR_PAIRING_TABLE,
                                (u8i%RF4CE_NWKC_MAX_PAIRING_TABLE_ENTRIES),
                                &uNibValue);
        if(uNibValue.sPairingTableEntry.eState  == E_PAIR_ACTIVE )
        {
            /* Active pairing entry found */
            (*u8CurrentPairingEntry) = (u8i%RF4CE_NWKC_MAX_PAIRING_TABLE_ENTRIES);
            return TRUE;
        }
    }

    /* No active pairing entry found */
    *u8CurrentPairingEntry = 0xFF;
    return FALSE;
}

/****************************************************************************
 *
 * NAME: u8NumOfActivePairingEntries
 *
 * DESCRIPTION:
 * Finds number of active pairing entries
 *
 * RETURNS:
 * void
 *
 ****************************************************************************/
PRIVATE uint8 u8NumOfActivePairingEntries()
{
    volatile uint8 u8i=0, u8Count=0;
    for(u8i=0; u8i<RF4CE_NWKC_MAX_PAIRING_TABLE_ENTRIES;u8i++)
    {
        (void)eRF4CE_NlmeGetReq(E_RF4CE_NIB_ATTR_PAIRING_TABLE,
                                u8i, &uNibValue);
        if(uNibValue.sPairingTableEntry.eState  == E_PAIR_ACTIVE )
        {
            /* Active pairing entry found */
            u8Count++;
        }
    }
    return u8Count;
}


#ifdef POWERSAVING
/****************************************************************************
 *
 * NAME: vSystemControl_ISR
 *
 * DESCRIPTION:
 *
 * RETURNS:
 *
 ****************************************************************************/
PRIVATE void vSystemControl_ISR(uint32 u32DeviceId, uint32 u32ItemBitmap)
{
	#ifdef DBG_ENABLE
	//	vPrintf("\nID = %x BM = %x", u32DeviceId, u32ItemBitmap);
	#endif

	/* Should only be called for system control events but check to be sure.. */
	if (E_AHI_DEVICE_SYSCTRL == u32DeviceId)
	{
		/* Is this a brown-out (falling voltage) event */
		if ((u32ItemBitmap & E_AHI_SYSCTRL_VREM_MASK) != 0)
		{
			/* Turn off status LED to indicate we are sleeping */
			//vAHI_DioSetOutput(DIO_STATUS_LED_MASK, 0);

			/* Put the device into sleep mode, allow wake via DIO interrupt */
			//vAHI_DioWakeEdge(0, DIO_WAKE_INPUT_MASK);
			//vAHI_DioWakeEnable(DIO_WAKE_INPUT_MASK, 0);

			/* Disable DIOs */
			// disable pullup
			vAHI_DioSetPullup(0x00000000, 0xFFFFFFFF);
			//set DIOs as input
			vAHI_DioSetDirection(0xFFFFFFFF, 0x00000000);
			//disable any wakeup
			vAHI_DioWakeEnable(0x00000000, 0xFFFFFFFF);

			vAHI_BrownOutConfigure(E_AHI_VBOREF_3V0,	/* Threshold */
								   FALSE,				/* Do not reset on event detection */
								   //TRUE,				/* Reset on event detection */
								   //TRUE,				/* Enable brownout detection */
								   FALSE,				/* Disable brownout detection */
								   FALSE,				/* Disable interrupt on exiting condition */
								   FALSE);				/* DSABLE interrupt on entering condition */

			//vAHI_Sleep(E_AHI_SLEEP_OSCOFF_RAMOFF);
			vAHI_Sleep(E_AHI_SLEEP_DEEP);
		}
	}
}
#endif



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