132 lines
4.9 KiB
C
132 lines
4.9 KiB
C
#ifndef INC_LIBSFRA_H_
|
|
#define INC_LIBSFRA_H_
|
|
|
|
#include <stdint.h>
|
|
|
|
#include "libsfra_config.h"
|
|
|
|
/*
|
|
* In some MCU/DSP, code runs much faster in RAM.
|
|
* This is particular for the ISR routine and the function it may call.
|
|
* Placing them in the memory yields short execution time and less penalty.
|
|
*
|
|
* On STM32 GCC + Makefile:
|
|
* 1. Declare macro in "libsfra_config.h":
|
|
* "#define SFRA_RAMFUNC(functionName) __attribute__ ((long_call, section (".ramfunc")))"
|
|
* 2. Add "*(.ramfunc)" to ".data" section.
|
|
*
|
|
*/
|
|
#ifndef SFRA_RAMFUNC
|
|
#define SFRA_RAMFUNC(functionName)
|
|
#endif
|
|
|
|
#if(SFRA_INT)
|
|
#include "fast_tri.h"
|
|
|
|
#define SFRA_OMEGA_DEC_BITS 8
|
|
|
|
typedef int32_t sfra_signal_t;
|
|
typedef int64_t sfra_integral_t;
|
|
#else // #if(SFRA_INT)
|
|
#include <math.h>
|
|
// Use float accelerated trigonometric functions.
|
|
#define SFRA_FLOAT_SIN(omega) sinf(omega)
|
|
#define SFRA_FLOAT_COS(omega) cosf(omega)
|
|
#endif // #if(SFRA_INT)
|
|
|
|
typedef float sfra_float_t;
|
|
typedef uint32_t sfra_size_t;
|
|
typedef int_least8_t sfra_flag_t;
|
|
|
|
typedef struct {
|
|
sfra_float_t *ctrl_real;
|
|
sfra_float_t *ctrl_nimg;
|
|
sfra_float_t *fb_real;
|
|
sfra_float_t *fb_nimg;
|
|
sfra_float_t *magnitudeVect;
|
|
sfra_float_t *phaseVect;
|
|
sfra_float_t *freqVect; //!< Frequency Vector
|
|
} sfra_result;
|
|
|
|
typedef struct {
|
|
sfra_float_t isrFreq; //!< SFRA ISR frequency
|
|
sfra_float_t freqStart; //!< Start frequency of SFRA sweep
|
|
sfra_float_t freqStep; //!< Log space between frequency points (optional)
|
|
sfra_size_t vecLength; //!< No. of Points in the SFRA
|
|
} sfra_setup;
|
|
|
|
typedef struct {
|
|
// Outer loop & state machine
|
|
sfra_flag_t start;
|
|
sfra_flag_t running;
|
|
sfra_flag_t done;
|
|
sfra_size_t freqIndex; //!< Index of the frequency vector
|
|
|
|
// Inner loop & state machine
|
|
volatile sfra_flag_t dtft_running; // Set and monitored by main(), clear by sfra_monitor() [in interrupt]
|
|
sfra_size_t data_count; // Set by main(), read by sfra_monitor() [in interrupt]
|
|
sfra_size_t data_index; // Clear by main(), read and write by sfra_monitor() [in interrupt]
|
|
|
|
#if(SFRA_INT)
|
|
fast_tri_omega_type foi_rad; // Set by main(), read by sfra_inject() [in interrupt]
|
|
fast_tri_ret_type foi_sin; // Pass intermediate value from sfra_inject() to sfra_monitor()
|
|
fast_tri_ret_type foi_cos; // Pass intermediate value from sfra_inject() to sfra_monitor()
|
|
volatile sfra_integral_t dtft_real_num; // Real part of x_out
|
|
volatile sfra_integral_t dtft_nimg_num; // Negative of imaginary part of x_out
|
|
volatile sfra_integral_t dtft_real_den; // Real part of x_control
|
|
volatile sfra_integral_t dtft_nimg_den; // Negative of imaginary part of x_control
|
|
#else
|
|
sfra_float_t foi_rad; // Set by main(), read by sfra_inject() [in interrupt]
|
|
sfra_float_t foi_sin; // Pass intermediate value from sfra_inject() to sfra_monitor()
|
|
sfra_float_t foi_cos; // Pass intermediate value from sfra_inject() to sfra_monitor()
|
|
volatile sfra_float_t dtft_real_num; // Real part of x_out
|
|
volatile sfra_float_t dtft_nimg_num; // Negative of imaginary part of x_out
|
|
volatile sfra_float_t dtft_real_den; // Real part of x_control
|
|
volatile sfra_float_t dtft_nimg_den; // Negative of imaginary part of x_control
|
|
#endif
|
|
} sfra_internal_state;
|
|
|
|
typedef struct {
|
|
sfra_result results;
|
|
sfra_setup config;
|
|
sfra_internal_state internal_state;
|
|
} sfra_t;
|
|
|
|
void sfra_init_all(void);
|
|
void sfra_start(sfra_t* sfra);
|
|
sfra_flag_t sfra_is_running(sfra_t* sfra);
|
|
sfra_flag_t sfra_is_done(sfra_t* sfra);
|
|
void sfra_clear_done(sfra_t* sfra);
|
|
void sfra_background_task(sfra_t* sfra);
|
|
|
|
#if(SFRA_INT)
|
|
/*
|
|
* Generate a sinusoidal perturbation with unit magnitude.
|
|
*
|
|
* @param sfra a pointer to an initialized sfra_t struct
|
|
* @return the sinusoidal perturbation, [-1,1] mapped to [-FAST_SIN_TABLE_SCALE, FAST_SIN_TABLE_SCALE]
|
|
*/
|
|
fast_tri_ret_type sfra_inject_int32(sfra_t* sfra);
|
|
|
|
/*
|
|
* Pass the signals to the "bode plotter". When measuring the open-loop transfer function of a closed-loop system,
|
|
* "control" and "feedback" should use the same base as the return value of sfra_inject_int32().
|
|
*
|
|
* @param sfra a pointer to an initialized sfra_t struct
|
|
* @param control the control output if measuring the open-loop transfer function of a closed-loop system.
|
|
* In a plant transfer function measurement, the perturbed reference signal (usually the duty-cycle) should be passed.
|
|
* @param feedback the feedback signal, usually is the ADC reading of the output voltage or current.
|
|
*/
|
|
void sfra_monitor_int32(sfra_t* sfra, sfra_signal_t control, sfra_signal_t feedback);
|
|
#else
|
|
sfra_float_t sfra_inject(sfra_t* sfra);
|
|
void sfra_monitor(sfra_t* sfra, sfra_float_t input, sfra_float_t output);
|
|
#endif
|
|
|
|
#if(SFRA_HAS_TEST)
|
|
void sfra_test_run(void);
|
|
void sfra_test_background_task(void);
|
|
#endif
|
|
|
|
#endif /* INC_LIBSFRA_H_ */
|