//-------------------------------------------------------------------------------------------------------------------------
// Copyright (c) Samsung Electronics Co., Ltd.  All rights reserved.
//-------------------------------------------------------------------------------------------------------------------------
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
//
// Module Name :    spi_Callback.c
//
// Abstract     :   SPI callback interface for Samsung S5PV210 CPU using external GPIO
//
// Environment :    Samsung S5PV210 / WinCE6.0
//
// 2010/02/10 asdf  Added Full duplex mode (Ver 1.01)
//                          Define SPI_FULL_DUPLEX in sources file to use full duplex
// 2009/07/10 asdf Modified for checking slave ready
//
//-------------------------------------------------------------------------------------------------------------------------


#ifdef SPI_EX_GPIO_CALLBACK

#include <windows.h>
#include <nkintr.h>
#include <ceddk.h>

#include <ddkreg.h>
#include <bsp.h>
#include <oal_intr.h>
#include <dma_controller.h>
#include <spi.h>
#include "spi_priv.h"


typedef enum 
{
	PIN_LOW = 0,
	PIN_HIGH
} PIN_STATE;

static PIN_STATE PinState;
static DWORD SleepTime;

BOOL HSPCALLBACK_SetSlaveReady(PSPI_PRIVATE_CONTEXT pSpiPrivate) // SLAVE SIDE
{
	PSPI_PUBLIC_CONTEXT pSpiPublic = pSpiPrivate->pSpiPublic;

    DBGMSG(SPI_INFO,(TEXT("[SPI] HSPCALLBACK_SetSlaveReady\r\n")));
	pSpiPublic->pGPIOregs->GPA0.GP_DAT |= (PIN_HIGH<<0x0); 


#if 0	
	if(PinState == PIN_LOW)
	{
		PinState = PIN_HIGH;
		pSpiPublic->pGPIOregs->GPA0.GP_DAT |= (PIN_HIGH<<0x0); 
	}
	else
	{
		PinState = PIN_LOW;
		pSpiPublic->pGPIOregs->GPA0.GP_DAT &= ~(PIN_HIGH<<0x0);
	}
#endif

	return TRUE;
}

BOOL HSPCALLBACK_ClrSlaveReady(PSPI_PRIVATE_CONTEXT pSpiPrivate)
{

/*	PSPI_PUBLIC_CONTEXT pSpiPublic = pSpiPrivate->pSpiPublic;
	pSpiPublic->pGPIOregs->GPLDAT &= ~(1<<13); */

	PSPI_PUBLIC_CONTEXT pSpiPublic = pSpiPrivate->pSpiPublic;

    DBGMSG(SPI_INFO,(TEXT("[SPI] HSPCALLBACK_ClrSlaveReady\r\n")));


	pSpiPublic->pGPIOregs->GPA0.GP_DAT &= ~(PIN_HIGH<<0x0);
	
	return TRUE;
}

BOOL HSPCALLBACK_GetSlaveReady(PSPI_PRIVATE_CONTEXT pSpiPrivate) // MASTER SIDE
{
	PSPI_PUBLIC_CONTEXT pSpiPublic = pSpiPrivate->pSpiPublic;
	PIN_STATE curPinState;
	DWORD tempTime = 0;


    DBGMSG(SPI_INFO,(TEXT("[SPI] HSPCALLBACK_GetSlaveReady\r\n")));
			
	SleepTime = 0;
	while(pSpiPrivate->dwTimeOutVal >= SleepTime)
	{
		SleepTime += tempTime;

		curPinState = (pSpiPublic->pGPIOregs->GPA0.GP_DAT & (PIN_HIGH));

		if(tempTime) 
		{
			Sleep(tempTime);
		}

		if((curPinState == PIN_HIGH))
		{
			SleepTime = 0;
            DBGMSG(SPI_INFO,(TEXT("[SPI] Slave Ready\r\n")));
			return TRUE;
		}
#if 0
		if((PinState == PIN_LOW) && (curPinState == PIN_HIGH))
		{

			PinState = curPinState;
			SleepTime = 0;
            DBGMSG(SPI_INFO,(TEXT("[SPI] Slave Ready\r\n")));
			return TRUE;
		}
		if((PinState == PIN_HIGH) && (curPinState == PIN_LOW))
		{

			PinState = curPinState;
			SleepTime = 0;
            DBGMSG(SPI_INFO,(TEXT("[SPI] Slave Ready\r\n")));
			return TRUE;
		}
#endif
		if(pSpiPrivate->dwTimeOutVal !=0) 
		{
			if(tempTime <= 50) tempTime += 5;
			else if(tempTime <= 500) tempTime += 50;
			else tempTime += 1000;
		}
	}
	
	return FALSE;
}

BOOL HSPCALLBACK_Init(PSPI_PRIVATE_CONTEXT pSpiPrivate)
{
	PSPI_PUBLIC_CONTEXT pSpiPublic = pSpiPrivate->pSpiPublic;
//  GPA0 INPUT for test purposes only..This port is shared with UART0 
//  and UART0 needs to be disabled before using this port.

	if(pSpiPrivate->dwMode == SPI_MASTER_MODE) 
	{
		pSpiPublic->pGPIOregs->GPA0.GP_PUD &= ~(0x3<<0x0);
		pSpiPublic->pGPIOregs->GPA0.GP_CON &= ~(0xF<<0x0);
	}
//  GPA0 OUTPUT for test purposes only..This port is shared with UART0 
//  and UART0 needs to be disabled before using this port.
	if(pSpiPrivate->dwMode == SPI_SLAVE_MODE) 
	{
		pSpiPublic->pGPIOregs->GPA0.GP_PUD &= ~(0x3<<0x0);
		pSpiPublic->pGPIOregs->GPA0.GP_CON &= ~(0xF<<0x0);
		pSpiPublic->pGPIOregs->GPA0.GP_CON |= (0x1<<0x0);
		pSpiPublic->pGPIOregs->GPA0.GP_DAT &= ~(1<<0x0);  
	}

	PinState = PIN_LOW;
	SleepTime = 0;

	pSpiPrivate->SetSlaveReady = HSPCALLBACK_SetSlaveReady;
	pSpiPrivate->ClrSlaveReady = HSPCALLBACK_ClrSlaveReady;
	pSpiPrivate->GetSlaveReady = HSPCALLBACK_GetSlaveReady;

	return TRUE;
}

BOOL HSPCALLBACK_Deinit(PSPI_PRIVATE_CONTEXT pSpiPrivate)
{
	PSPI_PUBLIC_CONTEXT pSpiPublic = pSpiPrivate->pSpiPublic;

    pSpiPrivate->SetSlaveReady = NULL;
	pSpiPrivate->ClrSlaveReady = NULL;
	pSpiPrivate->GetSlaveReady = NULL;

	return TRUE;
}

#endif 
