c2000ware-core-sdk/libraries/control/DCL/c28/include/DCL.h

423 lines
15 KiB
C
Raw Permalink Normal View History

2023-12-13 14:16:16 +03:00
/* DCL.h - C2000 Digital Control Library
*
*/
//#############################################################################
//!
//! Copyright: Copyright (C) 2023 Texas Instruments Incorporated -
//! All rights reserved not granted herein.
//! Limited License.
//!
//! Texas Instruments Incorporated grants a world-wide, royalty-free,
//! non-exclusive license under copyrights and patents it now or hereafter
//! owns or controls to make, have made, use, import, offer to sell and sell
//! ("Utilize") this software subject to the terms herein. With respect to the
//! foregoing patent license, such license is granted solely to the extent that
//! any such patent is necessary to Utilize the software alone. The patent
//! license shall not apply to any combinations which include this software,
//! other than combinations with devices manufactured by or for TI
//! ("TI Devices").
//! No hardware patent is licensed hereunder.
//!
//! Redistributions must preserve existing copyright notices and reproduce this
//! license (including the above copyright notice and the disclaimer and
//! (if applicable) source code license limitations below) in the documentation
//! and/or other materials provided with the distribution.
//!
//! Redistribution and use in binary form, without modification, are permitted
//! provided that the following conditions are met:
//!
//! * No reverse engineering, decompilation, or disassembly of this software is
//! permitted with respect to any software provided in binary form.
//! * Any redistribution and use are licensed by TI for use only
//! with TI Devices.
//! * Nothing shall obligate TI to provide you with source code for the
//! software licensed and provided to you in object code.
//!
//! If software source code is provided to you, modification and redistribution
//! of the source code are permitted provided that the following conditions
//! are met:
//!
//! * any redistribution and use of the source code, including any resulting
//! derivative works, are licensed by TI for use only with TI Devices.
//! * any redistribution and use of any object code compiled from the source
//! code and any resulting derivative works, are licensed by TI for use
//! only with TI Devices.
//!
//! Neither the name of Texas Instruments Incorporated nor the names of its
//! suppliers may be used to endorse or promote products derived from this
//! software without specific prior written permission.
//#############################################################################
#ifndef _C_DCL_H
#define _C_DCL_H
#ifdef __cplusplus
extern "C" {
#endif
//! \file DCL.h
//! \brief Contains the public interface to the common
//! Digital Controller Library functions
//! \brief Library version number formatted for numerical comparison
//!
#define DCL_VERSION 3040000
#ifndef C2000_IEEE754_TYPES
#define C2000_IEEE754_TYPES
#ifdef __TI_EABI__
typedef float float32_t;
typedef double float64_t;
#else
typedef float float32_t;
typedef long double float64_t;
#endif // __TI_EABI__
#endif // C2000_IEEE754_TYPES
#ifndef __TMS320C28XX_CLA__
#include <complex.h>
#include <math.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
//! \brief Local definitions of mathematical constants
//!
#define CONST_PI_32 3.14159265358979323846f
#define CONST_2PI_32 2.0f * CONST_PI_32
#define CONST_PI_64 3.1415926535897932384626433832795028841971693993751058209749445923078164062L
#define CONST_2PI_64 2.0L * CONST_PI_64
//! \brief Defines 32-bit null address for pointer initialization
//!
#define NULL_ADDR 0x00000000
//! \brief Define the acceptable FPU numerical tolerances
//!
#define DEFAULT_FPU32_TOL 1.0e-06f
#define DEFAULT_FPU64_TOL 1.0e-10f
//! \brief Determines numerical proximity to specified value
//!
#define F32_IS_VALUE(x,y) (((x < (y + DEFAULT_FPU32_TOL)) && (x > (y - DEFAULT_FPU32_TOL))) ? 1 : 0)
#define F64_IS_VALUE(x,y) (((x < (y + DEFAULT_FPU64_TOL)) && (x > (y - DEFAULT_FPU64_TOL))) ? 1 : 0)
//! \brief Determines numerical proximity to zero
//!
#define F32_IS_ZERO(x) F32_IS_VALUE(x,0.0f)
#define F64_IS_ZERO(x) F64_IS_VALUE(x,0.0L)
//! \brief Returns a random floating point result between -1.0 and +1.0
//! where 'a' is a single or double precision float.
//! Useful for initialization of arrays and matrices during test.
//! Ensure compiler switch "--fp_mode = relaxed" is set to ensure h/w division.
//!
//! \code
//! float32_t s = DCL_randf(1.0f);
//!
#define DCL_randf(a) (a * ((float32_t) rand() / (float32_t) (RAND_MAX >> 1) - 1.0f))
#define DCL_randf64(a) (a * ((float64_t) rand() / (float64_t) (RAND_MAX >> 1) - 1.0L))
//! \brief Defines the lower limit on derivative filter coefficient c2
//! in order for fc to lie below the Nyquist frequency
//!
#define DCL_C2_LIMIT_32 ((2.0f - CONST_PI_32) / (2.0f + CONST_PI_32))
#define DCL_C2_LIMIT_64 ((2.0L - CONST_PI_64) / (2.0L + CONST_PI_64))
//! \brief Define the default control period in seconds
//!
#define DCL_DEFAULT_T_F32 100.0e-06f
#define DCL_DEFAULT_T_F64 100.0e-06L
//! \brief Build the library with controller test points enabled
//!
#define DCL_TESTPOINTS_ENABLED
//! \brief Build the library with break points enabled
//!
#define DCL_BREAK_POINTS_ENABLED
//! \brief Defines a debug break point
//!
#ifdef DCL_BREAK_POINTS_ENABLED
#define DCL_BREAK_POINT asm(" ESTOP0")
#else
#define DCL_BREAK_POINT ;
#endif
//! \brief Boundary instructions for atomic code blocks
//! Global interrupt mask is set at start of atomic block and
//! restored to its' original value at the end
//!
#ifdef __TMS320C28XX__
#define DCL_DISABLE_INTS DCL_disableInts()
#define DCL_RESTORE_INTS(v) DCL_restoreInts(v)
//! \brief Sets global interrupts mask
//! \return Original ST1 register value
//!
static inline int16_t DCL_disableInts(void)
{
return __disable_interrupts();
}
//! \brief Restores global interrupts if they were previously enabled
//! \param[in] v Original ST1 register value
//! \return None
//!
static inline void DCL_restoreInts(int16_t v)
{
if (0 == (v & 0x1))
{
__enable_interrupts();
}
}
#else
#define DCL_DISABLE_INTS 0
#define DCL_RESTORE_INTS(v) ;
#warning "CPU not recognized. Parameter updates may not be atomic."
#endif
//--- Controller Common Support Structure ------------------------------------
//! \brief Defines the controller common support structure
//!
//! \details The CSS is accessed via a pointer in most of the DCL
//! controller structs. It contains data used for testing and
//! configuring the controller, as well as for error checking.
//!
typedef struct dcl_css {
float32_t tpt; //!< Test point
float32_t T; //!< Controller period in seconds
uint32_t sts; //!< Status word
uint32_t err; //!< Error code
uint32_t loc; //!< Error location
} DCL_CSS;
//! \brief Default values to initialize the CSS structure
//!
#define DCL_CSS_DEFAULTS { 0.0f, DCL_DEFAULT_T_F32, 0UL, 0UL, 0UL }
//! \brief Loads the controller period in the CSS
//! CSS pointer must be configured first
//! \param[in] p Pointer to the controller structure
//! \param[in] a Sample period in seconds
//! \return None
//!
#define DCL_SET_CONTROLLER_PERIOD(p,a) ((p)->css->T = a)
//! \brief Re-definition of legacy controller period call
//!
#define DCL_SET_SAMPLE_RATE DCL_SET_CONTROLLER_PERIOD
//--- Status word ------------------------------------------------------------
//! \brief Defines the library enumerated status bits
//!
//! \details To perform a safe parameter update, the user first loads new
//! parameters into the controller shadow parameter set, then sets
//! the STS_UPDATE_PENDING bit in the controller status word. The
//! next call to the update function performs the "shadow-to-
//! active" set copy while global interrupts are disabled.
//!
enum dcl_status_bits {
STS_NONE = 0UL, //!< Status empty
STS_UPDATE_PENDING = (1U << 0), //!< Parameter update pending
STS_CONTROLLER_RUNNING = (1U << 1), //!< Controller operation in progress
STS_ADJUSTMENT_RUNNING = (1U << 2) //!< Parameter adjustment in progress
};
//! \brief Macros to set the update flag in the status word to initiate
//! controller parameter update on next DCL_update() call, and to
//! clear the flag on completion.
//!
#define DCL_REQUEST_UPDATE(p) ((p)->css->sts |= STS_UPDATE_PENDING)
#define DCL_CLEAR_UPDATE_REQUEST(p) ((p)->css->sts &= ~STS_UPDATE_PENDING)
//! \brief Macro to determine whether a parameter update is pending
//! based on the STS_UPDATE_PENDING bit in the status word.
#define DCL_UPDATE_WAITING(p) (0U != ((p)->css->sts & STS_UPDATE_PENDING))
//! \brief Macros placed at the beginning and end of the controller
//! so that other functions know a control operation is in
//! progress. Typically only used with complex controllers
//! which may not be atomic.
//!
#define DCL_CONTROLLER_BEGIN(p) ((p)->css->sts |= STS_CONTROLLER_RUNNING)
#define DCL_CONTROLLER_END(p) ((p)->css->sts &= ~STS_CONTROLLER_RUNNING)
//! \brief Macro to determine whether a controller is being executed
//! based on the DCL_CONTROLLER_RUNNING bit in the status word.
#define DCL_CONTROLLER_IN_PROGRESS(p) (0U != ((p)->css->sts & STS_CONTROLLER_RUNNING))
//! \brief Macros to set the flag in the status word to denote
//! that parameter adjustment is in progress, and to
//! clear the flag when the target is reached.
//!
#define DCL_ADJUSTMENT_RUNNING(p) ((p)->css->sts |= STS_ADJUSTMENT_RUNNING)
#define DCL_ADJUSTMENT_COMPLETE(p) ((p)->css->sts &= ~STS_ADJUSTMENT_RUNNING)
//! \brief Macro to determine whether parameter adjustment is underway
//! based on the DCL_ADJUSTMENT_RUNNING bit in the status word.
#define DCL_ADJUSTMENT_IN_PROGRESS(p) (0U != ((p)->css->sts & STS_ADJUSTMENT_RUNNING))
//--- Error handling ---------------------------------------------------------
//! \brief Build the library with error handling enabled
//!
#define DCL_ERROR_HANDLING_ENABLED
//! \brief Defines the library enumerated error codes
//! These will be applied as bit masks in the error handler
//!
enum dcl_error_codes {
ERR_NONE = 0U, //!< No error
ERR_PARAM_RANGE = (1U << 0), //!< Parameter range exceeded
ERR_PARAM_INVALID = (1U << 1), //!< Parameter not valid
ERR_PARAM_WARN = (1U << 2), //!< Parameter warning
ERR_INPUT_RANGE = (1U << 3), //!< Input range exceeded
ERR_OVERFLOW = (1U << 4), //!< Numerical overflow
ERR_UNDERFLOW = (1U << 5), //!< Numerical underflow
ERR_VERSION = (1U << 6), //!< Incorrect DCL version
ERR_DEVICE = (1U << 7), //!< Device not supported
ERR_CONTROLLER = (1U << 8), //!< Controller operation not completed
ERR_TIMING = (1U << 9), //!< Timing error
ERR_COMPUTATION = (1U << 10) //!< Computation error
};
//! \brief Macro to clear stored error code in CSS
//!
#define DCL_CLEAR_ERROR_CODE(p) (p->css->err = ERR_NONE)
//! \brief Macro to store code location of error in CSS
//!
#define DCL_GET_ERROR_LOC(n) (n->loc = (ERR_NONE == n->err) ? NULL_ADDR : __LINE__)
//! \brief Define error handling routine
//!
#define DCL_RUN_ERROR_HANDLER(n) DCL_runErrorHandler(n)
//! \brief Prototype for external basic error handler [DCL_error.c]
//! \param[in] p Pointer to DCL_CSS structure
//! \return None
//!
extern void DCL_runErrorHandler(DCL_CSS *p);
//--- Polynomial stability functions -----------------------------------------
//! \brief Determines stability of a first order real polynomial
//! P(z) = z + a1
//! \param[in] a1 Coefficient a1
//! \return 'true' if the root has magnitude less than 1, 'false' otherwise
//!
static inline bool DCL_isStablePn1(float32_t a1)
{
return(((a1 * a1) < 1.0f) ? true : false);
}
//! \brief Determines stability of a second order polynomial with real coefficients
//! P(z) = a0 z^2 + a1 z + a2
//! \param[in] a1 Coefficient a1
//! \param[in] a2 Coefficient a2
//! \return 'true' if both roots have magnitude less than 1, 'false' otherwise
//!
static inline bool DCL_isStablePn2(float32_t a0, float32_t a1, float32_t a2)
{
float32_t b0, b1, c0;
b0 = a0 - a2 * a2 / a0;
b1 = a1 - a1 * a2 / a0;
c0 = b0 - b1 * b1 / b0;
if ((a0 > 0.0f) && (b0 > 0.0f) && (c0 > 0.0f))
{
return(true);
}
else
{
return(false);
}
}
//! \brief Determines stability of a third order polynomial with real coefficients
//! P(z) = a0 z^3 + a1 z^2 + a2 z + a3
//! \param[in] a1 Coefficient a1
//! \param[in] a2 Coefficient a2
//! \param[in] a3 Coefficient a3
//! \return 'true' if all roots have magnitude less than 1, 'false' otherwise
//!
static inline bool DCL_isStablePn3(float32_t a0, float32_t a1, float32_t a2, float32_t a3)
{
float32_t b0, b1, b2, c0, c1, d0;
b0 = a0 - a3 * a3 / a0;
b1 = a1 - a2 * a3 / a0;
b2 = a2 - a1 * a3 / a0;
c0 = b0 - b2 * b2 / b0;
c1 = b1 - b1 * b2 / b0;
d0 = c0 - c1 * c1 / c0;
if ((a0 > 0.0f) && (b0 > 0.0f) && (c0 > 0.0f) && (d0 > 0.0f))
{
return(true);
}
else
{
return(false);
}
}
//--- ZPK3 structure ---------------------------------------------------------
//! \brief Defines the DCL_ZPK3 controller structure.
//!
//! \details Allows controllers to be defined in terms of complex pole
//! and zero frequencies. The common structure consists of
//! three complex zeros, three complex poles, and a real gain.
//! All frequencies must be specified in radians/sec.
//!
typedef struct dcl_zpk3 {
float complex z1;
float complex z2;
float complex z3;
float complex p1;
float complex p2;
float complex p3;
float32_t K;
} DCL_ZPK3;
//! \brief Defines default values to initialize the DCL_ZPK3 structure
//!
#define ZPK3_DEFAULTS { 0.0f + 0.0f*I, 0.0f + 0.0f*I, 0.0f + 0.0f*I, \
0.0f + 0.0f*I, 0.0f + 0.0f*I, 0.0f + 0.0f*I, \
1.0f }
//! \brief Determines stability of a ZPK3 representation by checking pole magnitude
//! \param[in] q Pointer to DCL_ZPK3 structure
//! \return 'true' if all poles have magnitude less than 1, 'false' otherwise
//!
static inline bool DCL_isStableZpk3(DCL_ZPK3 *q)
{
return(((cabsf(q->p1) < 1.0f) && (cabsf(q->p2) < 1.0f) && (cabsf(q->p3) < 1.0f)) ? true : false);
}
//----------------------------------------------------------------------------
#endif // __TMS320C28XX_CLA__
#ifdef __cplusplus
}
#endif // extern "C"
#endif // _C_DCL_H
/* end of file */