
/** @file 
@brief Implementation of the ACI transport layer module 
@note		STM32F4xx specific
*/ 


#include "hal_aci_tl.h"
#include "stm32f4xx_spi.h"
#include "aci_queue.h"

aci_queue_t	aci_tx_q;
aci_queue_t	aci_rx_q;

static bool m_aci_spi_transfer(hal_aci_data_t * data_to_send, hal_aci_data_t * received_data);

/**
* @fn			void disableRDYNInterrupt(void)
* @brief	Disable RDYN interrupt
*/
static void disableRDYNInterrupt(void)
{
	NVIC_DisableIRQ(HAL_ACI_GPIO_RDYN_IRQn);
}

/**
* @fn			void enableRDYNInterrupt()
* @brief	Low level IRQ initialization for RDYN pin. Hardware dependent
*					Pre-requisite : RDYN configured as an input pin already
*/
static void enableRDYNInterrupt(void)
{
	EXTI_InitTypeDef	EXTI_InitStructure;
	
	// Enable clock for SYSCFG
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
	
	EXTI_InitStructure.EXTI_Line = (uint32_t)(1<<HAL_ACI_GPIO_RDYN);
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; 
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE; 
	EXTI_Init(&EXTI_InitStructure); 	
	
	NVIC_SetPriority(HAL_ACI_GPIO_RDYN_IRQn, 10);
	NVIC_EnableIRQ(HAL_ACI_GPIO_RDYN_IRQn);
}

/**
* @fn			void delayMs(__IO uint32_t ms)
* @brief 	Software delay tuned for only 180MHz system clock
* @param	ms		delay in milli seconds
*/
static void delayMs(__IO uint32_t ms)
{
  __IO uint32_t index = 0; 
  for(index = (45000 * ms); index != 0; index--)
  {
		;
  }
}

/**
* @brief		ACI Transport Layer initialization.
* @details
*  This function initializes the transport layer, including configuring the SPI, creating 
*  message queues for Commands and Events and setting up interrupt if required. 
*  @param None
*/
void hal_aci_tl_init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	SPI_InitTypeDef SPI_InitStructure;
	
	//enable peripheral clock for SPI4
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI4 , ENABLE);
	
	//enable RCC for GPIOB(GPIO) and GPIOE(SPI)
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_GPIOE, ENABLE);
	
	GPIO_InitStructure.GPIO_Pin = (uint16_t)(1<<HAL_ACI_GPIO_RDYN);	//define RDYN pin
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;										//input mode
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;										//weak pullup enabled
	GPIO_Init(HAL_ACI_GPIO_BASE, &GPIO_InitStructure);							//HAL_ACI_GPIO_RDYN configured as input
	
	GPIO_InitStructure.GPIO_Pin = (uint16_t)(1<<HAL_ACI_GPIO_RESET);//define RESET pin
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;										//output mode
	GPIO_Init(HAL_ACI_GPIO_BASE, &GPIO_InitStructure);							//HAL_ACI_GPIO_RESET configured as output
	
	GPIO_WriteBit(HAL_ACI_GPIO_BASE, (uint16_t)(1<<HAL_ACI_GPIO_RESET), Bit_RESET);	//keep RESET pin low
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;										//AF mode for SPI4

	//HAL_ACI_SPI_xxx define in hal_aci_tl.h
	GPIO_PinAFConfig(HAL_ACI_SPI_BASE, (uint8_t)HAL_ACI_SPI_SCK, GPIO_AF_SPI4);
	GPIO_InitStructure.GPIO_Pin = (uint16_t) (1<<HAL_ACI_SPI_SCK)	;
	GPIO_Init(HAL_ACI_SPI_BASE, &GPIO_InitStructure);
	
	GPIO_PinAFConfig(HAL_ACI_SPI_BASE, (uint8_t)HAL_ACI_SPI_MISO, GPIO_AF_SPI4);
	GPIO_InitStructure.GPIO_Pin = (uint16_t) (1<<HAL_ACI_SPI_MISO)	;
	GPIO_Init(HAL_ACI_SPI_BASE, &GPIO_InitStructure);
	
	GPIO_PinAFConfig(HAL_ACI_SPI_BASE, (uint8_t)HAL_ACI_SPI_MOSI, GPIO_AF_SPI4);
	GPIO_InitStructure.GPIO_Pin = (uint16_t) (1<<HAL_ACI_SPI_MOSI)	;
	GPIO_Init(HAL_ACI_SPI_BASE, &GPIO_InitStructure);
	
	GPIO_PinAFConfig(HAL_ACI_SPI_BASE, (uint8_t)HAL_ACI_SPI_REQN, GPIO_AF_SPI4);
	GPIO_InitStructure.GPIO_Pin = (uint16_t) (1<<HAL_ACI_SPI_REQN);
	GPIO_Init(HAL_ACI_SPI_BASE, &GPIO_InitStructure);
	
	//SPI init
	SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
	SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
	SPI_InitStructure.SPI_NSS = SPI_NSS_Hard;						//hardware SS for SPI (HAL_ACI_SPI_REQN)
	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_LSB;	//data order in lsb first
	SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
	SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;	
	SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;					//SCK steady state low
	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64;	//max. nRF8001 SPI clock = 3MHz
																																			//MCU sysclock @ 180MHz => SPI clock rate = 180/64=2.8MHz
	//enable SPI
	SPI_Init(HAL_ACI_SPI_CH, &SPI_InitStructure);			
	SPI_Cmd(HAL_ACI_SPI_CH, ENABLE);
	
	GPIO_WriteBit(HAL_ACI_GPIO_BASE, (uint16_t)(1<<HAL_ACI_GPIO_RESET), Bit_SET);	//keep RESET pin high for normal operation

	aci_queue_init(&aci_tx_q);
	aci_queue_init(&aci_rx_q);
	
	delayMs(62);
	
	enableRDYNInterrupt();
}

/**
* @fn			__irq void rdyn_isr(void)
* @brief	Interrupt service routine called when the RDYN line goes low. Runs the SPI transfer.
*/
__irq void hal_aci_tl_rdyn_isr(void)
{
	hal_aci_data_t 	data_to_send;
	hal_aci_data_t	received_data;
	
	if(EXTI_GetITStatus((uint32_t)(1<<HAL_ACI_GPIO_RDYN)) !=RESET){
        //Clear interrupt flag
        EXTI_ClearITPendingBit((uint32_t)(1<<HAL_ACI_GPIO_RDYN));		
	}
}
