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