330 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			330 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/******************************************************************************
 | 
						|
  * \attention
 | 
						|
  *
 | 
						|
  * <h2><center>© COPYRIGHT 2020 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:   ST25R3916 firmware
 | 
						|
 *      Revision: 
 | 
						|
 *      LANGUAGE:  ISO C99
 | 
						|
 */
 | 
						|
 | 
						|
/*! \file st25r3916_aat.c
 | 
						|
 *
 | 
						|
 *  \author 
 | 
						|
 *
 | 
						|
 *  \brief ST25R3916 Antenna Tuning 
 | 
						|
 *
 | 
						|
 * The antenna tuning algorithm tries to find the optimal settings for 
 | 
						|
 * the AAT_A and AAT_B registers, which are connected to variable capacitors 
 | 
						|
 * to tune the antenna matching.
 | 
						|
 *
 | 
						|
 */
 | 
						|
 
 | 
						|
 
 | 
						|
/*
 | 
						|
******************************************************************************
 | 
						|
* INCLUDES
 | 
						|
******************************************************************************
 | 
						|
*/
 | 
						|
#include "st25r3916_aat.h"
 | 
						|
#include "utils.h"
 | 
						|
#include "st_errno.h"
 | 
						|
#include "st25r3916.h"
 | 
						|
#include "st25r3916_com.h"
 | 
						|
#include "platform.h"
 | 
						|
#include "rfal_chip.h"
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
******************************************************************************
 | 
						|
* GLOBAL DEFINES
 | 
						|
******************************************************************************
 | 
						|
*/
 | 
						|
#define ST25R3916_AAT_CAP_DELAY_MAX           10                  /*!< Max Variable Capacitor settle delay */
 | 
						|
 | 
						|
/*
 | 
						|
******************************************************************************
 | 
						|
* GLOBAL MACROS
 | 
						|
******************************************************************************
 | 
						|
*/
 | 
						|
#define st25r3916AatLog(...)     /* platformLog(__VA_ARGS__) */   /*!< Logging macro */
 | 
						|
 | 
						|
/*
 | 
						|
******************************************************************************
 | 
						|
* LOCAL FUNCTION PROTOTYPES
 | 
						|
******************************************************************************
 | 
						|
*/
 | 
						|
static ReturnCode aatHillClimb(const struct st25r3916AatTuneParams *tuningParams, struct st25r3916AatTuneResult *tuningStatus);
 | 
						|
static int32_t aatGreedyDescent(uint32_t *f_min, const struct st25r3916AatTuneParams *tuningParams, struct st25r3916AatTuneResult *tuningStatus, int32_t previousDir);
 | 
						|
static int32_t aatSteepestDescent(uint32_t *f_min, const struct st25r3916AatTuneParams *tuningParams, struct st25r3916AatTuneResult *tuningStatus, int32_t previousDir, int32_t previousDir2);
 | 
						|
 | 
						|
static ReturnCode aatMeasure(uint8_t serCap, uint8_t parCap, uint8_t *amplitude, uint8_t *phase, uint16_t *measureCnt);
 | 
						|
static uint32_t aatCalcF(const struct st25r3916AatTuneParams *tuningParams, uint8_t amplitude, uint8_t phase);
 | 
						|
static ReturnCode aatStepDacVals(const struct st25r3916AatTuneParams *tuningParams,uint8_t *a, uint8_t *b, int32_t dir);
 | 
						|
 | 
						|
 | 
						|
 
 | 
						|
 | 
						|
/*******************************************************************************/
 | 
						|
ReturnCode st25r3916AatTune(const struct st25r3916AatTuneParams *tuningParams, struct st25r3916AatTuneResult *tuningStatus)
 | 
						|
{
 | 
						|
    ReturnCode err;
 | 
						|
    const struct st25r3916AatTuneParams *tp = tuningParams;
 | 
						|
    struct st25r3916AatTuneResult *ts = tuningStatus;
 | 
						|
    struct st25r3916AatTuneParams defaultTuningParams = 
 | 
						|
    {
 | 
						|
        .aat_a_min=0,
 | 
						|
        .aat_a_max=255,
 | 
						|
        .aat_a_start=127,
 | 
						|
        .aat_a_stepWidth=32,
 | 
						|
        .aat_b_min=0,
 | 
						|
        .aat_b_max=255,
 | 
						|
        .aat_b_start=127,
 | 
						|
        .aat_b_stepWidth=32,
 | 
						|
 | 
						|
        .phaTarget=128,
 | 
						|
        .phaWeight=2,
 | 
						|
        .ampTarget=196,
 | 
						|
        .ampWeight=1,
 | 
						|
 | 
						|
        .doDynamicSteps=true,
 | 
						|
        .measureLimit=50,
 | 
						|
    };
 | 
						|
    struct st25r3916AatTuneResult defaultTuneResult;
 | 
						|
    
 | 
						|
    if ((NULL != tp) && (
 | 
						|
          (tp->aat_a_min > tp->aat_a_max   )
 | 
						|
       || (tp->aat_a_start < tp->aat_a_min )
 | 
						|
       || (tp->aat_a_start > tp->aat_a_max )
 | 
						|
       || (tp->aat_b_min > tp->aat_b_max   )
 | 
						|
       || (tp->aat_b_start < tp->aat_b_min )
 | 
						|
       || (tp->aat_b_start > tp->aat_b_max )
 | 
						|
       ))
 | 
						|
    {
 | 
						|
        return ERR_PARAM;
 | 
						|
    }
 | 
						|
 | 
						|
    if (NULL == tp)
 | 
						|
    { /* Start from current caps with default params */
 | 
						|
        st25r3916ReadRegister(ST25R3916_REG_ANT_TUNE_A, &defaultTuningParams.aat_a_start);
 | 
						|
        st25r3916ReadRegister(ST25R3916_REG_ANT_TUNE_B, &defaultTuningParams.aat_b_start);
 | 
						|
        tp = &defaultTuningParams;
 | 
						|
    }
 | 
						|
 | 
						|
    if (NULL == ts){ts = &defaultTuneResult;}
 | 
						|
 | 
						|
    ts->measureCnt = 0; /* Clear current measure count */
 | 
						|
 
 | 
						|
    err = aatHillClimb(tp, ts);
 | 
						|
 | 
						|
    return err;
 | 
						|
}
 | 
						|
 | 
						|
/*******************************************************************************/
 | 
						|
static ReturnCode aatHillClimb(const struct st25r3916AatTuneParams *tuningParams, struct st25r3916AatTuneResult *tuningStatus)
 | 
						|
{
 | 
						|
    ReturnCode  err = ERR_NONE;
 | 
						|
    uint32_t f_min;
 | 
						|
    int32_t direction, gdirection;
 | 
						|
    uint8_t amp,phs;
 | 
						|
    struct st25r3916AatTuneParams tp = *tuningParams; // local copy to obey const
 | 
						|
 | 
						|
    tuningStatus->aat_a = tuningParams->aat_a_start;
 | 
						|
    tuningStatus->aat_b = tuningParams->aat_b_start;
 | 
						|
 | 
						|
    /* Get a proper start value */
 | 
						|
    aatMeasure(tuningStatus->aat_a,tuningStatus->aat_b,&,&phs,&tuningStatus->measureCnt);
 | 
						|
    f_min = aatCalcF(&tp, amp, phs);
 | 
						|
    direction = 0;
 | 
						|
 | 
						|
    st25r3916AatLog("%d %d: %d***\n",tuningStatus->aat_a,tuningStatus->aat_b,f_min);
 | 
						|
 | 
						|
    do {
 | 
						|
        direction = 0; /* Initially and after reducing step sizes we don't have a previous direction */
 | 
						|
        do {
 | 
						|
            /* With the greedy step below always executed aftwards the -direction does never need to be investigated */
 | 
						|
            direction = aatSteepestDescent(&f_min, &tp, tuningStatus, direction, -direction);
 | 
						|
            if (tuningStatus->measureCnt > tp.measureLimit)
 | 
						|
            {
 | 
						|
                err = ERR_OVERRUN;
 | 
						|
                break;
 | 
						|
            }
 | 
						|
            do
 | 
						|
            {
 | 
						|
                gdirection = aatGreedyDescent(&f_min, &tp, tuningStatus, direction);
 | 
						|
                if (tuningStatus->measureCnt > tp.measureLimit) {
 | 
						|
                    err = ERR_OVERRUN;
 | 
						|
                    break;
 | 
						|
                }
 | 
						|
            } while (0 != gdirection);
 | 
						|
        } while (0 != direction);
 | 
						|
        tp.aat_a_stepWidth /= 2U; /* Reduce step sizes */
 | 
						|
        tp.aat_b_stepWidth /= 2U;
 | 
						|
    } while (tp.doDynamicSteps && ((tp.aat_a_stepWidth>0U) || (tp.aat_b_stepWidth>0U)));
 | 
						|
    
 | 
						|
    return err;
 | 
						|
}
 | 
						|
 | 
						|
/*******************************************************************************/
 | 
						|
static int32_t aatSteepestDescent(uint32_t *f_min, const struct st25r3916AatTuneParams *tuningParams, struct st25r3916AatTuneResult *tuningStatus, int32_t previousDir, int32_t previousDir2)
 | 
						|
{
 | 
						|
    int32_t i;
 | 
						|
    uint8_t amp,phs;
 | 
						|
    uint32_t f;
 | 
						|
    int32_t bestdir = 0; /* Negative direction: decrease, Positive: increase. (-)1: aat_a, (-)2: aat_b */
 | 
						|
 | 
						|
    for (i = -2; i <= 2; i++)
 | 
						|
    {
 | 
						|
        uint8_t a = tuningStatus->aat_a , b = tuningStatus->aat_b;
 | 
						|
 | 
						|
        if ((0==i) || (i==-previousDir) || (i==-previousDir2))
 | 
						|
        { /* Skip no direction and avoid going backwards */
 | 
						|
            continue;
 | 
						|
        }
 | 
						|
        if (0U!=aatStepDacVals(tuningParams, &a, &b, i))
 | 
						|
        { /* If stepping did not change the value, omit this direction */
 | 
						|
            continue;
 | 
						|
        }
 | 
						|
 | 
						|
        aatMeasure(a,b,&,&phs,&tuningStatus->measureCnt);
 | 
						|
        f = aatCalcF(tuningParams, amp, phs);
 | 
						|
        st25r3916AatLog("%d : %d %d: %d",i,a, b, f);
 | 
						|
        if (f < *f_min)
 | 
						|
        { /* Value is better than all previous ones */
 | 
						|
            st25r3916AatLog("*");
 | 
						|
            *f_min = f;
 | 
						|
            bestdir = i;
 | 
						|
        }
 | 
						|
        st25r3916AatLog("\n");
 | 
						|
    }
 | 
						|
    if (0!=bestdir) 
 | 
						|
    { /* Walk into the best direction */
 | 
						|
        aatStepDacVals(tuningParams, &tuningStatus->aat_a, &tuningStatus->aat_b, bestdir);
 | 
						|
    }
 | 
						|
    return bestdir;
 | 
						|
}
 | 
						|
 | 
						|
/*******************************************************************************/
 | 
						|
static int32_t aatGreedyDescent(uint32_t *f_min, const struct st25r3916AatTuneParams *tuningParams, struct st25r3916AatTuneResult *tuningStatus, int32_t previousDir)
 | 
						|
{
 | 
						|
    uint8_t amp,phs;
 | 
						|
    uint32_t f;
 | 
						|
    uint8_t a = tuningStatus->aat_a , b = tuningStatus->aat_b;
 | 
						|
 | 
						|
    if (0U != aatStepDacVals(tuningParams, &a, &b, previousDir))
 | 
						|
    { /* If stepping did not change the value, omit this direction */
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    aatMeasure(a,b,&,&phs,&tuningStatus->measureCnt);
 | 
						|
    f = aatCalcF(tuningParams, amp, phs);
 | 
						|
    st25r3916AatLog("g : %d %d: %d",a, b, f);
 | 
						|
    if (f < *f_min)
 | 
						|
    { /* Value is better than previous one */
 | 
						|
        st25r3916AatLog("*\n");
 | 
						|
        tuningStatus->aat_a = a;
 | 
						|
        tuningStatus->aat_b = b;
 | 
						|
        *f_min = f;
 | 
						|
        return previousDir;
 | 
						|
    }
 | 
						|
    
 | 
						|
    st25r3916AatLog("\n");
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
/*******************************************************************************/
 | 
						|
static uint32_t aatCalcF(const struct st25r3916AatTuneParams *tuningParams, uint8_t amplitude, uint8_t phase)
 | 
						|
{
 | 
						|
    /* f(amp, pha) = (ampWeight * |amp - ampTarget|) + (phaWeight * |pha - phaTarget|) */
 | 
						|
    uint8_t ampTarget = tuningParams->ampTarget;
 | 
						|
    uint8_t phaTarget = tuningParams->phaTarget;
 | 
						|
 | 
						|
    uint32_t ampWeight = tuningParams->ampWeight;
 | 
						|
    uint32_t phaWeight = tuningParams->phaWeight;
 | 
						|
 | 
						|
    /* Temp variables to avoid MISRA R10.8 (cast on composite expression) */
 | 
						|
    uint8_t ad = ((amplitude > ampTarget)  ? (amplitude - ampTarget) : (ampTarget - amplitude));
 | 
						|
    uint8_t pd = ((phase > phaTarget)      ? (phase - phaTarget)     : (phaTarget - phase));
 | 
						|
 | 
						|
    uint32_t ampDelta = (uint32_t)ad;
 | 
						|
    uint32_t phaDelta = (uint32_t)pd;
 | 
						|
 | 
						|
    return ((ampWeight * ampDelta) + (phaWeight * phaDelta));
 | 
						|
}
 | 
						|
 | 
						|
/*******************************************************************************/
 | 
						|
static ReturnCode aatStepDacVals(const struct st25r3916AatTuneParams *tuningParams,uint8_t *a, uint8_t *b, int32_t dir)
 | 
						|
{
 | 
						|
    int16_t aat_a = (int16_t)*a, aat_b = (int16_t)*b;
 | 
						|
    
 | 
						|
    switch (abs(dir))
 | 
						|
    { /* Advance by steps size in requested direction */
 | 
						|
        case 1:
 | 
						|
            aat_a = (dir<0)?(aat_a - (int16_t)tuningParams->aat_a_stepWidth):(aat_a + (int16_t)tuningParams->aat_a_stepWidth);
 | 
						|
            if(aat_a < (int16_t)tuningParams->aat_a_min){ aat_a = (int16_t)tuningParams->aat_a_min; }
 | 
						|
            if(aat_a > (int16_t)tuningParams->aat_a_max){ aat_a = (int16_t)tuningParams->aat_a_max; }
 | 
						|
            if ((int16_t)*a == aat_a) {return ERR_PARAM;}
 | 
						|
            break;
 | 
						|
        case 2:
 | 
						|
            aat_b = (dir<0)?(aat_b - (int16_t)tuningParams->aat_b_stepWidth):(aat_b + (int16_t)tuningParams->aat_b_stepWidth);
 | 
						|
            if(aat_b < (int16_t)tuningParams->aat_b_min){ aat_b = (int16_t)tuningParams->aat_b_min; }
 | 
						|
            if(aat_b > (int16_t)tuningParams->aat_b_max){ aat_b = (int16_t)tuningParams->aat_b_max; }
 | 
						|
            if ((int16_t)*b == aat_b) {return ERR_PARAM;}
 | 
						|
            break;
 | 
						|
        default:
 | 
						|
            return ERR_REQUEST;
 | 
						|
    }
 | 
						|
    /* We only get here if actual values have changed. In all other cases an error is returned */
 | 
						|
    *a = (uint8_t)aat_a; 
 | 
						|
    *b = (uint8_t)aat_b;
 | 
						|
    
 | 
						|
    return ERR_NONE;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
/*******************************************************************************/
 | 
						|
static ReturnCode aatMeasure(uint8_t serCap, uint8_t parCap, uint8_t *amplitude, uint8_t *phase, uint16_t *measureCnt)
 | 
						|
{
 | 
						|
    ReturnCode err;
 | 
						|
 | 
						|
    *amplitude = 0; 
 | 
						|
    *phase     = 0;
 | 
						|
 | 
						|
    st25r3916WriteRegister(ST25R3916_REG_ANT_TUNE_A, serCap);
 | 
						|
    st25r3916WriteRegister(ST25R3916_REG_ANT_TUNE_B, parCap);
 | 
						|
 | 
						|
    /* Wait till caps have settled.. */
 | 
						|
    platformDelay( ST25R3916_AAT_CAP_DELAY_MAX );
 | 
						|
    
 | 
						|
    /* Get amplitude and phase .. */
 | 
						|
    err = rfalChipMeasureAmplitude(amplitude);
 | 
						|
    if (ERR_NONE == err)
 | 
						|
    {
 | 
						|
        err = rfalChipMeasurePhase(phase);
 | 
						|
    }
 | 
						|
      
 | 
						|
    if( measureCnt != NULL )
 | 
						|
    {
 | 
						|
        (*measureCnt)++;
 | 
						|
    }
 | 
						|
    return err;
 | 
						|
}
 |