/**
******************************************************************************
* @file drv_95HF.c
* @author MMY Application Team
* @version $Revision: 1348 $
* @date $Date: 2015-11-05 11:36:33 +0100 (Thu, 05 Nov 2015) $
* @brief This file provides set of driver functions to manage communication
* between MCU and xx95HF chip (CR95HF)
******************************************************************************
* @attention
*
*
© COPYRIGHT 2016 STMicroelectronics
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
//#ifdef __cplusplus
// extern "C" {
//#endif
/* Includes ------------------------------------------------------------------------------ */
#include "SPI.h"
#include "stdbool.h"
#include "drv_95HF.h"
#include "lib_pcd.h"
#include "Arduino.h"
/** @addtogroup BSP
* @{
*/
/** @addtogroup Components
* @{
*/
/** @addtogroup XX95HF
* @{
*/
/* External variables --------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private defines -----------------------------------------------------------*/
/* Private macros ------------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
static void drv95HF_InitializeSPI(int8_t sck, int8_t miso, int8_t mosi, int8_t ss, int8_t irq);
static void drv95HF_SendSPIResetByte(void);
static int8_t drv95HF_SPIPollingCommand(void);
/* Global variables ---------------------------------------------------------*/
/** @defgroup XX95HF_Global variables
* @{
*/
/**
* @brief buffer to exchange data with the RF tranceiver.
*/
uint8_t u95HFBuffer [RFTRANS_95HF_MAX_BUFFER_SIZE+3];
uint8_t sspin=0;
uint8_t irqpin=0;
/**
* @brief This uTimeOut variable is used as a timeout duting the communication with the RF tranceiver
*/
extern volatile bool uDataReady;
bool EnableTimeOut = true;
/* ConfigStructure */
drv95HF_ConfigStruct drv95HFConfig;
/**
* @}
*/
/* Private functions ---------------------------------------------------------*/
/** @defgroup XX95HF_Private_Functions
* @{
*/
/**
* @brief this functions initializes the SPI in order to communicate with the 95HF device
* @param None
* @retval void
*/
static void drv95HF_InitializeSPI(int8_t sck, int8_t miso, int8_t mosi, int8_t ss, int8_t irq)
{
sspin = ss;
irqpin = irq;
RFTRANS_SPI_Init(sck, miso, mosi, ss, irq);
}
/**
* @brief This function sends a reset command over SPI bus
* @param None
* @retval None
*/
static void drv95HF_SendSPIResetByte(void)
{
/* Send reset control byte */
SPI_SendReceiveByte(RFTRANS_95HF_COMMAND_RESET);
}
/**
* @brief This function polls 95HF chip until a response is ready or
* the counter of the timeout overflows
* @param None
* @retval PCD_POLLING_TIMEOUT : The time out was reached
* @retval PCD_SUCCESS_CODE : A response is available
*/
static int8_t drv95HF_SPIPollingCommand( void )
{
uint8_t Polling_Status = 0;
int timestamp_start = -1;
int timestamp_final = -1;
bool uTimeOut = false;
if(EnableTimeOut)
{
timestamp_start = millis();
}
DEV_SPI.beginTransaction(SPISettings(1500000, MSBFIRST, SPI_MODE3));
do
{
/* Low level on NSS */
SPI_driveNSS_Low();
delay(2);
/* poll the 95HF transceiver until he's ready ! */
Polling_Status = SPI_SendReceiveByte(RFTRANS_95HF_COMMAND_POLLING);
Polling_Status &= RFTRANS_95HF_FLAG_DATA_READY_MASK;
if(EnableTimeOut)
{
/* 3sec for LLCP can be improved to adjust it dynamically */
timestamp_final = millis();
if((timestamp_final - timestamp_start) > 3000)
{
uTimeOut = true;
}
}
}
while( Polling_Status != RFTRANS_95HF_FLAG_DATA_READY && uTimeOut != true );
/* High level on NSS */
SPI_driveNSS_High();
DEV_SPI.endTransaction();
if ( uTimeOut == true )
{
return RFTRANS_95HF_POLLING_TIMEOUT;
}
return RFTRANS_95HF_SUCCESS_CODE;
}
/**
* @}
*/
/** @defgroup drv_95HF_Public_Functions
* @{
*/
/**
* @brief Initilize the 95HF device config structure
* @param None
* @retval None
*/
void drv95HF_InitConfigStructure (void)
{
drv95HFConfig.uInterface = RFTRANS_95HF_INTERFACE_SPI;
drv95HFConfig.uState = RFTRANS_95HF_STATE_POWERUP;
drv95HFConfig.uCurrentProtocol = RFTRANS_95HF_PROTOCOL_UNKNOWN;
drv95HFConfig.uMode = RFTRANS_95HF_MODE_UNKNOWN;
}
/**
* @brief Send a reset sequence over SPI bus (Reset command ,wait ,negative pulse on IRQin).
* @param None
* @retval None
*/
void drv95HF_ResetSPI(void)
{
/* Deselect Rftransceiver over SPI */
SPI_driveNSS_High();
delay(1);
DEV_SPI.beginTransaction(SPISettings(1500000, MSBFIRST, SPI_MODE3));
/* Select 95HF device over SPI */
SPI_driveNSS_Low();
/* Send reset control byte */
drv95HF_SendSPIResetByte();
/* Deselect 95HF device over SPI */
SPI_driveNSS_High();
DEV_SPI.endTransaction();
delay(3);
/* send a pulse on IRQ_in*/
drv95HF_SendIRQINPulse();
delay(10); /* mandatory before issuing a new command */
drv95HFConfig.uState = RFTRANS_95HF_STATE_READY;
}
/**
* @brief returns the value of interface pin.
* Low level means UART bus was choose.
* High level means SPI bus was choose.
* @param None
* @retval Bit_RESET : 0
* @retval Bit_SET : 1
*/
//int8_t drv95HF_GetInterfacePinState(void)
//{
// return RFTRANS_95HF_GET_INTERFACE();
//}
/**
* @brief This function returns the IRQout state
* @param None
* @retval Pin set : 1
* @retval Pin reset : 0
*/
//int8_t drv95HF_GetIRQOutState(void)
//{
// if (HAL_GPIO_ReadPin(IRQOUT_RFTRANS_95HF_PORT, IRQOUT_RFTRANS_95HF_PIN) != GPIO_PIN_RESET)
// {
// return 0x01;
// }
// else
// {
// return 0x00;
// }
//}
/**
* @brief This function initialize MCU serial interface peripheral (SPI or UART)
* @param None
* @retval None
*/
void drv95HF_InitilizeSerialInterface(int8_t sck, int8_t miso, int8_t mosi, int8_t ss, int8_t irq)
{
/* -- Get interface pin state to select UART or SPI mode -- */
//if (drv95HF_GetInterfacePinState() != RFTRANS_95HF_INTERFACE_UART)
//{
/* -- Set communication type -- */
drv95HFConfig.uInterface = RFTRANS_95HF_INTERFACE_SPI;
/* -- Initialize SPI Interface -- */
drv95HF_InitializeSPI(sck, miso, mosi, ss, irq);
//}
}
/**
* @brief This function returns the Interface selected(UART or SPI)
* @param None
* @retval RFTRANS_INTERFACE_UART : the UART interface is selected
* @retval RFTRANS_INTERFACE_SPI : the SPI interface is selected
*/
uint8_t drv95HF_GetSerialInterface(void)
{
return drv95HFConfig.uInterface;
}
/**
* @brief This function sends a command over SPI bus
* @param *pData : pointer on data to send to the xx95HF
* @retval None
*/
void drv95HF_SendSPICommand(const uint8_t *pData)
{
uint8_t DummyBuffer[MAX_BUFFER_SIZE];
DEV_SPI.beginTransaction(SPISettings(1500000, MSBFIRST, SPI_MODE3));
/* Select xx95HF over SPI */
SPI_driveNSS_Low();
/* Send a sending request to xx95HF */
SPI_SendReceiveByte(RFTRANS_95HF_COMMAND_SEND);
if(*pData == ECHO)
{
/* Send a sending request to xx95HF */
SPI_SendReceiveByte(ECHO);
}
else
{
/* Transmit the buffer over SPI */
SPI_SendReceiveBuffer(pData, pData[RFTRANS_95HF_LENGTH_OFFSET]+RFTRANS_95HF_DATA_OFFSET, DummyBuffer);
}
/* Deselect xx95HF over SPI */
SPI_driveNSS_High();
DEV_SPI.endTransaction();
}
/**
* @brief This fucntion recovers a response from 95HF device
* @param *pData : pointer on data received from 95HF device
* @retval None
*/
void drv95HF_ReceiveSPIResponse(uint8_t *pData)
{
uint8_t DummyBuffer[MAX_BUFFER_SIZE];
DEV_SPI.beginTransaction(SPISettings(1500000, MSBFIRST, SPI_MODE3));
/* Select 95HF transceiver over SPI */
SPI_driveNSS_Low();
/* Request a response from 95HF transceiver */
SPI_SendReceiveByte(RFTRANS_95HF_COMMAND_RECEIVE);
/* Recover the "Command" byte */
pData[RFTRANS_95HF_COMMAND_OFFSET] = SPI_SendReceiveByte(DUMMY_BYTE);
if(pData[RFTRANS_95HF_COMMAND_OFFSET] == ECHO)
{
pData[RFTRANS_95HF_LENGTH_OFFSET] = 0x00;
/* In case we were in listen mode error code cancelled by user (0x85 0x00) must be retrieved */
pData[RFTRANS_95HF_LENGTH_OFFSET+1] = SPI_SendReceiveByte(DUMMY_BYTE);
pData[RFTRANS_95HF_LENGTH_OFFSET+2] = SPI_SendReceiveByte(DUMMY_BYTE);
}
else if(pData[RFTRANS_95HF_COMMAND_OFFSET] == 0xFF)
{
pData[RFTRANS_95HF_LENGTH_OFFSET] = 0x00;
pData[RFTRANS_95HF_LENGTH_OFFSET+1] = SPI_SendReceiveByte(DUMMY_BYTE);
pData[RFTRANS_95HF_LENGTH_OFFSET+2] = SPI_SendReceiveByte(DUMMY_BYTE);
}
else
{
/* Recover the "Length" byte */
pData[RFTRANS_95HF_LENGTH_OFFSET] = SPI_SendReceiveByte(DUMMY_BYTE);
/* Checks the data length */
if(pData[RFTRANS_95HF_LENGTH_OFFSET] != 0x00)
SPI_SendReceiveBuffer(DummyBuffer, pData[RFTRANS_95HF_LENGTH_OFFSET], &pData[RFTRANS_95HF_DATA_OFFSET]);
}
/* Deselect xx95HF over SPI */
SPI_driveNSS_High();
DEV_SPI.endTransaction();
}
/**
* @brief This function send a command to 95HF device over SPI or UART bus and receive its response
* @param *pCommand : pointer on the buffer to send to the 95HF device ( Command | Length | Data)
* @param *pResponse : pointer on the 95HF device response ( Command | Length | Data)
* @retval RFTRANS_95HF_SUCCESS_CODE : the function is succesful
*/
int8_t drv95HF_SendReceive(const uint8_t *pCommand, uint8_t *pResponse)
{
if(drv95HFConfig.uInterface == RFTRANS_95HF_INTERFACE_SPI)
{
/* First step - Sending command */
drv95HF_SendSPICommand(pCommand);
/* Second step - Polling */
if (drv95HF_SPIPollingCommand( ) != RFTRANS_95HF_SUCCESS_CODE)
{
*pResponse = RFTRANS_95HF_ERRORCODE_TIMEOUT;
return RFTRANS_95HF_POLLING_TIMEOUT;
}
/* Third step - Receiving bytes */
drv95HF_ReceiveSPIResponse(pResponse);
}
return RFTRANS_95HF_SUCCESS_CODE;
}
/**
* @brief This function send a command to 95HF device over SPI or UART bus
* @param *pCommand : pointer on the buffer to send to the 95HF ( Command | Length | Data)
* @retval None
*/
void drv95HF_SendCmd(const uint8_t *pCommand)
{
if(drv95HFConfig.uInterface == RFTRANS_95HF_INTERFACE_SPI)
/* First step - Sending command */
drv95HF_SendSPICommand(pCommand);
// else if(drv95HFConfig.uInterface == RFTRANS_95HF_INTERFACE_UART)
/* First step - Sending command */
// drv95HF_SendUARTCommand(pCommand);
}
/**
* @brief This function is a specific command. It's made polling and reading sequence.
* @param *pResponse : pointer on the 95HF device response ( Command | Length | Data)
* @retval RFTRANS_95HF_SUCCESS_CODE : the function is succesful
* @retval RFTRANS_95HF_POLLING_RFTRANS_95HF : the polling sequence returns an error
*/
int8_t drv95HF_PoolingReading (uint8_t *pResponse)
{
*pResponse =RFTRANS_95HF_ERRORCODE_DEFAULT;
*(pResponse+1) = 0x00;
if(drv95HFConfig.uInterface == RFTRANS_95HF_INTERFACE_SPI)
{
/* First step - Polling */
if (drv95HF_SPIPollingCommand( ) != RFTRANS_95HF_SUCCESS_CODE)
{ *pResponse = RFTRANS_95HF_ERRORCODE_TIMEOUT;
return RFTRANS_95HF_ERRORCODE_TIMEOUT;
}
/* Second step - Receiving bytes */
drv95HF_ReceiveSPIResponse(pResponse);
}
return RFTRANS_95HF_SUCCESS_CODE;
}
/**
* @brief Send a negative pulse on IRQin pin
* @param None
* @retval None
*/
void drv95HF_SendIRQINPulse(void)
{
if (drv95HFConfig.uInterface == RFTRANS_95HF_INTERFACE_SPI)
{
/* Send a pulse on IRQ_IN */
RFTRANS_95HF_IRQIN_HIGH() ;
delay(1);
RFTRANS_95HF_IRQIN_LOW() ;
delay(1);
RFTRANS_95HF_IRQIN_HIGH() ;
}
/* Need to wait 10ms after the pulse before to send the first command */
delay(10);
}
/**
* @brief this functions put the ST95HF in sleep/hibernate mode
* @param WU_source : Source selected to wake up the device (WU_TIMEOUT,WU_TAG,WU_FIELD,WU_IRQ,WU_SPI)
* @param mode : Can be IDLE_SLEEP_MODE or IDLE_HIBERNATE_MODE
* @retval None
*/
void drv95HF_Idle(const uint8_t WU_source, const uint8_t mode)
{
uint8_t pCommand[] = {RFTRANS_95HF_COMMAND_IDLE, IDLE_CMD_LENTH, 0, 0, 0, 0, 0 ,0x18 ,0x00 ,0x00 ,0x60 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00};
if (mode == IDLE_SLEEP_MODE) /* SLEEP */
{
/* Select the wake up source*/
pCommand[2] = WU_source;
/* Select SLEEP mode */
if (WU_source == WU_FIELD)
{
pCommand[3] = GETMSB(SLEEP_FIELD_ENTER_CTRL);
pCommand[4] = GETLSB(SLEEP_FIELD_ENTER_CTRL);
}
else
{
pCommand[3] = GETMSB(SLEEP_ENTER_CTRL);
pCommand[4] = GETLSB(SLEEP_ENTER_CTRL);
}
pCommand[5] = GETMSB(SLEEP_WU_CTRL);
pCommand[6] = GETLSB(SLEEP_WU_CTRL);
}
else /* HIBERNATE */
{
/* Select the wake up source, only IRQ is available for HIBERNATE mode*/
pCommand[2] = WU_IRQ;
/* Select HIBERNATE mode */
pCommand[3] = GETMSB(HIBERNATE_ENTER_CTRL);
pCommand[4] = GETLSB(HIBERNATE_ENTER_CTRL);
pCommand[5] = GETMSB(HIBERNATE_WU_CTRL);
pCommand[6] = GETLSB(HIBERNATE_WU_CTRL);
pCommand[10] = 0x00;
}
/* Send the command */
if(drv95HFConfig.uInterface == RFTRANS_95HF_INTERFACE_SPI)
/* First step - Sending command */
drv95HF_SendSPICommand(pCommand);
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
//#ifdef __cplusplus
//}
//#endif
/******************* (C) COPYRIGHT 2016 STMicroelectronics *****END OF FILE****/