 389ff92cc1
			
		
	
	
		389ff92cc1
		
			
		
	
	
	
	
		
			
			* Makefile, Scripts: new linter * About: remove ID from IC * Firmware: remove double define for DIVC/DIVR * Scripts: check folder names too. Docker: replace syntax check with make lint. * Reformat Sources and Migrate to new file naming convention * Docker: symlink clang-format-12 to clang-format * Add coding style guide
		
			
				
	
	
		
			367 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			367 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /******************************************************************************
 | |
|   * \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;
 | |
| }
 |