/*****************************************************************************\

  File Name: keypad.c

  Description: This module contains KEYPAD device specific functions.

  Copyright(c) 2007 Analog Devices Incorporated. All Rights Reserved.

  Revision History:


\*****************************************************************************/

/*****************************************************************************\

  Includes:

\*****************************************************************************/

#include <services/services.h>                /* system service includes */
#include <drivers/adi_dev.h>            
#include <SDK-ezkitutilities.h>

#include "adi_ssl_init.h"
#include "mediaplayer.h"
#include <drivers/keypad/adi_kpad.h>        /* Keypad driver includes */

/*****************************************************************************\

  Defines:

\*****************************************************************************/

 
#define KEYPAD_ARR_SIZE (10) /* number of KEYPAD commands that can be buffered */
/*#define USE_DEFERRED_CALLBACKS - be sure to not install DCB at IVG14 - IVG14 reserved by uCOS */

/*****************************************************************************\

  Declarations:

\*****************************************************************************/

/* handle to the driver*/
static ADI_DEV_DEVICE_HANDLE KeypadDriverHandle = NULL;

OS_EVENT *keypad_Q;						/* queue to hold KEYPAD commands */
void* keypad_arr[KEYPAD_ARR_SIZE]; 	/* Empty void* array to hold Q messages */

OS_EVENT *keypad_event;

/* Lookup table for the Keypad */
u8 KeyTable[4][4] = 
{
     {  'F','E','D','C'}, 
     {  'B','A','9','8'}, 
     {  '7','6','5','4'}, 
     {  '3','2','1','0'}, 
};

ADI_KPAD_KEY_PRESSED_RESULT KpadResult;

section("sdram0_bank2_stack") static OS_STK stack[THRD_STACKSIZE * sizeof(OS_STK)];

/*****************************************************************************\

  Externs:

\*****************************************************************************/

extern OS_EVENT *mgr_application_Q;

/*****************************************************************************\

  Function Prototypes:

\*****************************************************************************/


static void callback_keypad( void *AppHandle, u32  Event, void *pArg );
void thread_keypad(void *pInParam);
u8 MapKey(u8 mode,u16 keycode);
void launch_thread_keypad(void); 

int init_keypad_548(void);
int close_keypad_548(void);


/*********************************************************************

    Function:       KeypadCallback

    Description:    Ez-Kit callback service routine
    				for KeyPad Events
*********************************************************************/
section ("callback_code")
static void callback_keypad(void *AppHandle,u32  Event,void *pArg )
{
	
	ADI_KPAD_KEY_PRESSED_RESULT *pResult;
	
    /* Case of (event type) */
    switch (Event) {
	
        case ADI_KPAD_EVENT_KEYPRESSED:
			/* get the address of key pressed results buffer */
			pResult = (ADI_KPAD_KEY_PRESSED_RESULT *)pArg;
			
		    KpadResult.rowcolpos = pResult->rowcolpos;
		    KpadResult.mrowcol = pResult->mrowcol;
		    	
			if(OSQPost(keypad_Q, &KpadResult)!= OS_NO_ERR)
    			ezErrorCheck(1); /* wait for help */
    		
		    	
        break;
	        
	    default:	/* other events */
        break;
          
    }
}

/*********************************************************************

	Function:		Init_Keypad

	Description:	Initializes the keypad.  

*********************************************************************/

int init_keypad_548(void) {
	
	u32 Result = 0 ;/* assume success */
	
    if((Result = adi_dev_Open(  adi_dev_ManagerHandle,     		/* Dev manager Handle               */
                   	            &ADIKPADEntryPoint,             /* Device Entry point               */
                                0,                              /* Device number                    */
	                            NULL,                           /* No client handle                 */
                                &KeypadDriverHandle,	        /* DevMgr handle for this device    */
			                    ADI_DEV_DIRECTION_UNDEFINED,    /* data direction not used          */
           	                    NULL,         	                /* Handle to DMA Manager            */
               	                adi_dcb_QueueHandle,               /* Handle to callback manager       */
                       	        callback_keypad))		    	/* Callback Function                */
	   							!= ADI_DEV_RESULT_SUCCESS) 
    {
    	if(APP_TRACE_LEVEL)
    	{
        	APP_TRACE("Open Keypad driver Failed!, Error Code: 0x%08X\n",Result);
    	}
        return (Result);
    }
        
	ADI_DEV_CMD_VALUE_PAIR  KeypadConfig[]=
        {
            { ADI_KPAD_CMD_SET_ROW_NUMBER,      (void *)3	},  /* Enable Row 0-3                               */
            { ADI_KPAD_CMD_SET_COLUMN_NUMBER,   (void *)3   },  /* Enable Column 0-3                            */
            { ADI_KPAD_CMD_SET_IRQMODE,         (void *)2   },  /* Enable single & multiple key press interrupt */
            { ADI_KPAD_CMD_SET_DBON_COLDRV_TIME,(void *)8   },  /* Set de-bounce time delay as 8ms              */
            { ADI_DEV_CMD_END,					NULL        }   /* Terminate config table                                   */
	    };
    
	if((Result = adi_dev_Control(KeypadDriverHandle, ADI_DEV_CMD_TABLE, (void *)KeypadConfig))!= ADI_DEV_RESULT_SUCCESS)
    {
		if(APP_TRACE_LEVEL)
    		{
				APP_TRACE("Failed to configure Kepad controller registers, Error Code: 0x%08X\n",Result);
				
    		}
    			
			return (Result);

    }

    /**************** Enable Keypad ****************/
   	if((Result = adi_dev_Control(KeypadDriverHandle, ADI_KPAD_CMD_SET_KPAD_ENABLE, (void *)TRUE))!= ADI_DEV_RESULT_SUCCESS)
    {
		if(APP_TRACE_LEVEL)
    		{
				APP_TRACE("Failed to enable Keypad, Error Code: 0x%08X\n",Result);
    		}
			return (Result);

	}
        
	/* launch the KPAD handle thread */
	launch_thread_keypad();	    
	    
	return (Result);

}

/*********************************************************************

	Function:		close_keypad

	Description:	close the keypad.  

*********************************************************************/
int close_keypad_548(void)
{
	u32 Result= ADI_DEV_RESULT_SUCCESS;
	 
    /* disable Keypad */
    if (Result == ADI_DEV_RESULT_SUCCESS)
   		Result = adi_dev_Control(KeypadDriverHandle, ADI_KPAD_CMD_SET_KPAD_ENABLE, (void *)FALSE);
   		
   	if (Result == ADI_DEV_RESULT_SUCCESS)
   		Result = adi_dev_Close(KeypadDriverHandle);
   		
   	return (Result);

}





/*********************************************************************

	Function:	launch_thread_keypad																			
	
 	Parameters:	None 
																		
 	Return:		None														
																			
 	Description:	Launches the KEYPAD handle thread which handles all KEYPAD 
 					input keys
*********************************************************************/
void launch_thread_keypad(void) 
{
	/*OS_STK *stack;*/
	int Result;
	INT32U i;

	
	/* Create KEYPAD command Queue */
	keypad_Q = OSQCreate(keypad_arr, KEYPAD_ARR_SIZE);
	keypad_event = keypad_Q;
	
	
	
	Result = OSTaskCreateExt(thread_keypad, 
						(void *)keypad_event, 
						&stack[THRD_STACKSIZE -1], 
						THRD_PRIORITY_KPAD, 
						THRD_PRIORITY_KPAD, 
						&stack[0], 
						THRD_STACKSIZE , 
						(void *)0, 
						OS_TASK_OPT_STK_CHK );
						
	if(Result && APP_TRACE_LEVEL)
	{
		APP_TRACE("OSTaskCreateExt:thread_keypad failed %d\n",Result);
		ezErrorCheck(1); /* wait for help */
					
	}					
}/* end of launch_thread_keypad */


/*****************************************************************************

	Function:		MapKey
	
	Description:    Maps key(s) pressed to the Keypad lookup table

*****************************************************************************/

u8 MapKey(u8 mode,u16 keycode)
{
    
    u8 Col, Row, key;
     
    key = 0;
    
    /* IF (single key pressed) */
    if (mode == 1) 
    {     
        /*get the column position*/
        Col = (u8)((keycode & 0x0f00) >> 9);
        if(Col > 3) 
        {
            Col = 3;    /* column limit */
        }
    
        /*get the row position*/
        Row = (u8)((keycode & 0x000f) >> 1);
 	    if(Row > 3)
 	    {
 	        Row = 3;    /* row limit */
 	    }
 	    
        key = KeyTable[Col][Row];
    }
    
    return key;
}


/*****************************************************************************

	Function:		thread_keypad
	
	Description:    Keypad Thread task

*****************************************************************************/

void thread_keypad(void *pInParam)
{
	
	INT8U err;

	ADI_KPAD_KEY_PRESSED_RESULT *pResult;
	MPPMESSAGE	MessageToApp;
	u8 key;
	bool validKey;	
	
	OS_EVENT *queue;
	queue = keypad_event;
	


    while(1)
	{
		
	    /* pend on message queue */
	    pResult = (ADI_KPAD_KEY_PRESSED_RESULT *) OSQPend (queue, 0, &err);
		if (err && APP_TRACE_LEVEL) 
		{ 
			APP_TRACE("KPAD OSQPend error:%d\n",err);
		}

		/* Map this key press to the lookup table */
		key = MapKey(pResult->mrowcol,pResult->rowcolpos);
		
		/* assume valid key */
		validKey = TRUE;	

			switch(key)
			{
				case 0x33:/* '0' = previous */
					MessageToApp.uMID = MSGID_PREV_ENTRY;
					break;

				case 0x31:/* '1' = play/pause */
					MessageToApp.uMID = MSGID_PLAYER_PLAY;
					break;

				case 0x32:/* '2' = stop */
					MessageToApp.uMID = MSGID_PLAYER_STOP;
					break;

				case 0x37:/* '3' = next */
					MessageToApp.uMID = MSGID_NEXT_ENTRY;
					break;
				
				case 0x44:/* 'D' = down */
					MessageToApp.uMID = MSGID_VOLUME_DN;
					break;

				case 0x45:/* 'E' = up */
					MessageToApp.uMID = MSGID_VOLUME_UP;
					break;
					
					
				case 0x42:/* 'B' = terminate */
					MessageToApp.uMID = MSGID_TERMINATE_MPP;
					break;
					
				case 0x38:/* 'B' = connect */
					MessageToApp.uMID = MSGID_TEST;
					break;

				default:/* any other key */
					validKey = FALSE;
					break;
		 	
			}/* end of switch statement */
			
			if (validKey)
			{
				err = OSQPost(mgr_application_Q, &MessageToApp);
				if(err && APP_TRACE_LEVEL)
				{
	    			APP_TRACE("KPAD OSQPost error%d\n",err);
				}	
			}
	}	
}
