/******************************************************************************
* \attention
*
*
© COPYRIGHT 2020 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:
*
* 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: ST25R391x firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file rfal_analogConfig.c
*
* \author bkam
*
* \brief Funcitons to manage and set analog settings.
*
*/
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "rfal_analogConfig.h"
#include "rfal_chip.h"
#include "st_errno.h"
#include "platform.h"
#include "utils.h"
/* Check whether the Default Analog settings are to be used or custom ones */
#ifdef RFAL_ANALOG_CONFIG_CUSTOM
extern const uint8_t* rfalAnalogConfigCustomSettings;
extern const uint16_t rfalAnalogConfigCustomSettingsLength;
#else
#include "rfal_analogConfigTbl.h"
#endif
/*
******************************************************************************
* DEFINES
******************************************************************************
*/
#define RFAL_TEST_REG 0x0080U /*!< Test Register indicator */
/*
******************************************************************************
* MACROS
******************************************************************************
*/
/*
******************************************************************************
* LOCAL DATA TYPES
******************************************************************************
*/
#if RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG
static uint8_t
gRfalAnalogConfig[RFAL_ANALOG_CONFIG_TBL_SIZE]; /*!< Analog Configuration Settings List */
#endif /* RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG */
/*! Struct for Analog Config Look Up Table Update */
typedef struct {
const uint8_t*
currentAnalogConfigTbl; /*!< Reference to start of current Analog Configuration */
uint16_t configTblSize; /*!< Total size of Analog Configuration */
bool ready; /*!< Indicate if Look Up Table is complete and ready for use */
} rfalAnalogConfigMgmt;
static rfalAnalogConfigMgmt gRfalAnalogConfigMgmt; /*!< Analog Configuration LUT management */
/*
******************************************************************************
* LOCAL TABLES
******************************************************************************
*/
/*
******************************************************************************
* LOCAL FUNCTION PROTOTYPES
******************************************************************************
*/
static rfalAnalogConfigNum
rfalAnalogConfigSearch(rfalAnalogConfigId configId, uint16_t* configOffset);
#if RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG
static void rfalAnalogConfigPtrUpdate(const uint8_t* analogConfigTbl);
#endif /* RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG */
/*
******************************************************************************
* GLOBAL VARIABLE DEFINITIONS
******************************************************************************
*/
/*
******************************************************************************
* GLOBAL FUNCTIONS
******************************************************************************
*/
void rfalAnalogConfigInitialize(void) {
/* Use default Analog configuration settings in Flash by default. */
/* Check whether the Default Analog settings are to be used or custom ones */
#ifdef RFAL_ANALOG_CONFIG_CUSTOM
gRfalAnalogConfigMgmt.currentAnalogConfigTbl = (const uint8_t*)&rfalAnalogConfigCustomSettings;
gRfalAnalogConfigMgmt.configTblSize = rfalAnalogConfigCustomSettingsLength;
#else
gRfalAnalogConfigMgmt.currentAnalogConfigTbl =
(const uint8_t*)&rfalAnalogConfigDefaultSettings;
gRfalAnalogConfigMgmt.configTblSize = sizeof(rfalAnalogConfigDefaultSettings);
#endif
gRfalAnalogConfigMgmt.ready = true;
} /* rfalAnalogConfigInitialize() */
bool rfalAnalogConfigIsReady(void) {
return gRfalAnalogConfigMgmt.ready;
}
ReturnCode rfalAnalogConfigListWriteRaw(const uint8_t* configTbl, uint16_t configTblSize) {
#if RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG
/* Check if the Configuration Table exceed the Table size */
if(configTblSize >= RFAL_ANALOG_CONFIG_TBL_SIZE) {
rfalAnalogConfigInitialize(); /* Revert to default Analog Configuration */
return ERR_NOMEM;
}
/* Check for invalid parameters */
if((configTbl == NULL) || (configTblSize == 0U)) {
return ERR_PARAM;
}
/* NOTE: Function does not check for the validity of the Table contents (conf IDs, conf sets, register address) */
ST_MEMCPY(gRfalAnalogConfig, configTbl, configTblSize);
/* Update the total size of configuration settings */
gRfalAnalogConfigMgmt.configTblSize = configTblSize;
rfalAnalogConfigPtrUpdate(gRfalAnalogConfig);
return ERR_NONE;
#else
// If Analog Configuration Update is to be disabled
NO_WARNING(configTbl);
NO_WARNING(configTblSize);
return ERR_REQUEST;
#endif /* RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG */
}
ReturnCode rfalAnalogConfigListWrite(uint8_t more, const rfalAnalogConfig* config) {
#if RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG
rfalAnalogConfigId configId;
rfalAnalogConfigNum numConfig;
uint8_t configSize;
if(true == gRfalAnalogConfigMgmt.ready) { /* First Update to the Configuration list. */
gRfalAnalogConfigMgmt.ready = false; // invalidate the config List
gRfalAnalogConfigMgmt.configTblSize = 0; // Clear the config List
}
configId = GETU16(config->id);
/* Check validity of the Configuration ID. */
if((RFAL_ANALOG_CONFIG_TECH_RFU <= RFAL_ANALOG_CONFIG_ID_GET_TECH(configId)) ||
((RFAL_ANALOG_CONFIG_BITRATE_6780 < RFAL_ANALOG_CONFIG_ID_GET_BITRATE(configId)) &&
(RFAL_ANALOG_CONFIG_BITRATE_1OF4 > RFAL_ANALOG_CONFIG_ID_GET_BITRATE(configId))) ||
(RFAL_ANALOG_CONFIG_BITRATE_1OF256 < RFAL_ANALOG_CONFIG_ID_GET_BITRATE(configId))) {
rfalAnalogConfigInitialize(); /* Revert to default Analog Configuration */
return ERR_PARAM;
}
numConfig = config->num;
configSize =
(uint8_t)(sizeof(rfalAnalogConfigId) + sizeof(rfalAnalogConfigNum) + (numConfig * sizeof(rfalAnalogConfigRegAddrMaskVal)));
/* Check if the Configuration Set exceed the Table size. */
if(RFAL_ANALOG_CONFIG_TBL_SIZE <= (gRfalAnalogConfigMgmt.configTblSize + configSize)) {
rfalAnalogConfigInitialize(); /* Revert to default Analog Configuration */
return ERR_NOMEM;
}
/* NOTE: Function does not check for the validity of the Register Address. */
ST_MEMCPY(
&gRfalAnalogConfig[gRfalAnalogConfigMgmt.configTblSize],
(const uint8_t*)config,
configSize);
/* Increment the total size of configuration settings. */
gRfalAnalogConfigMgmt.configTblSize += configSize;
/* Check if it is the last Analog Configuration to load. */
if(RFAL_ANALOG_CONFIG_UPDATE_LAST ==
more) { /* Update the Analog Configuration to the new settings. */
rfalAnalogConfigPtrUpdate(gRfalAnalogConfig);
}
return ERR_NONE;
#else
// If Analog Configuration Update is to be disabled
NO_WARNING(config);
NO_WARNING(more);
return ERR_DISABLED;
#endif /* RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG */
} /* rfalAnalogConfigListUpdate() */
ReturnCode
rfalAnalogConfigListReadRaw(uint8_t* tblBuf, uint16_t tblBufLen, uint16_t* configTblSize) {
/* Check if the the current table will fit into the given buffer */
if(tblBufLen < gRfalAnalogConfigMgmt.configTblSize) {
return ERR_NOMEM;
}
/* Check for invalid parameters */
if(configTblSize == NULL) {
return ERR_PARAM;
}
/* Copy the whole Table to the given buffer */
if(gRfalAnalogConfigMgmt.configTblSize > 0U) /* MISRA 21.18 */
{
ST_MEMCPY(
tblBuf,
gRfalAnalogConfigMgmt.currentAnalogConfigTbl,
gRfalAnalogConfigMgmt.configTblSize);
}
*configTblSize = gRfalAnalogConfigMgmt.configTblSize;
return ERR_NONE;
}
ReturnCode rfalAnalogConfigListRead(
rfalAnalogConfigOffset* configOffset,
uint8_t* more,
rfalAnalogConfig* config,
rfalAnalogConfigNum numConfig) {
uint16_t configSize;
rfalAnalogConfigOffset offset = *configOffset;
rfalAnalogConfigNum numConfigSet;
/* Check if the number of register-mask-value settings for the respective Configuration ID will fit into the buffer passed in. */
if(gRfalAnalogConfigMgmt.currentAnalogConfigTbl[offset + sizeof(rfalAnalogConfigId)] >
numConfig) {
return ERR_NOMEM;
}
/* Get the number of Configuration set */
numConfigSet =
gRfalAnalogConfigMgmt.currentAnalogConfigTbl[offset + sizeof(rfalAnalogConfigId)];
/* Pass Configuration Register-Mask-Value sets */
configSize =
(sizeof(rfalAnalogConfigId) + sizeof(rfalAnalogConfigNum) +
(uint16_t)(numConfigSet * sizeof(rfalAnalogConfigRegAddrMaskVal)));
ST_MEMCPY((uint8_t*)config, &gRfalAnalogConfigMgmt.currentAnalogConfigTbl[offset], configSize);
*configOffset = offset + configSize;
/* Check if it is the last Analog Configuration in the Table.*/
*more =
(uint8_t)((*configOffset >= gRfalAnalogConfigMgmt.configTblSize) ? RFAL_ANALOG_CONFIG_UPDATE_LAST : RFAL_ANALOG_CONFIG_UPDATE_MORE);
return ERR_NONE;
} /* rfalAnalogConfigListRead() */
ReturnCode rfalSetAnalogConfig(rfalAnalogConfigId configId) {
rfalAnalogConfigOffset configOffset = 0;
rfalAnalogConfigNum numConfigSet;
const rfalAnalogConfigRegAddrMaskVal* configTbl;
ReturnCode retCode = ERR_NONE;
rfalAnalogConfigNum i;
if(true != gRfalAnalogConfigMgmt.ready) {
return ERR_REQUEST;
}
/* Search LUT for the specific Configuration ID. */
while(true) {
numConfigSet = rfalAnalogConfigSearch(configId, &configOffset);
if(RFAL_ANALOG_CONFIG_LUT_NOT_FOUND == numConfigSet) {
break;
}
configTbl =
(rfalAnalogConfigRegAddrMaskVal*)((uint32_t)gRfalAnalogConfigMgmt.currentAnalogConfigTbl + (uint32_t)configOffset);
/* Increment the offset to the next index to search from. */
configOffset += (uint16_t)(numConfigSet * sizeof(rfalAnalogConfigRegAddrMaskVal));
if((gRfalAnalogConfigMgmt.configTblSize + 1U) <
configOffset) { /* Error check make sure that the we do not access outside the configuration Table Size */
return ERR_NOMEM;
}
for(i = 0; i < numConfigSet; i++) {
if((GETU16(configTbl[i].addr) & RFAL_TEST_REG) != 0U) {
EXIT_ON_ERR(
retCode,
rfalChipChangeTestRegBits(
(GETU16(configTbl[i].addr) & ~RFAL_TEST_REG),
configTbl[i].mask,
configTbl[i].val));
} else {
EXIT_ON_ERR(
retCode,
rfalChipChangeRegBits(
GETU16(configTbl[i].addr), configTbl[i].mask, configTbl[i].val));
}
}
} /* while(found Analog Config Id) */
return retCode;
} /* rfalSetAnalogConfig() */
uint16_t rfalAnalogConfigGenModeID(rfalMode md, rfalBitRate br, uint16_t dir) {
uint16_t id;
/* Assign Poll/Listen Mode */
id = ((md >= RFAL_MODE_LISTEN_NFCA) ? RFAL_ANALOG_CONFIG_LISTEN : RFAL_ANALOG_CONFIG_POLL);
/* Assign Technology */
switch(md) {
case RFAL_MODE_POLL_NFCA:
case RFAL_MODE_POLL_NFCA_T1T:
case RFAL_MODE_LISTEN_NFCA:
id |= RFAL_ANALOG_CONFIG_TECH_NFCA;
break;
case RFAL_MODE_POLL_NFCB:
case RFAL_MODE_POLL_B_PRIME:
case RFAL_MODE_POLL_B_CTS:
case RFAL_MODE_LISTEN_NFCB:
id |= RFAL_ANALOG_CONFIG_TECH_NFCB;
break;
case RFAL_MODE_POLL_NFCF:
case RFAL_MODE_LISTEN_NFCF:
id |= RFAL_ANALOG_CONFIG_TECH_NFCF;
break;
case RFAL_MODE_POLL_NFCV:
case RFAL_MODE_POLL_PICOPASS:
id |= RFAL_ANALOG_CONFIG_TECH_NFCV;
break;
case RFAL_MODE_POLL_ACTIVE_P2P:
case RFAL_MODE_LISTEN_ACTIVE_P2P:
id |= RFAL_ANALOG_CONFIG_TECH_AP2P;
break;
default:
id = RFAL_ANALOG_CONFIG_TECH_CHIP;
break;
}
/* Assign Bitrate */
id |=
(((((uint16_t)(br) >= (uint16_t)RFAL_BR_52p97) ? (uint16_t)(br) : ((uint16_t)(br) + 1U))
<< RFAL_ANALOG_CONFIG_BITRATE_SHIFT) &
RFAL_ANALOG_CONFIG_BITRATE_MASK);
/* Assign Direction */
id |= ((dir << RFAL_ANALOG_CONFIG_DIRECTION_SHIFT) & RFAL_ANALOG_CONFIG_DIRECTION_MASK);
return id;
} /* rfalAnalogConfigGenModeID() */
/*
******************************************************************************
* LOCAL FUNCTIONS
******************************************************************************
*/
/*!
*****************************************************************************
* \brief Update the link to Analog Configuration LUT
*
* Update the link to the Analog Configuration LUT for the subsequent search
* of Analog Settings.
*
* \param[in] analogConfigTbl: reference to the start of the new Analog Configuration Table
*
*****************************************************************************
*/
#if RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG
static void rfalAnalogConfigPtrUpdate(const uint8_t* analogConfigTbl) {
gRfalAnalogConfigMgmt.currentAnalogConfigTbl = analogConfigTbl;
gRfalAnalogConfigMgmt.ready = true;
} /* rfalAnalogConfigPtrUpdate() */
#endif /* RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG */
/*!
*****************************************************************************
* \brief Search the Analog Configuration LUT for a specific Configuration ID.
*
* Search the Analog Configuration LUT for the Configuration ID.
*
* \param[in] configId: Configuration ID to search for.
* \param[in] configOffset: Configuration Offset in Table
*
* \return number of Configuration Sets
* \return #RFAL_ANALOG_CONFIG_LUT_NOT_FOUND in case Configuration ID is not found.
*****************************************************************************
*/
static rfalAnalogConfigNum
rfalAnalogConfigSearch(rfalAnalogConfigId configId, uint16_t* configOffset) {
rfalAnalogConfigId foundConfigId;
rfalAnalogConfigId configIdMaskVal;
const uint8_t* configTbl;
const uint8_t* currentConfigTbl;
uint16_t i;
currentConfigTbl = gRfalAnalogConfigMgmt.currentAnalogConfigTbl;
configIdMaskVal =
((RFAL_ANALOG_CONFIG_POLL_LISTEN_MODE_MASK | RFAL_ANALOG_CONFIG_BITRATE_MASK) |
((RFAL_ANALOG_CONFIG_TECH_CHIP == RFAL_ANALOG_CONFIG_ID_GET_TECH(configId)) ?
(RFAL_ANALOG_CONFIG_TECH_MASK | RFAL_ANALOG_CONFIG_CHIP_SPECIFIC_MASK) :
configId) |
((RFAL_ANALOG_CONFIG_NO_DIRECTION == RFAL_ANALOG_CONFIG_ID_GET_DIRECTION(configId)) ?
RFAL_ANALOG_CONFIG_DIRECTION_MASK :
configId));
/* When specific ConfigIDs are to be used, override search mask */
if((RFAL_ANALOG_CONFIG_ID_GET_DIRECTION(configId) == RFAL_ANALOG_CONFIG_DPO)) {
configIdMaskVal =
(RFAL_ANALOG_CONFIG_POLL_LISTEN_MODE_MASK | RFAL_ANALOG_CONFIG_TECH_MASK |
RFAL_ANALOG_CONFIG_BITRATE_MASK | RFAL_ANALOG_CONFIG_DIRECTION_MASK);
}
i = *configOffset;
while(i < gRfalAnalogConfigMgmt.configTblSize) {
configTbl = ¤tConfigTbl[i];
foundConfigId = GETU16(configTbl);
if(configId == (foundConfigId & configIdMaskVal)) {
*configOffset =
(uint16_t)(i + sizeof(rfalAnalogConfigId) + sizeof(rfalAnalogConfigNum));
return configTbl[sizeof(rfalAnalogConfigId)];
}
/* If Config Id does not match, increment to next Configuration Id */
i +=
(uint16_t)(sizeof(rfalAnalogConfigId) + sizeof(rfalAnalogConfigNum) + (configTbl[sizeof(rfalAnalogConfigId)] * sizeof(rfalAnalogConfigRegAddrMaskVal)));
} /* for */
return RFAL_ANALOG_CONFIG_LUT_NOT_FOUND;
} /* rfalAnalogConfigSearch() */