/****************************************************************************** * @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: * * 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. * ******************************************************************************/ /* * PROJECT: ST25R391x firmware * $Revision: $ * LANGUAGE: ISO C99 */ /*! \file rfal_dpo.c * * \author Martin Zechleitner * * \brief Functions to manage and set dynamic power settings. * */ /* ****************************************************************************** * INCLUDES ****************************************************************************** */ #include "rfal_dpoTbl.h" #include "rfal_dpo.h" #include "platform.h" #include "rfal_rf.h" #include "rfal_chip.h" #include "rfal_analogConfig.h" #include "utils.h" /* ****************************************************************************** * ENABLE SWITCH ****************************************************************************** */ #ifndef RFAL_FEATURE_DPO #define RFAL_FEATURE_DPO \ false /* Dynamic Power Module configuration missing. Disabled by default */ #endif #if RFAL_FEATURE_DPO /* ****************************************************************************** * DEFINES ****************************************************************************** */ #define RFAL_DPO_ANALOGCONFIG_SHIFT 13U #define RFAL_DPO_ANALOGCONFIG_MASK 0x6000U /* ****************************************************************************** * LOCAL DATA TYPES ****************************************************************************** */ static bool gRfalDpoIsEnabled = false; static uint8_t* gRfalCurrentDpo; static uint8_t gRfalDpoTableEntries; static uint8_t gRfalDpo[RFAL_DPO_TABLE_SIZE_MAX]; static uint8_t gRfalDpoTableEntry; static rfalDpoMeasureFunc gRfalDpoMeasureCallback = NULL; /* ****************************************************************************** * GLOBAL FUNCTIONS ****************************************************************************** */ void rfalDpoInitialize(void) { /* Use the default Dynamic Power values */ gRfalCurrentDpo = (uint8_t*)rfalDpoDefaultSettings; gRfalDpoTableEntries = (sizeof(rfalDpoDefaultSettings) / RFAL_DPO_TABLE_PARAMETER); ST_MEMCPY(gRfalDpo, gRfalCurrentDpo, sizeof(rfalDpoDefaultSettings)); /* by default use amplitude measurement */ gRfalDpoMeasureCallback = rfalChipMeasureAmplitude; /* by default DPO is disabled */ gRfalDpoIsEnabled = false; gRfalDpoTableEntry = 0; } void rfalDpoSetMeasureCallback(rfalDpoMeasureFunc pMeasureFunc) { gRfalDpoMeasureCallback = pMeasureFunc; } /*******************************************************************************/ ReturnCode rfalDpoTableWrite(rfalDpoEntry* powerTbl, uint8_t powerTblEntries) { uint8_t entry = 0; /* check if the table size parameter is too big */ if((powerTblEntries * RFAL_DPO_TABLE_PARAMETER) > RFAL_DPO_TABLE_SIZE_MAX) { return ERR_NOMEM; } /* check if the first increase entry is 0xFF */ if((powerTblEntries == 0) || (powerTbl == NULL)) { return ERR_PARAM; } /* check if the entries of the dynamic power table are valid */ for(entry = 0; entry < powerTblEntries; entry++) { if(powerTbl[entry].inc < powerTbl[entry].dec) { return ERR_PARAM; } } /* copy the data set */ ST_MEMCPY(gRfalDpo, powerTbl, (powerTblEntries * RFAL_DPO_TABLE_PARAMETER)); gRfalCurrentDpo = gRfalDpo; gRfalDpoTableEntries = powerTblEntries; if(gRfalDpoTableEntry > powerTblEntries) { /* is always greater then zero, otherwise we already returned ERR_PARAM */ gRfalDpoTableEntry = (powerTblEntries - 1); } return ERR_NONE; } /*******************************************************************************/ ReturnCode rfalDpoTableRead(rfalDpoEntry* tblBuf, uint8_t tblBufEntries, uint8_t* tableEntries) { /* wrong request */ if((tblBuf == NULL) || (tblBufEntries < gRfalDpoTableEntries) || (tableEntries == NULL)) { return ERR_PARAM; } /* Copy the whole Table to the given buffer */ ST_MEMCPY(tblBuf, gRfalCurrentDpo, (tblBufEntries * RFAL_DPO_TABLE_PARAMETER)); *tableEntries = gRfalDpoTableEntries; return ERR_NONE; } /*******************************************************************************/ ReturnCode rfalDpoAdjust(void) { uint8_t refValue = 0; uint16_t modeID; rfalBitRate br; rfalDpoEntry* dpoTable = (rfalDpoEntry*)gRfalCurrentDpo; /* Check if the Power Adjustment is disabled and * * if the callback to the measurement method is properly set */ if((gRfalCurrentDpo == NULL) || (!gRfalDpoIsEnabled) || (gRfalDpoMeasureCallback == NULL)) { return ERR_PARAM; } /* Ensure that the current mode is Passive Poller */ if(!rfalIsModePassivePoll(rfalGetMode())) { return ERR_WRONG_STATE; } /* Ensure a proper measure reference value */ if(ERR_NONE != gRfalDpoMeasureCallback(&refValue)) { return ERR_IO; } if(refValue >= dpoTable[gRfalDpoTableEntry].inc) { /* Increase the output power */ /* the top of the table represents the highest amplitude value*/ if(gRfalDpoTableEntry == 0) { /* maximum driver value has been reached */ } else { /* go up in the table to decrease the driver resistance */ gRfalDpoTableEntry--; } } else if(refValue <= dpoTable[gRfalDpoTableEntry].dec) { /* decrease the output power */ /* The bottom is the highest possible value */ if((gRfalDpoTableEntry + 1) >= gRfalDpoTableEntries) { /* minimum driver value has been reached */ } else { /* go down in the table to increase the driver resistance */ gRfalDpoTableEntry++; } } else { /* Fall through to always write dpo and its associated analog configs */ } /* Get the new value for RFO resistance form the table and apply the new RFO resistance setting */ rfalChipSetRFO(dpoTable[gRfalDpoTableEntry].rfoRes); /* Apply the DPO Analog Config according to this treshold */ /* Technology field is being extended for DPO: 2msb are used for treshold step (only 4 allowed) */ rfalGetBitRate(&br, NULL); /* Obtain current Tx bitrate */ modeID = rfalAnalogConfigGenModeID( rfalGetMode(), br, RFAL_ANALOG_CONFIG_DPO); /* Generate Analog Config mode ID */ modeID |= ((gRfalDpoTableEntry << RFAL_DPO_ANALOGCONFIG_SHIFT) & RFAL_DPO_ANALOGCONFIG_MASK); /* Add DPO treshold step|level */ rfalSetAnalogConfig(modeID); /* Apply DPO Analog Config */ return ERR_NONE; } /*******************************************************************************/ rfalDpoEntry* rfalDpoGetCurrentTableEntry(void) { rfalDpoEntry* dpoTable = (rfalDpoEntry*)gRfalCurrentDpo; return &dpoTable[gRfalDpoTableEntry]; } /*******************************************************************************/ void rfalDpoSetEnabled(bool enable) { gRfalDpoIsEnabled = enable; } /*******************************************************************************/ bool rfalDpoIsEnabled(void) { return gRfalDpoIsEnabled; } #endif /* RFAL_FEATURE_DPO */