MCUXpresso_LPC55S69/devices/LPC55S69/drivers/fsl_powerquad.h

2806 lines
133 KiB
C

/*
* Copyright 2018-2023 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FSL_POWERQUAD_H_
#define FSL_POWERQUAD_H_
#if defined(__CC_ARM)
#elif defined(__ICCARM__)
#include <intrinsics.h>
#elif defined(__GNUC__)
#include <arm_acle.h>
#endif /* defined(__CC_ARM) */
#include "fsl_common.h"
#include "fsl_powerquad_data.h"
/*!
* @addtogroup powerquad
* @{
*/
/*******************************************************************************
* Definitions
******************************************************************************/
/*! @name Driver version */
/*! @{ */
#define FSL_POWERQUAD_DRIVER_VERSION (MAKE_VERSION(2, 2, 0)) /*!< Version. */
/*! @} */
/* For backword compatibility. */
#define PQ_VectorBiqaudDf2F32 PQ_VectorBiquadDf2F32
#define PQ_VectorBiqaudDf2Fixed32 PQ_VectorBiquadDf2Fixed32
#define PQ_VectorBiqaudDf2Fixed16 PQ_VectorBiquadDf2Fixed16
#define PQ_VectorBiqaudCascadeDf2F32 PQ_VectorBiquadCascadeDf2F32
#define PQ_VectorBiqaudCascadeDf2Fixed32 PQ_VectorBiquadCascadeDf2Fixed32
#define PQ_VectorBiqaudCascadeDf2Fixed16 PQ_VectorBiquadCascadeDf2Fixed16
#define PQ_Vector8BiqaudDf2CascadeF32 PQ_Vector8BiquadDf2CascadeF32
#define PQ_Vector8BiqaudDf2CascadeFixed32 PQ_Vector8BiquadDf2CascadeFixed32
#define PQ_Vector8BiqaudDf2CascadeFixed16 PQ_Vector8BiquadDf2CascadeFixed16
#define PQ_FLOAT32 0U
#define PQ_FIXEDPT 1U
#define CP_PQ 0U
#define CP_MTX 1U
#define CP_FFT 2U
#define CP_FIR 3U
#define CP_CORDIC 5U
#define PQ_TRANS 0U
#define PQ_TRIG 1U
#define PQ_BIQUAD 2U
#define PQ_TRANS_FIXED 4U
#define PQ_TRIG_FIXED 5U
#define PQ_BIQUAD_FIXED 6U
#define PQ_INV 0U
#define PQ_LN 1U
#define PQ_SQRT 2U
#define PQ_INVSQRT 3U
#define PQ_ETOX 4U
#define PQ_ETONX 5U
#define PQ_DIV 6U
#define PQ_SIN 0U
#define PQ_COS 1U
#define PQ_BIQ0_CALC 1U
#define PQ_BIQ1_CALC 1U
#define PQ_COMP0_ONLY (0U << 1U)
#define PQ_COMP1_ONLY (1U << 1U)
#define CORDIC_ITER(x) ((uint32_t)(x) << 2U)
#define CORDIC_MIU(x) ((uint32_t)(x) << 1U)
#define CORDIC_T(x) ((uint32_t)(x) << 0U)
#define CORDIC_ARCTAN CORDIC_T(1U) | CORDIC_MIU(0U)
#define CORDIC_ARCTANH CORDIC_T(1U) | CORDIC_MIU(1U)
#define INST_BUSY 0x80000000U
#define PQ_ERRSTAT_OVERFLOW 0U
#define PQ_ERRSTAT_NAN 1U
#define PQ_ERRSTAT_FIXEDOVERFLOW 2U
#define PQ_ERRSTAT_UNDERFLOW 3U
#define PQ_TRANS_CFFT 0U
#define PQ_TRANS_IFFT 1U
#define PQ_TRANS_CDCT 2U
#define PQ_TRANS_IDCT 3U
#define PQ_TRANS_RFFT 4U
#define PQ_TRANS_RDCT 6U
#define PQ_MTX_SCALE 1U
#define PQ_MTX_MULT 2U
#define PQ_MTX_ADD 3U
#define PQ_MTX_INV 4U
#define PQ_MTX_PROD 5U
#define PQ_MTX_SUB 7U
#define PQ_VEC_DOTP 9U
#define PQ_MTX_TRAN 10U
/* FIR engine operation type */
#define PQ_FIR_FIR 0U
#define PQ_FIR_CONVOLUTION 1U
#define PQ_FIR_CORRELATION 2U
#define PQ_FIR_INCREMENTAL 4U
#define _pq_ln0(x) __arm_mcr(CP_PQ, PQ_LN, (uint32_t)(x), PQ_FLOAT32 | PQ_COMP0_ONLY, 0, PQ_TRANS)
#define _pq_inv0(x) __arm_mcr(CP_PQ, PQ_INV, (uint32_t)(x), PQ_FLOAT32 | PQ_COMP0_ONLY, 0, PQ_TRANS)
#define _pq_sqrt0(x) __arm_mcr(CP_PQ, PQ_SQRT, (uint32_t)(x), PQ_FLOAT32 | PQ_COMP0_ONLY, 0, PQ_TRANS)
#define _pq_invsqrt0(x) __arm_mcr(CP_PQ, PQ_INVSQRT, (uint32_t)(x), PQ_FLOAT32 | PQ_COMP0_ONLY, 0, PQ_TRANS)
#define _pq_etox0(x) __arm_mcr(CP_PQ, PQ_ETOX, (uint32_t)(x), PQ_FLOAT32 | PQ_COMP0_ONLY, 0, PQ_TRANS)
#define _pq_etonx0(x) __arm_mcr(CP_PQ, PQ_ETONX, (uint32_t)(x), PQ_FLOAT32 | PQ_COMP0_ONLY, 0, PQ_TRANS)
#define _pq_sin0(x) __arm_mcr(CP_PQ, PQ_SIN, (uint32_t)(x), PQ_FLOAT32 | PQ_COMP0_ONLY, 0, PQ_TRIG)
#define _pq_cos0(x) __arm_mcr(CP_PQ, PQ_COS, (uint32_t)(x), PQ_FLOAT32 | PQ_COMP0_ONLY, 0, PQ_TRIG)
#define _pq_biquad0(x) __arm_mcr(CP_PQ, PQ_BIQ0_CALC, (uint32_t)(x), PQ_FLOAT32 | PQ_COMP0_ONLY, 0, PQ_BIQUAD)
#define _pq_ln_fx0(x) __arm_mcr(CP_PQ, PQ_LN, (uint32_t)(x), PQ_FIXEDPT | PQ_COMP0_ONLY, 0, PQ_TRANS_FIXED)
#define _pq_inv_fx0(x) __arm_mcr(CP_PQ, PQ_INV, (uint32_t)(x), PQ_FIXEDPT | PQ_COMP0_ONLY, 0, PQ_TRANS_FIXED)
#define _pq_sqrt_fx0(x) __arm_mcr(CP_PQ, PQ_SQRT, (uint32_t)(x), PQ_FIXEDPT | PQ_COMP0_ONLY, 0, PQ_TRANS_FIXED)
#define _pq_invsqrt_fx0(x) __arm_mcr(CP_PQ, PQ_INVSQRT, (uint32_t)(x), PQ_FIXEDPT | PQ_COMP0_ONLY, 0, PQ_TRANS_FIXED)
#define _pq_etox_fx0(x) __arm_mcr(CP_PQ, PQ_ETOX, (uint32_t)(x), PQ_FIXEDPT | PQ_COMP0_ONLY, 0, PQ_TRANS_FIXED)
#define _pq_etonx_fx0(x) __arm_mcr(CP_PQ, PQ_ETONX, (uint32_t)(x), PQ_FIXEDPT | PQ_COMP0_ONLY, 0, PQ_TRANS_FIXED)
#define _pq_sin_fx0(x) __arm_mcr(CP_PQ, PQ_SIN, (uint32_t)(x), PQ_FIXEDPT | PQ_COMP0_ONLY, 0, PQ_TRIG_FIXED)
#define _pq_cos_fx0(x) __arm_mcr(CP_PQ, PQ_COS, (uint32_t)(x), PQ_FIXEDPT | PQ_COMP0_ONLY, 0, PQ_TRIG_FIXED)
#define _pq_biquad0_fx(x) __arm_mcr(CP_PQ, PQ_BIQ0_CALC, (uint32_t)(x), PQ_FIXEDPT | PQ_COMP0_ONLY, 0, PQ_BIQUAD_FIXED)
#define _pq_div0(x) __arm_mcrr(CP_PQ, PQ_FLOAT32 | PQ_COMP0_ONLY, (uint64_t)(x), PQ_DIV)
#define _pq_div1(x) __arm_mcrr(CP_PQ, PQ_FLOAT32 | PQ_COMP1_ONLY, (uint64_t)(x), PQ_DIV)
#define _pq_ln1(x) __arm_mcr(CP_PQ, PQ_LN, (uint32_t)(x), PQ_FLOAT32 | PQ_COMP1_ONLY, 0, PQ_TRANS)
#define _pq_inv1(x) __arm_mcr(CP_PQ, PQ_INV, (uint32_t)(x), PQ_FLOAT32 | PQ_COMP1_ONLY, 0, PQ_TRANS)
#define _pq_sqrt1(x) __arm_mcr(CP_PQ, PQ_SQRT, (uint32_t)(x), PQ_FLOAT32 | PQ_COMP1_ONLY, 0, PQ_TRANS)
#define _pq_invsqrt1(x) __arm_mcr(CP_PQ, PQ_INVSQRT, (uint32_t)(x), PQ_FLOAT32 | PQ_COMP1_ONLY, 0, PQ_TRANS)
#define _pq_etox1(x) __arm_mcr(CP_PQ, PQ_ETOX, (uint32_t)(x), PQ_FLOAT32 | PQ_COMP1_ONLY, 0, PQ_TRANS)
#define _pq_etonx1(x) __arm_mcr(CP_PQ, PQ_ETONX, (uint32_t)(x), PQ_FLOAT32 | PQ_COMP1_ONLY, 0, PQ_TRANS)
#define _pq_sin1(x) __arm_mcr(CP_PQ, PQ_SIN, (uint32_t)(x), PQ_FLOAT32 | PQ_COMP1_ONLY, 0, PQ_TRIG)
#define _pq_cos1(x) __arm_mcr(CP_PQ, PQ_COS, (uint32_t)(x), PQ_FLOAT32 | PQ_COMP1_ONLY, 0, PQ_TRIG)
#define _pq_biquad1(x) __arm_mcr(CP_PQ, PQ_BIQ1_CALC, (uint32_t)(x), PQ_FLOAT32 | PQ_COMP1_ONLY, 0, PQ_BIQUAD)
#define _pq_ln_fx1(x) __arm_mcr(CP_PQ, PQ_LN, (uint32_t)(x), PQ_FIXEDPT | PQ_COMP1_ONLY, 0, PQ_TRANS_FIXED)
#define _pq_inv_fx1(x) __arm_mcr(CP_PQ, PQ_INV, (uint32_t)(x), PQ_FIXEDPT | PQ_COMP1_ONLY, 0, PQ_TRANS_FIXED)
#define _pq_sqrt_fx1(x) __arm_mcr(CP_PQ, PQ_SQRT, (uint32_t)(x), PQ_FIXEDPT | PQ_COMP1_ONLY, 0, PQ_TRANS_FIXED)
#define _pq_invsqrt_fx1(x) __arm_mcr(CP_PQ, PQ_INVSQRT, (uint32_t)(x), PQ_FIXEDPT | PQ_COMP1_ONLY, 0, PQ_TRANS_FIXED)
#define _pq_etox_fx1(x) __arm_mcr(CP_PQ, PQ_ETOX, (uint32_t)(x), PQ_FIXEDPT | PQ_COMP1_ONLY, 0, PQ_TRANS_FIXED)
#define _pq_etonx_fx1(x) __arm_mcr(CP_PQ, PQ_ETONX, (uint32_t)(x), PQ_FIXEDPT | PQ_COMP1_ONLY, 0, PQ_TRANS_FIXED)
#define _pq_sin_fx1(x) __arm_mcr(CP_PQ, PQ_SIN, (uint32_t)(x), PQ_FIXEDPT | PQ_COMP1_ONLY, 0, PQ_TRIG_FIXED)
#define _pq_cos_fx1(x) __arm_mcr(CP_PQ, PQ_COS, (uint32_t)(x), PQ_FIXEDPT | PQ_COMP1_ONLY, 0, PQ_TRIG_FIXED)
#define _pq_biquad1_fx(x) __arm_mcr(CP_PQ, PQ_BIQ1_CALC, (uint32_t)(x), PQ_FIXEDPT | PQ_COMP1_ONLY, 0, PQ_BIQUAD_FIXED)
#define _pq_readMult0() __arm_mrc(CP_PQ, 0, PQ_FLOAT32 | PQ_COMP0_ONLY, 0, 0)
#define _pq_readAdd0() __arm_mrc(CP_PQ, 1, PQ_FLOAT32 | PQ_COMP0_ONLY, 0, 0)
#define _pq_readMult1() __arm_mrc(CP_PQ, 0, PQ_FLOAT32 | PQ_COMP1_ONLY, 0, 0)
#define _pq_readAdd1() __arm_mrc(CP_PQ, 1, PQ_FLOAT32 | PQ_COMP1_ONLY, 0, 0)
#define _pq_readMult0_fx() __arm_mrc(CP_PQ, 0, PQ_FIXEDPT | PQ_COMP0_ONLY, 0, 0)
#define _pq_readAdd0_fx() __arm_mrc(CP_PQ, 1, PQ_FIXEDPT | PQ_COMP0_ONLY, 0, 0)
#define _pq_readMult1_fx() __arm_mrc(CP_PQ, 0, PQ_FIXEDPT | PQ_COMP1_ONLY, 0, 0)
#define _pq_readAdd1_fx() __arm_mrc(CP_PQ, 1, PQ_FIXEDPT | PQ_COMP1_ONLY, 0, 0)
/*! Parameter used for vector ln(x) */
#define PQ_LN_INF PQ_LN, 1, PQ_TRANS
/*! Parameter used for vector 1/x */
#define PQ_INV_INF PQ_INV, 0, PQ_TRANS
/*! Parameter used for vector sqrt(x) */
#define PQ_SQRT_INF PQ_SQRT, 0, PQ_TRANS
/*! Parameter used for vector 1/sqrt(x) */
#define PQ_ISQRT_INF PQ_INVSQRT, 0, PQ_TRANS
/*! Parameter used for vector e^x */
#define PQ_ETOX_INF PQ_ETOX, 0, PQ_TRANS
/*! Parameter used for vector e^(-x) */
#define PQ_ETONX_INF PQ_ETONX, 0, PQ_TRANS
/*! Parameter used for vector sin(x) */
#define PQ_SIN_INF PQ_SIN, 1, PQ_TRIG
/*! Parameter used for vector cos(x) */
#define PQ_COS_INF PQ_COS, 1, PQ_TRIG
/*
* Workaround used in vector functions:
*
* 1. In floating sin/cos case, there must be at least 5 core clock cycles
* between MCR and following MRRC
* 2. In fixed sin/cos case, there must be one NOP between two MCR
*/
/*
* Register assignment for the vector calculation assembly.
* r0: pSrc, r1: pDest, r2-r7: Data
*/
#define PQ_RUN_OPCODE_R3_R2(BATCH_OPCODE, BATCH_MACHINE) \
__asm volatile( \
" MCR p0,%[opcode],r3,c2,c0,%[machine] \n" \
" MCR p0,%[opcode],r2,c0,c0,%[machine] \n" ::[opcode] "i"(BATCH_OPCODE), \
[machine] "i"(BATCH_MACHINE))
#define PQ_RUN_OPCODE_R5_R4(BATCH_OPCODE, BATCH_MACHINE) \
__asm volatile( \
" MCR p0,%[opcode],r5,c2,c0,%[machine] \n" \
" MCR p0,%[opcode],r4,c0,c0,%[machine] \n" ::[opcode] "i"(BATCH_OPCODE), \
[machine] "i"(BATCH_MACHINE))
#define PQ_RUN_OPCODE_R7_R6(BATCH_OPCODE, BATCH_MACHINE) \
__asm volatile( \
" MCR p0,%[opcode],r7,c2,c0,%[machine] \n" \
" MCR p0,%[opcode],r6,c0,c0,%[machine] \n" ::[opcode] "i"(BATCH_OPCODE), \
[machine] "i"(BATCH_MACHINE))
#define PQ_Vector8_FP(middle, last, BATCH_OPCODE, DOUBLE_READ_ADDERS, BATCH_MACHINE) \
PQ_RUN_OPCODE_R3_R2(BATCH_OPCODE, BATCH_MACHINE); \
if (middle) \
{ \
__asm volatile("STRD r4,r5,[r1],#8"); /* store fourth two results */ \
} \
__asm volatile("LDMIA r0!,{r4-r5}"); /* load next 2 datas */ \
__asm volatile("NOP"); \
__asm volatile("NOP"); \
if (DOUBLE_READ_ADDERS) \
{ \
__asm volatile("MRRC p0,#0,r2,r3,c1"); \
} \
else \
{ \
__asm volatile("MRRC p0,#0,r2,r3,c0"); \
} \
PQ_RUN_OPCODE_R5_R4(BATCH_OPCODE, BATCH_MACHINE); \
__asm volatile("STRD r2,r3,[r1],#8"); /* store first two results */ \
__asm volatile("LDMIA r0!,{r6-r7}"); /* load next 2 datas */ \
__asm volatile("NOP"); \
__asm volatile("NOP"); \
if (DOUBLE_READ_ADDERS) \
{ \
__asm volatile("MRRC p0,#0,r4,r5,c1"); \
} \
else \
{ \
__asm volatile("MRRC p0,#0,r4,r5,c0"); \
} \
PQ_RUN_OPCODE_R7_R6(BATCH_OPCODE, BATCH_MACHINE); \
__asm volatile("STRD r4,r5,[r1],#8"); /* store second two results */ \
__asm volatile("LDRD r4,r5,[r0],#8"); /* load last 2 of the 8 */ \
__asm volatile("NOP"); \
__asm volatile("NOP"); \
if (DOUBLE_READ_ADDERS) \
{ \
__asm volatile("MRRC p0,#0,r6,r7,c1"); \
} \
else \
{ \
__asm volatile("MRRC p0,#0,r6,r7,c0"); \
} \
PQ_RUN_OPCODE_R5_R4(BATCH_OPCODE, BATCH_MACHINE); \
__asm volatile("STRD r6,r7,[r1],#8"); /* store third two results */ \
if (!last) \
{ \
__asm volatile("LDRD r2,r3,[r0],#8"); /* load first two of next 8 */ \
} \
else \
{ \
__asm volatile("NOP"); \
__asm volatile("NOP"); \
__asm volatile("NOP"); \
} \
__asm volatile("NOP"); \
__asm volatile("NOP"); \
if (DOUBLE_READ_ADDERS) \
{ \
__asm volatile("MRRC p0,#0,r4,r5,c1"); \
} \
else \
{ \
__asm volatile("MRRC p0,#0,r4,r5,c0"); \
} \
if (last) \
{ \
__asm volatile("STRD r4,r5,[r1],#8"); /* store fourth two results */ \
}
#define PQ_RUN_OPCODE_R2_R3(BATCH_OPCODE, BATCH_MACHINE) \
__asm volatile( \
" MCR p0,%[opcode],r2,c1,c0,%[machine] \n" \
" NOP \n" \
" MCR p0,%[opcode],r3,c3,c0,%[machine] \n" ::[opcode] "i"(BATCH_OPCODE), \
[machine] "i"(BATCH_MACHINE))
#define PQ_RUN_OPCODE_R4_R5(BATCH_OPCODE, BATCH_MACHINE) \
__asm volatile( \
" MCR p0,%[opcode],r4,c1,c0,%[machine] \n" \
" NOP \n" \
" MCR p0,%[opcode],r5,c3,c0,%[machine] \n" ::[opcode] "i"(BATCH_OPCODE), \
[machine] "i"(BATCH_MACHINE))
#define PQ_RUN_OPCODE_R6_R7(BATCH_OPCODE, BATCH_MACHINE) \
__asm volatile( \
" MCR p0,%[opcode],r6,c1,c0,%[machine] \n" \
" NOP \n" \
" MCR p0,%[opcode],r7,c3,c0,%[machine] \n" ::[opcode] "i"(BATCH_OPCODE), \
[machine] "i"(BATCH_MACHINE))
#define PQ_Vector8_FX(middle, last, BATCH_OPCODE, DOUBLE_READ_ADDERS, BATCH_MACHINE) \
PQ_RUN_OPCODE_R2_R3(BATCH_OPCODE, BATCH_MACHINE); \
if (middle) \
{ \
__asm volatile("STRD r4,r5,[r1],#8"); /* store fourth two results */ \
} \
__asm volatile("LDMIA r0!,{r4-r7}"); /* load next 4 datas */ \
if (DOUBLE_READ_ADDERS) \
{ \
__asm volatile("MRC p0,#0x1,r2,c1,c0,#0"); \
__asm volatile("MRC p0,#0x1,r3,c3,c0,#0"); \
} \
else \
{ \
__asm volatile("MRC p0,#0,r2,c1,c0,#0"); \
__asm volatile("MRC p0,#0,r3,c3,c0,#0"); \
} \
PQ_RUN_OPCODE_R4_R5(BATCH_OPCODE, BATCH_MACHINE); \
__asm volatile("STRD r2,r3,[r1],#8"); /* store first two results */ \
if (DOUBLE_READ_ADDERS) \
{ \
__asm volatile("MRC p0,#0x1,r4,c1,c0,#0"); \
__asm volatile("MRC p0,#0x1,r5,c3,c0,#0"); \
} \
else \
{ \
__asm volatile("MRC p0,#0,r4,c1,c0,#0"); \
__asm volatile("MRC p0,#0,r5,c3,c0,#0"); \
} \
PQ_RUN_OPCODE_R6_R7(BATCH_OPCODE, BATCH_MACHINE); \
__asm volatile("STRD r4,r5,[r1],#8"); /* store second two results */ \
__asm volatile("LDRD r4,r5,[r0],#8"); /* load last 2 of the 8 */ \
if (DOUBLE_READ_ADDERS) \
{ \
__asm volatile("MRC p0,#0x1,r6,c1,c0,#0"); \
__asm volatile("MRC p0,#0x1,r7,c3,c0,#0"); \
} \
else \
{ \
__asm volatile("MRC p0,#0,r6,c1,c0,#0"); \
__asm volatile("MRC p0,#0,r7,c3,c0,#0"); \
} \
PQ_RUN_OPCODE_R4_R5(BATCH_OPCODE, BATCH_MACHINE); \
__asm volatile("STRD r6,r7,[r1],#8"); /* store third two results */ \
if (!last) \
__asm volatile("LDRD r2,r3,[r0],#8"); /* load first two of next 8 */ \
if (DOUBLE_READ_ADDERS) \
{ \
__asm volatile("MRC p0,#0x1,r4,c1,c0,#0"); \
__asm volatile("MRC p0,#0x1,r5,c3,c0,#0"); \
} \
else \
{ \
__asm volatile("MRC p0,#0,r4,c1,c0,#0"); \
__asm volatile("MRC p0,#0,r5,c3,c0,#0"); \
} \
if (last) \
{ \
__asm volatile("STRD r4,r5,[r1],#8"); /* store fourth two results */ \
}
/*!
* @brief Start 32-bit data vector calculation.
*
* Start the vector calculation, the input data could be float, int32_t or Q31.
*
* @param pSrc Pointer to the source data.
* @param pDst Pointer to the destination data.
*/
#define PQ_Initiate_Vector_Func(pSrc, pDst) \
__asm volatile( \
"MOV r0, %[psrc] \n" \
"MOV r1, %[pdst] \n" \
"PUSH {r2-r7} \n" \
"LDRD r2,r3,[r0],#8 \n" ::[psrc] "r"(pSrc), \
[pdst] "r"(pDst) \
: "r0", "r1")
/*!
* @brief End vector calculation.
*
* This function should be called after vector calculation.
*/
#define PQ_End_Vector_Func() __asm volatile("POP {r2-r7}")
/*
* Register assignment for the vector calculation assembly.
* r0: pSrc, r1: pDest, r2: length, r3: middle, r4-r9: Data, r10:dra
*/
/*!
* @brief Start 32-bit data vector calculation.
*
* Start the vector calculation, the input data could be float, int32_t or Q31.
*
* @param PSRC Pointer to the source data.
* @param PDST Pointer to the destination data.
* @param LENGTH Number of the data, must be multiple of 8.
*/
#define PQ_StartVector(PSRC, PDST, LENGTH) \
__asm volatile( \
"MOV r0, %[psrc] \n" \
"MOV r1, %[pdst] \n" \
"MOV r2, %[length] \n" \
"PUSH {r3-r10} \n" \
"MOV r3, #0 \n" \
"MOV r10, #0 \n" \
"LDRD r4,r5,[r0],#8 \n" ::[psrc] "r"(PSRC), \
[pdst] "r"(PDST), [length] "r"(LENGTH) \
: "r0", "r1", "r2")
/*!
* @brief Start 16-bit data vector calculation.
*
* Start the vector calculation, the input data could be int16_t. This function
* should be use with @ref PQ_Vector8Fixed16.
*
* @param PSRC Pointer to the source data.
* @param PDST Pointer to the destination data.
* @param LENGTH Number of the data, must be multiple of 8.
*/
#define PQ_StartVectorFixed16(PSRC, PDST, LENGTH) \
__asm volatile( \
"MOV r0, %[psrc] \n" \
"MOV r1, %[pdst] \n" \
"MOV r2, %[length] \n" \
"PUSH {r3-r10} \n" \
"MOV r3, #0 \n" \
"LDRSH r4,[r0],#2 \n" \
"LDRSH r5,[r0],#2 \n" ::[psrc] "r"(PSRC), \
[pdst] "r"(PDST), [length] "r"(LENGTH) \
: "r0", "r1", "r2")
/*!
* @brief Start Q15-bit data vector calculation.
*
* Start the vector calculation, the input data could be Q15. This function
* should be use with @ref PQ_Vector8Q15. This function is dedicate for
* SinQ15/CosQ15 vector calculation. Because PowerQuad only supports Q31 Sin/Cos
* fixed function, so the input Q15 data is left shift 16 bits first, after
* Q31 calculation, the output data is right shift 16 bits.
*
* @param PSRC Pointer to the source data.
* @param PDST Pointer to the destination data.
* @param LENGTH Number of the data, must be multiple of 8.
*/
#define PQ_StartVectorQ15(PSRC, PDST, LENGTH) \
__asm volatile( \
"MOV r0, %[psrc] \n" \
"MOV r1, %[pdst] \n" \
"MOV r2, %[length] \n" \
"PUSH {r3-r10} \n" \
"MOV r3, #0 \n" \
"LDR r5,[r0],#4 \n" \
"LSL r4,r5,#16 \n" \
"BFC r5,#0,#16 \n" ::[psrc] "r"(PSRC), \
[pdst] "r"(PDST), [length] "r"(LENGTH) \
: "r0", "r1", "r2")
/*!
* @brief End vector calculation.
*
* This function should be called after vector calculation.
*/
#define PQ_EndVector() __asm volatile("POP {r3-r10} \n")
/*!
* @brief Float data vector calculation.
*
* Float data vector calculation, the input data should be float. The parameter
* could be PQ_LN_INF, PQ_INV_INF, PQ_SQRT_INF, PQ_ISQRT_INF, PQ_ETOX_INF, PQ_ETONX_INF.
* For example, to calculate sqrt of a vector, use like this:
* @code
#define VECTOR_LEN 8
float input[VECTOR_LEN] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0};
float output[VECTOR_LEN];
PQ_StartVector(input, output, VECTOR_LEN);
PQ_Vector8F32(PQ_SQRT_INF);
PQ_EndVector();
@endcode
*
*/
#define PQ_Vector8F32(BATCH_OPCODE, DOUBLE_READ_ADDERS, BATCH_MACHINE) \
__asm volatile( \
"1: \n" \
" MCR p0,%[opcode],r5,c2,c0,%[machine] \n" \
" MCR p0,%[opcode],r4,c0,c0,%[machine] \n" \
" CMP r3, #0 \n" \
" ITE NE \n" \
" STRDNE r6,r7,[r1],#8 \n" /* store fourth two results */ \
" MOVEQ r3, #1 \n" /* middle = 1 */ \
" LDMIA r0!,{r6-r9} \n" /* load next 4 datas */ \
" MOV r10,%[dra] \n" \
" CMP r10, #0 \n" \
" ITE NE \n" \
" MRRCNE p0,#0,r4,r5,c1 \n" \
" MRRCEQ p0,#0,r4,r5,c0 \n" \
" MCR p0,%[opcode],r7,c2,c0,%[machine] \n" \
" MCR p0,%[opcode],r6,c0,c0,%[machine] \n" \
" STRD r4,r5,[r1],#8 \n" /* store first two results */ \
" MOV r10,%[dra] \n" \
" CMP r10, #0 \n" \
" ITE NE \n" \
" MRRCNE p0,#0,r6,r7,c1 \n" \
" MRRCEQ p0,#0,r6,r7,c0 \n" \
" MCR p0,%[opcode],r9,c2,c0,%[machine] \n" \
" MCR p0,%[opcode],r8,c0,c0,%[machine] \n" \
" STRD r6,r7,[r1],#8 \n" /* store second two results */ \
" LDRD r6,r7,[r0],#8 \n" /* load last 2 of the 8 */ \
" CMP r10, #0 \n" \
" ITE NE \n" \
" MRRCNE p0,#0,r8,r9,c1 \n" \
" MRRCEQ p0,#0,r8,r9,c0 \n" \
" MCR p0,%[opcode],r7,c2,c0,%[machine] \n" \
" MCR p0,%[opcode],r6,c0,c0,%[machine] \n" \
" STRD r8,r9,[r1],#8 \n" /* store third two results */ \
" SUBS r2, r2, #8 \n" /* length -= 8; if (length != 0) */ \
" IT NE \n" \
" LDRDNE r4,r5,[r0],#8 \n" /* load first two of next 8 */ \
" CMP r10, #0 \n" \
" ITE NE \n" \
" MRRCNE p0,#0,r6,r7,c1 \n" \
" MRRCEQ p0,#0,r6,r7,c0 \n" \
" CMP r2, #0 \n" /* if (length == 0) */ \
" BNE 1b \n" \
" STRD r6,r7,[r1],#8 \n" /* store fourth two results */ \
::[opcode] "i"(BATCH_OPCODE), \
[dra] "i"(DOUBLE_READ_ADDERS), [machine] "i"(BATCH_MACHINE))
/*!
* @brief Fixed 32bits data vector calculation.
*
* Float data vector calculation, the input data should be 32-bit integer. The parameter
* could be PQ_LN_INF, PQ_INV_INF, PQ_SQRT_INF, PQ_ISQRT_INF, PQ_ETOX_INF, PQ_ETONX_INF.
* PQ_SIN_INF, PQ_COS_INF. When this function is used for sin/cos calculation, the input
* data should be in the format Q1.31.
* For example, to calculate sqrt of a vector, use like this:
* @code
#define VECTOR_LEN 8
int32_t input[VECTOR_LEN] = {1, 4, 9, 16, 25, 36, 49, 64};
int32_t output[VECTOR_LEN];
PQ_StartVector(input, output, VECTOR_LEN);
PQ_Vector8F32(PQ_SQRT_INF);
PQ_EndVector();
@endcode
*
*/
#define PQ_Vector8Fixed32(BATCH_OPCODE, DOUBLE_READ_ADDERS, BATCH_MACHINE) \
__asm volatile( \
"1: \n" \
" MCR p0,%[opcode],r4,c1,c0,%[machine] \n" \
" NOP \n" \
" MCR p0,%[opcode],r5,c3,c0,%[machine] \n" \
" CMP r3, #0 \n" \
" ITE NE \n" \
" STRDNE r6,r7,[r1],#8 \n" /* store fourth two results */ \
" MOVEQ r3, #1 \n" /* middle = 1 */ \
" LDMIA r0!,{r6-r9} \n" /* load next 4 datas */ \
" MRC p0,%[dra],r4,c1,c0,#0 \n" \
" MRC p0,%[dra],r5,c3,c0,#0 \n" \
" MCR p0,%[opcode],r6,c1,c0,%[machine] \n" \
" NOP \n" \
" MCR p0,%[opcode],r7,c3,c0,%[machine] \n" \
" STRD r4,r5,[r1],#8 \n" /* store first two results */ \
" MRC p0,%[dra],r6,c1,c0,#0 \n" \
" MRC p0,%[dra],r7,c3,c0,#0 \n" \
" MCR p0,%[opcode],r8,c1,c0,%[machine] \n" \
" NOP \n" \
" MCR p0,%[opcode],r9,c3,c0,%[machine] \n" \
" STRD r6,r7,[r1],#8 \n" /* store second two results */ \
" LDRD r6,r7,[r0],#8 \n" /* load last 2 of the 8 */ \
" MRC p0,%[dra],r8,c1,c0,#0 \n" \
" MRC p0,%[dra],r9,c3,c0,#0 \n" \
" MCR p0,%[opcode],r6,c1,c0,%[machine] \n" \
" NOP \n" \
" MCR p0,%[opcode],r7,c3,c0,%[machine] \n" \
" STRD r8,r9,[r1],#8 \n" /* store third two results */ \
" SUBS r2, r2, #8 \n" /* length -= 8; if (length != 0) */ \
" IT NE \n" \
" LDRDNE r4,r5,[r0],#8 \n" /* load first two of next 8 */ \
" MRC p0,%[dra],r6,c1,c0,#0 \n" \
" MRC p0,%[dra],r7,c3,c0,#0 \n" \
" CMP r2, #0 \n" /* if (length == 0) */ \
" BNE 1b \n" \
" STRD r6,r7,[r1],#8 \n" /* store fourth two results */ \
::[opcode] "i"(BATCH_OPCODE), \
[dra] "i"(DOUBLE_READ_ADDERS), [machine] "i"(BATCH_MACHINE))
/*!
* @brief Fixed 32bits data vector calculation.
*
* Float data vector calculation, the input data should be 16-bit integer. The parameter
* could be PQ_LN_INF, PQ_INV_INF, PQ_SQRT_INF, PQ_ISQRT_INF, PQ_ETOX_INF, PQ_ETONX_INF.
* For example, to calculate sqrt of a vector, use like this:
* @code
#define VECTOR_LEN 8
int16_t input[VECTOR_LEN] = {1, 4, 9, 16, 25, 36, 49, 64};
int16_t output[VECTOR_LEN];
PQ_StartVector(input, output, VECTOR_LEN);
PQ_Vector8F32(PQ_SQRT_INF);
PQ_EndVector();
@endcode
*
*/
#define PQ_Vector8Fixed16(BATCH_OPCODE, DOUBLE_READ_ADDERS, BATCH_MACHINE) \
__asm volatile( \
"1: \n" \
" MCR p0,%[opcode],r4,c1,c0,%[machine] \n" \
" MCR p0,%[opcode],r5,c3,c0,%[machine] \n" \
" CMP r3, #0 \n" \
" ITTE NE \n" \
" STRHNE r6,[r1],#2 \n" /* store fourth two results */ \
" STRHNE r7,[r1],#2 \n" /* store fourth two results */ \
" MOVEQ r3, #1 \n" /* middle = 1 */ \
" LDRSH r6,[r0],#2 \n" /* load next 2 of the 8 */ \
" LDRSH r7,[r0],#2 \n" /* load next 2 of the 8 */ \
" MRC p0,%[dra],r4,c1,c0,#0 \n" \
" MRC p0,%[dra],r5,c3,c0,#0 \n" \
" MCR p0,%[opcode],r6,c1,c0,%[machine] \n" \
" MCR p0,%[opcode],r7,c3,c0,%[machine] \n" \
" STRH r4,[r1],#2 \n" /* store first two results */ \
" STRH r5,[r1],#2 \n" /* store first two results */ \
" LDRSH r8,[r0],#2 \n" /* load next 2 of the 8 */ \
" LDRSH r9,[r0],#2 \n" /* load next 2 of the 8 */ \
" MRC p0,%[dra],r6,c1,c0,#0 \n" \
" MRC p0,%[dra],r7,c3,c0,#0 \n" \
" MCR p0,%[opcode],r8,c1,c0,%[machine] \n" \
" MCR p0,%[opcode],r9,c3,c0,%[machine] \n" \
" STRH r6,[r1],#2 \n" /* store second two results */ \
" STRH r7,[r1],#2 \n" /* store second two results */ \
" LDRSH r6,[r0],#2 \n" /* load last 2 of the 8 */ \
" LDRSH r7,[r0],#2 \n" /* load last 2 of the 8 */ \
" MRC p0,%[dra],r8,c1,c0,#0 \n" \
" MRC p0,%[dra],r9,c3,c0,#0 \n" \
" MCR p0,%[opcode],r6,c1,c0,%[machine] \n" \
" MCR p0,%[opcode],r7,c3,c0,%[machine] \n" \
" STRH r8,[r1],#2 \n" /* store third two results */ \
" STRH r9,[r1],#2 \n" /* store third two results */ \
" SUBS r2, r2, #8 \n" /* length -= 8; if (length != 0) */ \
" ITT NE \n" \
" LDRSHNE r4,[r0],#2 \n" /* load first two of next 8 */ \
" LDRSHNE r5,[r0],#2 \n" /* load first two of next 8 */ \
" MRC p0,%[dra],r6,c1,c0,#0 \n" \
" MRC p0,%[dra],r7,c3,c0,#0 \n" \
" CMP r2, #0 \n" /* if (length == 0) */ \
" BNE 1b \n" \
" STRH r6,[r1],#2 \n" /* store fourth two results */ \
" STRH r7,[r1],#2 \n" /* store fourth two results */ \
::[opcode] "i"(BATCH_OPCODE), \
[dra] "i"(DOUBLE_READ_ADDERS), [machine] "i"(BATCH_MACHINE))
/*!
* @brief Q15 data vector calculation.
*
* Q15 data vector calculation, this function should only be used for sin/cos Q15 calculation,
* and the coprocessor output prescaler must be set to 31 before this function. This function
* loads Q15 data and left shift 16 bits, calculate and right shift 16 bits, then stores to
* the output array. The input range -1 to 1 means -pi to pi.
* For example, to calculate sin of a vector, use like this:
* @code
#define VECTOR_LEN 8
int16_t input[VECTOR_LEN] = {...}
int16_t output[VECTOR_LEN];
const pq_prescale_t prescale =
{
.inputPrescale = 0,
.outputPrescale = 31,
.outputSaturate = 0
};
PQ_SetCoprocessorScaler(POWERQUAD, const pq_prescale_t *prescale);
PQ_StartVectorQ15(pSrc, pDst, length);
PQ_Vector8Q15(PQ_SQRT_INF);
PQ_EndVector();
@endcode
*
*/
#define PQ_Vector8Q15(BATCH_OPCODE, DOUBLE_READ_ADDERS, BATCH_MACHINE) \
__asm volatile( \
"1: \n" \
" MCR p0,%[opcode],r4,c1,c0,%[machine] \n" \
" NOP \n" \
" MCR p0,%[opcode],r5,c3,c0,%[machine] \n" \
" CMP r3, #0 \n" \
" ITTTE NE \n" \
" LSRNE r6,r6,#16 \n" /* store fourth two results */ \
" BFINE r7,r6,#0,#16 \n" /* store fourth two results */ \
" STRNE r7,[r1],#4 \n" /* store fourth two results */ \
" MOVEQ r3, #1 \n" /* middle = 1 */ \
" LDR r7,[r0],#4 \n" /* load next 2 of the 8 */ \
" LSL r6,r7,#16 \n" /* load next 2 of the 8 */ \
" BFC r7,#0,#16 \n" /* load next 2 of the 8 */ \
" MRC p0,%[dra],r4,c1,c0,#0 \n" \
" MRC p0,%[dra],r5,c3,c0,#0 \n" \
" MCR p0,%[opcode],r6,c1,c0,%[machine] \n" \
" NOP \n" \
" MCR p0,%[opcode],r7,c3,c0,%[machine] \n" \
" LSR r4,r4,#16 \n" /* store first two results */ \
" BFI r5,r4,#0,#16 \n" /* store first two results */ \
" STR r5,[r1],#4 \n" /* store first two results */ \
" LDR r9,[r0],#4 \n" /* load next 2 of the 8 */ \
" LSL r8,r9,#16 \n" /* load next 2 of the 8 */ \
" BFC r9,#0,#16 \n" /* load next 2 of the 8 */ \
" MRC p0,%[dra],r6,c1,c0,#0 \n" \
" MRC p0,%[dra],r7,c3,c0,#0 \n" \
" MCR p0,%[opcode],r8,c1,c0,%[machine] \n" \
" NOP \n" \
" MCR p0,%[opcode],r9,c3,c0,%[machine] \n" \
" LSR r6,r6,#16 \n" /* store second two results */ \
" BFI r7,r6,#0,#16 \n" /* store second two results */ \
" STR r7,[r1],#4 \n" /* store second two results */ \
" LDR r7,[r0],#4 \n" /* load next 2 of the 8 */ \
" LSL r6,r7,#16 \n" /* load next 2 of the 8 */ \
" BFC r7,#0,#16 \n" /* load next 2 of the 8 */ \
" MRC p0,%[dra],r8,c1,c0,#0 \n" \
" MRC p0,%[dra],r9,c3,c0,#0 \n" \
" MCR p0,%[opcode],r6,c1,c0,%[machine] \n" \
" NOP \n" \
" MCR p0,%[opcode],r7,c3,c0,%[machine] \n" \
" LSR r8,r8,#16 \n" /* store third two results */ \
" BFI r9,r8,#0,#16 \n" /* store third two results */ \
" STR r9,[r1],#4 \n" /* store third two results */ \
" SUBS r2, r2, #8 \n" /* length -= 8; if (length != 0) */ \
" ITTT NE \n" \
" LDRNE r5,[r0],#4 \n" /* load next 2 of the 8 */ \
" LSLNE r4,r5,#16 \n" /* load next 2 of the 8 */ \
" BFCNE r5,#0,#16 \n" /* load next 2 of the 8 */ \
" MRC p0,%[dra],r6,c1,c0,#0 \n" \
" MRC p0,%[dra],r7,c3,c0,#0 \n" \
" CMP r2, #0 \n" /* if (length == 0) */ \
" BNE 1b \n" \
" LSR r6,r6,#16 \n" /* store fourth two results */ \
" BFI r7,r6,#0,#16 \n" /* store fourth two results */ \
" STR r7,[r1],#4 \n" /* store fourth two results */ \
::[opcode] "i"(BATCH_OPCODE), \
[dra] "i"(DOUBLE_READ_ADDERS), [machine] "i"(BATCH_MACHINE))
/*!
* @brief Float data vector biquad direct form II calculation.
*
* Biquad filter, the input and output data are float data. Biquad side 0 is used. Example:
* @code
#define VECTOR_LEN 16
float input[VECTOR_LEN] = {1024.0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
float output[VECTOR_LEN];
pq_biquad_state_t state =
{
.param =
{
.a_1 = xxx,
.a_2 = xxx,
.b_0 = xxx,
.b_1 = xxx,
.b_2 = xxx,
},
};
PQ_BiquadRestoreInternalState(POWERQUAD, 0, &state);
PQ_Initiate_Vector_Func(pSrc,pDst);
PQ_DF2_Vector8_FP(false,false);
PQ_DF2_Vector8_FP(true,true);
PQ_End_Vector_Func();
@endcode
*
*/
#define PQ_DF2_Vector8_FP(middle, last) \
__asm volatile("MCR p0,#0x1,r2,c0,c0,#6"); /* write biquad0*/ \
if (middle) \
{ \
__asm volatile("STR r5,[r1],#4"); /* store last result*/ \
} \
__asm volatile("LDRD r4,r5,[r0],#8"); /* load next 2 datas */ \
__asm volatile("MRC p0,#0x1,r2,c0,c0,#0"); /* read biquad0*/ \
__asm volatile("MCR p0,#0x1,r3,c0,c0,#6"); /* write biquad0 */ \
__asm volatile("MRC p0,#0x1,r3,c0,c0,#0"); /* read biquad0*/ \
__asm volatile("MCR p0,#0x1,r4,c0,c0,#6"); /* write biquad0 */ \
__asm volatile("STRD r2,r3,[r1],#8"); /* store first 2 results */ \
__asm volatile("MRC p0,#0x1,r4,c0,c0,#0"); \
__asm volatile("MCR p0,#0x1,r5,c0,c0,#6"); \
__asm volatile("LDRD r6,r7,[r0],#8"); /* load next 2 datas */ \
__asm volatile("MRC p0,#0x1,r5,c0,c0,#0"); \
__asm volatile("MCR p0,#0x1,r6,c0,c0,#6"); \
__asm volatile("STRD r4,r5,[r1],#8"); /* store next 2 results */ \
__asm volatile("MRC p0,#0x1,r6,c0,c0,#0"); \
__asm volatile("MCR p0,#0x1,r7,c0,c0,#6"); \
__asm volatile("LDRD r4,r5,[r0],#8"); /* load next 2 datas */ \
__asm volatile("MRC p0,#0x1,r7,c0,c0,#0"); \
__asm volatile("MCR p0,#0x1,r4,c0,c0,#6"); \
__asm volatile("STRD r6,r7,[r1],#8"); /* store next 2 results */ \
__asm volatile("MRC p0,#0x1,r4,c0,c0,#0"); \
__asm volatile("MCR p0,#0x1,r5,c0,c0,#6"); \
if (!last) \
{ \
__asm volatile("LDRD r2,r3,[r0],#8"); /* load first two of next 8 */ \
} \
__asm volatile("STR r4,[r1],#4"); \
__asm volatile("MRC p0,#0x1,r5,c0,c0,#0"); \
if (last) \
{ \
__asm volatile("STR r5,[r1],#4"); /* store last result */ \
}
/*!
* @brief Fixed data vector biquad direct form II calculation.
*
* Biquad filter, the input and output data are fixed data. Biquad side 0 is used. Example:
* @code
#define VECTOR_LEN 16
int32_t input[VECTOR_LEN] = {1024, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int32_t output[VECTOR_LEN];
pq_biquad_state_t state =
{
.param =
{
.a_1 = xxx,
.a_2 = xxx,
.b_0 = xxx,
.b_1 = xxx,
.b_2 = xxx,
},
};
PQ_BiquadRestoreInternalState(POWERQUAD, 0, &state);
PQ_Initiate_Vector_Func(pSrc,pDst);
PQ_DF2_Vector8_FX(false,false);
PQ_DF2_Vector8_FX(true,true);
PQ_End_Vector_Func();
@endcode
*
*/
#define PQ_DF2_Vector8_FX(middle, last) \
__asm volatile("MCR p0,#0x1,r2,c1,c0,#6"); /* write biquad0*/ \
if (middle) \
{ \
__asm volatile("STR r5,[r1],#4"); /* store last result*/ \
} \
__asm volatile("LDRD r4,r5,[r0],#8"); /* load next 2 datas */ \
__asm volatile("MRC p0,#0x1,r2,c1,c0,#0"); /* read biquad0*/ \
__asm volatile("MCR p0,#0x1,r3,c1,c0,#6"); /* write biquad0 */ \
__asm volatile("MRC p0,#0x1,r3,c1,c0,#0"); \
__asm volatile("MCR p0,#0x1,r4,c1,c0,#6"); \
__asm volatile("STRD r2,r3,[r1],#8"); /* store first 2 results */ \
__asm volatile("MRC p0,#0x1,r4,c1,c0,#0"); \
__asm volatile("MCR p0,#0x1,r5,c1,c0,#6"); \
__asm volatile("LDRD r6,r7,[r0],#8"); \
__asm volatile("MRC p0,#0x1,r5,c1,c0,#0"); \
__asm volatile("MCR p0,#0x1,r6,c1,c0,#6"); \
__asm volatile("STRD r4,r5,[r1],#8"); /* store next 2 results */ \
__asm volatile("MRC p0,#0x1,r6,c1,c0,#0"); \
__asm volatile("MCR p0,#0x1,r7,c1,c0,#6"); \
__asm volatile("LDRD r4,r5,[r0],#8"); \
__asm volatile("MRC p0,#0x1,r7,c1,c0,#0"); \
__asm volatile("MCR p0,#0x1,r4,c1,c0,#6"); \
__asm volatile("STRD r6,r7,[r1],#8"); /* store next 2 results */ \
__asm volatile("MRC p0,#0x1,r4,c1,c0,#0"); \
__asm volatile("MCR p0,#0x1,r5,c1,c0,#6"); \
if (!last) \
{ \
__asm volatile("LDRD r2,r3,[r0],#8"); /* load two of next 8 */ \
} \
__asm volatile("STR r4,[r1],#4"); /* store 7th results */ \
__asm volatile("MRC p0,#0x1,r5,c1,c0,#0"); \
if (last) \
{ \
__asm volatile("STR r5,[r1],#4"); /* store last result */ \
}
/*!
* @brief Float data vector biquad direct form II calculation.
*
* Biquad filter, the input and output data are float data. Biquad side 0 is used. Example:
* @code
#define VECTOR_LEN 8
float input[VECTOR_LEN] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0};
float output[VECTOR_LEN];
pq_biquad_state_t state =
{
.param =
{
.a_1 = xxx,
.a_2 = xxx,
.b_0 = xxx,
.b_1 = xxx,
.b_2 = xxx,
},
};
PQ_BiquadRestoreInternalState(POWERQUAD, 0, &state);
PQ_StartVector(input, output, VECTOR_LEN);
PQ_Vector8BiquadDf2F32();
PQ_EndVector();
@endcode
*
*/
#define PQ_Vector8BiquadDf2F32() \
__asm volatile( \
"1: \n" \
" MCR p0,#0x1,r4,c0,c0,#6 \n" /* write biquad0*/ \
" CMP r3, #0 \n" \
" ITE NE \n" \
" STRNE r7,[r1],#4 \n" /* store last result*/ \
" MOVEQ r3, #1 \n" /* middle = 1 */ \
" LDMIA r0!,{r6-r9} \n" /* load next 4 datas */ \
" MRC p0,#0x1,r4,c0,c0,#0 \n" /* read biquad0*/ \
" MCR p0,#0x1,r5,c0,c0,#6 \n" /* write biquad0 */ \
" MRC p0,#0x1,r5,c0,c0,#0 \n" /* read biquad0*/ \
" MCR p0,#0x1,r6,c0,c0,#6 \n" /* write biquad0 */ \
" MRC p0,#0x1,r6,c0,c0,#0 \n" /* read biquad0 */ \
" MCR p0,#0x1,r7,c0,c0,#6 \n" /* write biquad0 */ \
" MRC p0,#0x1,r7,c0,c0,#0 \n" /* read biquad0 */ \
" MCR p0,#0x1,r8,c0,c0,#6 \n" /* write biquad0*/ \
" STMIA r1!,{r4-r7} \n" /* store first four results */ \
" MRC p0,#0x1,r8,c0,c0,#0 \n" /* read biquad0*/ \
" MCR p0,#0x1,r9,c0,c0,#6 \n" /* write biquad0*/ \
" LDRD r6,r7,[r0],#8 \n" /* load next 2 items*/ \
" MRC p0,#0x1,r9,c0,c0,#0 \n" /* read biquad0*/ \
" MCR p0,#0x1,r6,c0,c0,#6 \n" /* write biquad0*/ \
" STRD r8,r9,[r1],#8 \n" /* store third two results */ \
" MRC p0,#0x1,r6,c0,c0,#0 \n" /* read biquad0*/ \
" MCR p0,#0x1,r7,c0,c0,#6 \n" /* write biquad0*/ \
" SUBS r2, r2, #8 \n" /* length -= 8; if (length != 0) */ \
" IT NE \n" \
" LDRDNE r4,r5,[r0],#8 \n" /* load first two of next 8 */ \
" STR r6,[r1],#4 \n" /* store 7th results */ \
" MRC p0,#0x1,r7,c0,c0,#0 \n" /* read biquad0*/ \
" CMP r2, #0 \n" /* if (length == 0) */ \
" BNE 1b \n" \
" STR r7,[r1],#4 \n" /* store last result */ \
)
/*!
* @brief Fixed 32-bit data vector biquad direct form II calculation.
*
* Biquad filter, the input and output data are Q31 or 32-bit integer. Biquad side 0 is used. Example:
* @code
#define VECTOR_LEN 8
int32_t input[VECTOR_LEN] = {1, 2, 3, 4, 5, 6, 7, 8};
int32_t output[VECTOR_LEN];
pq_biquad_state_t state =
{
.param =
{
.a_1 = xxx,
.a_2 = xxx,
.b_0 = xxx,
.b_1 = xxx,
.b_2 = xxx,
},
};
PQ_BiquadRestoreInternalState(POWERQUAD, 0, &state);
PQ_StartVector(input, output, VECTOR_LEN);
PQ_Vector8BiquadDf2Fixed32();
PQ_EndVector();
@endcode
*
*/
#define PQ_Vector8BiquadDf2Fixed32() \
__asm volatile( \
"1: \n" \
" MCR p0,#0x1,r4,c1,c0,#6 \n" /* write biquad0*/ \
" CMP r3, #0 \n" \
" ITE NE \n" \
" STRNE r7,[r1],#4 \n" /* store last result*/ \
" MOVEQ r3, #1 \n" /* middle = 1 */ \
" LDMIA r0!,{r6-r9} \n" /* load next 4 datas */ \
" MRC p0,#0x1,r4,c1,c0,#0 \n" /* read biquad0*/ \
" MCR p0,#0x1,r5,c1,c0,#6 \n" /* write biquad0 */ \
" MRC p0,#0x1,r5,c1,c0,#0 \n" /* read biquad0*/ \
" MCR p0,#0x1,r6,c1,c0,#6 \n" /* write biquad0 */ \
" MRC p0,#0x1,r6,c1,c0,#0 \n" /* read biquad0 */ \
" MCR p0,#0x1,r7,c1,c0,#6 \n" /* write biquad0 */ \
" MRC p0,#0x1,r7,c1,c0,#0 \n" /* read biquad0 */ \
" MCR p0,#0x1,r8,c1,c0,#6 \n" /* write biquad0*/ \
" STMIA r1!,{r4-r7} \n" /* store first four results */ \
" MRC p0,#0x1,r8,c1,c0,#0 \n" /* read biquad0*/ \
" MCR p0,#0x1,r9,c1,c0,#6 \n" /* write biquad0*/ \
" LDRD r6,r7,[r0],#8 \n" /* load next 2 items*/ \
" MRC p0,#0x1,r9,c1,c0,#0 \n" /* read biquad0*/ \
" MCR p0,#0x1,r6,c1,c0,#6 \n" /* write biquad0*/ \
" STRD r8,r9,[r1],#8 \n" /* store third two results */ \
" MRC p0,#0x1,r6,c1,c0,#0 \n" /* read biquad0*/ \
" MCR p0,#0x1,r7,c1,c0,#6 \n" /* write biquad0*/ \
" SUBS r2, r2, #8 \n" /* length -= 8; if (length != 0) */ \
" IT NE \n" \
" LDRDNE r4,r5,[r0],#8 \n" /* load first two of next 8 */ \
" STR r6,[r1],#4 \n" /* store 7th results */ \
" MRC p0,#0x1,r7,c1,c0,#0 \n" /* read biquad0*/ \
" CMP r2, #0 \n" /* if (length == 0) */ \
" BNE 1b \n" \
" STR r7,[r1],#4 \n" /* store last result */ \
)
/*!
* @brief Fixed 16-bit data vector biquad direct form II calculation.
*
* Biquad filter, the input and output data are Q15 or 16-bit integer. Biquad side 0 is used. Example:
* @code
#define VECTOR_LEN 8
int16_t input[VECTOR_LEN] = {1, 2, 3, 4, 5, 6, 7, 8};
int16_t output[VECTOR_LEN];
pq_biquad_state_t state =
{
.param =
{
.a_1 = xxx,
.a_2 = xxx,
.b_0 = xxx,
.b_1 = xxx,
.b_2 = xxx,
},
};
PQ_BiquadRestoreInternalState(POWERQUAD, 0, &state);
PQ_StartVector(input, output, VECTOR_LEN);
PQ_Vector8BiquadDf2Fixed16();
PQ_EndVector();
@endcode
*
*/
#define PQ_Vector8BiquadDf2Fixed16() \
__asm volatile( \
"1: \n" \
" MCR p0,#0x1,r4,c1,c0,#6 \n" /* write biquad0*/ \
" CMP r3, #0 \n" \
" ITE NE \n" \
" STRHNE r7,[r1],#2 \n" /* store last result*/ \
" MOVEQ r3, #1 \n" /* middle = 1 */ \
" LDRSH r6,[r0],#2 \n" /* load next 2 of the 8*/ \
" LDRSH r7,[r0],#2 \n" /* load next 2 of the 8*/ \
" MRC p0,#0x1,r4,c1,c0,#0 \n" /* read biquad0*/ \
" MCR p0,#0x1,r5,c1,c0,#6 \n" /* write biquad0 */ \
" MRC p0,#0x1,r5,c1,c0,#0 \n" /* read biquad0*/ \
" LDRSH r8,[r0],#2 \n" /* load next 2 of the 8*/ \
" LDRSH r9,[r0],#2 \n" /* load next 2 of the 8*/ \
" MCR p0,#0x1,r6,c1,c0,#6 \n" /* write biquad0 */ \
" MRC p0,#0x1,r6,c1,c0,#0 \n" /* read biquad0 */ \
" MCR p0,#0x1,r7,c1,c0,#6 \n" /* write biquad0 */ \
" MRC p0,#0x1,r7,c1,c0,#0 \n" /* read biquad0 */ \
" STRH r4,[r1],#2 \n" /* store first 4 results */ \
" STRH r5,[r1],#2 \n" /* store first 4 results */ \
" MCR p0,#0x1,r8,c1,c0,#6 \n" /* write biquad0*/ \
" STRH r6,[r1],#2 \n" /* store first 4 results */ \
" STRH r7,[r1],#2 \n" /* store first 4 results */ \
" MRC p0,#0x1,r8,c1,c0,#0 \n" /* read biquad0*/ \
" MCR p0,#0x1,r9,c1,c0,#6 \n" /* write biquad0*/ \
" LDRSH r6,[r0],#2 \n" /* load next 1 of the 8*/ \
" LDRSH r7,[r0],#2 \n" /* load next 1 of the 8*/ \
" MRC p0,#0x1,r9,c1,c0,#0 \n" /* read biquad0*/ \
" MCR p0,#0x1,r6,c1,c0,#6 \n" /* write biquad0*/ \
" STRH r8,[r1],#2 \n" /* store next two results */ \
" STRH r9,[r1],#2 \n" /* store next two results */ \
" MRC p0,#0x1,r6,c1,c0,#0 \n" /* read biquad0*/ \
" MCR p0,#0x1,r7,c1,c0,#6 \n" /* write biquad0*/ \
" SUBS r2, r2, #8 \n" /* length -= 8; if (length != 0) */ \
" ITT NE \n" \
" LDRSHNE r4,[r0],#2 \n" /* load first two of next 8*/ \
" LDRSHNE r5,[r0],#2 \n" /* load first two of next 8*/ \
" STRH r6,[r1],#2 \n" /* store 7th results */ \
" MRC p0,#0x1,r7,c1,c0,#0 \n" /* read biquad0*/ \
" CMP r2, #0 \n" /* if (length == 0) */ \
" BNE 1b \n" \
" STRH r7,[r1],#2 \n" /* store last result */ \
)
/*!
* @brief Float data vector direct form II biquad cascade filter.
*
* The input and output data are float data. The data flow is
* input -> biquad side 1 -> biquad side 0 -> output.
*
* @code
#define VECTOR_LEN 16
float input[VECTOR_LEN] = {1024.0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
float output[VECTOR_LEN];
pq_biquad_state_t state0 =
{
.param =
{
.a_1 = xxx,
.a_2 = xxx,
.b_0 = xxx,
.b_1 = xxx,
.b_2 = xxx,
},
};
pq_biquad_state_t state1 =
{
.param =
{
.a_1 = xxx,
.a_2 = xxx,
.b_0 = xxx,
.b_1 = xxx,
.b_2 = xxx,
},
};
PQ_BiquadRestoreInternalState(POWERQUAD, 0, &state0);
PQ_BiquadRestoreInternalState(POWERQUAD, 1, &state1);
PQ_Initiate_Vector_Func(pSrc, pDst);
PQ_DF2_Cascade_Vector8_FP(false, false);
PQ_DF2_Cascade_Vector8_FP(true, true);
PQ_End_Vector_Func();
@endcode
*
*/
#define PQ_DF2_Cascade_Vector8_FP(middle, last) \
__asm volatile("MCR p0,#0x1,r2,c2,c0,#6"); /* write biquad1*/ \
if (middle) \
{ \
__asm volatile("MCR p0,#0x1,r5,c0,c0,#6"); /* write biquad0*/ \
__asm volatile("MRRC p0,#0,r5,r2,c1"); /* read both biquad*/ \
} \
else \
{ \
__asm volatile("MRC p0,#0x1,r2,c2,c0,#0"); /* read biquad1*/ \
} \
__asm volatile("MCR p0,#0x1,r3,c2,c0,#6"); /* write biquad1*/ \
__asm volatile("MCR p0,#0x1,r2,c0,c0,#6"); /* write biquad0*/ \
if (middle) \
{ \
__asm volatile("STRD r4,r5,[r1],#8"); /* store last two results*/ \
} \
__asm volatile("LDRD r4,r5,[r0],#8"); /* load next 2 datas */ \
__asm volatile("MRRC p0,#0,r2,r3,c1"); /* read both biquad*/ \
__asm volatile("MCR p0,#0x1,r4,c2,c0,#6"); /* write biquad1*/ \
__asm volatile("MCR p0,#0x1,r3,c0,c0,#6"); /* write biquad0*/ \
__asm volatile("LDRD r6,r7,[r0],#8"); \
__asm volatile("MRRC p0,#0,r3,r4,c1"); \
__asm volatile("MCR p0,#0x1,r5,c2,c0,#6"); \
__asm volatile("MCR p0,#0x1,r4,c0,c0,#6"); \
__asm volatile("STRD r2,r3,[r1],#8"); /* store first two results */ \
__asm volatile("MRRC p0,#0,r4,r5,c1"); \
__asm volatile("MCR p0,#0x1,r6,c2,c0,#6"); \
__asm volatile("MCR p0,#0x1,r5,c0,c0,#6"); \
__asm volatile("STR r4,[r1],#4"); \
__asm volatile("MRRC p0,#0,r5,r6,c1"); \
__asm volatile("MCR p0,#0x1,r7,c2,c0,#6"); \
__asm volatile("MCR p0,#0x1,r6,c0,c0,#6"); \
__asm volatile("STR r5,[r1],#4"); \
__asm volatile("LDRD r4,r5,[r0],#8"); \
__asm volatile("MRRC p0,#0,r6,r7,c1"); \
__asm volatile("MCR p0,#0x1,r4,c2,c0,#6"); \
__asm volatile("MCR p0,#0x1,r7,c0,c0,#6"); \
if (!last) \
{ \
__asm volatile("LDRD r2,r3,[r0],#8"); /* load first two of next 8 */ \
} \
__asm volatile("MRRC p0,#0,r7,r4,c1"); \
__asm volatile("MCR p0,#0x1,r5,c2,c0,#6"); \
__asm volatile("MCR p0,#0x1,r4,c0,c0,#6"); \
__asm volatile("STRD r6,r7,[r1],#8"); /* store third two results */ \
__asm volatile("MRRC p0,#0,r4,r5,c1"); \
if (last) \
{ \
__asm volatile("MCR p0,#0x1,r5,c0,c0,#6"); /* write biquad0*/ \
__asm volatile("MRC p0,#0x1,r5,c0,c0,#0"); /* read biquad0*/ \
__asm volatile("STRD r4,r5,[r1],#8"); /* store fourth two results */ \
}
/*!
* @brief Fixed data vector direct form II biquad cascade filter.
*
* The input and output data are fixed data. The data flow is
* input -> biquad side 1 -> biquad side 0 -> output.
*
* @code
#define VECTOR_LEN 16
int32_t input[VECTOR_LEN] = {1024.0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int32_t output[VECTOR_LEN];
pq_biquad_state_t state0 =
{
.param =
{
.a_1 = xxx,
.a_2 = xxx,
.b_0 = xxx,
.b_1 = xxx,
.b_2 = xxx,
},
};
pq_biquad_state_t state1 =
{
.param =
{
.a_1 = xxx,
.a_2 = xxx,
.b_0 = xxx,
.b_1 = xxx,
.b_2 = xxx,
},
};
PQ_BiquadRestoreInternalState(POWERQUAD, 0, &state0);
PQ_BiquadRestoreInternalState(POWERQUAD, 1, &state1);
PQ_Initiate_Vector_Func(pSrc, pDst);
PQ_DF2_Cascade_Vector8_FX(false, false);
PQ_DF2_Cascade_Vector8_FX(true, true);
PQ_End_Vector_Func();
@endcode
*
*/
#define PQ_DF2_Cascade_Vector8_FX(middle, last) \
__asm volatile("MCR p0,#0x1,r2,c3,c0,#6"); /* write biquad1*/ \
if (middle) \
{ \
__asm volatile("MCR p0,#0x1,r5,c1,c0,#6"); /* write biquad0*/ \
__asm volatile("MRC p0,#0x1,r5,c1,c0,#0"); /* read biquad0*/ \
__asm volatile("MRC p0,#0x1,r2,c3,c0,#0"); /* read biquad1*/ \
} \
else \
{ \
__asm volatile("MRC p0,#0x1,r2,c3,c0,#0"); /* read biquad1*/ \
} \
__asm volatile("MCR p0,#0x1,r3,c3,c0,#6"); /* write biquad1*/ \
__asm volatile("MCR p0,#0x1,r2,c1,c0,#6"); /* write biquad0*/ \
if (middle) \
{ \
__asm volatile("STRD r4,r5,[r1],#8"); /* store last two results*/ \
} \
__asm volatile("LDRD r4,r5,[r0],#8"); /* load next 2 datas */ \
__asm volatile("MRC p0,#0x1,r2,c1,c0,#0"); /* read biquad0*/ \
__asm volatile("MRC p0,#0x1,r3,c3,c0,#0"); /* read biquad1*/ \
__asm volatile("MCR p0,#0x1,r4,c3,c0,#6"); /* write biquad1*/ \
__asm volatile("MCR p0,#0x1,r3,c1,c0,#6"); /* write biquad0*/ \
__asm volatile("LDRD r6,r7,[r0],#8"); \
__asm volatile("MRC p0,#0x1,r3,c1,c0,#0"); \
__asm volatile("MRC p0,#0x1,r4,c3,c0,#0"); \
__asm volatile("MCR p0,#0x1,r5,c3,c0,#6"); \
__asm volatile("MCR p0,#0x1,r4,c1,c0,#6"); \
__asm volatile("STRD r2,r3,[r1],#8"); \
__asm volatile("MRC p0,#0x1,r4,c1,c0,#0"); \
__asm volatile("MRC p0,#0x1,r5,c3,c0,#0"); \
__asm volatile("MCR p0,#0x1,r6,c3,c0,#6"); \
__asm volatile("MCR p0,#0x1,r5,c1,c0,#6"); \
__asm volatile("STR r4,[r1],#4"); \
__asm volatile("MRC p0,#0x1,r5,c1,c0,#0"); \
__asm volatile("MRC p0,#0x1,r6,c3,c0,#0"); \
__asm volatile("MCR p0,#0x1,r7,c3,c0,#6"); \
__asm volatile("MCR p0,#0x1,r6,c1,c0,#6"); \
__asm volatile("STR r5,[r1],#4"); \
__asm volatile("LDRD r4,r5,[r0],#8"); \
__asm volatile("MRC p0,#0x1,r6,c1,c0,#0"); \
__asm volatile("MRC p0,#0x1,r7,c3,c0,#0"); \
__asm volatile("MCR p0,#0x1,r4,c3,c0,#6"); \
__asm volatile("MCR p0,#0x1,r7,c1,c0,#6"); \
if (!last) \
{ \
__asm volatile("LDRD r2,r3,[r0],#8"); /* load first two of next 8 */ \
} \
__asm volatile("MRC p0,#0x1,r7,c1,c0,#0"); \
__asm volatile("MRC p0,#0x1,r4,c3,c0,#0"); \
__asm volatile("MCR p0,#0x1,r5,c3,c0,#6"); \
__asm volatile("MCR p0,#0x1,r4,c1,c0,#6"); \
__asm volatile("STRD r6,r7,[r1],#8"); /* store third two results */ \
__asm volatile("MRC p0,#0x1,r4,c1,c0,#0"); /* read biquad0*/ \
__asm volatile("MRC p0,#0x1,r5,c3,c0,#0"); /* read biquad1*/ \
if (last) \
{ \
__asm volatile("MCR p0,#0x1,r5,c1,c0,#6"); /* write biquad0*/ \
__asm volatile("MRC p0,#0x1,r5,c1,c0,#0"); /* read biquad0*/ \
__asm volatile("STRD r4,r5,[r1],#8"); /* store fourth two results */ \
}
/*!
* @brief Float data vector direct form II biquad cascade filter.
*
* The input and output data are float data. The data flow is
* input -> biquad side 1 -> biquad side 0 -> output.
*
* @code
#define VECTOR_LEN 8
float input[VECTOR_LEN] = {1, 2, 3, 4, 5, 6, 7, 8};
float output[VECTOR_LEN];
pq_biquad_state_t state0 =
{
.param =
{
.a_1 = xxx,
.a_2 = xxx,
.b_0 = xxx,
.b_1 = xxx,
.b_2 = xxx,
},
};
pq_biquad_state_t state1 =
{
.param =
{
.a_1 = xxx,
.a_2 = xxx,
.b_0 = xxx,
.b_1 = xxx,
.b_2 = xxx,
},
};
PQ_BiquadRestoreInternalState(POWERQUAD, 0, &state0);
PQ_BiquadRestoreInternalState(POWERQUAD, 1, &state1);
PQ_StartVector(input, output, VECTOR_LEN);
PQ_Vector8BiquadDf2CascadeF32();
PQ_EndVector();
@endcode
*
*/
#define PQ_Vector8BiquadDf2CascadeF32() \
__asm volatile( \
"1: \n" \
" MCR p0,#0x1,r4,c2,c0,#2 \n" /* write biquad1*/ \
" CMP r3, #0 \n" \
" ITTE NE \n" \
" MCRNE p0,#0x1,r7,c0,c0,#2 \n" /* write biquad0*/ \
" MRRCNE p0,#0,r7,r4,c1 \n" /* read both biquad*/ \
" MRCEQ p0,#0x1,r4,c2,c0,#0 \n" /* read biquad1*/ \
" MCR p0,#0x1,r5,c2,c0,#2 \n" /* write biquad1*/ \
" MCR p0,#0x1,r4,c0,c0,#2 \n" /* write biquad0*/ \
" CMP r3, #0 \n" \
" ITE NE \n" \
" STRDNE r6,r7,[r1],#8 \n" /* store last two results*/ \
" MOVEQ r3, #1 \n" /* middle = 1 */ \
" LDMIA r0!,{r6-r9} \n" /* load next 4 datas */ \
" MRRC p0,#0,r4,r5,c1 \n" /* read both biquad*/ \
" MCR p0,#0x1,r6,c2,c0,#2 \n" /* write biquad1*/ \
" MCR p0,#0x1,r5,c0,c0,#2 \n" /* write biquad0*/ \
" MRRC p0,#0,r5,r6,c1 \n" /* read both biquad*/ \
" MCR p0,#0x1,r7,c2,c0,#2 \n" /* write biquad1*/ \
" MCR p0,#0x1,r6,c0,c0,#2 \n" /* write biquad0*/ \
" MRRC p0,#0,r6,r7,c1 \n" /* read both biquad*/ \
" MCR p0,#0x1,r8,c2,c0,#2 \n" /* write biquad1*/ \
" MCR p0,#0x1,r7,c0,c0,#2 \n" /* write biquad0*/ \
" MRRC p0,#0,r7,r8,c1 \n" /* read both biquad*/ \
" MCR p0,#0x1,r9,c2,c0,#2 \n" /* write biquad1*/ \
" MCR p0,#0x1,r8,c0,c0,#2 \n" /* write biquad0*/ \
" STMIA r1!,{R4-R7} \n" /* store first and second two results */ \
" LDRD r6,r7,[r0],#8 \n" /* load last 2 of the 8 */ \
" MRRC p0,#0,r8,r9,c1 \n" /* read both biquad*/ \
" MCR p0,#0x1,r6,c2,c0,#2 \n" /* write biquad1*/ \
" MCR p0,#0x1,r9,c0,c0,#2 \n" /* write biquad0*/ \
" SUBS r2, r2, #8 \n" /* length -= 8; if (length != 0) */ \
" IT NE \n" \
" LDRDNE r4,r5,[r0],#8 \n" /* load first two of next 8 */ \
" MRRC p0,#0,r9,r6,c1 \n" /* read both biquad*/ \
" MCR p0,#0x1,r7,c2,c0,#2 \n" /* write biquad1*/ \
" MCR p0,#0x1,r6,c0,c0,#2 \n" /* write biquad0*/ \
" STRD r8,r9,[r1],#8 \n" /* store third two results */ \
" MRRC p0,#0,r6,r7,c1 \n" /* read both biquad*/ \
" CMP r2, #0 \n" /* if (length == 0) */ \
" BNE 1b \n" \
" MCR p0,#0x1,r7,c0,c0,#2 \n" /* write biquad0*/ \
" MRC p0,#0x1,r7,c0,c0,#0 \n" /* read biquad0*/ \
" STRD r6,r7,[r1],#8 \n" /* store fourth two results */ \
)
/*!
* @brief Fixed 32-bit data vector direct form II biquad cascade filter.
*
* The input and output data are fixed 32-bit data. The data flow is
* input -> biquad side 1 -> biquad side 0 -> output.
*
* @code
#define VECTOR_LEN 8
int32_t input[VECTOR_LEN] = {1, 2, 3, 4, 5, 6, 7, 8};
int32_t output[VECTOR_LEN];
pq_biquad_state_t state0 =
{
.param =
{
.a_1 = xxx,
.a_2 = xxx,
.b_0 = xxx,
.b_1 = xxx,
.b_2 = xxx,
},
};
pq_biquad_state_t state1 =
{
.param =
{
.a_1 = xxx,
.a_2 = xxx,
.b_0 = xxx,
.b_1 = xxx,
.b_2 = xxx,
},
};
PQ_BiquadRestoreInternalState(POWERQUAD, 0, &state0);
PQ_BiquadRestoreInternalState(POWERQUAD, 1, &state1);
PQ_StartVector(input, output, VECTOR_LEN);
PQ_Vector8BiquadDf2CascadeFixed32();
PQ_EndVector();
@endcode
*
*/
#define PQ_Vector8BiquadDf2CascadeFixed32() \
__asm volatile( \
"1: \n" \
" MCR p0,#0x1,r4,c3,c0,#6 \n" /* write biquad1*/ \
" CMP r3, #0 \n" \
" ITTTE NE \n" \
" MCRNE p0,#0x1,r7,c1,c0,#6 \n" /* write biquad0*/ \
" MRCNE p0,#0x1,r7,c1,c0,#0 \n" /* read biquad0*/ \
" MRCNE p0,#0x1,r4,c3,c0,#0 \n" /* read biquad1*/ \
" MRCEQ p0,#0x1,r4,c3,c0,#0 \n" /* read biquad1*/ \
" MCR p0,#0x1,r5,c3,c0,#6 \n" /* write biquad1*/ \
" MCR p0,#0x1,r4,c1,c0,#6 \n" /* write biquad0*/ \
" CMP r3, #0 \n" \
" ITE NE \n" \
" STRDNE r6,r7,[r1],#8 \n" /* store last two results*/ \
" MOVEQ r3, #1 \n" /* middle = 1 */ \
" LDMIA r0!,{r6-r9} \n" /* load next 4 datas */ \
" MRC p0,#0x1,r4,c1,c0,#0 \n" /* read biquad0*/ \
" MRC p0,#0x1,r5,c3,c0,#0 \n" /* read biquad1*/ \
" MCR p0,#0x1,r6,c3,c0,#6 \n" /* write biquad1*/ \
" MCR p0,#0x1,r5,c1,c0,#6 \n" /* write biquad0*/ \
" MRC p0,#0x1,r5,c1,c0,#0 \n" /* read biquad0*/ \
" MRC p0,#0x1,r6,c3,c0,#0 \n" /* read biquad1*/ \
" MCR p0,#0x1,r7,c3,c0,#6 \n" /* write biquad1*/ \
" MCR p0,#0x1,r6,c1,c0,#6 \n" /* write biquad0*/ \
" MRC p0,#0x1,r6,c1,c0,#0 \n" /* read biquad0*/ \
" MRC p0,#0x1,r7,c3,c0,#0 \n" /* read biquad1*/ \
" MCR p0,#0x1,r8,c3,c0,#6 \n" /* write biquad1*/ \
" MCR p0,#0x1,r7,c1,c0,#6 \n" /* write biquad0*/ \
" MRC p0,#0x1,r7,c1,c0,#0 \n" /* read biquad0*/ \
" MRC p0,#0x1,r8,c3,c0,#0 \n" /* read biquad1*/ \
" MCR p0,#0x1,r9,c3,c0,#6 \n" /* write biquad1*/ \
" MCR p0,#0x1,r8,c1,c0,#6 \n" /* write biquad0*/ \
" STMIA r1!,{R4-R7} \n" /* store first and second two results */ \
" LDRD r6,r7,[r0],#8 \n" /* load last 2 of the 8 */ \
" MRC p0,#0x1,r8,c1,c0,#0 \n" /* read biquad0*/ \
" MRC p0,#0x1,r9,c3,c0,#0 \n" /* read biquad1*/ \
" MCR p0,#0x1,r6,c3,c0,#6 \n" /* write biquad1*/ \
" MCR p0,#0x1,r9,c1,c0,#6 \n" /* write biquad0*/ \
" SUBS r2, r2, #8 \n" /* length -= 8; if (length != 0) */ \
" IT NE \n" \
" LDRDNE r4,r5,[r0],#8 \n" /* load first two of next 8 */ \
" MRC p0,#0x1,r9,c1,c0,#0 \n" /* read biquad0*/ \
" MRC p0,#0x1,r6,c3,c0,#0 \n" /* read biquad1*/ \
" MCR p0,#0x1,r7,c3,c0,#6 \n" /* write biquad1*/ \
" MCR p0,#0x1,r6,c1,c0,#6 \n" /* write biquad0*/ \
" STRD r8,r9,[r1],#8 \n" /* store third two results */ \
" MRC p0,#0x1,r6,c1,c0,#0 \n" /* read biquad0*/ \
" MRC p0,#0x1,r7,c3,c0,#0 \n" /* read biquad1*/ \
" CMP r2, #0 \n" /* if (length == 0) */ \
" BNE 1b \n" \
" MCR p0,#0x1,r7,c1,c0,#6 \n" /* write biquad0*/ \
" MRC p0,#0x1,r7,c1,c0,#0 \n" /* read biquad0*/ \
" STRD r6,r7,[r1],#8 \n" /* store fourth two results */ \
)
/*!
* @brief Fixed 16-bit data vector direct form II biquad cascade filter.
*
* The input and output data are fixed 16-bit data. The data flow is
* input -> biquad side 1 -> biquad side 0 -> output.
*
* @code
#define VECTOR_LEN 8
int32_t input[VECTOR_LEN] = {1, 2, 3, 4, 5, 6, 7, 8};
int32_t output[VECTOR_LEN];
pq_biquad_state_t state0 =
{
.param =
{
.a_1 = xxx,
.a_2 = xxx,
.b_0 = xxx,
.b_1 = xxx,
.b_2 = xxx,
},
};
pq_biquad_state_t state1 =
{
.param =
{
.a_1 = xxx,
.a_2 = xxx,
.b_0 = xxx,
.b_1 = xxx,
.b_2 = xxx,
},
};
PQ_BiquadRestoreInternalState(POWERQUAD, 0, &state0);
PQ_BiquadRestoreInternalState(POWERQUAD, 1, &state1);
PQ_StartVector(input, output, VECTOR_LEN);
PQ_Vector8BiquadDf2CascadeFixed16();
PQ_EndVector();
@endcode
*
*/
#define PQ_Vector8BiquadDf2CascadeFixed16() \
__asm volatile( \
"1: \n" \
" MCR p0,#0x1,r4,c3,c0,#6 \n" /* write biquad1*/ \
" CMP r3, #0 \n" \
" ITTTE NE \n" \
" MCRNE p0,#0x1,r7,c1,c0,#6 \n" /* write biquad0*/ \
" MRCNE p0,#0x1,r7,c1,c0,#0 \n" /* read biquad0*/ \
" MRCNE p0,#0x1,r4,c3,c0,#0 \n" /* read biquad1*/ \
" MRCEQ p0,#0x1,r4,c3,c0,#0 \n" /* read biquad1*/ \
" MCR p0,#0x1,r5,c3,c0,#6 \n" /* write biquad1*/ \
" MCR p0,#0x1,r4,c1,c0,#6 \n" /* write biquad0*/ \
" CMP r3, #0 \n" \
" ITTE NE \n" \
" STRHNE r6,[r1],#2 \n" /* store last two results*/ \
" STRHNE r7,[r1],#2 \n" /* store last two results*/ \
" MOVEQ r3, #1 \n" /* middle = 1 */ \
" LDRSH r6,[r0],#2 \n" /* load next 2 of the 8*/ \
" LDRSH r7,[r0],#2 \n" /* load next 2 of the 8*/ \
" MRC p0,#0x1,r4,c1,c0,#0 \n" /* read biquad0*/ \
" MRC p0,#0x1,r5,c3,c0,#0 \n" /* read biquad1*/ \
" MCR p0,#0x1,r6,c3,c0,#6 \n" /* write biquad1*/ \
" MCR p0,#0x1,r5,c1,c0,#6 \n" /* write biquad0*/ \
" MRC p0,#0x1,r5,c1,c0,#0 \n" /* read biquad0*/ \
" MRC p0,#0x1,r6,c3,c0,#0 \n" /* read biquad1*/ \
" LDRSH r8,[r0],#2 \n" /* load next 2 of the 8*/ \
" LDRSH r9,[r0],#2 \n" /* load next 2 of the 8*/ \
" MCR p0,#0x1,r7,c3,c0,#6 \n" /* write biquad1*/ \
" MCR p0,#0x1,r6,c1,c0,#6 \n" /* write biquad0*/ \
" MRC p0,#0x1,r6,c1,c0,#0 \n" /* read biquad0*/ \
" MRC p0,#0x1,r7,c3,c0,#0 \n" /* read biquad1*/ \
" STRH r4,[r1],#2 \n" /* store first 4 results */ \
" STRH r5,[r1],#2 \n" /* store first 4 results */ \
" MCR p0,#0x1,r8,c3,c0,#6 \n" /* write biquad1*/ \
" MCR p0,#0x1,r7,c1,c0,#6 \n" /* write biquad0*/ \
" MRC p0,#0x1,r7,c1,c0,#0 \n" /* read biquad0*/ \
" MRC p0,#0x1,r8,c3,c0,#0 \n" /* read biquad1*/ \
" MCR p0,#0x1,r9,c3,c0,#6 \n" /* write biquad1*/ \
" MCR p0,#0x1,r8,c1,c0,#6 \n" /* write biquad0*/ \
" STRH r6,[r1],#2 \n" /* store first 4 results */ \
" STRH r7,[r1],#2 \n" /* store first 4 results */ \
" LDRSH r6,[r0],#2 \n" /* load last 2 of the 8*/ \
" LDRSH r7,[r0],#2 \n" /* load last 2 of the 8*/ \
" MRC p0,#0x1,r8,c1,c0,#0 \n" /* read biquad0*/ \
" MRC p0,#0x1,r9,c3,c0,#0 \n" /* read biquad1*/ \
" MCR p0,#0x1,r6,c3,c0,#6 \n" /* write biquad1*/ \
" MCR p0,#0x1,r9,c1,c0,#6 \n" /* write biquad0*/ \
" SUBS r2, r2, #8 \n" /* length -= 8; if (length != 0) */ \
" ITT NE \n" \
" LDRSHNE r4,[r0],#2 \n" /* load first two of next 8*/ \
" LDRSHNE r5,[r0],#2 \n" /* load first two of next 8*/ \
" MRC p0,#0x1,r9,c1,c0,#0 \n" /* read biquad0*/ \
" MRC p0,#0x1,r6,c3,c0,#0 \n" /* read biquad1*/ \
" MCR p0,#0x1,r7,c3,c0,#6 \n" /* write biquad1*/ \
" MCR p0,#0x1,r6,c1,c0,#6 \n" /* write biquad0*/ \
" STRH r8,[r1],#2 \n" /* store third two results */ \
" STRH r9,[r1],#2 \n" /* store third two results */ \
" MRC p0,#0x1,r6,c1,c0,#0 \n" /* read biquad0*/ \
" MRC p0,#0x1,r7,c3,c0,#0 \n" /* read biquad1*/ \
" CMP r2, #0 \n" /* if (length == 0) */ \
" BNE 1b \n" \
" MCR p0,#0x1,r7,c1,c0,#6 \n" /* write biquad0*/ \
" MRC p0,#0x1,r7,c1,c0,#0 \n" /* read biquad0*/ \
" STRH r6,[r1],#2 \n" /* store fourth two results */ \
" STRH r7,[r1],#2 \n" /* store fourth two results */ \
)
/*! @brief Make the length used for matrix functions. */
#define POWERQUAD_MAKE_MATRIX_LEN(mat1Row, mat1Col, mat2Col) \
(((uint32_t)(mat1Row) << 0U) | ((uint32_t)(mat1Col) << 8U) | ((uint32_t)(mat2Col) << 16U))
/*! @brief Convert Q31 to float. */
#define PQ_Q31_2_FLOAT(x) (((float)(x)) / 2147483648.0f)
/*! @brief Convert Q15 to float. */
#define PQ_Q15_2_FLOAT(x) (((float)(x)) / 32768.0f)
/*! @brief powerquad computation engine */
typedef enum
{
kPQ_CP_PQ = 0, /*!< Math engine.*/
kPQ_CP_MTX = 1, /*!< Matrix engine.*/
kPQ_CP_FFT = 2, /*!< FFT engine.*/
kPQ_CP_FIR = 3, /*!< FIR engine.*/
kPQ_CP_CORDIC = 5 /*!< CORDIC engine.*/
} pq_computationengine_t;
/*! @brief powerquad data structure format type */
typedef enum
{
kPQ_16Bit = 0, /*!< Int16 Fixed point.*/
kPQ_32Bit = 1, /*!< Int32 Fixed point.*/
kPQ_Float = 2 /*!< Float point.*/
} pq_format_t;
/*! @brief Coprocessor prescale */
typedef struct
{
int8_t inputPrescale; /*!< Input prescale.*/
int8_t outputPrescale; /*!< Output prescale.*/
int8_t outputSaturate; /*!< Output saturate at n bits, for example 0x11 is 8 bit space,
the value will be truncated at +127 or -128.*/
} pq_prescale_t;
/*! @brief powerquad data structure format */
typedef struct
{
pq_format_t inputAFormat; /*!< Input A format.*/
int8_t inputAPrescale; /*!< Input A prescale, for example 1.5 can be 1.5*2^n if you scale by 'shifting'
('scaling' by a factor of n).*/
pq_format_t inputBFormat; /*!< Input B format.*/
int8_t inputBPrescale; /*!< Input B prescale.*/
pq_format_t outputFormat; /*!< Out format.*/
int8_t outputPrescale; /*!< Out prescale.*/
pq_format_t tmpFormat; /*!< Temp format.*/
int8_t tmpPrescale; /*!< Temp prescale.*/
pq_format_t machineFormat; /*!< Machine format.*/
uint32_t *tmpBase; /*!< Tmp base address.*/
} pq_config_t;
/*! @brief Struct to save biquad parameters. */
typedef struct _pq_biquad_param
{
float v_n_1; /*!< v[n-1], set to 0 when initialization. */
float v_n; /*!< v[n], set to 0 when initialization. */
float a_1; /*!< a[1] */
float a_2; /*!< a[2] */
float b_0; /*!< b[0] */
float b_1; /*!< b[1] */
float b_2; /*!< b[2] */
} pq_biquad_param_t;
/*! @brief Struct to save biquad state. */
typedef struct _pq_biquad_state
{
pq_biquad_param_t param; /*!< Filter parameter. */
uint32_t compreg; /*!< Internal register, set to 0 when initialization. */
} pq_biquad_state_t;
/*! @brief Instance structure for the direct form II Biquad cascade filter */
typedef struct
{
uint8_t numStages; /**< Number of 2nd order stages in the filter.*/
pq_biquad_state_t *pState; /**< Points to the array of state coefficients.*/
} pq_biquad_cascade_df2_instance;
/*! @brief CORDIC iteration */
typedef enum
{
kPQ_Iteration_8 = 0, /*!< Iterate 8 times.*/
kPQ_Iteration_16, /*!< Iterate 16 times.*/
kPQ_Iteration_24 /*!< Iterate 24 times.*/
} pq_cordic_iter_t;
/*! @brief Conversion between integer and float type */
typedef union _pq_float
{
float floatX; /*!< Float type.*/
uint32_t integerX; /*!< Unsigned interger type.*/
} pq_float_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus */
/*!
* @name POWERQUAD functional Operation
* @{
*/
/*!
* @brief Get default configuration.
*
* This function initializes the POWERQUAD configuration structure to a default value.
* FORMAT register field definitions
* Bits[15:8] scaler (for scaled 'q31' formats)
* Bits[5:4] external format. 00b=q15, 01b=q31, 10b=float
* Bits[1:0] internal format. 00b=q15, 01b=q31, 10b=float
* POWERQUAD->INAFORMAT = (config->inputAPrescale << 8U) | (config->inputAFormat << 4U) | config->machineFormat
*
* For all Powerquad operations internal format must be float (with the only exception being
* the FFT related functions, ie FFT/IFFT/DCT/IDCT which must be set to q31).
* The default values are:
* config->inputAFormat = kPQ_Float;
* config->inputAPrescale = 0;
* config->inputBFormat = kPQ_Float;
* config->inputBPrescale = 0;
* config->outputFormat = kPQ_Float;
* config->outputPrescale = 0;
* config->tmpFormat = kPQ_Float;
* config->tmpPrescale = 0;
* config->machineFormat = kPQ_Float;
* config->tmpBase = 0xE0000000;
*
* @param config Pointer to "pq_config_t" structure.
*/
void PQ_GetDefaultConfig(pq_config_t *config);
/*!
* @brief Set configuration with format/prescale.
*
* @param base POWERQUAD peripheral base address
* @param config Pointer to "pq_config_t" structure.
*/
void PQ_SetConfig(POWERQUAD_Type *base, const pq_config_t *config);
/*!
* @brief set coprocessor scaler for coprocessor instructions, this function is used to
* set output saturation and scaleing for input/output.
*
* @param base POWERQUAD peripheral base address
* @param prescale Pointer to "pq_prescale_t" structure.
*/
static inline void PQ_SetCoprocessorScaler(POWERQUAD_Type *base, const pq_prescale_t *prescale)
{
assert(NULL != prescale);
base->CPPRE = POWERQUAD_CPPRE_CPPRE_IN(prescale->inputPrescale) |
POWERQUAD_CPPRE_CPPRE_OUT(prescale->outputPrescale) |
((uint32_t)prescale->outputSaturate << POWERQUAD_CPPRE_CPPRE_SAT_SHIFT);
}
/*!
* @brief Initializes the POWERQUAD module.
*
* @param base POWERQUAD peripheral base address.
*/
void PQ_Init(POWERQUAD_Type *base);
/*!
* @brief De-initializes the POWERQUAD module.
*
* @param base POWERQUAD peripheral base address.
*/
void PQ_Deinit(POWERQUAD_Type *base);
/*!
* @brief Set format for non-coprecessor instructions.
*
* @param base POWERQUAD peripheral base address
* @param engine Computation engine
* @param format Data format
*/
void PQ_SetFormat(POWERQUAD_Type *base, pq_computationengine_t engine, pq_format_t format);
/*!
* @brief Wait for the completion.
*
* @param base POWERQUAD peripheral base address
*/
static inline void PQ_WaitDone(POWERQUAD_Type *base)
{
/* wait for the completion */
while ((base->CONTROL & INST_BUSY) == INST_BUSY)
{
__WFE();
}
}
/*!
* @brief Processing function for the floating-point natural log.
*
* @param *pSrc points to the block of input data. The range of the input value is (0 +INFINITY).
* @param *pDst points to the block of output data
*/
static inline void PQ_LnF32(float *pSrc, float *pDst)
{
pq_float_t val;
val.floatX = *pSrc;
_pq_ln0(val.integerX);
val.integerX = _pq_readAdd0();
*pDst = val.floatX;
}
/*!
* @brief Processing function for the floating-point reciprocal.
*
* @param *pSrc points to the block of input data. The range of the input value is non-zero.
* @param *pDst points to the block of output data
*/
static inline void PQ_InvF32(float *pSrc, float *pDst)
{
pq_float_t val;
val.floatX = *pSrc;
_pq_inv0(val.integerX);
val.integerX = _pq_readMult0();
*pDst = val.floatX;
}
/*!
* @brief Processing function for the floating-point square-root.
*
* @param *pSrc points to the block of input data. The range of the input value is [0 +INFINITY).
* @param *pDst points to the block of output data
*/
static inline void PQ_SqrtF32(float *pSrc, float *pDst)
{
pq_float_t val;
val.floatX = *pSrc;
_pq_sqrt0(val.integerX);
val.integerX = _pq_readMult0();
*pDst = val.floatX;
}
/*!
* @brief Processing function for the floating-point inverse square-root.
*
* @param *pSrc points to the block of input data. The range of the input value is (0 +INFINITY).
* @param *pDst points to the block of output data
*/
static inline void PQ_InvSqrtF32(float *pSrc, float *pDst)
{
pq_float_t val;
val.floatX = *pSrc;
_pq_invsqrt0(val.integerX);
val.integerX = _pq_readMult0();
*pDst = val.floatX;
}
/*!
* @brief Processing function for the floating-point natural exponent.
*
* @param *pSrc points to the block of input data. The range of the input value is (-INFINITY +INFINITY).
* @param *pDst points to the block of output data
*/
static inline void PQ_EtoxF32(float *pSrc, float *pDst)
{
pq_float_t val;
val.floatX = *pSrc;
_pq_etox0(val.integerX);
val.integerX = _pq_readMult0();
*pDst = val.floatX;
}
/*!
* @brief Processing function for the floating-point natural exponent with negative parameter.
*
* @param *pSrc points to the block of input data. The range of the input value is (-INFINITY +INFINITY).
* @param *pDst points to the block of output data
*/
static inline void PQ_EtonxF32(float *pSrc, float *pDst)
{
pq_float_t val;
val.floatX = *pSrc;
_pq_etonx0(val.integerX);
val.integerX = _pq_readMult0();
*pDst = val.floatX;
}
/*!
* @brief Processing function for the floating-point sine.
*
* @param *pSrc points to the block of input data. The input value is in radians, the range is (-INFINITY
* +INFINITY).
* @param *pDst points to the block of output data
*/
static inline void PQ_SinF32(float *pSrc, float *pDst)
{
pq_float_t val;
val.floatX = *pSrc;
_pq_sin0(val.integerX);
val.integerX = _pq_readAdd0();
*pDst = val.floatX;
}
/*!
* @brief Processing function for the floating-point cosine.
*
* @param *pSrc points to the block of input data. The input value is in radians, the range is (-INFINITY
* +INFINITY).
* @param *pDst points to the block of output data
*/
static inline void PQ_CosF32(float *pSrc, float *pDst)
{
pq_float_t val;
val.floatX = *pSrc;
_pq_cos0(val.integerX);
val.integerX = _pq_readAdd0();
*pDst = val.floatX;
}
/*!
* @brief Processing function for the floating-point biquad.
*
* @param *pSrc points to the block of input data
* @param *pDst points to the block of output data
*/
static inline void PQ_BiquadF32(float *pSrc, float *pDst)
{
pq_float_t val;
val.floatX = *pSrc;
_pq_biquad0(val.integerX);
val.integerX = _pq_readAdd0();
*pDst = val.floatX;
}
/*!
* @brief Processing function for the floating-point division.
*
* Get x1 / x2.
*
* @param x1 x1
* @param x2 x2
* @param *pDst points to the block of output data
*/
static inline void PQ_DivF32(float *x1, float *x2, float *pDst)
{
pq_float_t X1;
pq_float_t X2;
X1.floatX = *x1;
X2.floatX = *x2;
uint64_t input = (uint64_t)(X2.integerX) | ((uint64_t)(X1.integerX) << 32U);
_pq_div0(input);
X1.integerX = _pq_readMult0();
*pDst = X1.floatX;
}
/*!
* @brief Processing function for the floating-point biquad.
*
* @param *pSrc points to the block of input data
* @param *pDst points to the block of output data
*/
static inline void PQ_Biquad1F32(float *pSrc, float *pDst)
{
pq_float_t val;
val.floatX = *pSrc;
_pq_biquad1(val.integerX);
val.integerX = _pq_readAdd1();
*pDst = val.floatX;
}
/*!
* @brief Processing function for the fixed natural log.
*
* @param val value to be calculated. The range of the input value is (0 +INFINITY).
* @return returns ln(val).
*/
static inline int32_t PQ_LnFixed(int32_t val)
{
_pq_ln_fx0(val);
return (int32_t)_pq_readAdd0_fx();
}
/*!
* @brief Processing function for the fixed reciprocal.
*
* @param val value to be calculated. The range of the input value is non-zero.
* @return returns inv(val).
*/
static inline int32_t PQ_InvFixed(int32_t val)
{
_pq_inv_fx0(val);
return (int32_t)_pq_readMult0_fx();
}
/*!
* @brief Processing function for the fixed square-root.
*
* @param val value to be calculated. The range of the input value is [0 +INFINITY).
* @return returns sqrt(val).
*/
static inline uint32_t PQ_SqrtFixed(uint32_t val)
{
_pq_sqrt_fx0(val);
return _pq_readMult0_fx();
}
/*!
* @brief Processing function for the fixed inverse square-root.
*
* @param val value to be calculated. The range of the input value is (0 +INFINITY).
* @return returns 1/sqrt(val).
*/
static inline int32_t PQ_InvSqrtFixed(int32_t val)
{
_pq_invsqrt_fx0(val);
return (int32_t)_pq_readMult0_fx();
}
/*!
* @brief Processing function for the Fixed natural exponent.
*
* @param val value to be calculated. The range of the input value is (-INFINITY +INFINITY).
* @return returns etox^(val).
*/
static inline int32_t PQ_EtoxFixed(int32_t val)
{
_pq_etox_fx0(val);
return (int32_t)_pq_readMult0_fx();
}
/*!
* @brief Processing function for the fixed natural exponent with negative parameter.
*
* @param val value to be calculated. The range of the input value is (-INFINITY +INFINITY).
* @return returns etonx^(val).
*/
static inline int32_t PQ_EtonxFixed(int32_t val)
{
_pq_etonx_fx0(val);
return (int32_t)_pq_readMult0_fx();
}
/*!
* @brief Processing function for the fixed sine.
*
* @param val value to be calculated. The input value is [-1, 1] in Q31 format, which means [-pi, pi].
* @return returns sin(val).
*/
static inline int32_t PQ_SinQ31(int32_t val)
{
int32_t ret;
uint32_t cppre;
#if defined(FSL_FEATURE_POWERQUAD_SIN_COS_FIX_ERRATA) && FSL_FEATURE_POWERQUAD_SIN_COS_FIX_ERRATA
pq_float_t magic;
pq_float_t valFloat;
magic.integerX = 0x30c90fdb;
valFloat.floatX = magic.floatX * (float)val;
#endif
cppre = POWERQUAD->CPPRE;
POWERQUAD->CPPRE = POWERQUAD_CPPRE_CPPRE_OUT(31);
#if defined(FSL_FEATURE_POWERQUAD_SIN_COS_FIX_ERRATA) && FSL_FEATURE_POWERQUAD_SIN_COS_FIX_ERRATA
_pq_sin0(valFloat.integerX);
(void)_pq_readAdd0();
ret = (int32_t)_pq_readAdd0_fx();
#else
_pq_sin_fx0(val);
ret = (int32_t)_pq_readAdd0_fx();
#endif
POWERQUAD->CPPRE = cppre;
return ret;
}
/*!
* @brief Processing function for the fixed sine.
*
* @param val value to be calculated. The input value is [-1, 1] in Q15 format, which means [-pi, pi].
* @return returns sin(val).
*/
static inline int16_t PQ_SinQ15(int16_t val)
{
uint32_t ret;
uint32_t cppre;
#if defined(FSL_FEATURE_POWERQUAD_SIN_COS_FIX_ERRATA) && FSL_FEATURE_POWERQUAD_SIN_COS_FIX_ERRATA
pq_float_t magic;
pq_float_t valFloat;
magic.integerX = 0x30c90fdbU;
valFloat.floatX = magic.floatX * (float)(uint32_t)((uint32_t)val << 16U);
#endif
cppre = POWERQUAD->CPPRE;
/* Don't use 15 here, it is wrong then val is 0x4000 */
POWERQUAD->CPPRE = POWERQUAD_CPPRE_CPPRE_OUT(31);
#if defined(FSL_FEATURE_POWERQUAD_SIN_COS_FIX_ERRATA) && FSL_FEATURE_POWERQUAD_SIN_COS_FIX_ERRATA
_pq_sin0(valFloat.integerX);
(void)_pq_readAdd0();
ret = (_pq_readAdd0_fx() >> 16U);
#else
_pq_sin_fx0((uint32_t)val << 16U);
ret = (_pq_readAdd0_fx() >> 16U);
#endif
POWERQUAD->CPPRE = cppre;
return (int16_t)ret;
}
/*!
* @brief Processing function for the fixed cosine.
*
* @param val value to be calculated. The input value is [-1, 1] in Q31 format, which means [-pi, pi].
* @return returns cos(val).
*/
static inline int32_t PQ_CosQ31(int32_t val)
{
int32_t ret;
uint32_t cppre;
#if defined(FSL_FEATURE_POWERQUAD_SIN_COS_FIX_ERRATA) && FSL_FEATURE_POWERQUAD_SIN_COS_FIX_ERRATA
pq_float_t magic;
pq_float_t valFloat;
magic.integerX = 0x30c90fdb;
valFloat.floatX = magic.floatX * (float)val;
#endif
cppre = POWERQUAD->CPPRE;
POWERQUAD->CPPRE = POWERQUAD_CPPRE_CPPRE_OUT(31);
#if defined(FSL_FEATURE_POWERQUAD_SIN_COS_FIX_ERRATA) && FSL_FEATURE_POWERQUAD_SIN_COS_FIX_ERRATA
_pq_cos0(valFloat.integerX);
(void)_pq_readAdd0();
ret = (int32_t)_pq_readAdd0_fx();
#else
_pq_cos_fx0(val);
ret = (int32_t)_pq_readAdd0_fx();
#endif
POWERQUAD->CPPRE = cppre;
return ret;
}
/*!
* @brief Processing function for the fixed sine.
*
* @param val value to be calculated. The input value is [-1, 1] in Q15 format, which means [-pi, pi].
* @return returns sin(val).
*/
static inline int16_t PQ_CosQ15(int16_t val)
{
uint32_t ret;
uint32_t cppre;
#if defined(FSL_FEATURE_POWERQUAD_SIN_COS_FIX_ERRATA) && FSL_FEATURE_POWERQUAD_SIN_COS_FIX_ERRATA
pq_float_t magic;
pq_float_t valFloat;
magic.integerX = 0x30c90fdbU;
valFloat.floatX = magic.floatX * (float)(uint32_t)((uint32_t)val << 16U);
#endif
cppre = POWERQUAD->CPPRE;
POWERQUAD->CPPRE = POWERQUAD_CPPRE_CPPRE_OUT(31);
#if defined(FSL_FEATURE_POWERQUAD_SIN_COS_FIX_ERRATA) && FSL_FEATURE_POWERQUAD_SIN_COS_FIX_ERRATA
_pq_cos0(valFloat.integerX);
(void)_pq_readAdd0();
ret = _pq_readAdd0_fx() >> 16U;
#else
_pq_cos_fx0((uint32_t)val << 16U);
ret = _pq_readAdd0_fx() >> 16U;
#endif
POWERQUAD->CPPRE = cppre;
return (int16_t)ret;
}
/*!
* @brief Processing function for the fixed biquad.
*
* @param val value to be calculated
* @return returns biquad(val).
*/
static inline int32_t PQ_BiquadFixed(int32_t val)
{
_pq_biquad0_fx(val);
return (int32_t)_pq_readAdd0_fx();
}
/*!
* @brief Processing function for the floating-point vectorised natural log.
*
* @param *pSrc points to the block of input data
* @param *pDst points to the block of output data
* @param length the block of input data.
*/
void PQ_VectorLnF32(float *pSrc, float *pDst, int32_t length);
/*!
* @brief Processing function for the floating-point vectorised reciprocal.
*
* @param *pSrc points to the block of input data
* @param *pDst points to the block of output data
* @param length the block of input data.
*/
void PQ_VectorInvF32(float *pSrc, float *pDst, int32_t length);
/*!
* @brief Processing function for the floating-point vectorised square-root.
*
* @param *pSrc points to the block of input data
* @param *pDst points to the block of output data
* @param length the block of input data.
*/
void PQ_VectorSqrtF32(float *pSrc, float *pDst, int32_t length);
/*!
* @brief Processing function for the floating-point vectorised inverse square-root.
*
* @param *pSrc points to the block of input data
* @param *pDst points to the block of output data
* @param length the block of input data.
*/
void PQ_VectorInvSqrtF32(float *pSrc, float *pDst, int32_t length);
/*!
* @brief Processing function for the floating-point vectorised natural exponent.
*
* @param *pSrc points to the block of input data
* @param *pDst points to the block of output data
* @param length the block of input data.
*/
void PQ_VectorEtoxF32(float *pSrc, float *pDst, int32_t length);
/*!
* @brief Processing function for the floating-point vectorised natural exponent with negative parameter.
*
* @param *pSrc points to the block of input data
* @param *pDst points to the block of output data
* @param length the block of input data.
*/
void PQ_VectorEtonxF32(float *pSrc, float *pDst, int32_t length);
/*!
* @brief Processing function for the floating-point vectorised sine
*
* @param *pSrc points to the block of input data
* @param *pDst points to the block of output data
* @param length the block of input data.
*/
void PQ_VectorSinF32(float *pSrc, float *pDst, int32_t length);
/*!
* @brief Processing function for the floating-point vectorised cosine.
*
* @param *pSrc points to the block of input data
* @param *pDst points to the block of output data
* @param length the block of input data.
*/
void PQ_VectorCosF32(float *pSrc, float *pDst, int32_t length);
/*!
* @brief Processing function for the Q31 vectorised natural log.
*
* @param *pSrc points to the block of input data
* @param *pDst points to the block of output data
* @param length the block of input data.
*/
void PQ_VectorLnFixed32(int32_t *pSrc, int32_t *pDst, int32_t length);
/*!
* @brief Processing function for the Q31 vectorised reciprocal.
*
* @param *pSrc points to the block of input data
* @param *pDst points to the block of output data
* @param length the block of input data.
*/
void PQ_VectorInvFixed32(int32_t *pSrc, int32_t *pDst, int32_t length);
/*!
* @brief Processing function for the 32-bit integer vectorised square-root.
*
* @param *pSrc points to the block of input data
* @param *pDst points to the block of output data
* @param length the block of input data.
*/
void PQ_VectorSqrtFixed32(int32_t *pSrc, int32_t *pDst, int32_t length);
/*!
* @brief Processing function for the 32-bit integer vectorised inverse square-root.
*
* @param *pSrc points to the block of input data
* @param *pDst points to the block of output data
* @param length the block of input data.
*/
void PQ_VectorInvSqrtFixed32(int32_t *pSrc, int32_t *pDst, int32_t length);
/*!
* @brief Processing function for the 32-bit integer vectorised natural exponent.
*
* @param *pSrc points to the block of input data
* @param *pDst points to the block of output data
* @param length the block of input data.
*/
void PQ_VectorEtoxFixed32(int32_t *pSrc, int32_t *pDst, int32_t length);
/*!
* @brief Processing function for the 32-bit integer vectorised natural exponent with negative parameter.
*
* @param *pSrc points to the block of input data
* @param *pDst points to the block of output data
* @param length the block of input data.
*/
void PQ_VectorEtonxFixed32(int32_t *pSrc, int32_t *pDst, int32_t length);
/*!
* @brief Processing function for the Q15 vectorised sine
*
* @param *pSrc points to the block of input data
* @param *pDst points to the block of output data
* @param length the block of input data.
*/
void PQ_VectorSinQ15(int16_t *pSrc, int16_t *pDst, int32_t length);
/*!
* @brief Processing function for the Q15 vectorised cosine.
*
* @param *pSrc points to the block of input data
* @param *pDst points to the block of output data
* @param length the block of input data.
*/
void PQ_VectorCosQ15(int16_t *pSrc, int16_t *pDst, int32_t length);
/*!
* @brief Processing function for the Q31 vectorised sine
*
* @param *pSrc points to the block of input data
* @param *pDst points to the block of output data
* @param length the block of input data.
*/
void PQ_VectorSinQ31(int32_t *pSrc, int32_t *pDst, int32_t length);
/*!
* @brief Processing function for the Q31 vectorised cosine.
*
* @param *pSrc points to the block of input data
* @param *pDst points to the block of output data
* @param length the block of input data.
*/
void PQ_VectorCosQ31(int32_t *pSrc, int32_t *pDst, int32_t length);
/*!
* @brief Processing function for the 16-bit integer vectorised natural log.
*
* @param *pSrc points to the block of input data
* @param *pDst points to the block of output data
* @param length the block of input data.
*/
void PQ_VectorLnFixed16(int16_t *pSrc, int16_t *pDst, int32_t length);
/*!
* @brief Processing function for the 16-bit integer vectorised reciprocal.
*
* @param *pSrc points to the block of input data
* @param *pDst points to the block of output data
* @param length the block of input data.
*/
void PQ_VectorInvFixed16(int16_t *pSrc, int16_t *pDst, int32_t length);
/*!
* @brief Processing function for the 16-bit integer vectorised square-root.
*
* @param *pSrc points to the block of input data
* @param *pDst points to the block of output data
* @param length the block of input data.
*/
void PQ_VectorSqrtFixed16(int16_t *pSrc, int16_t *pDst, int32_t length);
/*!
* @brief Processing function for the 16-bit integer vectorised inverse square-root.
*
* @param *pSrc points to the block of input data
* @param *pDst points to the block of output data
* @param length the block of input data.
*/
void PQ_VectorInvSqrtFixed16(int16_t *pSrc, int16_t *pDst, int32_t length);
/*!
* @brief Processing function for the 16-bit integer vectorised natural exponent.
*
* @param *pSrc points to the block of input data
* @param *pDst points to the block of output data
* @param length the block of input data.
*/
void PQ_VectorEtoxFixed16(int16_t *pSrc, int16_t *pDst, int32_t length);
/*!
* @brief Processing function for the 16-bit integer vectorised natural exponent with negative parameter.
*
* @param *pSrc points to the block of input data
* @param *pDst points to the block of output data
* @param length the block of input data.
*/
void PQ_VectorEtonxFixed16(int16_t *pSrc, int16_t *pDst, int32_t length);
/*!
* @brief Processing function for the floating-point vectorised biquad direct form II.
*
* @param *pSrc points to the block of input data
* @param *pDst points to the block of output data
* @param length the block size of input data.
*/
void PQ_VectorBiquadDf2F32(float *pSrc, float *pDst, int32_t length);
/*!
* @brief Processing function for the 32-bit integer vectorised biquad direct form II.
*
* @param *pSrc points to the block of input data
* @param *pDst points to the block of output data
* @param length the block size of input data
*/
void PQ_VectorBiquadDf2Fixed32(int32_t *pSrc, int32_t *pDst, int32_t length);
/*!
* @brief Processing function for the 16-bit integer vectorised biquad direct form II.
*
* @param *pSrc points to the block of input data
* @param *pDst points to the block of output data
* @param length the block size of input data
*/
void PQ_VectorBiquadDf2Fixed16(int16_t *pSrc, int16_t *pDst, int32_t length);
/*!
* @brief Processing function for the floating-point vectorised biquad direct form II.
*
* @param *pSrc points to the block of input data
* @param *pDst points to the block of output data
* @param length the block size of input data
*/
void PQ_VectorBiquadCascadeDf2F32(float *pSrc, float *pDst, int32_t length);
/*!
* @brief Processing function for the 32-bit integer vectorised biquad direct form II.
*
* @param *pSrc points to the block of input data
* @param *pDst points to the block of output data
* @param length the block size of input data
*/
void PQ_VectorBiquadCascadeDf2Fixed32(int32_t *pSrc, int32_t *pDst, int32_t length);
/*!
* @brief Processing function for the 16-bit integer vectorised biquad direct form II.
*
* @param *pSrc points to the block of input data
* @param *pDst points to the block of output data
* @param length the block size of input data
*/
void PQ_VectorBiquadCascadeDf2Fixed16(int16_t *pSrc, int16_t *pDst, int32_t length);
/*!
* @brief Processing function for the fixed inverse trigonometric.
*
* Get the inverse tangent, the behavior is like c function atan.
*
* @param base POWERQUAD peripheral base address
* @param x value of opposite
* @param y value of adjacent
* @param iteration iteration times
* @return The return value is in the range of -2^26 to 2^26, which means -pi/2 to pi/2.
* @note The sum of x and y should not exceed the range of int32_t.
* @note Larger input number gets higher output accuracy, for example the arctan(0.5),
* the result of PQ_ArctanFixed(POWERQUAD, 100000, 200000, kPQ_Iteration_24) is more
* accurate than PQ_ArctanFixed(POWERQUAD, 1, 2, kPQ_Iteration_24).
*/
int32_t PQ_ArctanFixed(POWERQUAD_Type *base, int32_t x, int32_t y, pq_cordic_iter_t iteration);
/*!
* @brief Processing function for the fixed inverse trigonometric.
*
* @param base POWERQUAD peripheral base address
* @param x value of opposite
* @param y value of adjacent
* @param iteration iteration times
* @return The return value is radians, 2^27 means pi. The range is -1.118 to 1.118 radians.
* @note The sum of x and y should not exceed the range of int32_t.
* @note Larger input number gets higher output accuracy, for example the arctanh(0.5),
* the result of PQ_ArctanhFixed(POWERQUAD, 100000, 200000, kPQ_Iteration_24) is more
* accurate than PQ_ArctanhFixed(POWERQUAD, 1, 2, kPQ_Iteration_24).
*/
int32_t PQ_ArctanhFixed(POWERQUAD_Type *base, int32_t x, int32_t y, pq_cordic_iter_t iteration);
/*!
* @brief Processing function for the fixed inverse trigonometric.
*
* Get the inverse tangent, it calculates the angle in radians for the quadrant.
* The behavior is like c function atan2.
*
* @param base POWERQUAD peripheral base address
* @param x value of opposite
* @param y value of adjacent
* @param iteration iteration times
* @return The return value is in the range of -2^27 to 2^27, which means -pi to pi.
* @note The sum of x and y should not exceed the range of int32_t.
* @note Larger input number gets higher output accuracy, for example the arctan(0.5),
* the result of PQ_Arctan2Fixed(POWERQUAD, 100000, 200000, kPQ_Iteration_24) is more
* accurate than PQ_Arctan2Fixed(POWERQUAD, 1, 2, kPQ_Iteration_24).
*/
int32_t PQ_Arctan2Fixed(POWERQUAD_Type *base, int32_t x, int32_t y, pq_cordic_iter_t iteration);
/*!
* @brief Processing function for the fixed biquad.
*
* @param val value to be calculated
* @return returns biquad(val).
*/
static inline int32_t PQ_Biquad1Fixed(int32_t val)
{
_pq_biquad1_fx(val);
return (int32_t)_pq_readAdd1_fx();
}
/*!
* @brief Processing function for the complex FFT.
*
* @param base POWERQUAD peripheral base address
* @param length number of input samples
* @param pData input data
* @param pResult output data.
*/
void PQ_TransformCFFT(POWERQUAD_Type *base, uint32_t length, void *pData, void *pResult);
/*!
* @brief Processing function for the real FFT.
*
* @param base POWERQUAD peripheral base address
* @param length number of input samples
* @param pData input data
* @param pResult output data.
*/
void PQ_TransformRFFT(POWERQUAD_Type *base, uint32_t length, void *pData, void *pResult);
/*!
* @brief Processing function for the inverse complex FFT.
*
* @param base POWERQUAD peripheral base address
* @param length number of input samples
* @param pData input data
* @param pResult output data.
*/
void PQ_TransformIFFT(POWERQUAD_Type *base, uint32_t length, void *pData, void *pResult);
/*!
* @brief Processing function for the complex DCT.
*
* @param base POWERQUAD peripheral base address
* @param length number of input samples
* @param pData input data
* @param pResult output data.
*/
void PQ_TransformCDCT(POWERQUAD_Type *base, uint32_t length, void *pData, void *pResult);
/*!
* @brief Processing function for the real DCT.
*
* @param base POWERQUAD peripheral base address
* @param length number of input samples
* @param pData input data
* @param pResult output data.
*/
void PQ_TransformRDCT(POWERQUAD_Type *base, uint32_t length, void *pData, void *pResult);
/*!
* @brief Processing function for the inverse complex DCT.
*
* @param base POWERQUAD peripheral base address
* @param length number of input samples
* @param pData input data
* @param pResult output data.
*/
void PQ_TransformIDCT(POWERQUAD_Type *base, uint32_t length, void *pData, void *pResult);
/*!
* @brief Processing function for backup biquad context.
*
* @param base POWERQUAD peripheral base address
* @param biquad_num biquad side
* @param state point to states.
*/
void PQ_BiquadBackUpInternalState(POWERQUAD_Type *base, int32_t biquad_num, pq_biquad_state_t *state);
/*!
* @brief Processing function for restore biquad context.
*
* @param base POWERQUAD peripheral base address
* @param biquad_num biquad side
* @param state point to states.
*/
void PQ_BiquadRestoreInternalState(POWERQUAD_Type *base, int32_t biquad_num, pq_biquad_state_t *state);
/*!
* @brief Initialization function for the direct form II Biquad cascade filter.
*
* @param[in,out] *S points to an instance of the filter data structure.
* @param[in] numStages number of 2nd order stages in the filter.
* @param[in] *pState points to the state buffer.
*/
void PQ_BiquadCascadeDf2Init(pq_biquad_cascade_df2_instance *S, uint8_t numStages, pq_biquad_state_t *pState);
/*!
* @brief Processing function for the floating-point direct form II Biquad cascade filter.
*
* @param[in] *S points to an instance of the filter data structure.
* @param[in] *pSrc points to the block of input data.
* @param[out] *pDst points to the block of output data
* @param[in] blockSize number of samples to process.
*/
void PQ_BiquadCascadeDf2F32(const pq_biquad_cascade_df2_instance *S, float *pSrc, float *pDst, uint32_t blockSize);
/*!
* @brief Processing function for the Q31 direct form II Biquad cascade filter.
*
* @param[in] *S points to an instance of the filter data structure.
* @param[in] *pSrc points to the block of input data.
* @param[out] *pDst points to the block of output data
* @param[in] blockSize number of samples to process.
*/
void PQ_BiquadCascadeDf2Fixed32(const pq_biquad_cascade_df2_instance *S,
int32_t *pSrc,
int32_t *pDst,
uint32_t blockSize);
/*!
* @brief Processing function for the Q15 direct form II Biquad cascade filter.
*
* @param[in] *S points to an instance of the filter data structure.
* @param[in] *pSrc points to the block of input data.
* @param[out] *pDst points to the block of output data
* @param[in] blockSize number of samples to process.
*/
void PQ_BiquadCascadeDf2Fixed16(const pq_biquad_cascade_df2_instance *S,
int16_t *pSrc,
int16_t *pDst,
uint32_t blockSize);
/*!
* @brief Processing function for the FIR.
*
* @param base POWERQUAD peripheral base address
* @param pAData the first input sequence
* @param ALength number of the first input sequence
* @param pBData the second input sequence
* @param BLength number of the second input sequence
* @param pResult array for the output data
* @param opType operation type, could be PQ_FIR_FIR, PQ_FIR_CONVOLUTION, PQ_FIR_CORRELATION.
*/
void PQ_FIR(POWERQUAD_Type *base,
const void *pAData,
int32_t ALength,
const void *pBData,
int32_t BLength,
void *pResult,
uint32_t opType);
/*!
* @brief Processing function for the incremental FIR.
* This function can be used after pq_fir() for incremental FIR
* operation when new x data are available
*
* @param base POWERQUAD peripheral base address
* @param ALength number of input samples
* @param BLength number of taps
* @param xOffset offset for number of input samples
*/
void PQ_FIRIncrement(POWERQUAD_Type *base, int32_t ALength, int32_t BLength, int32_t xOffset);
/*!
* @brief Processing function for the matrix addition.
*
* @param base POWERQUAD peripheral base address
* @param length rows and cols for matrix. LENGTH register configuration:
* LENGTH[23:16] = M2 cols
* LENGTH[15:8] = M1 cols
* LENGTH[7:0] = M1 rows
* This could be constructed using macro @ref POWERQUAD_MAKE_MATRIX_LEN.
* @param pAData input matrix A
* @param pBData input matrix B
* @param pResult array for the output data.
*/
void PQ_MatrixAddition(POWERQUAD_Type *base, uint32_t length, void *pAData, void *pBData, void *pResult);
/*!
* @brief Processing function for the matrix subtraction.
*
* @param base POWERQUAD peripheral base address
* @param length rows and cols for matrix. LENGTH register configuration:
* LENGTH[23:16] = M2 cols
* LENGTH[15:8] = M1 cols
* LENGTH[7:0] = M1 rows
* This could be constructed using macro @ref POWERQUAD_MAKE_MATRIX_LEN.
* @param pAData input matrix A
* @param pBData input matrix B
* @param pResult array for the output data.
*/
void PQ_MatrixSubtraction(POWERQUAD_Type *base, uint32_t length, void *pAData, void *pBData, void *pResult);
/*!
* @brief Processing function for the matrix multiplication.
*
* @param base POWERQUAD peripheral base address
* @param length rows and cols for matrix. LENGTH register configuration:
* LENGTH[23:16] = M2 cols
* LENGTH[15:8] = M1 cols
* LENGTH[7:0] = M1 rows
* This could be constructed using macro @ref POWERQUAD_MAKE_MATRIX_LEN.
* @param pAData input matrix A
* @param pBData input matrix B
* @param pResult array for the output data.
*/
void PQ_MatrixMultiplication(POWERQUAD_Type *base, uint32_t length, void *pAData, void *pBData, void *pResult);
/*!
* @brief Processing function for the matrix product.
*
* @param base POWERQUAD peripheral base address
* @param length rows and cols for matrix. LENGTH register configuration:
* LENGTH[23:16] = M2 cols
* LENGTH[15:8] = M1 cols
* LENGTH[7:0] = M1 rows
* This could be constructed using macro @ref POWERQUAD_MAKE_MATRIX_LEN.
* @param pAData input matrix A
* @param pBData input matrix B
* @param pResult array for the output data.
*/
void PQ_MatrixProduct(POWERQUAD_Type *base, uint32_t length, void *pAData, void *pBData, void *pResult);
/*!
* @brief Processing function for the vector dot product.
*
* @param base POWERQUAD peripheral base address
* @param length length of vector
* @param pAData input vector A
* @param pBData input vector B
* @param pResult array for the output data.
*/
void PQ_VectorDotProduct(POWERQUAD_Type *base, uint32_t length, void *pAData, void *pBData, void *pResult);
/*!
* @brief Processing function for the matrix inverse.
*
* @param base POWERQUAD peripheral base address
* @param length rows and cols for matrix. LENGTH register configuration:
* LENGTH[23:16] = M2 cols
* LENGTH[15:8] = M1 cols
* LENGTH[7:0] = M1 rows
* This could be constructed using macro @ref POWERQUAD_MAKE_MATRIX_LEN.
* @param pData input matrix
* @param pTmpData input temporary matrix, pTmpData length not less than pData lenght and 1024 words is sufficient for
* the largest supported matrix.
* @param pResult array for the output data, round down for fixed point.
*/
void PQ_MatrixInversion(POWERQUAD_Type *base, uint32_t length, void *pData, void *pTmpData, void *pResult);
/*!
* @brief Processing function for the matrix transpose.
*
* @param base POWERQUAD peripheral base address
* @param length rows and cols for matrix. LENGTH register configuration:
* LENGTH[23:16] = M2 cols
* LENGTH[15:8] = M1 cols
* LENGTH[7:0] = M1 rows
* This could be constructed using macro @ref POWERQUAD_MAKE_MATRIX_LEN.
* @param pData input matrix
* @param pResult array for the output data.
*/
void PQ_MatrixTranspose(POWERQUAD_Type *base, uint32_t length, void *pData, void *pResult);
/*!
* @brief Processing function for the matrix scale.
*
* @param base POWERQUAD peripheral base address
* @param length rows and cols for matrix. LENGTH register configuration:
* LENGTH[23:16] = M2 cols
* LENGTH[15:8] = M1 cols
* LENGTH[7:0] = M1 rows
* This could be constructed using macro @ref POWERQUAD_MAKE_MATRIX_LEN.
* @param misc scaling parameters
* @param pData input matrix
* @param pResult array for the output data.
*/
void PQ_MatrixScale(POWERQUAD_Type *base, uint32_t length, float misc, const void *pData, void *pResult);
/*! @} */
#if defined(__cplusplus)
}
#endif /* __cplusplus */
/*! @}*/
#endif /* FSL_POWERQUAD_H_ */