/** ****************************************************************************** * @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****/