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