更新README
This commit is contained in:
@@ -0,0 +1,454 @@
|
||||
/**
|
||||
* @file sfra_f32.c
|
||||
* @brief 软件频率响应分析器 (SFRA) 库实现,完全兼容 TI SFRA_F32 接口。
|
||||
* @details 实现功率级传函 H(s)、系统开环传函 GH(s) 和闭环传函 CL(s) 的测量。
|
||||
* 支持浮点运算,自动检测上位机参数变化并更新频率向量。
|
||||
*/
|
||||
|
||||
#include "sfra_f32.h"
|
||||
#include <math.h>
|
||||
|
||||
/*============================================================================
|
||||
* 常量定义
|
||||
*============================================================================*/
|
||||
#define TWO_PI (2.0f * 3.14159265358979323846f)
|
||||
#define RAD_TO_DEG (180.0f / 3.14159265358979323846f)
|
||||
#define INVALID_MAG_DB (-200.0f)
|
||||
|
||||
/*============================================================================
|
||||
* 内部静态数据(单实例,非重入)
|
||||
*============================================================================*/
|
||||
typedef struct {
|
||||
uint16_t active; /**< 扫频是否激活 */
|
||||
uint16_t dtft_running; /**< 当前频率点是否正在累积 DTFT */
|
||||
uint16_t freqIndex; /**< 当前频率点索引 */
|
||||
uint16_t dataIndex; /**< 当前频率点的采样计数器 */
|
||||
uint16_t dataCount; /**< 当前频率点总采样数 */
|
||||
|
||||
float32_t foi_rad; /**< 每个采样的角度增量 (rad) */
|
||||
float32_t foi_sin; /**< 当前采样点 sin 值 */
|
||||
float32_t foi_cos; /**< 当前采样点 cos 值 */
|
||||
|
||||
/* DTFT 累加器 (使用 e^{-jwt} 核) */
|
||||
float32_t dtft_real_inj; /**< 注入信号 I 的实部 */
|
||||
float32_t dtft_imag_inj; /**< 注入信号 I 的虚部 */
|
||||
float32_t dtft_real_fb; /**< 反馈信号 Y 的实部 */
|
||||
float32_t dtft_imag_fb; /**< 反馈信号 Y 的虚部 */
|
||||
float32_t dtft_real_ctrl; /**< 控制输出 U 的实部 */
|
||||
float32_t dtft_imag_ctrl; /**< 控制输出 U 的虚部 */
|
||||
|
||||
/* 影子变量:用于检测上位机参数变更 */
|
||||
float32_t shadow_amplitude; /**< 上次同步的注入幅度 */
|
||||
float32_t shadow_freqStart; /**< 上次同步的起始频率 */
|
||||
float32_t shadow_freqStep; /**< 上次同步的频率步进乘数 */
|
||||
int16_t shadow_speed; /**< 上次同步的扫频速度 */
|
||||
|
||||
int16_t storeH; /**< 是否存储 H 向量 */
|
||||
int16_t storeGH; /**< 是否存储 GH 向量 */
|
||||
int16_t storeCL; /**< 是否存储 CL 向量 */
|
||||
} SFRA_Internal;
|
||||
|
||||
static SFRA_Internal s_sfra = {0};
|
||||
|
||||
/*============================================================================
|
||||
* 辅助函数
|
||||
*============================================================================*/
|
||||
|
||||
/**
|
||||
* @brief 计算指定频率点需要累积的采样点数(基于 libsfra 的周期对齐策略)
|
||||
* @param foi_hz 注入频率 (Hz)
|
||||
* @param isrFreq 控制 ISR 频率 (Hz)
|
||||
* @param speed 速度因子(越大扫频越慢,累积周期越多)
|
||||
* @return 采样点数
|
||||
*/
|
||||
static uint16_t calcDataCount(float32_t foi_hz, float32_t isrFreq, int16_t speed)
|
||||
{
|
||||
uint16_t cycles;
|
||||
if (foi_hz < 10.0f)
|
||||
cycles = 10;
|
||||
else if (foi_hz < 100.0f)
|
||||
cycles = (uint16_t)ceilf(foi_hz);
|
||||
else
|
||||
cycles = 100;
|
||||
|
||||
cycles = (uint16_t)((float32_t)cycles * (float32_t)speed);
|
||||
if (cycles < 4) cycles = 4;
|
||||
|
||||
float32_t samples_per_cycle = isrFreq / foi_hz;
|
||||
return (uint16_t)ceilf(samples_per_cycle * cycles);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 复数除法:计算 (num_re + j*num_im) / (den_re + j*den_im)
|
||||
* @param re_num 分子实部
|
||||
* @param im_num 分子虚部
|
||||
* @param re_den 分母实部
|
||||
* @param im_den 分母虚部
|
||||
* @param mag 输出幅值 (dB)
|
||||
* @param phase_deg 输出相位 (度)
|
||||
*/
|
||||
static void complexDiv(float32_t re_num, float32_t im_num,
|
||||
float32_t re_den, float32_t im_den,
|
||||
float32_t *mag, float32_t *phase_deg)
|
||||
{
|
||||
float32_t den_sq = re_den * re_den + im_den * im_den;
|
||||
if (den_sq < 1e-12f) {
|
||||
*mag = INVALID_MAG_DB;
|
||||
*phase_deg = 0.0f;
|
||||
return;
|
||||
}
|
||||
float32_t re = (re_num * re_den + im_num * im_den) / den_sq;
|
||||
float32_t im = (im_num * re_den - re_num * im_den) / den_sq;
|
||||
*mag = 10.0f * log10f(re * re + im * im);
|
||||
*phase_deg = atan2f(im, re) * RAD_TO_DEG;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 从指定索引开始重新生成频率向量(使用当前的 freqStart 和 freqStep)
|
||||
* @param obj SFRA 对象指针
|
||||
* @param startIdx 起始索引(该点之前的频率点保持不变)
|
||||
*/
|
||||
static void regenerateFreqVectorFrom(SFRA_F32 *obj, uint16_t startIdx)
|
||||
{
|
||||
if (!obj || !obj->freqVect || obj->vecLength <= 0) return;
|
||||
if (startIdx >= (uint16_t)obj->vecLength) return;
|
||||
|
||||
for (int16_t i = startIdx; i < obj->vecLength; i++) {
|
||||
if (i == 0) {
|
||||
obj->freqVect[0] = obj->freqStart;
|
||||
} else {
|
||||
obj->freqVect[i] = obj->freqVect[i-1] * obj->freqStep;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*============================================================================
|
||||
* 公开 API 实现
|
||||
*============================================================================*/
|
||||
|
||||
void SFRA_F32_reset(SFRA_F32 *obj)
|
||||
{
|
||||
if (!obj) return;
|
||||
obj->state = 0;
|
||||
obj->status = 0;
|
||||
obj->freqIndex = 0;
|
||||
obj->start = 0;
|
||||
|
||||
s_sfra.active = 0;
|
||||
s_sfra.dtft_running = 0;
|
||||
s_sfra.freqIndex = 0;
|
||||
s_sfra.dataIndex = 0;
|
||||
s_sfra.dataCount = 0;
|
||||
s_sfra.foi_rad = 0;
|
||||
s_sfra.foi_sin = 0;
|
||||
s_sfra.foi_cos = 0;
|
||||
s_sfra.dtft_real_inj = 0;
|
||||
s_sfra.dtft_imag_inj = 0;
|
||||
s_sfra.dtft_real_fb = 0;
|
||||
s_sfra.dtft_imag_fb = 0;
|
||||
s_sfra.dtft_real_ctrl = 0;
|
||||
s_sfra.dtft_imag_ctrl = 0;
|
||||
|
||||
s_sfra.shadow_amplitude = obj->amplitude;
|
||||
s_sfra.shadow_freqStart = obj->freqStart;
|
||||
s_sfra.shadow_freqStep = obj->freqStep;
|
||||
s_sfra.shadow_speed = obj->speed;
|
||||
}
|
||||
|
||||
void SFRA_F32_config(SFRA_F32 *obj,
|
||||
float32_t isrFrequency,
|
||||
float32_t injectionAmplitude,
|
||||
int16_t noFreqPoints,
|
||||
float32_t fraSweepStartFreq,
|
||||
float32_t freqStep,
|
||||
float32_t *h_magVect,
|
||||
float32_t *h_phaseVect,
|
||||
float32_t *gh_magVect,
|
||||
float32_t *gh_phaseVect,
|
||||
float32_t *cl_magVect,
|
||||
float32_t *cl_phaseVect,
|
||||
float32_t *freqVect,
|
||||
int16_t speed)
|
||||
{
|
||||
if (!obj) return;
|
||||
obj->isrFreq = isrFrequency;
|
||||
obj->amplitude = injectionAmplitude;
|
||||
obj->vecLength = noFreqPoints;
|
||||
obj->freqStart = fraSweepStartFreq;
|
||||
obj->freqStep = freqStep;
|
||||
obj->speed = speed;
|
||||
|
||||
obj->h_magVect = h_magVect;
|
||||
obj->h_phaseVect = h_phaseVect;
|
||||
obj->gh_magVect = gh_magVect;
|
||||
obj->gh_phaseVect = gh_phaseVect;
|
||||
obj->cl_magVect = cl_magVect;
|
||||
obj->cl_phaseVect = cl_phaseVect;
|
||||
obj->freqVect = freqVect;
|
||||
|
||||
obj->storeH = (h_magVect && h_phaseVect) ? 1 : 0;
|
||||
obj->storeGH = (gh_magVect && gh_phaseVect) ? 1 : 0;
|
||||
obj->storeCL = (cl_magVect && cl_phaseVect) ? 1 : 0;
|
||||
|
||||
s_sfra.storeH = obj->storeH;
|
||||
s_sfra.storeGH = obj->storeGH;
|
||||
s_sfra.storeCL = obj->storeCL;
|
||||
|
||||
s_sfra.shadow_amplitude = injectionAmplitude;
|
||||
s_sfra.shadow_freqStart = fraSweepStartFreq;
|
||||
s_sfra.shadow_freqStep = freqStep;
|
||||
s_sfra.shadow_speed = speed;
|
||||
|
||||
SFRA_F32_reset(obj);
|
||||
}
|
||||
|
||||
void SFRA_F32_initFreqArrayWithLogSteps(SFRA_F32 *obj,
|
||||
float32_t fra_sweep_start_freq,
|
||||
float32_t freqStep)
|
||||
{
|
||||
if (!obj || !obj->freqVect || obj->vecLength <= 0) return;
|
||||
obj->freqVect[0] = fra_sweep_start_freq;
|
||||
for (int16_t i = 1; i < obj->vecLength; i++) {
|
||||
obj->freqVect[i] = obj->freqVect[i-1] * freqStep;
|
||||
}
|
||||
s_sfra.shadow_freqStart = fra_sweep_start_freq;
|
||||
s_sfra.shadow_freqStep = freqStep;
|
||||
}
|
||||
|
||||
void SFRA_F32_resetFreqRespArray(SFRA_F32 *obj)
|
||||
{
|
||||
if (!obj) return;
|
||||
uint16_t len = obj->vecLength;
|
||||
if (obj->storeH && obj->h_magVect && obj->h_phaseVect) {
|
||||
for (uint16_t i = 0; i < len; i++) {
|
||||
obj->h_magVect[i] = 0.0f;
|
||||
obj->h_phaseVect[i] = 0.0f;
|
||||
}
|
||||
}
|
||||
if (obj->storeGH && obj->gh_magVect && obj->gh_phaseVect) {
|
||||
for (uint16_t i = 0; i < len; i++) {
|
||||
obj->gh_magVect[i] = 0.0f;
|
||||
obj->gh_phaseVect[i] = 0.0f;
|
||||
}
|
||||
}
|
||||
if (obj->storeCL && obj->cl_magVect && obj->cl_phaseVect) {
|
||||
for (uint16_t i = 0; i < len; i++) {
|
||||
obj->cl_magVect[i] = 0.0f;
|
||||
obj->cl_phaseVect[i] = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SFRA_F32_updateInjectionAmplitude(SFRA_F32 *obj, float32_t new_injection_amplitude)
|
||||
{
|
||||
if (obj) {
|
||||
obj->amplitude = new_injection_amplitude;
|
||||
s_sfra.shadow_amplitude = new_injection_amplitude;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 注入函数:生成正弦扰动并叠加到参考值上。
|
||||
* @param ref 原始参考值
|
||||
* @return 叠加扰动后的参考值
|
||||
*/
|
||||
float SFRA_F32_inject(float ref)
|
||||
{
|
||||
if (!s_sfra.active || !s_sfra.dtft_running) return ref;
|
||||
|
||||
float32_t angle = s_sfra.foi_rad * s_sfra.dataIndex;
|
||||
s_sfra.foi_cos = cosf(angle);
|
||||
s_sfra.foi_sin = sinf(angle);
|
||||
return ref + s_sfra.shadow_amplitude * s_sfra.foi_cos;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 收集函数:在控制 ISR 中调用,累积 DTFT 数据。
|
||||
* @param control_output 控制输出指针(例如占空比)
|
||||
* @param feedback 反馈信号指针(例如 ADC 读数)
|
||||
*/
|
||||
void SFRA_F32_collect(float *control_output, float *feedback)
|
||||
{
|
||||
if (!s_sfra.active || !s_sfra.dtft_running) return;
|
||||
if (!control_output || !feedback) return;
|
||||
|
||||
float32_t ctrl = *control_output;
|
||||
float32_t fb = *feedback;
|
||||
float32_t cosv = s_sfra.foi_cos;
|
||||
float32_t sinv = s_sfra.foi_sin;
|
||||
|
||||
/* DTFT 采用 e^{-jwt} 核,虚部为负号 */
|
||||
s_sfra.dtft_real_fb += fb * cosv;
|
||||
s_sfra.dtft_imag_fb -= fb * sinv;
|
||||
|
||||
s_sfra.dtft_real_ctrl += ctrl * cosv;
|
||||
s_sfra.dtft_imag_ctrl -= ctrl * sinv;
|
||||
|
||||
float32_t inj = s_sfra.shadow_amplitude * cosv;
|
||||
s_sfra.dtft_real_inj += inj * cosv;
|
||||
s_sfra.dtft_imag_inj -= inj * sinv;
|
||||
|
||||
s_sfra.dataIndex++;
|
||||
if (s_sfra.dataIndex >= s_sfra.dataCount) {
|
||||
s_sfra.dtft_running = 0; /* 当前频率点累积完成 */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 后台任务:状态机,管理扫频流程,计算传函并存储结果。
|
||||
* @param obj SFRA 对象指针
|
||||
* @note 传函定义:
|
||||
* - H(s) = Y / U (功率级传函,用于开环模式)
|
||||
* - GH(s) = Y / (I - Y) (系统开环传函,闭环模式下测量)
|
||||
* - CL(s) = Y / I (系统闭环传函)
|
||||
*/
|
||||
void SFRA_F32_runBackgroundTask(SFRA_F32 *obj)
|
||||
{
|
||||
if (!obj) return;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* 1. 扫频未激活时,检测参数变化并更新频率向量
|
||||
*------------------------------------------------------------------------*/
|
||||
if (!s_sfra.active) {
|
||||
if (obj->amplitude != s_sfra.shadow_amplitude) {
|
||||
s_sfra.shadow_amplitude = obj->amplitude;
|
||||
}
|
||||
if (obj->speed != s_sfra.shadow_speed) {
|
||||
s_sfra.shadow_speed = obj->speed;
|
||||
}
|
||||
if (obj->freqStart != s_sfra.shadow_freqStart ||
|
||||
obj->freqStep != s_sfra.shadow_freqStep) {
|
||||
regenerateFreqVectorFrom(obj, 0);
|
||||
s_sfra.shadow_freqStart = obj->freqStart;
|
||||
s_sfra.shadow_freqStep = obj->freqStep;
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* 2. 启动新扫频
|
||||
*------------------------------------------------------------------------*/
|
||||
if (!s_sfra.active && obj->start) {
|
||||
s_sfra.active = 1;
|
||||
s_sfra.freqIndex = 0;
|
||||
obj->start = 0;
|
||||
obj->state = 1;
|
||||
obj->status = 1;
|
||||
obj->freqIndex = 0;
|
||||
|
||||
if (obj->freqVect && obj->vecLength > 0) {
|
||||
float32_t freq = obj->freqVect[0];
|
||||
s_sfra.dataCount = calcDataCount(freq, obj->isrFreq, obj->speed);
|
||||
|
||||
uint16_t cycles_raw;
|
||||
if (freq < 10.0f) cycles_raw = 10;
|
||||
else if (freq < 100.0f) cycles_raw = (uint16_t)ceilf(freq);
|
||||
else cycles_raw = 100;
|
||||
cycles_raw = (uint16_t)((float32_t)cycles_raw * obj->speed);
|
||||
if (cycles_raw < 4) cycles_raw = 4;
|
||||
|
||||
s_sfra.foi_rad = TWO_PI * (float32_t)cycles_raw / (float32_t)s_sfra.dataCount;
|
||||
|
||||
s_sfra.dataIndex = 0;
|
||||
s_sfra.dtft_real_inj = 0;
|
||||
s_sfra.dtft_imag_inj = 0;
|
||||
s_sfra.dtft_real_fb = 0;
|
||||
s_sfra.dtft_imag_fb = 0;
|
||||
s_sfra.dtft_real_ctrl = 0;
|
||||
s_sfra.dtft_imag_ctrl = 0;
|
||||
s_sfra.dtft_running = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!s_sfra.active) {
|
||||
obj->state = 0;
|
||||
obj->status = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (s_sfra.dtft_running) return;
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* 3. 当前频率点 DTFT 已完成,计算并存储各类传函
|
||||
*------------------------------------------------------------------------*/
|
||||
uint16_t idx = s_sfra.freqIndex;
|
||||
if (idx < (uint16_t)obj->vecLength) {
|
||||
float32_t mag, phase;
|
||||
|
||||
/* 功率级传函 H(s) = Y / U */
|
||||
if (s_sfra.storeH && obj->h_magVect && obj->h_phaseVect) {
|
||||
complexDiv(s_sfra.dtft_real_fb, s_sfra.dtft_imag_fb,
|
||||
s_sfra.dtft_real_ctrl, s_sfra.dtft_imag_ctrl,
|
||||
&mag, &phase);
|
||||
obj->h_magVect[idx] = mag;
|
||||
obj->h_phaseVect[idx] = phase;
|
||||
}
|
||||
|
||||
/* 开环传函 GH(s) = Y / (I - Y) */
|
||||
if (s_sfra.storeGH && obj->gh_magVect && obj->gh_phaseVect) {
|
||||
float32_t re_iy = s_sfra.dtft_real_inj - s_sfra.dtft_real_fb;
|
||||
float32_t im_iy = s_sfra.dtft_imag_inj - s_sfra.dtft_imag_fb;
|
||||
complexDiv(s_sfra.dtft_real_fb, s_sfra.dtft_imag_fb,
|
||||
re_iy, im_iy, &mag, &phase);
|
||||
obj->gh_magVect[idx] = mag;
|
||||
obj->gh_phaseVect[idx] = phase;
|
||||
}
|
||||
|
||||
/* 闭环传函 CL(s) = Y / I */
|
||||
if (s_sfra.storeCL && obj->cl_magVect && obj->cl_phaseVect) {
|
||||
complexDiv(s_sfra.dtft_real_fb, s_sfra.dtft_imag_fb,
|
||||
s_sfra.dtft_real_inj, s_sfra.dtft_imag_inj,
|
||||
&mag, &phase);
|
||||
obj->cl_magVect[idx] = mag;
|
||||
obj->cl_phaseVect[idx] = phase;
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
* 4. 准备下一个频率点(如果参数已变化,则重新生成剩余频率向量)
|
||||
*------------------------------------------------------------------------*/
|
||||
s_sfra.freqIndex++;
|
||||
obj->freqIndex = s_sfra.freqIndex;
|
||||
|
||||
if (s_sfra.freqIndex < (uint16_t)obj->vecLength) {
|
||||
/* 检测频率参数变化,重新生成剩余频率点 */
|
||||
if (obj->freqStart != s_sfra.shadow_freqStart ||
|
||||
obj->freqStep != s_sfra.shadow_freqStep) {
|
||||
regenerateFreqVectorFrom(obj, s_sfra.freqIndex);
|
||||
s_sfra.shadow_freqStart = obj->freqStart;
|
||||
s_sfra.shadow_freqStep = obj->freqStep;
|
||||
}
|
||||
if (obj->speed != s_sfra.shadow_speed) {
|
||||
s_sfra.shadow_speed = obj->speed;
|
||||
}
|
||||
|
||||
float32_t freq = obj->freqVect[s_sfra.freqIndex];
|
||||
s_sfra.dataCount = calcDataCount(freq, obj->isrFreq, obj->speed);
|
||||
|
||||
uint16_t cycles_raw;
|
||||
if (freq < 10.0f) cycles_raw = 10;
|
||||
else if (freq < 100.0f) cycles_raw = (uint16_t)ceilf(freq);
|
||||
else cycles_raw = 100;
|
||||
cycles_raw = (uint16_t)((float32_t)cycles_raw * obj->speed);
|
||||
if (cycles_raw < 4) cycles_raw = 4;
|
||||
|
||||
s_sfra.foi_rad = TWO_PI * (float32_t)cycles_raw / (float32_t)s_sfra.dataCount;
|
||||
|
||||
s_sfra.dataIndex = 0;
|
||||
s_sfra.dtft_real_inj = 0;
|
||||
s_sfra.dtft_imag_inj = 0;
|
||||
s_sfra.dtft_real_fb = 0;
|
||||
s_sfra.dtft_imag_fb = 0;
|
||||
s_sfra.dtft_real_ctrl = 0;
|
||||
s_sfra.dtft_imag_ctrl = 0;
|
||||
s_sfra.dtft_running = 1;
|
||||
obj->state = 1;
|
||||
obj->status = 1;
|
||||
} else {
|
||||
/* 扫频结束 */
|
||||
s_sfra.active = 0;
|
||||
obj->state = 0;
|
||||
obj->status = 2;
|
||||
obj->freqIndex = obj->vecLength;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
//###########################################################################
|
||||
//
|
||||
// FILE: sfra_f32.h
|
||||
//
|
||||
// TITLE: Prototypes and Definitions for the C28x FPU SFRA Library
|
||||
//
|
||||
// AUTHOR: Manish Bhardwaj (C2000 Systems Solutions, Houston , TX)
|
||||
//
|
||||
//#############################################################################
|
||||
// $TI Release: C2000 Software Frequency Response Analyzer Library v1.50.02.00 $
|
||||
// $Release Date: Tue Aug 26 14:08:13 CDT 2025 $
|
||||
// $Copyright:
|
||||
// Copyright (C) 2025 Texas Instruments Incorporated - http://www.ti.com/
|
||||
//
|
||||
// ALL RIGHTS RESERVED
|
||||
// $
|
||||
//#############################################################################
|
||||
|
||||
#ifndef SFRA_F32_H
|
||||
#define SFRA_F32_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! \addtogroup SFRA
|
||||
//! @{
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//
|
||||
// the includes & defines
|
||||
//
|
||||
#ifndef C2000_IEEE754_TYPES
|
||||
#define C2000_IEEE754_TYPES
|
||||
#ifdef _TI_EABI_
|
||||
typedef float float32_t;
|
||||
typedef double float64_t;
|
||||
#else // TI COFF
|
||||
typedef float float32_t;
|
||||
typedef long double float64_t;
|
||||
#endif // _TI_EABI_
|
||||
#endif // C2000_IEEE754_TYPES}}
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef __TI_EABI__
|
||||
#define SFRA_F32_inject __SFRA_F32_inject
|
||||
#define SFRA_F32_collect __SFRA_F32_collect
|
||||
#else
|
||||
#define SFRA_F32_inject _SFRA_F32_inject
|
||||
#define SFRA_F32_collect _SFRA_F32_collect
|
||||
#endif
|
||||
//! \brief Defines the SFRA_F32 structure
|
||||
//!
|
||||
//! \details The SFRA_F32 can be used to run a software based
|
||||
//! frequency response analysis on power converters
|
||||
//!
|
||||
typedef struct{
|
||||
float32_t *h_magVect; //!< Plant Mag SFRA Vector
|
||||
float32_t *h_phaseVect; //!< Plant Phase SFRA Vector
|
||||
float32_t *gh_magVect; //!< Open Loop Mag SFRA Vector
|
||||
float32_t *gh_phaseVect; //!< Open Loop Phase SFRA Vector
|
||||
float32_t *cl_magVect; //!< Closed Loop Mag SFRA Vector
|
||||
float32_t *cl_phaseVect; //!< Closed Loop Phase SFRA Vector
|
||||
float32_t *freqVect; //!< Frequency Vector
|
||||
float32_t amplitude; //!< Injection Amplitude
|
||||
float32_t isrFreq; //!< SFRA ISR frequency
|
||||
float32_t freqStart; //!< Start frequency of SFRA sweep
|
||||
float32_t freqStep; //!< Log space between frequency points (optional)
|
||||
int16_t start; //!< Command to start SFRA
|
||||
int16_t state; //!< State of SFRA
|
||||
int16_t status; //!< Status of SFRA
|
||||
int16_t vecLength; //!< No. of Points in the SFRA
|
||||
int16_t freqIndex; //!< Index of the frequency vector
|
||||
int16_t storeH; //!< Flag to indicate if H vector is stored
|
||||
int16_t storeGH; //!< Flag to indicate if GH vector is stored
|
||||
int16_t storeCL; //!< Flag to indicate if CL vector is stored
|
||||
int16_t speed; //!< variable to change the speed of the sweep
|
||||
}SFRA_F32;
|
||||
|
||||
//! \brief Resets internal data of SFRA_F32 module
|
||||
//! \param SFRA_F_obj Pointer to the SFRA_F32 structure
|
||||
//!
|
||||
extern void SFRA_F32_reset(SFRA_F32 *SFRA_F_obj);
|
||||
|
||||
//! \brief Configures the SFRA_F32 module
|
||||
//! \param *SFRA_F_obj Pointer to the SFRA_F32 structure
|
||||
//! \param isrFrequency Frequency at which SFRA routine in called,
|
||||
//! typically the control ISR rate
|
||||
//! \param injectionAmplitude Per Unit (PU) injection amplitude
|
||||
//! \param noFreqPoints Number of frequency points sweeped
|
||||
//! \param fraSweepStartFreq Start frequency of SFRA sweep
|
||||
//! \param freqStep Multiplier used to keep frequency points log step apart
|
||||
//! \param *h_magVect Pointer to array that stores plant FRA magnitude data
|
||||
//! \param *h_phaseVect Pointer to array that stores plant FRA phase data
|
||||
//! \param *gh_magVect Pointer to array that stores OL FRA magnitude data
|
||||
//! \param *gh_phaseVect Pointer to array that stores OL FRA phase data
|
||||
//! \param *cl_magVect Pointer to array that stores OL FRA magnitude data
|
||||
//! \param *cl_phaseVect Pointer to array that stores OL FRA phase data
|
||||
//! \param *freqVect Pointer to array that stores the freq points for the sweep
|
||||
//! \param speed indiactes the speed of the sweep
|
||||
//!
|
||||
extern void SFRA_F32_config(SFRA_F32 *SFRA_F_obj,
|
||||
float32_t isrFrequency,
|
||||
float32_t injectionAmplitude,
|
||||
int16_t noFreqPoints,
|
||||
float32_t fraSweepStartFreq,
|
||||
float32_t freqStep,
|
||||
float32_t *h_magVect,
|
||||
float32_t *h_phaseVect,
|
||||
float32_t *gh_magVect,
|
||||
float32_t *gh_phaseVect,
|
||||
float32_t *cl_magVect,
|
||||
float32_t *cl_phaseVect,
|
||||
float32_t *freqVect,
|
||||
int16_t speed);
|
||||
|
||||
//! \brief Initailizes the freq vectors with points that are log step apart
|
||||
//! \param *SFRA_F_obj Pointer to the SFRA_F32 structure
|
||||
//! \param fra_sweep_start_freq Start frequency of SFRA sweep
|
||||
//! \param freqStep Multiplier used to keep frequency points log step apart
|
||||
//!
|
||||
extern void SFRA_F32_initFreqArrayWithLogSteps(SFRA_F32 *SFRA_F_obj,
|
||||
float32_t fra_sweep_start_freq,
|
||||
float32_t freqStep);
|
||||
|
||||
//! \brief Resets the response data stored in the ol and plant
|
||||
//! phase and mag vector
|
||||
//! \param *SFRA_F_obj Pointer to the SFRA_F32 structure pointer
|
||||
//!
|
||||
extern void SFRA_F32_resetFreqRespArray(SFRA_F32 *SFRA_F_obj);
|
||||
|
||||
//! \brief Updates injection amplitude
|
||||
//! \param *SFRA_F_obj Pointer to the SFRA_F32 structure
|
||||
//! \param new_injection_amplitude Injection amplitude
|
||||
//!
|
||||
extern void SFRA_F32_updateInjectionAmplitude(SFRA_F32 *SFRA_F_obj,
|
||||
float32_t new_injection_amplitude);
|
||||
|
||||
//! \brief Injects small signal disturbance into the control loop
|
||||
//! \param ref refernce value on which the injection is added
|
||||
//! \return Routine returns the reference plus the injection when SFRA sweep
|
||||
//! is active, when SFRA sweep is not active that is if SFRA state is 0
|
||||
//! it returns the the refernce without any change
|
||||
//!
|
||||
extern float SFRA_F32_inject(float ref);
|
||||
|
||||
//! \brief Collects the response of the loop because of small signal disturbance
|
||||
//! injected
|
||||
//! \param *control_output pointer to the variable where control output is saved
|
||||
//! note though the parameter is passed by reference
|
||||
//! it is unchanged by the module
|
||||
//! \param *feedback pointer to the variable where control output is saved
|
||||
//! note though the parameter is passed by reference
|
||||
//! it is unchanged by the module
|
||||
//!
|
||||
extern void SFRA_F32_collect(float *control_output, float *feedback);
|
||||
|
||||
//! \brief Runs the background task, this routine executes the state machine
|
||||
//! when a frequency sweep is started and is responsible for changing
|
||||
//! the frequency points and saving the measured results in an array
|
||||
//! \param *SFRA_F_obj Pointer to the SFRA_F32 structure pointer
|
||||
//!
|
||||
extern void SFRA_F32_runBackgroundTask(SFRA_F32 *SFRA_F_obj);
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Close the Doxygen group.
|
||||
//! @}
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // extern "C"
|
||||
|
||||
#endif // end of SFRA_F32_H definition
|
||||
@@ -0,0 +1,880 @@
|
||||
//###########################################################################
|
||||
//
|
||||
// FILE: sfra_gui_scicomms_driverlib.c
|
||||
//
|
||||
// TITLE: Comms kernel as an interface to SFRA GUI
|
||||
//
|
||||
// AUTHOR: Manish Bhardwaj (C2000 Systems Solutions, Houston , TX)
|
||||
//
|
||||
//#############################################################################
|
||||
// $TI Release: C2000 Software Frequency Response Analyzer Library v1.50.02.00 $
|
||||
// $Release Date: Tue Aug 26 14:08:13 CDT 2025 $
|
||||
// $Copyright:
|
||||
// Copyright (C) 2025 Texas Instruments Incorporated - http://www.ti.com/
|
||||
//
|
||||
// ALL RIGHTS RESERVED
|
||||
// $
|
||||
//#############################################################################
|
||||
|
||||
#include <stdint.h>
|
||||
#include "driverlib.h"
|
||||
#include "device.h"
|
||||
#include "sfra_gui_scicomms_driverlib.h"
|
||||
|
||||
//
|
||||
// Function prototypes for Command RECEIVE State machine
|
||||
// ------------------------------------------------------------
|
||||
//
|
||||
void SFRA_GUI_getCmdByte(void);
|
||||
void SFRA_GUI_echoCmdByte(void);
|
||||
void SFRA_GUI_getSizeByte(void);
|
||||
void SFRA_GUI_echoSizeByte(void);
|
||||
void SFRA_GUI_getDataByte(void);
|
||||
void SFRA_GUI_echoDataByte(void);
|
||||
void SFRA_GUI_packWord(void);
|
||||
void SFRA_GUI_packArray(void);
|
||||
void SFRA_GUI_cmdInterpreter(void);
|
||||
|
||||
//
|
||||
// Function prototypes for Command Interpreter and dispatcher
|
||||
//
|
||||
void SFRA_GUI_lifePulseTsk(void); // 0
|
||||
void SFRA_GUI_setText(void); // 1
|
||||
void SFRA_GUI_setButton(void); // 2
|
||||
void SFRA_GUI_setSlider(void); // 3
|
||||
void SFRA_GUI_getVariable(void); // 4
|
||||
void SFRA_GUI_getArray(void); // 5
|
||||
void SFRA_GUI_getData(void); // 6
|
||||
void SFRA_GUI_setData32(void); // 7
|
||||
void SFRA_GUI_spareTsk08(void); // 8
|
||||
|
||||
void SFRA_GUI_sendData(void);
|
||||
|
||||
//
|
||||
// Variable declarations
|
||||
// State pointer for Command Packet Receive
|
||||
//
|
||||
void (*SFRA_GUI_rcvTaskPointer)(void);
|
||||
|
||||
//
|
||||
// Array of pointers to Function (that are tasks)
|
||||
//
|
||||
void (*SFRA_GUI_cmdDispatcher[SFRA_GUI_CMD_NUMBER])(void);
|
||||
|
||||
volatile int16_t *SFRA_GUI_varSetTxtList[16];
|
||||
volatile int16_t *SFRA_GUI_varSetBtnList[16];
|
||||
volatile int16_t *SFRA_GUI_varSetSldrList[16];
|
||||
volatile int16_t *SFRA_GUI_varGetList[16];
|
||||
volatile int32_t *SFRA_GUI_arrayGetList[16];
|
||||
volatile int16_t *SFRA_GUI_dataGetList[16];
|
||||
volatile uint32_t *SFRA_GUI_dataSetList[16];
|
||||
|
||||
volatile int16_t SFRA_GUI_commsOKflg;
|
||||
volatile int16_t SFRA_GUI_serialCommsTimer;
|
||||
|
||||
volatile uint32_t SFRA_GUI_sci_base_addr;
|
||||
|
||||
uint16_t SFRA_GUI_lowByteFlag;
|
||||
uint16_t SFRA_GUI_sendTaskPtr;
|
||||
uint16_t SFRA_GUI_rxChar;
|
||||
uint16_t SFRA_GUI_rxWord;
|
||||
uint16_t SFRA_GUI_cmdPacket[SFRA_GUI_PKT_SIZE];
|
||||
uint16_t SFRA_GUI_taskDoneFlag;
|
||||
uint16_t SFRA_GUI_numWords;
|
||||
uint16_t SFRA_GUI_wordsLeftToGet;
|
||||
|
||||
uint16_t SFRA_GUI_dataOut16;
|
||||
int32_t SFRA_GUI_dataOut32;
|
||||
|
||||
int16_t *SFRA_GUI_memDataPtr16;
|
||||
int32_t *SFRA_GUI_memDataPtr32;
|
||||
|
||||
//
|
||||
// for debug
|
||||
//
|
||||
int16_t SFRA_GUI_rcvTskPtrShdw;
|
||||
|
||||
int16_t SFRA_GUI_delayer;
|
||||
|
||||
int16_t SFRA_GUI_memGetPtr;
|
||||
uint32_t SFRA_GUI_memGetAddress;
|
||||
int16_t SFRA_GUI_memGetAmount;
|
||||
|
||||
int16_t SFRA_GUI_memSetPtr;
|
||||
uint32_t SFRA_GUI_memSetValue;
|
||||
|
||||
uint32_t SFRA_GUI_temp;
|
||||
|
||||
uint16_t SFRA_GUI_led_flag;
|
||||
uint16_t SFRA_GUI_led_gpio;
|
||||
|
||||
uint16_t SFRA_GUI_sweep_start;
|
||||
|
||||
void SFRA_GUI_config(volatile uint32_t sci_base,
|
||||
uint32_t vbus_clk,
|
||||
uint32_t baudrate,
|
||||
uint16_t scirx_gpio_pin,
|
||||
uint32_t scirx_gpio_pin_config,
|
||||
uint16_t scitx_gpio_pin,
|
||||
uint32_t scitx_gpio_pin_config,
|
||||
uint16_t led_indicator_flag,
|
||||
uint16_t led_gpio_pin,
|
||||
uint32_t led_gpio_pin_config,
|
||||
SFRA_F32 *sfra,
|
||||
uint16_t plot_option)
|
||||
{
|
||||
int16_t j = 0;
|
||||
|
||||
//
|
||||
// setup Gpio for SCI comms for SFRA
|
||||
//
|
||||
|
||||
GPIO_setPinConfig(scirx_gpio_pin_config);
|
||||
GPIO_setPinConfig(scitx_gpio_pin_config);
|
||||
GPIO_setQualificationMode(scirx_gpio_pin, GPIO_QUAL_ASYNC);
|
||||
GPIO_setQualificationMode(scitx_gpio_pin, GPIO_QUAL_ASYNC);
|
||||
|
||||
//
|
||||
// Note: Assumes Clocks to SCI are turned on in setupDevice()->Device_init()
|
||||
// Note: Assumes GPIO pins for SCIA are configured to Primary function
|
||||
//
|
||||
|
||||
//
|
||||
// 1 stop bit, No parity, 8 char bits,
|
||||
//
|
||||
SCI_setConfig(sci_base,
|
||||
vbus_clk, baudrate,
|
||||
(SCI_CONFIG_WLEN_8 |
|
||||
SCI_CONFIG_STOP_ONE |
|
||||
SCI_CONFIG_PAR_NONE));
|
||||
//
|
||||
// No loopback
|
||||
//
|
||||
SCI_disableLoopback(sci_base);
|
||||
|
||||
SCI_enableInterrupt(sci_base, SCI_INT_RXRDY_BRKDT | SCI_INT_TXRDY);
|
||||
|
||||
//
|
||||
// Relinquish SCI from Reset by SW Reset and setting TXE, and RXE bits
|
||||
//
|
||||
SCI_enableModule(sci_base);
|
||||
SCI_performSoftwareReset(sci_base);
|
||||
|
||||
HWREGH(sci_base + SCI_O_FFTX) = 0x8040;
|
||||
HWREGH(sci_base + SCI_O_FFRX) = 0x204f;
|
||||
HWREGH(sci_base + SCI_O_FFCT) = 0x0;
|
||||
|
||||
//
|
||||
// Disable RX ERR, SLEEP, TXWAKE
|
||||
//
|
||||
SCI_clearInterruptStatus(sci_base,
|
||||
SCI_INT_TXRDY | SCI_INT_RXRDY_BRKDT );
|
||||
|
||||
//
|
||||
// Initialize the CmdPacket Rcv Handler state machine ptr
|
||||
//
|
||||
SFRA_GUI_rcvTaskPointer = &SFRA_GUI_getCmdByte;
|
||||
//
|
||||
// DEBUG
|
||||
//
|
||||
SFRA_GUI_rcvTskPtrShdw = 1;
|
||||
//
|
||||
// Init to 1st state
|
||||
//
|
||||
SFRA_GUI_sendTaskPtr = 0;
|
||||
//
|
||||
// Start with LSB during Byte-to-Word packing
|
||||
//
|
||||
SFRA_GUI_lowByteFlag = 1;
|
||||
|
||||
SFRA_GUI_dataOut16 = 0;
|
||||
SFRA_GUI_dataOut32 = 0;
|
||||
|
||||
//
|
||||
// for debug
|
||||
//
|
||||
SFRA_GUI_rcvTskPtrShdw = 0;
|
||||
|
||||
SFRA_GUI_delayer = 0;
|
||||
|
||||
SFRA_GUI_memGetPtr = 0;
|
||||
SFRA_GUI_memGetAddress = 0x00000000;
|
||||
SFRA_GUI_memGetAmount = 0;
|
||||
|
||||
SFRA_GUI_memSetPtr = 0;
|
||||
SFRA_GUI_memSetValue = 0x00000000;
|
||||
|
||||
SFRA_GUI_sweep_start = 0;
|
||||
SFRA_GUI_serialCommsTimer = 0;
|
||||
SFRA_GUI_commsOKflg = 0;
|
||||
|
||||
SFRA_GUI_sci_base_addr = sci_base;
|
||||
|
||||
//
|
||||
// clear Command Packet
|
||||
//
|
||||
for (j = 0; j < SFRA_GUI_PKT_SIZE; j++)
|
||||
{
|
||||
SFRA_GUI_cmdPacket[j] = 0x0;
|
||||
}
|
||||
|
||||
j = 0;
|
||||
|
||||
//
|
||||
// init all dispatch Tasks
|
||||
//
|
||||
SFRA_GUI_cmdDispatcher[0] = SFRA_GUI_lifePulseTsk;
|
||||
SFRA_GUI_cmdDispatcher[1] = SFRA_GUI_setText;
|
||||
SFRA_GUI_cmdDispatcher[2] = SFRA_GUI_setButton;
|
||||
SFRA_GUI_cmdDispatcher[3] = SFRA_GUI_setSlider;
|
||||
SFRA_GUI_cmdDispatcher[4] = SFRA_GUI_getVariable;
|
||||
SFRA_GUI_cmdDispatcher[5] = SFRA_GUI_getArray;
|
||||
SFRA_GUI_cmdDispatcher[6] = SFRA_GUI_getData;
|
||||
SFRA_GUI_cmdDispatcher[7] = SFRA_GUI_setData32;
|
||||
SFRA_GUI_cmdDispatcher[8] = SFRA_GUI_spareTsk08;
|
||||
|
||||
|
||||
|
||||
SFRA_GUI_varSetBtnList[0] = (int16_t *)&(SFRA_GUI_sweep_start);
|
||||
|
||||
SFRA_GUI_varGetList[0] = (int16_t *)&(sfra->vecLength);
|
||||
SFRA_GUI_varGetList[1] = (int16_t *)&(sfra->status);
|
||||
SFRA_GUI_varGetList[2] = (int16_t *)&(sfra->freqIndex);
|
||||
|
||||
//
|
||||
//"Setable" variables
|
||||
// assign GUI "setable" by Text parameter address
|
||||
//
|
||||
SFRA_GUI_dataSetList[0] = (uint32_t *)&(sfra->freqStart);
|
||||
SFRA_GUI_dataSetList[1] = (uint32_t *)&(sfra->amplitude);
|
||||
SFRA_GUI_dataSetList[2] = (uint32_t *)&(sfra->freqStep);
|
||||
|
||||
//
|
||||
// assign a GUI "getable" parameter array address
|
||||
//
|
||||
SFRA_GUI_arrayGetList[0] = (int32_t *)sfra->freqVect;
|
||||
|
||||
|
||||
if(plot_option == SFRA_GUI_PLOT_GH_CL)
|
||||
{
|
||||
SFRA_GUI_arrayGetList[1] = (int32_t *)sfra->gh_magVect;
|
||||
SFRA_GUI_arrayGetList[2] = (int32_t *)sfra->gh_phaseVect;
|
||||
|
||||
SFRA_GUI_arrayGetList[3] = (int32_t *)sfra->cl_magVect;
|
||||
SFRA_GUI_arrayGetList[4] = (int32_t *)sfra->cl_phaseVect;
|
||||
}
|
||||
//
|
||||
// default is to plot gh and h
|
||||
//
|
||||
else
|
||||
{
|
||||
SFRA_GUI_arrayGetList[1] = (int32_t *)sfra->gh_magVect;
|
||||
SFRA_GUI_arrayGetList[2] = (int32_t *)sfra->gh_phaseVect;
|
||||
|
||||
SFRA_GUI_arrayGetList[3] = (int32_t *)sfra->h_magVect;
|
||||
SFRA_GUI_arrayGetList[4] = (int32_t *)sfra->h_phaseVect;
|
||||
}
|
||||
|
||||
|
||||
|
||||
SFRA_GUI_arrayGetList[5] = (int32_t *)&(sfra->freqStart);
|
||||
SFRA_GUI_arrayGetList[6] = (int32_t *)&(sfra->amplitude);
|
||||
SFRA_GUI_arrayGetList[7] = (int32_t *)&(sfra->freqStep);
|
||||
|
||||
|
||||
if(led_indicator_flag == 1)
|
||||
{
|
||||
GPIO_setDirectionMode(led_gpio_pin, GPIO_DIR_MODE_OUT);
|
||||
GPIO_setQualificationMode(led_gpio_pin, GPIO_QUAL_SYNC);
|
||||
GPIO_setPinConfig(led_gpio_pin_config);
|
||||
SFRA_GUI_led_flag = 1;
|
||||
SFRA_GUI_led_gpio = led_gpio_pin;
|
||||
}
|
||||
else
|
||||
{
|
||||
SFRA_GUI_led_flag = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// Host Command RECEIVE and DISPATCH State Machine
|
||||
//
|
||||
|
||||
//
|
||||
// State Machine Entry Point
|
||||
//
|
||||
void SFRA_GUI_runSerialHostComms(SFRA_F32 *sfra)
|
||||
{
|
||||
if(SFRA_GUI_sweep_start == 1)
|
||||
{
|
||||
SFRA_GUI_sweep_start = 0;
|
||||
sfra->start = 1;
|
||||
}
|
||||
//
|
||||
// Call routine pointed to by state pointer
|
||||
//
|
||||
(*SFRA_GUI_rcvTaskPointer)();
|
||||
|
||||
SFRA_GUI_serialCommsTimer++;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Task 1
|
||||
//
|
||||
void SFRA_GUI_getCmdByte(void)
|
||||
{
|
||||
//
|
||||
// check if a char has been received
|
||||
//
|
||||
if((SCI_getRxStatus(SFRA_GUI_sci_base_addr) & SCI_RXSTATUS_READY ) != 0)
|
||||
{
|
||||
SFRA_GUI_rxChar = SCI_readCharBlockingNonFIFO(SFRA_GUI_sci_base_addr);
|
||||
//
|
||||
// point to next state
|
||||
//
|
||||
SFRA_GUI_rcvTaskPointer = &SFRA_GUI_echoCmdByte;
|
||||
SFRA_GUI_serialCommsTimer = 0;
|
||||
//
|
||||
// DEBUG
|
||||
//RcvTskPtrShdw = 2;
|
||||
//
|
||||
SFRA_GUI_echoCmdByte();
|
||||
}
|
||||
//
|
||||
//~2.5 s timeout, SFRA GUI function is called at 100Hz (recommended)
|
||||
// hence 2500/100 = 2.5sec
|
||||
//
|
||||
else if((SCI_getRxStatus(SFRA_GUI_sci_base_addr)&SCI_RXSTATUS_BREAK) != 0
|
||||
|| SFRA_GUI_serialCommsTimer > 2500)
|
||||
{
|
||||
|
||||
SCI_enableModule(SFRA_GUI_sci_base_addr);
|
||||
|
||||
//
|
||||
// If break detected or serialport times out, reset SCI
|
||||
//--- Needed by some serialports when code is run with an emulator
|
||||
//
|
||||
SCI_performSoftwareReset(SFRA_GUI_sci_base_addr);
|
||||
|
||||
SCI_clearInterruptStatus(SFRA_GUI_sci_base_addr,
|
||||
SCI_INT_TXRDY | SCI_INT_RXRDY_BRKDT);
|
||||
|
||||
asm(" RPT#8 || NOP");
|
||||
|
||||
//
|
||||
// Init to 1st state
|
||||
//
|
||||
SFRA_GUI_sendTaskPtr = 0;
|
||||
SFRA_GUI_serialCommsTimer = 0;
|
||||
|
||||
//
|
||||
// go back and wait for new CMD
|
||||
//
|
||||
SFRA_GUI_commsOKflg = 0;
|
||||
SFRA_GUI_rcvTaskPointer = &SFRA_GUI_getCmdByte;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Task 2
|
||||
//
|
||||
void SFRA_GUI_echoCmdByte(void)
|
||||
{
|
||||
//
|
||||
// is TXBUF empty ?, that is TXRDY = 1
|
||||
//
|
||||
if(SCI_isTransmitterBusy(SFRA_GUI_sci_base_addr) == 0)
|
||||
{
|
||||
SCI_writeCharBlockingNonFIFO(SFRA_GUI_sci_base_addr, SFRA_GUI_rxChar);
|
||||
SFRA_GUI_cmdPacket[0] = SFRA_GUI_rxChar;
|
||||
SFRA_GUI_rcvTaskPointer = &SFRA_GUI_getSizeByte;
|
||||
//
|
||||
// DEBUG
|
||||
// RcvTskPtrShdw = 3;
|
||||
// Un-comment for simple echo test
|
||||
// RcvTaskPointer = &GetCmdByte;
|
||||
// Reset Time-out timer
|
||||
//
|
||||
SFRA_GUI_serialCommsTimer = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// Task 3
|
||||
//
|
||||
void SFRA_GUI_getSizeByte(void)
|
||||
{
|
||||
//
|
||||
// check if a char has been received
|
||||
//
|
||||
if((SCI_getRxStatus(SFRA_GUI_sci_base_addr) & SCI_RXSTATUS_READY ) != 0)
|
||||
{
|
||||
SFRA_GUI_rxChar = SCI_readCharBlockingNonFIFO(SFRA_GUI_sci_base_addr);
|
||||
|
||||
//
|
||||
// point to next state
|
||||
//
|
||||
SFRA_GUI_rcvTaskPointer = &SFRA_GUI_echoSizeByte;
|
||||
//
|
||||
// DEBUG
|
||||
//RcvTskPtrShdw = 4;
|
||||
//
|
||||
SFRA_GUI_echoSizeByte();
|
||||
}
|
||||
|
||||
//
|
||||
// 1000*1mS = 1.0 sec timeout, SFRA GUI function is called at 1ms
|
||||
//
|
||||
else if(SFRA_GUI_serialCommsTimer > 1000)
|
||||
{
|
||||
SFRA_GUI_commsOKflg = 0;
|
||||
//
|
||||
// Abort, go back wait for new CMD
|
||||
//
|
||||
SFRA_GUI_rcvTaskPointer = &SFRA_GUI_getCmdByte;
|
||||
SFRA_GUI_serialCommsTimer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Task 4
|
||||
//
|
||||
void SFRA_GUI_echoSizeByte(void)
|
||||
{
|
||||
//
|
||||
// is TXBUF empty ?, that is TXRDY = 1
|
||||
//
|
||||
if(SCI_isTransmitterBusy(SFRA_GUI_sci_base_addr) == 0)
|
||||
{
|
||||
SCI_writeCharBlockingNonFIFO(SFRA_GUI_sci_base_addr, SFRA_GUI_rxChar);
|
||||
SFRA_GUI_cmdPacket[1] = SFRA_GUI_rxChar;
|
||||
SFRA_GUI_rcvTaskPointer = &SFRA_GUI_getDataByte;
|
||||
//
|
||||
// DEBUG
|
||||
//RcvTskPtrShdw = 5;
|
||||
// Un-comment for Test
|
||||
//RcvTaskPointer = &GetCmdByte;
|
||||
// Reset Time-out timer
|
||||
//
|
||||
SFRA_GUI_serialCommsTimer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Task 5
|
||||
//
|
||||
void SFRA_GUI_getDataByte(void)
|
||||
{
|
||||
//
|
||||
// check if a char has been received
|
||||
//
|
||||
if((SCI_getRxStatus(SFRA_GUI_sci_base_addr) & SCI_RXSTATUS_READY ) != 0)
|
||||
{
|
||||
SFRA_GUI_rxChar = SCI_readCharBlockingNonFIFO(SFRA_GUI_sci_base_addr);
|
||||
//
|
||||
// point to next state
|
||||
//
|
||||
SFRA_GUI_rcvTaskPointer = &SFRA_GUI_echoDataByte;
|
||||
//
|
||||
// DEBUG
|
||||
//RcvTskPtrShdw = 6;
|
||||
//
|
||||
SFRA_GUI_echoDataByte();
|
||||
}
|
||||
|
||||
//
|
||||
// 1000*1mS = 1 sec timeout, SFRA GUI function is called at 1ms/100Hz
|
||||
//
|
||||
else if(SFRA_GUI_serialCommsTimer > 1000)
|
||||
{
|
||||
SFRA_GUI_commsOKflg = 0;
|
||||
//
|
||||
// Abort, go back wait for new CMD
|
||||
//
|
||||
SFRA_GUI_rcvTaskPointer = &SFRA_GUI_getCmdByte;
|
||||
SFRA_GUI_serialCommsTimer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Task 6
|
||||
//
|
||||
void SFRA_GUI_echoDataByte(void)
|
||||
{
|
||||
//
|
||||
// is TXBUF empty ?, that is TXRDY = 1
|
||||
//
|
||||
if(SCI_isTransmitterBusy(SFRA_GUI_sci_base_addr) == 0)
|
||||
{
|
||||
SCI_writeCharBlockingNonFIFO(SFRA_GUI_sci_base_addr, SFRA_GUI_rxChar);
|
||||
SFRA_GUI_rcvTaskPointer = &SFRA_GUI_packWord;
|
||||
//
|
||||
// DEBUG
|
||||
//RcvTskPtrShdw = 7;
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// expects LSB first then MSB // Task 7
|
||||
//
|
||||
void SFRA_GUI_packWord(void)
|
||||
{
|
||||
if(SFRA_GUI_lowByteFlag == 1)
|
||||
{
|
||||
SFRA_GUI_rxWord = SFRA_GUI_rxChar;
|
||||
SFRA_GUI_lowByteFlag = 0;
|
||||
SFRA_GUI_rcvTaskPointer = &SFRA_GUI_getDataByte;
|
||||
//
|
||||
// DEBUG
|
||||
// RcvTskPtrShdw = 5;
|
||||
//
|
||||
SFRA_GUI_getDataByte();
|
||||
}
|
||||
else
|
||||
{
|
||||
SFRA_GUI_rxWord = SFRA_GUI_rxWord | (SFRA_GUI_rxChar << 8);
|
||||
SFRA_GUI_lowByteFlag = 1;
|
||||
//
|
||||
// store data in packet
|
||||
//
|
||||
SFRA_GUI_cmdPacket[2] = SFRA_GUI_rxWord;
|
||||
SFRA_GUI_rcvTaskPointer = &SFRA_GUI_cmdInterpreter;
|
||||
//
|
||||
// DEBUG
|
||||
// RcvTskPtrShdw = 8;
|
||||
// indicate new task underway
|
||||
//
|
||||
SFRA_GUI_taskDoneFlag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Task 8
|
||||
//
|
||||
void SFRA_GUI_cmdInterpreter(void)
|
||||
{
|
||||
if(SFRA_GUI_taskDoneFlag == 0)
|
||||
{
|
||||
//
|
||||
// dispatch Task
|
||||
//
|
||||
(*SFRA_GUI_cmdDispatcher[SFRA_GUI_cmdPacket[0]])();
|
||||
}
|
||||
|
||||
//
|
||||
// Incase Task never finishes
|
||||
// 2500*1mS = 2.5 sec timeout
|
||||
//
|
||||
if(SFRA_GUI_serialCommsTimer > 2500)
|
||||
{
|
||||
SFRA_GUI_commsOKflg = 0;
|
||||
//
|
||||
// Abort, go back wait for new CMD
|
||||
//
|
||||
SFRA_GUI_rcvTaskPointer = &SFRA_GUI_getCmdByte;
|
||||
SFRA_GUI_serialCommsTimer = 0;
|
||||
}
|
||||
if(SFRA_GUI_taskDoneFlag == 1)
|
||||
{
|
||||
SFRA_GUI_rcvTaskPointer = &SFRA_GUI_getCmdByte;
|
||||
//
|
||||
// DEBUG
|
||||
//RcvTskPtrShdw = 1;
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Slave Tasks commanded by Host
|
||||
//
|
||||
|
||||
//
|
||||
// CmdPacket[0] = 0
|
||||
//
|
||||
void SFRA_GUI_lifePulseTsk(void)
|
||||
{
|
||||
if(SFRA_GUI_led_flag == 1)
|
||||
{
|
||||
//
|
||||
// LED2-ON
|
||||
//
|
||||
if(SFRA_GUI_cmdPacket[2] == 0x0000 && SFRA_GUI_cmdPacket[1] == 0x00)
|
||||
{
|
||||
GPIO_togglePin(SFRA_GUI_led_gpio);
|
||||
}
|
||||
//
|
||||
// LED2-OFF
|
||||
//
|
||||
if(SFRA_GUI_cmdPacket[2] == 0x0001 && SFRA_GUI_cmdPacket[1] == 0x00)
|
||||
{
|
||||
GPIO_togglePin(SFRA_GUI_led_gpio);
|
||||
}
|
||||
//
|
||||
// LED2-Toggle
|
||||
//
|
||||
if(SFRA_GUI_cmdPacket[2] == 0x0002 && SFRA_GUI_cmdPacket[1] == 0x00)
|
||||
{
|
||||
GPIO_togglePin(SFRA_GUI_led_gpio);
|
||||
}
|
||||
}
|
||||
|
||||
SFRA_GUI_commsOKflg = 1;
|
||||
SFRA_GUI_serialCommsTimer = 0;
|
||||
SFRA_GUI_taskDoneFlag = 1;
|
||||
}
|
||||
|
||||
//
|
||||
// CmdPacket[0] = 1
|
||||
//
|
||||
void SFRA_GUI_setText(void)
|
||||
{
|
||||
*SFRA_GUI_varSetTxtList[SFRA_GUI_cmdPacket[1]] = SFRA_GUI_cmdPacket[2];
|
||||
|
||||
//
|
||||
// indicate Task execution is complete
|
||||
//
|
||||
SFRA_GUI_taskDoneFlag = 1;
|
||||
}
|
||||
|
||||
//
|
||||
// CmdPacket[0] = 2
|
||||
//
|
||||
void SFRA_GUI_setButton(void)
|
||||
{
|
||||
*SFRA_GUI_varSetBtnList[SFRA_GUI_cmdPacket[1]] = SFRA_GUI_cmdPacket[2];
|
||||
|
||||
//
|
||||
// indicate Task execution is complete
|
||||
//
|
||||
SFRA_GUI_taskDoneFlag = 1;
|
||||
}
|
||||
|
||||
//
|
||||
// CmdPacket[0] = 3
|
||||
//
|
||||
void SFRA_GUI_setSlider(void)
|
||||
{
|
||||
*SFRA_GUI_varSetSldrList[SFRA_GUI_cmdPacket[1]] = SFRA_GUI_cmdPacket[2];
|
||||
//
|
||||
// indicate Task execution is complete
|
||||
//
|
||||
SFRA_GUI_taskDoneFlag = 1;
|
||||
}
|
||||
|
||||
//
|
||||
// CmdPacket[0] = 4
|
||||
//
|
||||
void SFRA_GUI_getVariable(void)
|
||||
{
|
||||
SFRA_GUI_sendData();
|
||||
}
|
||||
|
||||
//
|
||||
//Send a Uint16 array one element at a time
|
||||
// CmdPacket[0] = 5
|
||||
//
|
||||
void SFRA_GUI_getArray(void)
|
||||
{
|
||||
SFRA_GUI_sendData();
|
||||
}
|
||||
|
||||
//
|
||||
// CmdPacket[0] = 6
|
||||
//
|
||||
void SFRA_GUI_getData(void)
|
||||
{
|
||||
switch(SFRA_GUI_memGetPtr)
|
||||
{
|
||||
case 0:
|
||||
SFRA_GUI_memGetAddress = SFRA_GUI_cmdPacket[2];
|
||||
SFRA_GUI_memGetPtr = 1;
|
||||
|
||||
SFRA_GUI_wordsLeftToGet = 1;
|
||||
SFRA_GUI_sendTaskPtr = 1;
|
||||
SFRA_GUI_taskDoneFlag = 1;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
SFRA_GUI_temp = SFRA_GUI_cmdPacket[2];
|
||||
SFRA_GUI_memGetAddress = SFRA_GUI_memGetAddress +
|
||||
(SFRA_GUI_temp << 16);
|
||||
SFRA_GUI_memDataPtr16 = (int16_t *)SFRA_GUI_memGetAddress;
|
||||
SFRA_GUI_dataOut16 = *SFRA_GUI_memDataPtr16;
|
||||
SFRA_GUI_sendData();
|
||||
|
||||
if(SFRA_GUI_taskDoneFlag == 1)
|
||||
{
|
||||
SFRA_GUI_memGetPtr = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// indicate Task execution is complete
|
||||
// TaskDoneFlag = 1;
|
||||
//
|
||||
}
|
||||
|
||||
//
|
||||
// CmdPacket[0] = 7 [Edited to get 32-bit set text and set label working]
|
||||
//
|
||||
void SFRA_GUI_setData32(void)
|
||||
{
|
||||
switch(SFRA_GUI_memSetPtr)
|
||||
{
|
||||
case 0:
|
||||
SFRA_GUI_memSetValue = SFRA_GUI_cmdPacket[2];
|
||||
SFRA_GUI_memSetPtr = 1;
|
||||
|
||||
SFRA_GUI_taskDoneFlag = 1;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
SFRA_GUI_temp = SFRA_GUI_cmdPacket[2];
|
||||
SFRA_GUI_memSetValue = SFRA_GUI_memSetValue + (SFRA_GUI_temp << 16);
|
||||
|
||||
*SFRA_GUI_dataSetList[SFRA_GUI_cmdPacket[1]] = SFRA_GUI_memSetValue;
|
||||
|
||||
SFRA_GUI_memSetPtr = 0;
|
||||
SFRA_GUI_taskDoneFlag = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// CmdPacket[0] = 8
|
||||
//
|
||||
void SFRA_GUI_spareTsk08(void)
|
||||
{
|
||||
//
|
||||
// indicate Task execution is complete
|
||||
//
|
||||
SFRA_GUI_taskDoneFlag = 1;
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
void SFRA_GUI_sendData(void)
|
||||
{
|
||||
if(SFRA_GUI_cmdPacket[0] == 0x04 || SFRA_GUI_cmdPacket[0] == 0x06)
|
||||
{
|
||||
switch(SFRA_GUI_sendTaskPtr)
|
||||
{
|
||||
case 0: //initialization
|
||||
|
||||
SFRA_GUI_memDataPtr16 =
|
||||
(int16_t *) SFRA_GUI_varGetList[SFRA_GUI_cmdPacket[1]];
|
||||
SFRA_GUI_dataOut16 = *SFRA_GUI_memDataPtr16;
|
||||
SFRA_GUI_wordsLeftToGet = SFRA_GUI_cmdPacket[2];
|
||||
//
|
||||
//Note that case 0 rolls into case 1 (no break)
|
||||
//
|
||||
|
||||
case 1: //send LSB
|
||||
if(SFRA_GUI_wordsLeftToGet > 0)
|
||||
{
|
||||
if(SCI_isTransmitterBusy(SFRA_GUI_sci_base_addr) == 0)
|
||||
{
|
||||
SCI_writeCharBlockingNonFIFO(SFRA_GUI_sci_base_addr,
|
||||
SFRA_GUI_dataOut16 & 0x000000FF);
|
||||
SFRA_GUI_sendTaskPtr = 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SFRA_GUI_sendTaskPtr = 0;
|
||||
SFRA_GUI_taskDoneFlag = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: //send MSB
|
||||
if(SCI_isTransmitterBusy(SFRA_GUI_sci_base_addr) == 0)
|
||||
{
|
||||
SCI_writeCharBlockingNonFIFO(SFRA_GUI_sci_base_addr,
|
||||
SFRA_GUI_dataOut16 >> 8 & 0x000000FF);
|
||||
|
||||
SFRA_GUI_memDataPtr16 = SFRA_GUI_memDataPtr16 + 1;
|
||||
SFRA_GUI_dataOut16 = *SFRA_GUI_memDataPtr16;
|
||||
SFRA_GUI_wordsLeftToGet = SFRA_GUI_wordsLeftToGet - 1;
|
||||
SFRA_GUI_sendTaskPtr = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(SFRA_GUI_sendTaskPtr)
|
||||
{
|
||||
case 0: //initialization
|
||||
SFRA_GUI_memDataPtr32 =
|
||||
(int32_t *) SFRA_GUI_arrayGetList[SFRA_GUI_cmdPacket[1]];
|
||||
SFRA_GUI_dataOut32 = *SFRA_GUI_memDataPtr32;
|
||||
SFRA_GUI_wordsLeftToGet = SFRA_GUI_cmdPacket[2];
|
||||
//
|
||||
//Note that case 0 rolls into case 1 (no break)
|
||||
//
|
||||
case 1: //send LSB
|
||||
if(SFRA_GUI_wordsLeftToGet > 0)
|
||||
{
|
||||
if(SCI_isTransmitterBusy(SFRA_GUI_sci_base_addr) == 0)
|
||||
{
|
||||
SCI_writeCharBlockingNonFIFO(SFRA_GUI_sci_base_addr,
|
||||
SFRA_GUI_dataOut32 & 0x000000FF);
|
||||
SFRA_GUI_sendTaskPtr = 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SFRA_GUI_sendTaskPtr = 0;
|
||||
SFRA_GUI_taskDoneFlag = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
if(SCI_isTransmitterBusy(SFRA_GUI_sci_base_addr) == 0)
|
||||
{
|
||||
SCI_writeCharBlockingNonFIFO(SFRA_GUI_sci_base_addr,
|
||||
SFRA_GUI_dataOut32 >> 8 & 0x000000FF);
|
||||
SFRA_GUI_sendTaskPtr = 3;
|
||||
}
|
||||
|
||||
case 3:
|
||||
if(SCI_isTransmitterBusy(SFRA_GUI_sci_base_addr) == 0)
|
||||
{
|
||||
SCI_writeCharBlockingNonFIFO(SFRA_GUI_sci_base_addr,
|
||||
SFRA_GUI_dataOut32 >> 16 & 0x000000FF);
|
||||
SFRA_GUI_sendTaskPtr = 4;
|
||||
}
|
||||
|
||||
case 4:
|
||||
//
|
||||
// send MSB
|
||||
//
|
||||
if(SCI_isTransmitterBusy(SFRA_GUI_sci_base_addr) == 0)
|
||||
{
|
||||
SCI_writeCharBlockingNonFIFO(SFRA_GUI_sci_base_addr,
|
||||
SFRA_GUI_dataOut32 >> 24 & 0x000000FF);
|
||||
|
||||
SFRA_GUI_memDataPtr32 = SFRA_GUI_memDataPtr32 + 1;
|
||||
SFRA_GUI_dataOut32 = *SFRA_GUI_memDataPtr32;
|
||||
SFRA_GUI_wordsLeftToGet = SFRA_GUI_wordsLeftToGet - 1;
|
||||
SFRA_GUI_sendTaskPtr = 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
//###########################################################################
|
||||
//
|
||||
// FILE: sfra_gui_scicomms_driverlib.h
|
||||
//
|
||||
// TITLE: Comms kernel as an interface to SFRA GUI header file
|
||||
//
|
||||
// AUTHOR: Manish Bhardwaj (C2000 Systems Solutions, Houston , TX)
|
||||
//
|
||||
//#############################################################################
|
||||
// $TI Release: C2000 Software Frequency Response Analyzer Library v1.50.02.00 $
|
||||
// $Release Date: Tue Aug 26 14:08:13 CDT 2025 $
|
||||
// $Copyright:
|
||||
// Copyright (C) 2025 Texas Instruments Incorporated - http://www.ti.com/
|
||||
//
|
||||
// ALL RIGHTS RESERVED
|
||||
// $
|
||||
//#############################################################################
|
||||
#ifndef SFRA_GUI_H
|
||||
#define SFRA_GUI_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include "driverlib.h"
|
||||
#include "device.h"
|
||||
#include "sfra_f32.h"
|
||||
|
||||
#define SFRA_GUI_PKT_SIZE 6
|
||||
#define SFRA_GUI_CMD_NUMBER 16
|
||||
#define SFRA_GUI_MAX_CMD_NUM 8
|
||||
|
||||
|
||||
#define SFRA_GUI_PLOT_GH_H 1
|
||||
#define SFRA_GUI_PLOT_GH_CL 2
|
||||
|
||||
//
|
||||
//! \brief Configures the SFRA_GUI module
|
||||
//! \param sci_base Base address of the SCI module used by the SFRA GUI
|
||||
//! \param vbus_clk Frequency of the VBUS, used by the SCI module
|
||||
//! \param baudrate baudrate used by the SFRA GUI
|
||||
//! \param scirx_gpio_pin GPIO pin used for SCI_RX
|
||||
//! \param scirx_gpio_pin_config GPIO pin config used for SCI_RX
|
||||
//! \param scitx_gpio_pin GPIO pin used for SCI_TX
|
||||
//! \param scitx_gpio_pin_config GPIO pin config used for SCI_TX
|
||||
//! \param led_indicator_flag Flag to indicate if LED toggle for SFRA_GUI is
|
||||
//! enabled, 1 -> Enable , anything else Disable
|
||||
//! \param led_gpio_pin GPIO pin used for LED, if led_flag_indicator is 1
|
||||
//! otherwise pass 0
|
||||
//! \param led_gpio_pin_config GPIO pin config value for LED,
|
||||
//! if led_flag_indicator is 1 otherwise pass 0
|
||||
//! \param *sfra Pointer to sfra object
|
||||
//! \param plot_option used to select what SFRA GUI will plot,
|
||||
//! 1 - GH & H
|
||||
//! 2 - CL & H
|
||||
//!
|
||||
void SFRA_GUI_config( volatile uint32_t sci_base,
|
||||
uint32_t vbus_clk,
|
||||
uint32_t baudrate,
|
||||
uint16_t scirx_gpio_pin,
|
||||
uint32_t scirx_gpio_pin_config,
|
||||
uint16_t scitx_gpio_pin,
|
||||
uint32_t scitx_gpio_pin_config,
|
||||
uint16_t led_indicator_flag,
|
||||
uint16_t led_gpio_pin,
|
||||
uint32_t led_gpio_pin_config,
|
||||
SFRA_F32 *sfra,
|
||||
uint16_t plot_option);
|
||||
|
||||
//
|
||||
//! \brief Runs the serial host comms GUI ,
|
||||
//! needs to be called at ~100ms for proper function
|
||||
//! \param *sfra Pointer to sfra object
|
||||
//!
|
||||
void SFRA_GUI_runSerialHostComms(SFRA_F32 *sfra);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // extern "C"
|
||||
|
||||
#endif // end of SFRA_F32_H definition
|
||||
|
||||
|
||||
Reference in New Issue
Block a user