#include <stdlib.h> 
#include <malloc.h>

#include "NDTSCommonHALInternal.h"
#include "NDTSError.h"
#include "NDTSCommonHALErrors.h"


void NDTS_HAL_DLL_Initialise()
{
	halGlobalState.isInitialised = NDTS_BFalse ;

	// Register our GetCodeString function
	NDTS_RegisterGetCodeStringFunction(NDTS_ERROR_HAL_SDK_INDEX, &NDTS_HAL_GetCodeString) ;
}

void NDTS_HAL_DLL_Uninitialise()
{
}

void NDTS_HAL_ClearGlobalState()
{
	unsigned long i ;

	for (i = 0 ; i < NDTS_HAL_NUMBER_OF_BUFFERED_HALS ; i++)
		halGlobalState.ppHALInfos[i] = 0 ;

	halGlobalState.numberOfActiveHALs = 0 ;
}

void NDTS_HAL_FreeGlobalState()
{
	unsigned long i ;

	for (i = 0 ; i < halGlobalState.numberOfActiveHALs ; i++)
	{
		free(halGlobalState.ppHALInfos[i]->pFuncs) ;
		free(halGlobalState.ppHALInfos[i]) ;
	}

	halGlobalState.numberOfActiveHALs = 0 ;
}

void NDTS_HAL_ClearHALFunctionPointers(NDTS_HAL_Funcs *pFuncs)
{
	pFuncs->fpNDTS_HAL_GetBoardsIDs = 0 ;
	pFuncs->fpNDTS_HAL_AddBoard = 0 ;
	pFuncs->fpNDTS_HAL_RemoveBoard = 0 ;
	pFuncs->fpNDTS_HAL_OpenDMAChannel = 0 ;
	pFuncs->fpNDTS_HAL_CloseDMAChannel = 0 ;
	pFuncs->fpNDTS_HAL_GetCommonBufferInfo = 0 ;
	pFuncs->fpNDTS_HAL_PerformDMARead = 0 ;
	pFuncs->fpNDTS_HAL_PerformDMAWrite = 0 ;
	pFuncs->fpNDTS_HAL_SetWord = 0 ;
	pFuncs->fpNDTS_HAL_GetWord = 0 ;
	pFuncs->fpNDTS_HAL_BoardByteCopy = 0 ;
	pFuncs->fpNDTS_HAL_WriteSecondaryDeviceID = 0 ;
}

NDTS_Boolean NDTS_HAL_CheckHALFunctionPointers(const NDTS_HAL_Funcs *pFuncs)
{
	return pFuncs->fpNDTS_HAL_GetBoardsIDs != 0 && 
		   pFuncs->fpNDTS_HAL_AddBoard != 0 &&
		   pFuncs->fpNDTS_HAL_RemoveBoard != 0 &&
		   pFuncs->fpNDTS_HAL_OpenDMAChannel != 0 &&
		   pFuncs->fpNDTS_HAL_CloseDMAChannel != 0 &&
		   pFuncs->fpNDTS_HAL_GetCommonBufferInfo != 0 &&
		   pFuncs->fpNDTS_HAL_PerformDMARead != 0 &&
		   pFuncs->fpNDTS_HAL_PerformDMAWrite != 0 &&
		   pFuncs->fpNDTS_HAL_SetWord != 0 &&
		   pFuncs->fpNDTS_HAL_GetWord != 0 &&
		   pFuncs->fpNDTS_HAL_BoardByteCopy != 0 &&
		   pFuncs->fpNDTS_HAL_WriteSecondaryDeviceID != 0 ?
				NDTS_BTrue : NDTS_BFalse ;
}

NDTS_Boolean NDTS_HAL_GetHALInfo(NDTS_CardSecondaryIDs cardID, NDTS_HAL_Info **ppHALInfo)
{
	unsigned long halCount = 0 ;
	NDTS_Boolean isCardIDFound = NDTS_BFalse ;

	// Find HAL for the input cardID
	while (!isCardIDFound && halCount < halGlobalState.numberOfActiveHALs)
	{
		if (halGlobalState.ppHALInfos[halCount]->secondaryDeviceID == cardID)
			isCardIDFound = NDTS_BTrue ;
		else
			halCount++ ;
	}
	
	if (!isCardIDFound)
	{
		NDTS_HAL_HandleHALError(NDTS_HAL_GetHALInfo_MissingHAL) ;
		return NDTS_BFalse ;
	}

	*ppHALInfo = halGlobalState.ppHALInfos[halCount] ;

	return NDTS_BTrue ;
}

NDTS_Boolean CALL_CONV NDTS_HAL_GetCardInternalIndex(NDTS_HAL_Info *pHALInfo, NDTS_CardSecondaryIDs cardID, unsigned long cardIndex, unsigned long *pInternalCardIndex)
{
	unsigned long cardCount = 0 ;
	NDTS_Boolean isCardIndexFound = NDTS_BFalse ;

	// Find internal card index for external card index
	while (!isCardIndexFound && cardCount < pHALInfo->numberOfActiveCards)
	{
		if (pHALInfo->secondaryDeviceID == cardID &&
			pHALInfo->ppBoardIDs[cardCount]->cardIndex == cardIndex)
			isCardIndexFound = NDTS_BTrue ;
		else
			cardCount++ ;
	}

	if (!isCardIndexFound)
	{
		NDTS_HAL_HandleHALError(NDTS_HAL_GetCardInternalIndex_MissingCard) ;
		return NDTS_BFalse ;
	}

	*pInternalCardIndex = pHALInfo->ppBoardIDs[cardCount]->internalCardIndex ;

	return NDTS_BTrue ;
}