/*****************************************************************************\

  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 <drivers/touchscreen/adi_max1233.h>	/* MAX1233 driver includes    */
            
#include <SDK-ezkitutilities.h>

#include "adi_ssl_init.h"
#include "mediaplayer.h"
#include "adi_max1233.h"


/*****************************************************************************

Processor specific Macros

*****************************************************************************/



/* SPI Device number connected to MAX1233 */
#define     MAX1233_SPI_DEV_NUMBER       1	// use "alternate" device mapping of SPI over PortG/Mux2


/* SPI Device chipselect used to access MAX1233 registers */
#define     MAX1233_SPI_CS               4  /* Use SPISSEL4 (PH8) as chip select for Max1233 */
											/* to allow the use of rotary and keypad at the same time */


#define     MAX1233_SPI_CLOCK_FREQ 	10000000	// run SPI at 10 MHz, per MAX1233 spec

// default bits for KBD (see include file)
#define DEFAULT_KEY_BITS                       \
      (MAX1233_VAL_DBN120 << MAX1233_POS_DBN)   \
	| (MAX1233_VAL_HLD7  << MAX1233_POS_HLD)

ADI_DEV_ACCESS_REGISTER MAX1233_EnterPowerDownMode[] =
{
	
	// turn off DAC
    { MAX1233_REG_DAC_CNTL,		(MAX1233_VAL_DAPD_OFF << MAX1233_POS_DAC_CNTL_DAPD) 				},
    
    // turn off keyboard
    { MAX1233_REG_KEY,			(DEFAULT_KEY_BITS | (MAX1233_VAL_KEYSTS3 << MAX1233_POS_KEYSTS))	},

    // end
    { ADI_DEV_REGEND,			 0 																	}
};  

/* Configuration table to do a MAX1233 dummy read to clear any pending reads of both touchscreen and keypad data */
ADI_DEV_ACCESS_REGISTER MAX1233_DummyRead[] =
{	
	{ MAX1233_REG_KPD, 	0 },
	{ ADI_DEV_REGEND,	0 }
};

/***********************************************************
******      KEYPAD control register configuration table  ***
************************************************************/
ADI_DEV_ACCESS_REGISTER DetectKeyPressIntAndScan[] =
{
	// advance MAX1233 keyboard scanner to mode 1
    { MAX1233_REG_KEY,			(DEFAULT_KEY_BITS | (MAX1233_VAL_KEYSTS2 << MAX1233_POS_KEYSTS))	},

	// end
    { ADI_DEV_REGEND,			0 																	}
};

/*****************************************************************************

Static data

*****************************************************************************/

/* handle to the TouchScreen driver */
static ADI_DEV_DEVICE_HANDLE MAX1233DriverHandle;




// SPI Baud Rate Register Value
u32		SpiBaudRateRegValue;




/*****************************************************************************

MAX1233 device register configuration table(s)

*****************************************************************************/
/* Pin I/O settings on the BF527 processor to communicate with the MAX1233 */
ADI_DEV_CMD_VALUE_PAIR  MAX1233_BF527_SPIConfiguration[]=
{
	// configure Kookaburra pins to talk to the Max
	{ ADI_MAX1233_CMD_SET_SPI_DEVICE_NUMBER,   	(void *)MAX1233_SPI_DEV_NUMBER  },  /* SPI device to use              */
	{ ADI_MAX1233_CMD_SET_SPI_CS,              	(void *)MAX1233_SPI_CS          },  /* SPI CS for MAX1233             */
	{ ADI_MAX1233_CMD_SET_SPI_BAUD,				(void *)&SpiBaudRateRegValue    },  /* override default SPI baud rate */
	{ ADI_DEV_CMD_END,					       	NULL                            }   /* Terminate config table         */
}; 





/*****************************************************************************\

  KEYPAD thread and message queue

\*****************************************************************************/
#define KEYPAD_ARR_SIZE (20) /* number of KEYPAD commands that can be buffered */

/* BF-527 Keypad map */
#define PLAY_KEY		0x4000
#define STOP_KEY		0x2000
#define UP_KEY			0x1000
#define DOWN_KEY		0x0100
#define VOLUME_UP_KEY	0x0002
#define VOLUME_DOWN_KEY	0x0004
#define TERMINATE_KEY	0x0010


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;

static u16 KeyData;

section("sdram0_bank2_stack") static OS_STK stack[THRD_STACKSIZE * sizeof(OS_STK)];
extern OS_EVENT *mgr_application_Q;
/*****************************************************************************\

  Function Prototypes:

\*****************************************************************************/
static void keypad_callback( void *AppHandle, u32  Event, void *pArg );
void thread_keypad(void *pInParam);
void launch_thread_keypad(void); 

int init_keypad_MAX1233(void);
int close_keypad_MAX1233(void);

/*********************************************************************

	Function:		init_keypad_MAX1233

	Description:	Initializes the keypad.  

*********************************************************************/

int init_keypad_MAX1233(void) {
	
	u32 Result = 0 ;/* assume success */
	u32		fcclk, fsclk, fvco;  // system clock settings

	/* Get the actual sclk*/
	if((Result = adi_pwr_GetFreq (&fcclk, &fsclk, &fvco)) != ADI_FLAG_RESULT_SUCCESS)
	{
		printf("Failed to get clock settings from power service, Error Code: 0x%08X\n",Result);
	}
	
	/* compute the desired SPI baud rate register value
	 from equation: SPI_BAUD = SCLKf / (2*SPICLKf) and
	 send it down as part of MAX1233_BF527_HardwareConfiguration command table 
	 */
	SpiBaudRateRegValue = fsclk / (2*MAX1233_SPI_CLOCK_FREQ);

	
	/* open the MAX1233 driver */
	if((Result = adi_dev_Open(  adi_dev_ManagerHandle,     		/* Dev manager Handle                       */
								&ADIMAX1233EntryPoint,          /* Device Entry point                       */
								0,                              /* Device number                            */
								NULL,                           /* Client handle                            */
								&MAX1233DriverHandle,           /* Location to store MAX1233 driver handle  */
								ADI_DEV_DIRECTION_BIDIRECTIONAL,/* Data Direction                           */
								adi_dma_ManagerHandle,         	/* Handle to DMA Manager                    */
								adi_dcb_QueueHandle,          /* Handle to callback manager               */
								keypad_callback))		    	/* Callback Function                        */
					!= ADI_DEV_RESULT_SUCCESS) 
	{
		printf("Open MAX1233 driver Failed!, Error Code: 0x%08X\n",Result);
			return (Result);

	}

	if((Result = adi_dev_Control(MAX1233DriverHandle, ADI_DEV_CMD_TABLE, (void *)MAX1233_BF527_SPIConfiguration))!= ADI_DEV_RESULT_SUCCESS)
	{
		printf("Failed to configure MAX1233 driver: 0x%08X\n",Result);
			return (Result);

	}
	
		/**************** Put the Maxim in power-down mode ****************/
	if((Result = adi_dev_Control(MAX1233DriverHandle, ADI_DEV_CMD_REGISTER_TABLE_WRITE, (void *)MAX1233_EnterPowerDownMode))!= ADI_DEV_RESULT_SUCCESS)
	{
		printf("Failed to initialize MAX1233 device: 0x%08X\n",Result);
	}
	

	/**************** Do a dummy read to unblock any pending MAX1233 interrupts ****************/
	if((Result = adi_dev_Control(MAX1233DriverHandle, ADI_DEV_CMD_REGISTER_TABLE_READ, (void *)MAX1233_DummyRead))!= ADI_DEV_RESULT_SUCCESS)
	{
		printf("Failed to read MAX1233 device: 0x%08X\n",Result);
	}


    	/**************** ENABLE KEYIRQ ****************/
	if((Result = adi_dev_Control(MAX1233DriverHandle,ADI_MAX1233_CMD_INSTALL_KEYIRQ,(void *)TRUE )) != ADI_DEV_RESULT_SUCCESS) {
		printf("Failed to enable MAX1233 KEYIRQ: 0x%08X\n",Result);
			return (Result);
	}
	
	/**************** ENABLE BUSYIRQ ****************/
	if((Result = adi_dev_Control(MAX1233DriverHandle,ADI_MAX1233_CMD_INSTALL_BUSYIRQ,(void *)TRUE )) != ADI_DEV_RESULT_SUCCESS) {
		printf("Failed to enable BUSYIRQ: 0x%08X\n",Result);
	}
	
		
	/**************** Configure MAX1233 Keypad Device registers ****************/
	if((Result = adi_dev_Control(MAX1233DriverHandle, ADI_DEV_CMD_REGISTER_TABLE_WRITE, (void *)DetectKeyPressIntAndScan)) != ADI_DEV_RESULT_SUCCESS)
	{
		printf("Failed to begin MAX1233 device: 0x%08X\n",Result);
	}


	
	/* launch the KPAD handle thread */
	launch_thread_keypad();	    

	
	return (Result);

}

/*********************************************************************

	Function:		close_keypad_MAX1233

	Description:	close the keypad.  

*********************************************************************/
int close_keypad_MAX1233(void)
{
	u32 Result= ADI_DEV_RESULT_SUCCESS;
	 
 	/* close the MAX1233 driver */
	if(ADI_DEV_RESULT_SUCCESS != (Result = adi_dev_Close(MAX1233DriverHandle)) )
	{
		printf("Failed to close MAX1233 driver, Error Code: 0x%08X\n",Result);
	}

   	return (Result);

}




/*********************************************************************

    Function:       keypad_callback

    Description:    Callback service routine for 
    				Keypad data ready
*********************************************************************/
static void keypad_callback(void *AppHandle,u32  Event, void *pArg)
{
	u32 Result;
	int err;
	
	switch (Event)
	{
       	// Case (flag interrupt occurred)
		case ADI_MAX1233_EVENT_KEY_BUSYIRQ:

			KeyData = *((u16*)pArg);
		
			/* scan completed,informs keypad thread */
			err = OSQPost(keypad_Q, (void*)&KeyData);
			if(err != OS_NO_ERR)
    		APP_TRACE("post keypad_Q error %d\n",err);	ezErrorCheck(err); /* wait for help */
        	        
		break;

		default:	// other events
		break;
	}
}


/*********************************************************************

	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) 
{
	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, 
						KPAD_THREAD_ID, 
						&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:		thread_keypad
	
	Description:    Keypad Thread task

*****************************************************************************/

void thread_keypad(void *pInParam)
{
	INT8U err;

	MPPMESSAGE	MessageToApp;
	bool validKey;
	u16 *KeyNum;



	OS_EVENT *queue;
	queue = keypad_event;
	 
	u32 Result;
	int busy;

    while(1)
	{
		
	    /* pend on message queue */
	    KeyNum = (u16*)OSQPend (queue, 0, &err);
		if (err && APP_TRACE_LEVEL) 
		{ 
			APP_TRACE("KPAD OSQPend error:%d\n",err);
		}
		


		/* assume valid key */
		validKey = TRUE;	

		switch(*KeyNum)
		{

				case PLAY_KEY:/* '2' = play/pause */
					MessageToApp.uMID = MSGID_PLAYER_PLAY;
					break;

				case STOP_KEY:/* '3' = stop */
					MessageToApp.uMID = MSGID_PLAYER_STOP;
					break;
					
				case UP_KEY:/* previous */
					MessageToApp.uMID = MSGID_PREV_ENTRY;
					break;

					
				case DOWN_KEY:/* next */
					MessageToApp.uMID = MSGID_NEXT_ENTRY;
					break;

				case VOLUME_UP_KEY:/* '0' = volume up */
					MessageToApp.uMID = MSGID_VOLUME_UP;
					break;
					
				case VOLUME_DOWN_KEY:/* 'Help' = volume down */
					MessageToApp.uMID = MSGID_VOLUME_DN;
					break;
		
					
				case TERMINATE_KEY:/* 'enter' = terminate */
					MessageToApp.uMID = MSGID_TERMINATE_MPP;
					break;
					

				default:/* any other key */
					validKey = FALSE;
					ezToggleLED(2);/* for debugging */

					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);
			}
		
		}





	
	}/* end of while(1) */	
	

}
