198 lines
6.0 KiB
C
198 lines
6.0 KiB
C
/*
|
|
* Copyright (c) 2022, Shenzhen CVA Innovation CO.,LTD
|
|
* All rights reserved.
|
|
*
|
|
* Shenzhen CVA Innovation CO.,LTD (CVA chip) is supplying this file for use
|
|
* exclusively with CVA's microcontroller products. This file can be freely
|
|
* distributed within development tools that are supporting such microcontroller
|
|
* products.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
|
|
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
|
|
* CVA SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
|
|
* OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
|
|
*/
|
|
|
|
#ifndef _INTERP1D_H_
|
|
#define _INTERP1D_H_
|
|
|
|
/*! \brief Contains public interface to various functions related
|
|
* to the 1-D Linear Interpolation
|
|
*/
|
|
|
|
/*******************************************************************************
|
|
* the includes
|
|
******************************************************************************/
|
|
|
|
#include <stdint.h>
|
|
#include "common/iqmath/iqmath.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/*******************************************************************************
|
|
* the defines
|
|
******************************************************************************/
|
|
|
|
/*******************************************************************************
|
|
* the typedefs
|
|
******************************************************************************/
|
|
|
|
typedef struct _Interp1d_PointType_
|
|
{
|
|
_iq x; /*!< x. */
|
|
_iq y; /*!< y. */
|
|
} Interp1d_PointType;
|
|
|
|
/*******************************************************************************
|
|
* the globals
|
|
******************************************************************************/
|
|
|
|
/*******************************************************************************
|
|
* the function prototypes
|
|
******************************************************************************/
|
|
|
|
/*! \brief This is an linear interpolate calculation function using 2 x and the scale as input
|
|
* The result x should satisfy: scale = (x-x1) / (x2-x1)
|
|
*
|
|
* \param[in] x1 : x value of point 1
|
|
* \param[in] x2 : x value of point 2
|
|
* \param[in] scale : the scale = (x-x1) / (x2-x1)
|
|
* \return the value x in the scale equation
|
|
*/
|
|
static inline _iq Interp1d(_iq x1, _iq x2, _iq scale)
|
|
{
|
|
return (_IQmpy(scale, x2 - x1) + x1);
|
|
}
|
|
|
|
/*! \brief This is an linear interpolate calculation function using 2 points as input
|
|
* Calculate y for the given x, based on two points - (x1, y1) and (x2, y2)
|
|
*
|
|
* \note If x1 is equal to x2, which is not actually allowed, it will return
|
|
* (y1+y2)/2 instead. User should prevent this situation.
|
|
*
|
|
* \param[in] x1 : x value of point 1
|
|
* \param[in] y1 : y value of point 1
|
|
* \param[in] x2 : x value of point 2
|
|
* \param[in] y2 : y value of point 2
|
|
* \param[in] x : x value of the target point
|
|
* \return the y value of the target point
|
|
*/
|
|
static inline _iq Interp1dPoints(_iq x1, _iq y1, _iq x2, _iq y2, _iq x)
|
|
{
|
|
return (x2 != x1) ? (_IQmpy(_IQdiv(y2 - y1, x2 - x1), x - x1) + y1) : _IQdiv2(y2 + y1);
|
|
}
|
|
|
|
/*! \brief This is an linear interpolate calculation function using the whole table as input
|
|
*
|
|
* \note The values in x[] must be from smallest to biggest
|
|
*
|
|
* \param[in] u0 : x value of the target point
|
|
* \param[in] x[] : the x value array
|
|
* \param[in] y[] : the y value array
|
|
* \param[in] maxIndex : max index of the array
|
|
* \return the y value of the target point
|
|
*/
|
|
static inline _iq Interp1dTable(_iq u0, const _iq x[], const _iq y[], uint32_t maxIndex)
|
|
{
|
|
_iq frac;
|
|
uint32_t right;
|
|
uint32_t left;
|
|
uint32_t bpIdx;
|
|
|
|
if(u0 <= x[0U])
|
|
{
|
|
left = 0U;
|
|
frac = (x[1U] == x[0U]) ? _IQ(0.5) : _IQdiv(u0 - x[0U], x[1U] - x[0U]);
|
|
}
|
|
else if(u0 < x[maxIndex])
|
|
{
|
|
/* Binary Search */
|
|
bpIdx = maxIndex >> 1U;
|
|
left = 0U;
|
|
right = maxIndex;
|
|
while(right - left > 1U)
|
|
{
|
|
if(u0 < x[bpIdx])
|
|
{
|
|
right = bpIdx;
|
|
}
|
|
else
|
|
{
|
|
left = bpIdx;
|
|
}
|
|
|
|
bpIdx = (right + left) >> 1U;
|
|
}
|
|
|
|
frac = (x[left + 1U] != x[left]) ? _IQdiv(u0 - x[left], x[left + 1U] - x[left]) : _IQ(0.5);
|
|
}
|
|
else
|
|
{
|
|
left = maxIndex - 1U;
|
|
frac = (x[maxIndex] != x[maxIndex - 1U]) ? _IQdiv(u0 - x[maxIndex - 1U], x[maxIndex] - x[maxIndex - 1U]) : _IQ(0.5);
|
|
}
|
|
|
|
return (_IQmpy(_IQ(1.0) - frac, y[left]) + _IQmpy(y[left + 1U], frac));
|
|
}
|
|
|
|
/*! \brief This is an linear interpolate calculation function using the whole table as input
|
|
*
|
|
* \note The values in pPt[].x must be from smallest to biggest
|
|
*
|
|
* \param[in] u0 : x value of the target point
|
|
* \param[in] pPt : the pointer to the points array
|
|
* \param[in] maxIndex : max index of the array
|
|
* \return the y value of the target point
|
|
*/
|
|
static inline _iq Interp1dPtArray(_iq u0, const Interp1d_PointType *pPt, uint32_t maxIndex)
|
|
{
|
|
_iq frac;
|
|
uint32_t right;
|
|
uint32_t left;
|
|
uint32_t bpIdx;
|
|
|
|
if(u0 <= pPt[0U].x)
|
|
{
|
|
left = 0U;
|
|
frac = (pPt[1U].x == pPt[0U].x) ? _IQ(0.5) : _IQdiv(u0 - pPt[0U].x, pPt[1U].x - pPt[0U].x);
|
|
}
|
|
else if(u0 < pPt[maxIndex].x)
|
|
{
|
|
/* Binary Search */
|
|
bpIdx = maxIndex >> 1U;
|
|
left = 0U;
|
|
right = maxIndex;
|
|
while(right - left > 1U)
|
|
{
|
|
if(u0 < pPt[bpIdx].x)
|
|
{
|
|
right = bpIdx;
|
|
}
|
|
else
|
|
{
|
|
left = bpIdx;
|
|
}
|
|
|
|
bpIdx = (right + left) >> 1U;
|
|
}
|
|
|
|
frac = (pPt[left + 1U].x != pPt[left].x) ? _IQdiv(u0 - pPt[left].x, pPt[left + 1U].x - pPt[left].x) : _IQ(0.5);
|
|
}
|
|
else
|
|
{
|
|
left = maxIndex - 1U;
|
|
frac = (pPt[maxIndex].x != pPt[maxIndex - 1U].x) ? _IQdiv(u0 - pPt[maxIndex - 1U].x, pPt[maxIndex].x - pPt[maxIndex - 1U].x) : _IQ(0.5);
|
|
}
|
|
|
|
return (_IQmpy(_IQ(1.0) - frac, pPt[left].y) + _IQmpy(pPt[left + 1U].y, frac));
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif /* extern "C" */
|
|
|
|
#endif /* _INTERP1D_H_ */
|