/* ---------------------------------------------------------------------------
 * BusProtocol.c - v0.1                                (c) 2008 Micro-key bv
 * ---------------------------------------------------------------------------
 * Micro-key bv
 * Industrieweg 28, 9804 TG Noordhorn
 * Postbus 92, 9800 AB Zuidhorn
 * The Netherlands
 * Tel: +31 594 503020
 * Fax: +31 594 505825
 * Email: support@microkey.nl  
 * Web: www.microkey.nl
 * ---------------------------------------------------------------------------
 * Description: 
 * ---------------------------------------------------------------------------
 * Version(s):  0.1, Jan 28, 2008, FSc
 *                   Creation.
 * ---------------------------------------------------------------------------
 */

/* ---------------------------------------------------------------------------
 * System include files
 * ---------------------------------------------------------------------------
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* ---------------------------------------------------------------------------
 * Application include files
 * ---------------------------------------------------------------------------
 */
#include "types.h"
#include "ElecStatusCache.h"

#include "FreeRTOS.h"

/* ---------------------------------------------------------------------------
 * Local constant and macro definitions
 * ---------------------------------------------------------------------------
 */
#define MAX_NR_DEVICES   20
#define CACHE_NOT_USED   0xFF

/* ---------------------------------------------------------------------------
 * Global variable definitions
 * ---------------------------------------------------------------------------
 */


/* ---------------------------------------------------------------------------
 * Local variable definitions
 * ---------------------------------------------------------------------------
 */
static UINT16 *bpecAdcReadCache[MAX_NR_DEVICES];
static UINT8 bpecAdcReadCacheSize[MAX_NR_DEVICES];
static UINT16 *bpecDacReadBackCache[MAX_NR_DEVICES];
static UINT8 bpecDacReadBackCacheSize[MAX_NR_DEVICES];
static BOOLEAN *bpecDioReadCache[MAX_NR_DEVICES];
static UINT8 bpecDioReadCacheSize[MAX_NR_DEVICES];
static BOOLEAN *bpecDioReadBackCache[MAX_NR_DEVICES];
static UINT8 bpecDioReadBackCacheSize[MAX_NR_DEVICES];
static t_bpec_write_callback bpecWriteCallback;
static int bpecBusProtocolHandle;

/* ---------------------------------------------------------------------------
 * Local function definitions
 * ---------------------------------------------------------------------------
 */

void bpecInit()
{
	int i;
	
	bpecWriteCallback = NULL;
	bpecBusProtocolHandle = -1;
	
	// Empty the administration
	for (i = 0; i < MAX_NR_DEVICES; i++)
		{
		bpecAdcReadCache[i] = NULL;
		bpecAdcReadCacheSize[i] = CACHE_NOT_USED;
		bpecDacReadBackCache[i] = NULL;
		bpecDacReadBackCacheSize[i] = CACHE_NOT_USED;
		bpecDioReadCache[i] = NULL;
		bpecDioReadCacheSize[i] = CACHE_NOT_USED;
		bpecDioReadBackCache[i] = NULL;
		bpecDioReadBackCacheSize[i] = CACHE_NOT_USED;
		}
}

void bpecAttachWriteCallback(int busProtocolHandle, t_bpec_write_callback callback)
{
	bpecBusProtocolHandle = busProtocolHandle;
	bpecWriteCallback = callback;
}

void bpecDetachWriteCallback()
{
	bpecBusProtocolHandle = -1;
	bpecWriteCallback = NULL;
}

void bpecWriteDacValue( UINT8 device, UINT8 channel, UINT16 dacValue )
{
	if (bpecWriteCallback != NULL)
	{
		bpecWriteCallback( bpecBusProtocolHandle, FALSE, device, channel, dacValue );
	}
}

void bpecWriteDioValue( UINT8 device, UINT8 channel, BOOLEAN doValue )
{
	if (bpecWriteCallback != NULL)
	{
		bpecWriteCallback( bpecBusProtocolHandle, TRUE, device, channel, (UINT16)doValue );
	}
}

void bpecSetAdcReadCache( UINT8 device, UINT16 adcValues[], UINT8 nrOfAdcValues)
{
	static int NrOfAllocs = 0;
	if (bpecAdcReadCacheSize[device] != nrOfAdcValues)
		{
		if (bpecAdcReadCacheSize[device] == CACHE_NOT_USED)
			{
			NrOfAllocs++;
			bpecAdcReadCache[device] = pvPortMalloc( nrOfAdcValues * sizeof(UINT16) );
			if (bpecAdcReadCache[device] != NULL)
				{
				bpecAdcReadCacheSize[device] = nrOfAdcValues;
				memcpy(bpecAdcReadCache[device], adcValues, nrOfAdcValues * sizeof(UINT16));
				} /* else Failure */
			}
		/* else Failure */
		}
	else 
		{
		memcpy(bpecAdcReadCache[device], adcValues, nrOfAdcValues * sizeof(UINT16));
		}
}

void bpecSetDioReadCache( UINT8 device, BOOLEAN dioValues[], UINT8 nrOfDioValues)
{
	if (bpecDioReadCacheSize[device] != nrOfDioValues)
		{
		if (bpecDioReadCacheSize[device] == CACHE_NOT_USED)
			{
			bpecDioReadCache[device] = pvPortMalloc( nrOfDioValues * sizeof(BOOLEAN) );
			if (bpecDioReadCache[device] != NULL)
				{
				bpecDioReadCacheSize[device] = nrOfDioValues;
				memcpy(bpecDioReadCache[device], dioValues, nrOfDioValues * sizeof(BOOLEAN));
				} /* else Failure */
			}
		/* else Failure */
		}
	else 
		{
		memcpy(bpecDioReadCache[device], dioValues, nrOfDioValues * sizeof(BOOLEAN));
		}
}

void bpecSetDioReadBackCache( UINT8 device, BOOLEAN dioValues[], UINT8 nrOfDioValues)
{
	static int NrOfWritings = 0;
	static int LastSetDevice = 0;
	static int LastSetNrOfDioValues = 0;
	NrOfWritings++;
	LastSetDevice = device;
	LastSetNrOfDioValues = nrOfDioValues;
	
	if (bpecDioReadBackCacheSize[device] != nrOfDioValues)
		{
		if (bpecDioReadBackCacheSize[device] == CACHE_NOT_USED)
			{
			bpecDioReadBackCache[device] = pvPortMalloc( nrOfDioValues * sizeof(BOOLEAN) );
			if (bpecDioReadBackCache[device] != NULL)
				{
				bpecDioReadBackCacheSize[device] = nrOfDioValues;
				memcpy(bpecDioReadBackCache[device], dioValues, nrOfDioValues * sizeof(BOOLEAN));
				} /* else Failure */
			}
		/* else Failure */
		}
	else 
		{
		memcpy(bpecDioReadBackCache[device], dioValues, nrOfDioValues * sizeof(BOOLEAN));
		}
	
}

void bpecSetDacReadBackCache( UINT8 device, UINT16 dacValues[], UINT8 nrOfDacValues)
{
	if (bpecDacReadBackCacheSize[device] != nrOfDacValues)
		{
		if (bpecDacReadBackCacheSize[device] == CACHE_NOT_USED)
			{
			bpecDacReadBackCache[device] = pvPortMalloc( nrOfDacValues * sizeof(UINT16) );
			if (bpecDacReadBackCache[device] != NULL)
				{
				bpecDacReadBackCacheSize[device] = nrOfDacValues;
				memcpy(bpecDacReadBackCache[device], dacValues, nrOfDacValues * sizeof(UINT16));
				} /* else Failure */
			}
			/* else Failure */
		}
	else 
		{
		memcpy(bpecDacReadBackCache[device], dacValues, nrOfDacValues * sizeof(UINT16));
		}
}

UINT16 bpecAdcRead( UINT8 device, UINT8 channel )
{
	UINT16 result = 0;
	
	if (bpecAdcReadCacheSize[device] != CACHE_NOT_USED)
		{
		if (channel < bpecAdcReadCacheSize[device])
			{
			result = (bpecAdcReadCache[device])[channel];
			}
		}
	
	return result;
}

BOOLEAN bpecDioRead( UINT8 device, UINT8 channel )
{
	BOOLEAN result = FALSE;
	
	if (bpecDioReadCacheSize[device] != CACHE_NOT_USED)
		{
		if (channel < bpecDioReadCacheSize[device])
			{
			result = (bpecDioReadCache[device])[channel];
			}
		}
	
	return result;
}

BOOLEAN bpecDioReadBack( UINT8 device, UINT8 channel )
{
	BOOLEAN result = FALSE;
	
	if (bpecDioReadBackCacheSize[device] != CACHE_NOT_USED)
		{
		if (channel < bpecDioReadBackCacheSize[device])
			{
			result = (bpecDioReadBackCache[device])[channel];
			}
		}
	
	return result;
}

UINT16 bpecDacReadBack( UINT8 device, UINT8 channel )
{
	UINT16 result = 0;
	
	if (bpecDacReadBackCacheSize[device] != CACHE_NOT_USED)
		{
		if (channel < bpecDacReadBackCacheSize[device])
			{
			result = (bpecDacReadBackCache[device])[channel];
			}
		}
	
	return result;
}
