#ifndef FILE_SPI_H_
#define FILE_SPI_H_

// ****************************************************************************
// CONDITIONAL COMPILATION DIRECTIVES: Conditional compilation control
// ****************************************************************************


// ****************************************************************************
// INCLUDE FILES: Header files of modules referenced by this module
// ****************************************************************************
#include <stdint.h>
#include <delay.h>
#include <sam4sd32c.h>
#include <conf_board.h>


// ****************************************************************************
// MODULE DOCUMENTATION: Detailed description of the module
// ****************************************************************************


// ****************************************************************************
// PUBLIC TYPES: Public types shared with other modules
// ****************************************************************************
typedef enum
{
	SPI_POL_0,
	SPI_POL_1
} spi_pol_e;

typedef enum
{
	SPI_PHA_1,
	SPI_PHA_0
} spi_pha_e;	// Inverted in register

//brief Enum with SPI communication's bits width members. SPI bits width from 8 to 16
typedef enum
{
	SPI_8_BIT,
	SPI_9_BIT,
	SPI_10_BIT,
	SPI_11_BIT,
	SPI_12_BIT,
	SPI_13_BIT,
	SPI_14_BIT,
	SPI_15_BIT,
	SPI_16_BIT
} spi_bits_e;

// brief Enum with orientation members
typedef enum
{
	axis_A,
	axis_B,
	axis_C,
	axis_mainboard
} sensor_axis_e;

// brief Enum with board number 
typedef enum
{
	board_1,
	board_2,
	board_3,
	board_4,
	board_5,
	board_6,
	board_mb
} sensor_board_e;

// brief Enum with chip select members
typedef enum
{
	chip_EEPROM,
	chip_1,
	chip_2,
	chip_3,
	chip_4,
	chip_5,
	chip_6,
	chip_7,
	chip_imu,
	chip_adc,
	chip_hum
} sensor_select_e;


// ****************************************************************************
// PUBLIC MACROS: Public #define directives shared with other modules
// ****************************************************************************


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


// ****************************************************************************
// PUBLIC FUNCTIONS: Public functions shared with other modules
// ****************************************************************************
//---------------------------------------------------------------------
//! @brief A routine that initializes master channel of SPI module.
//!
//! Initializes SPI module to communicate as master in specified mode
//! with specified frequency. If the frequency is below or above the
//! limit, frequency is silently limited to allowed value inside the
//! function.
//!
//! @param[in]    freqHz  Set SPI frequency in Hz
//!                       Max - peripheral clock
//!                       Min - peripheral clock / 255
//! @param[in]    pol     Set POL mode (0 or 1)
//! @param[in]    pha     Set PHA mode (0 or 1)
//! @param[in]    bits    Number of bits in a single word
//! @param[in]    delay   in us
//! @param[out]   none
//! @return       none
//---------------------------------------------------------------------
void SPI_master_init(uint32_t freqHz, spi_pol_e pol, spi_pha_e pha, spi_bits_e bits, uint16_t delay);

//---------------------------------------------------------------------
//! @brief This function De-configure SPI interface.
//!
//! @param[in] none
//! @param[out] none
//! @return none
//---------------------------------------------------------------------
void SPI_master_deinit(void);

//---------------------------------------------------------------------
//! @brief This function resets SPI
//!
//! @param[in] none
//! @param[out] none
//! @return none
//---------------------------------------------------------------------
void SPI_master_reset(void);

//---------------------------------------------------------------------
//! @brief This function write data into SPI
//!
//! @param[in] data      16bits unsigned number with data
//! @param[out] none
//! @return none
//---------------------------------------------------------------------
void SPI_master_write(uint16_t data);

//---------------------------------------------------------------------
//! @brief This function reads from SPI.
//!
//! @param[in] none
//! @param[out] none
//! @return Received 8-bit or 16-bits word
//---------------------------------------------------------------------
uint16_t SPI_master_read(void);

//---------------------------------------------------------------------
//! @brief This function sets SPI for communication with specific chip
//!
//! @param[in] dec_val      Index of selected chip
//!                         (chip_EEPROM, chip_1  - chip_6)
//! @param[out] none
//! @return none
//---------------------------------------------------------------------
void SPI_setDec (sensor_select_e dec_val);

//---------------------------------------------------------------------
//! @brief This function asserts the pre-configured SPI chip select
//!
//! Chip select chosen by the SPI_ConfigureCs is asserted (activated)
//! in order to communicate with specific chip on specific board 
//!
//! @param[in] none
//! @param[out] none
//! @return none
//---------------------------------------------------------------------
void SPI_setCs( void );

//---------------------------------------------------------------------
//! @brief  This function resets all chip selects
//!
//! @param[in] none
//! @param[out] none
//! @return none
//---------------------------------------------------------------------
void SPI_resetAllCs(void);

//---------------------------------------------------------------------
//! @brief  Configure the chip select for subsequent SPI transactions
//!
//! Specific chip select signal is configured to be used for SPI
//! read and write transfers following call of this function.
//! Chip select is chosen based on the hard-coded mapping between
//! axes and their respective gpio signals used as the chip selects.
//! SPI_setCs calls are operating the chip select chosen by 
//! the latest call of the SPI_ConfigureCs. 
//!
//! @param[in] axis  Index of selected axis (in range axis_A - axis_C)
//! @param[in] board Index of selected board (in range board_1 - board_6)
//! @param[out] none
//! @return none
//---------------------------------------------------------------------
void SPI_ConfigureCs(sensor_axis_e axis, sensor_board_e board);

//---------------------------------------------------------------------
//! @brief  Update the peripheral clock value used inside SPI module
//!
//! Peripheral clock value is needed for determination of SPI bit rate.
//! Peripheral clock is provided by ASF drivers by call of dedicated
//! function, however it is not desired to call such function with
//! each call of SPI master init function, because of execution time.
//! Taking into account that peripheral clock is constant during entire
//! runtime once initialized, it is sufficient to call ASF drivers once
//! and store the peripheral clock value to the SPI module's internal 
//! variable.
//!
//! @param[in] N/A
//! @param[out] N/A
//! @return none
//---------------------------------------------------------------------
void SPI_UpdatePeriphClk(void);


#endif /* FILE_SPI_H_ */