mirror of
https://gitlab.com/fabinfra/fabhardware/FabReader2.git
synced 2025-03-12 22:51:51 +01:00
458 lines
13 KiB
C
458 lines
13 KiB
C
|
|
||
|
/******************************************************************************
|
||
|
* \attention
|
||
|
*
|
||
|
* <h2><center>© COPYRIGHT 2016 STMicroelectronics</center></h2>
|
||
|
*
|
||
|
* 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:
|
||
|
*
|
||
|
* 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.
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
|
||
|
|
||
|
/*
|
||
|
* PROJECT: ST25R3911 firmware
|
||
|
* Revision:
|
||
|
* LANGUAGE: ISO C99
|
||
|
*/
|
||
|
|
||
|
/*! \file
|
||
|
*
|
||
|
* \author Ulrich Herrmann
|
||
|
*
|
||
|
* \brief Implementation of ST25R3911 communication.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
******************************************************************************
|
||
|
* INCLUDES
|
||
|
******************************************************************************
|
||
|
*/
|
||
|
#include "st25r3911_com.h"
|
||
|
#include "st25r3911.h"
|
||
|
#include "utils.h"
|
||
|
|
||
|
|
||
|
/*
|
||
|
******************************************************************************
|
||
|
* LOCAL DEFINES
|
||
|
******************************************************************************
|
||
|
*/
|
||
|
|
||
|
#define ST25R3911_WRITE_MODE (0U) /*!< ST25R3911 SPI Operation Mode: Write */
|
||
|
#define ST25R3911_READ_MODE (1U << 6) /*!< ST25R3911 SPI Operation Mode: Read */
|
||
|
#define ST25R3911_FIFO_LOAD (2U << 6) /*!< ST25R3911 SPI Operation Mode: FIFO Load */
|
||
|
#define ST25R3911_FIFO_READ (0xBFU) /*!< ST25R3911 SPI Operation Mode: FIFO Read */
|
||
|
#define ST25R3911_CMD_MODE (3U << 6) /*!< ST25R3911 SPI Operation Mode: Direct Command */
|
||
|
|
||
|
#define ST25R3911_CMD_LEN (1U) /*!< ST25R3911 CMD length */
|
||
|
#define ST25R3911_BUF_LEN (ST25R3911_CMD_LEN+ST25R3911_FIFO_DEPTH) /*!< ST25R3911 communication buffer: CMD + FIFO length */
|
||
|
|
||
|
/*
|
||
|
******************************************************************************
|
||
|
* LOCAL VARIABLES
|
||
|
******************************************************************************
|
||
|
*/
|
||
|
|
||
|
#ifdef ST25R391X_COM_SINGLETXRX
|
||
|
static uint8_t comBuf[ST25R3911_BUF_LEN]; /*!< ST25R3911 communication buffer */
|
||
|
#endif /* ST25R391X_COM_SINGLETXRX */
|
||
|
|
||
|
/*
|
||
|
******************************************************************************
|
||
|
* LOCAL FUNCTION PROTOTYPES
|
||
|
******************************************************************************
|
||
|
*/
|
||
|
|
||
|
static inline void st25r3911CheckFieldSetLED(uint8_t value)
|
||
|
{
|
||
|
if ((ST25R3911_REG_OP_CONTROL_tx_en & value) != 0U)
|
||
|
{
|
||
|
#ifdef PLATFORM_LED_FIELD_PIN
|
||
|
platformLedOn( PLATFORM_LED_FIELD_PORT, PLATFORM_LED_FIELD_PIN );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
platformLedOff( PLATFORM_LED_FIELD_PORT, PLATFORM_LED_FIELD_PIN );
|
||
|
#endif /* PLATFORM_LED_FIELD_PIN */
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
******************************************************************************
|
||
|
* GLOBAL FUNCTIONS
|
||
|
******************************************************************************
|
||
|
*/
|
||
|
void st25r3911ReadRegister(uint8_t reg, uint8_t* value)
|
||
|
{
|
||
|
#ifdef ST25R391X_COM_SINGLETXRX
|
||
|
uint8_t* buf = comBuf;
|
||
|
#else /* ST25R391X_COM_SINGLETXRX */
|
||
|
uint8_t buf[2];
|
||
|
#endif /* ST25R391X_COM_SINGLETXRX */
|
||
|
|
||
|
platformProtectST25R391xComm();
|
||
|
platformSpiSelect();
|
||
|
|
||
|
buf[0] = (reg | ST25R3911_READ_MODE);
|
||
|
buf[1] = 0;
|
||
|
|
||
|
platformSpiTxRx(buf, buf, 2);
|
||
|
|
||
|
if(value != NULL)
|
||
|
{
|
||
|
*value = buf[1];
|
||
|
}
|
||
|
|
||
|
platformSpiDeselect();
|
||
|
platformUnprotectST25R391xComm();
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
void st25r3911ReadMultipleRegisters(uint8_t reg, uint8_t* values, uint8_t length)
|
||
|
{
|
||
|
#if !defined(ST25R391X_COM_SINGLETXRX)
|
||
|
uint8_t cmd = (reg | ST25R3911_READ_MODE);
|
||
|
#endif /* !ST25R391X_COM_SINGLETXRX */
|
||
|
|
||
|
if (length > 0U)
|
||
|
{
|
||
|
platformProtectST25R391xComm();
|
||
|
platformSpiSelect();
|
||
|
|
||
|
#ifdef ST25R391X_COM_SINGLETXRX
|
||
|
|
||
|
ST_MEMSET( comBuf, 0x00, MIN( (ST25R3911_CMD_LEN + (uint32_t)length), ST25R3911_BUF_LEN ) );
|
||
|
comBuf[0] = (reg | ST25R3911_READ_MODE);
|
||
|
|
||
|
platformSpiTxRx(comBuf, comBuf, MIN( (ST25R3911_CMD_LEN + length), ST25R3911_BUF_LEN ) ); /* Transceive as a single SPI call */
|
||
|
ST_MEMCPY( values, &comBuf[ST25R3911_CMD_LEN], MIN( length, ST25R3911_BUF_LEN - ST25R3911_CMD_LEN ) ); /* Copy from local buf to output buffer and skip cmd byte */
|
||
|
|
||
|
#else /* ST25R391X_COM_SINGLETXRX */
|
||
|
|
||
|
/* Since the result comes one byte later, let's first transmit the adddress with discarding the result */
|
||
|
platformSpiTxRx(&cmd, NULL, ST25R3911_CMD_LEN);
|
||
|
platformSpiTxRx(NULL, values, length);
|
||
|
|
||
|
#endif /* ST25R391X_COM_SINGLETXRX */
|
||
|
|
||
|
platformSpiDeselect();
|
||
|
platformUnprotectST25R391xComm();
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
void st25r3911ReadTestRegister(uint8_t reg, uint8_t* value)
|
||
|
{
|
||
|
|
||
|
#ifdef ST25R391X_COM_SINGLETXRX
|
||
|
uint8_t* buf = comBuf;
|
||
|
#else /* ST25R391X_COM_SINGLETXRX */
|
||
|
uint8_t buf[3];
|
||
|
#endif /* ST25R391X_COM_SINGLETXRX */
|
||
|
|
||
|
platformProtectST25R391xComm();
|
||
|
platformSpiSelect();
|
||
|
|
||
|
buf[0] = ST25R3911_CMD_TEST_ACCESS;
|
||
|
buf[1] = (reg | ST25R3911_READ_MODE);
|
||
|
buf[2] = 0x00;
|
||
|
|
||
|
platformSpiTxRx(buf, buf, 3);
|
||
|
|
||
|
if(value != NULL)
|
||
|
{
|
||
|
*value = buf[2];
|
||
|
}
|
||
|
|
||
|
platformSpiDeselect();
|
||
|
platformUnprotectST25R391xComm();
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
void st25r3911WriteTestRegister(uint8_t reg, uint8_t value)
|
||
|
{
|
||
|
#ifdef ST25R391X_COM_SINGLETXRX
|
||
|
uint8_t* buf = comBuf;
|
||
|
#else /* ST25R391X_COM_SINGLETXRX */
|
||
|
uint8_t buf[3];
|
||
|
#endif /* ST25R391X_COM_SINGLETXRX */
|
||
|
|
||
|
platformProtectST25R391xComm();
|
||
|
platformSpiSelect();
|
||
|
|
||
|
buf[0] = ST25R3911_CMD_TEST_ACCESS;
|
||
|
buf[1] = (reg | ST25R3911_WRITE_MODE);
|
||
|
buf[2] = value;
|
||
|
|
||
|
platformSpiTxRx(buf, NULL, 3);
|
||
|
|
||
|
platformSpiDeselect();
|
||
|
platformUnprotectST25R391xComm();
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
void st25r3911WriteRegister(uint8_t reg, uint8_t value)
|
||
|
{
|
||
|
#ifdef ST25R391X_COM_SINGLETXRX
|
||
|
uint8_t* buf = comBuf;
|
||
|
#else /* ST25R391X_COM_SINGLETXRX */
|
||
|
uint8_t buf[2];
|
||
|
#endif /* ST25R391X_COM_SINGLETXRX */
|
||
|
|
||
|
if (ST25R3911_REG_OP_CONTROL == reg)
|
||
|
{
|
||
|
st25r3911CheckFieldSetLED(value);
|
||
|
}
|
||
|
|
||
|
platformProtectST25R391xComm();
|
||
|
platformSpiSelect();
|
||
|
|
||
|
buf[0] = reg | ST25R3911_WRITE_MODE;
|
||
|
buf[1] = value;
|
||
|
|
||
|
platformSpiTxRx(buf, NULL, 2);
|
||
|
|
||
|
platformSpiDeselect();
|
||
|
platformUnprotectST25R391xComm();
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
void st25r3911ClrRegisterBits( uint8_t reg, uint8_t clr_mask )
|
||
|
{
|
||
|
uint8_t tmp;
|
||
|
|
||
|
st25r3911ReadRegister(reg, &tmp);
|
||
|
tmp &= ~clr_mask;
|
||
|
st25r3911WriteRegister(reg, tmp);
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
void st25r3911SetRegisterBits( uint8_t reg, uint8_t set_mask )
|
||
|
{
|
||
|
uint8_t tmp;
|
||
|
|
||
|
st25r3911ReadRegister(reg, &tmp);
|
||
|
tmp |= set_mask;
|
||
|
st25r3911WriteRegister(reg, tmp);
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
void st25r3911ChangeRegisterBits(uint8_t reg, uint8_t valueMask, uint8_t value)
|
||
|
{
|
||
|
st25r3911ModifyRegister(reg, valueMask, (valueMask & value) );
|
||
|
}
|
||
|
|
||
|
void st25r3911ModifyRegister(uint8_t reg, uint8_t clr_mask, uint8_t set_mask)
|
||
|
{
|
||
|
uint8_t tmp;
|
||
|
|
||
|
st25r3911ReadRegister(reg, &tmp);
|
||
|
|
||
|
/* mask out the bits we don't want to change */
|
||
|
tmp &= ~clr_mask;
|
||
|
/* set the new value */
|
||
|
tmp |= set_mask;
|
||
|
st25r3911WriteRegister(reg, tmp);
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
void st25r3911ChangeTestRegisterBits( uint8_t reg, uint8_t valueMask, uint8_t value )
|
||
|
{
|
||
|
uint8_t rdVal;
|
||
|
uint8_t wrVal;
|
||
|
|
||
|
/* Read current reg value */
|
||
|
st25r3911ReadTestRegister(reg, &rdVal);
|
||
|
|
||
|
/* Compute new value */
|
||
|
wrVal = (rdVal & ~valueMask);
|
||
|
wrVal |= (value & valueMask);
|
||
|
|
||
|
/* Write new reg value */
|
||
|
st25r3911WriteTestRegister(reg, wrVal );
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
void st25r3911WriteMultipleRegisters(uint8_t reg, const uint8_t* values, uint8_t length)
|
||
|
{
|
||
|
#if !defined(ST25R391X_COM_SINGLETXRX)
|
||
|
uint8_t cmd = (reg | ST25R3911_WRITE_MODE);
|
||
|
#endif /* !ST25R391X_COM_SINGLETXRX */
|
||
|
|
||
|
if ((reg <= ST25R3911_REG_OP_CONTROL) && ((reg+length) >= ST25R3911_REG_OP_CONTROL))
|
||
|
{
|
||
|
st25r3911CheckFieldSetLED(values[ST25R3911_REG_OP_CONTROL-reg]);
|
||
|
}
|
||
|
|
||
|
if (length > 0U)
|
||
|
{
|
||
|
/* make this operation atomic */
|
||
|
platformProtectST25R391xComm();
|
||
|
platformSpiSelect();
|
||
|
|
||
|
#ifdef ST25R391X_COM_SINGLETXRX
|
||
|
|
||
|
comBuf[0] = (reg | ST25R3911_WRITE_MODE);
|
||
|
ST_MEMCPY( &comBuf[ST25R3911_CMD_LEN], values, MIN( length, ST25R3911_BUF_LEN - ST25R3911_CMD_LEN ) );
|
||
|
|
||
|
platformSpiTxRx( comBuf, NULL, MIN( (ST25R3911_CMD_LEN + length), ST25R3911_BUF_LEN ) );
|
||
|
|
||
|
#else /*ST25R391X_COM_SINGLETXRX*/
|
||
|
|
||
|
platformSpiTxRx( &cmd, NULL, ST25R3911_CMD_LEN );
|
||
|
platformSpiTxRx( values, NULL, length );
|
||
|
|
||
|
#endif /*ST25R391X_COM_SINGLETXRX*/
|
||
|
|
||
|
platformSpiDeselect();
|
||
|
platformUnprotectST25R391xComm();
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
void st25r3911WriteFifo(const uint8_t* values, uint8_t length)
|
||
|
{
|
||
|
#if !defined(ST25R391X_COM_SINGLETXRX)
|
||
|
uint8_t cmd = ST25R3911_FIFO_LOAD;
|
||
|
#endif /* !ST25R391X_COM_SINGLETXRX */
|
||
|
|
||
|
if (length > 0U)
|
||
|
{
|
||
|
platformProtectST25R391xComm();
|
||
|
platformSpiSelect();
|
||
|
|
||
|
#ifdef ST25R391X_COM_SINGLETXRX
|
||
|
|
||
|
comBuf[0] = ST25R3911_FIFO_LOAD;
|
||
|
ST_MEMCPY( &comBuf[ST25R3911_CMD_LEN], values, MIN( length, ST25R3911_BUF_LEN - ST25R3911_CMD_LEN ) );
|
||
|
|
||
|
platformSpiTxRx( comBuf, NULL, MIN( (ST25R3911_CMD_LEN + length), ST25R3911_BUF_LEN ) );
|
||
|
|
||
|
#else /*ST25R391X_COM_SINGLETXRX*/
|
||
|
|
||
|
platformSpiTxRx( &cmd, NULL, ST25R3911_CMD_LEN );
|
||
|
platformSpiTxRx( values, NULL, length );
|
||
|
|
||
|
#endif /*ST25R391X_COM_SINGLETXRX*/
|
||
|
|
||
|
platformSpiDeselect();
|
||
|
platformUnprotectST25R391xComm();
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
void st25r3911ReadFifo(uint8_t* buf, uint8_t length)
|
||
|
{
|
||
|
#if !defined(ST25R391X_COM_SINGLETXRX)
|
||
|
uint8_t cmd = ST25R3911_FIFO_READ;
|
||
|
#endif /* !ST25R391X_COM_SINGLETXRX */
|
||
|
|
||
|
if(length > 0U)
|
||
|
{
|
||
|
platformProtectST25R391xComm();
|
||
|
platformSpiSelect();
|
||
|
|
||
|
#ifdef ST25R391X_COM_SINGLETXRX
|
||
|
|
||
|
ST_MEMSET( comBuf, 0x00, MIN( (ST25R3911_CMD_LEN + (uint32_t)length), ST25R3911_BUF_LEN ) );
|
||
|
comBuf[0] = ST25R3911_FIFO_READ;
|
||
|
|
||
|
platformSpiTxRx( comBuf, comBuf, MIN( (ST25R3911_CMD_LEN + length), ST25R3911_BUF_LEN ) ); /* Transceive as a single SPI call */
|
||
|
ST_MEMCPY( buf, &comBuf[ST25R3911_CMD_LEN], MIN( length, ST25R3911_BUF_LEN - ST25R3911_CMD_LEN ) ); /* Copy from local buf to output buffer and skip cmd byte */
|
||
|
|
||
|
#else /*ST25R391X_COM_SINGLETXRX*/
|
||
|
|
||
|
platformSpiTxRx( &cmd, NULL, ST25R3911_CMD_LEN );
|
||
|
platformSpiTxRx( NULL, buf, length );
|
||
|
|
||
|
#endif /*ST25R391X_COM_SINGLETXRX*/
|
||
|
|
||
|
platformSpiDeselect();
|
||
|
platformUnprotectST25R391xComm();
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
void st25r3911ExecuteCommand( uint8_t cmd )
|
||
|
{
|
||
|
uint8_t tmpCmd; /* MISRA 17.8 */
|
||
|
|
||
|
#ifdef PLATFORM_LED_FIELD_PIN
|
||
|
if ( (cmd >= ST25R3911_CMD_TRANSMIT_WITH_CRC) && (cmd <= ST25R3911_CMD_RESPONSE_RF_COLLISION_0))
|
||
|
{
|
||
|
platformLedOff(PLATFORM_LED_FIELD_PORT, PLATFORM_LED_FIELD_PIN);
|
||
|
}
|
||
|
#endif /* PLATFORM_LED_FIELD_PIN */
|
||
|
|
||
|
tmpCmd = (cmd | ST25R3911_CMD_MODE);
|
||
|
|
||
|
platformProtectST25R391xComm();
|
||
|
platformSpiSelect();
|
||
|
|
||
|
platformSpiTxRx( &tmpCmd, NULL, ST25R3911_CMD_LEN );
|
||
|
|
||
|
platformSpiDeselect();
|
||
|
platformUnprotectST25R391xComm();
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
void st25r3911ExecuteCommands(const uint8_t *cmds, uint8_t length)
|
||
|
{
|
||
|
platformProtectST25R391xComm();
|
||
|
platformSpiSelect();
|
||
|
|
||
|
platformSpiTxRx( cmds, NULL, length );
|
||
|
|
||
|
platformSpiDeselect();
|
||
|
platformUnprotectST25R391xComm();
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
bool st25r3911IsRegValid( uint8_t reg )
|
||
|
{
|
||
|
if( !(( (int16_t)reg >= (int16_t)ST25R3911_REG_IO_CONF1) && (reg <= ST25R3911_REG_CAPACITANCE_MEASURE_RESULT)) && (reg != ST25R3911_REG_IC_IDENTITY) )
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
******************************************************************************
|
||
|
* LOCAL FUNCTIONS
|
||
|
******************************************************************************
|
||
|
*/
|
||
|
|