// ****************************************************************************
// INCLUDE FILES: Header files of modules referenced by this module
// ****************************************************************************
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <malloc.h>
#include <assert.h>
#include <sam4sd32c.h>
#include <conf_board.h>
#include <udi_cdc.h>
#include <spi.h>
#include <sensors_universal.h>
#include <DriverLibrary.h>
#include <ISTPManager.h>
#include <StopWatch.h>


// ****************************************************************************
// PRIVATE TYPES: Private types used by this module only
// ****************************************************************************
typedef uint8_t (*DLSBInit_t)( SensorMemory_t * sensorMemory );
typedef void (*DLSBRead_t)(float* Result,SensorMemory_t* sensorMemory,uint32_t* len);
typedef uint8_t (*DLSBReadFifo_t)(uint32_t* Result,SensorMemory_t* sensorMemory,uint32_t* len);
typedef void (*DLSBClearFifo_t)(SensorMemory_t* sensorMemory);
typedef void (*DLSBClear_t)(SensorMemory_t* sensorMemory);


// ****************************************************************************
// PRIVATE MACROS: Private #define directives used by this module only
// ****************************************************************************


// ****************************************************************************
// PRIVATE VARIABLES: Variables used by this module only (static)
// ****************************************************************************

// Prototypes of private functions used in the following private variables
// initializers.
static void DLSBClearDummy(SensorMemory_t* sensorMemory);
static void DLSBClearFifoDummy(SensorMemory_t* sensorMemory);
static uint8_t DLSBReadFifoDummy(uint32_t* Result,SensorMemory_t* sensorMemory,uint32_t* len);

static const DLSBInit_t const DLSBInit[NUM_SENSOR_BOARDS] =
{
    &DriverExampleInit           
}; 

static const DLSBRead_t const DLSBRead[NUM_SENSOR_BOARDS] = 
{
    &DriverExampleRead           
};

static const DLSBReadFifo_t const DLSBReadFifo[NUM_SENSOR_BOARDS] =
{
	&DriverExampleFIFO       
};


static const DLSBClearFifo_t const DLSBClearFifo[NUM_SENSOR_BOARDS] =
{
	&DriverExampleClearFIFO         
};

static const DLSBClear_t const DLSBClear[NUM_SENSOR_BOARDS] =
{
	&DriverExampleClear            
};


// ****************************************************************************
// PRIVATE FUNCTIONS PROTOTYPES: Functions used by this module only (static)
// ****************************************************************************


// ****************************************************************************
// PUBLIC VARIABLES: Public variables shared with other modules
// ****************************************************************************


// ****************************************************************************
// PRIVATE FUNCTIONS: Private functions used by this module only
// ****************************************************************************
static void DLSBClearDummy(SensorMemory_t* sensorMemory)
{}
static void DLSBClearFifoDummy(SensorMemory_t* sensorMemory)
{}
static uint8_t DLSBReadFifoDummy(uint32_t* Result,SensorMemory_t* sensorMemory,uint32_t* len)
{
	return 0;
}	


// ****************************************************************************
// PUBLIC FUNCTIONS: Public functions shared with other modules
// ****************************************************************************
int8_t InitSensorBoard( SensorMemory_t * sensorMemory )
{
    int8_t Result = 0;
    sensor_axis_e Axis = GetAxis( sensorMemory->Axis );
    sensor_board_e Board = GetBoard( sensorMemory->Board );
    
    // Pre-select chip select line
    SPI_ConfigureCs(Axis, Board);

    // Call init function for the specific sensor board
    Result = DLSBInit[sensorMemory->Driver](sensorMemory);
        
    return Result;
}

void ReadSensorBoard( SensorMemory_t * sensorMemory, uint32_t * sensorData, uint32_t * sensorDataLength )
{
    sensor_axis_e Axis = GetAxis( sensorMemory->Axis );
    sensor_board_e Board = GetBoard( sensorMemory->Board );
    uint8_t fifoOverflowActive;
    
    // Pre-select chip select    
    SPI_ConfigureCs(Axis, Board);

    if( ISTP_FIFO_MODE_INACTIVE == (ISTPMGetGlobalProperties()->FifoMode) )
    {
        // Call standard (non-fifo) read function for the specific sensor board
        DLSBRead[sensorMemory->Driver]((float*)sensorData, sensorMemory, sensorDataLength);
    }
    else
    {
        _SWStart(SW_ID_READ_SB);
        // Call fifo read function for the specific sensor board
        fifoOverflowActive = DLSBReadFifo[sensorMemory->Driver](sensorData, sensorMemory, sensorDataLength);
        if( fifoOverflowActive )
        {
            ISTPMSetAlertFifoOverflow(1);
        }
        _SWElapsedTimeUs(SW_ID_READ_SB);
    }
}

void ClearSensorBoardFifo( SensorMemory_t * sensorMemory )
{
    sensor_axis_e Axis = GetAxis( sensorMemory->Axis );
    sensor_board_e Board = GetBoard( sensorMemory->Board );
    
    // Pre-select chip select    
    SPI_ConfigureCs(Axis, Board);

    DLSBClearFifo[sensorMemory->Driver](sensorMemory);
}

void ClearSensorBoard( SensorMemory_t * sensorMemory )
{
    sensor_axis_e Axis = GetAxis( sensorMemory->Axis );
    sensor_board_e Board = GetBoard( sensorMemory->Board );
    
    // Pre-select chip select    
    SPI_ConfigureCs(Axis, Board);

    DLSBClear[sensorMemory->Driver](sensorMemory);
}