Stimulate/components/signal_generators/src/sine_generator.c

200 lines
6.2 KiB
C
Raw Normal View History

2025-09-26 14:16:44 +08:00
#include "sine_generator.h"
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include "esp_log.h"
// 初始化正弦波生成器
void sine_generator_init(sine_generator_t *generator, float sample_rate) {
if (generator == NULL) return;
memset(generator, 0, sizeof(sine_generator_t));
// 设置默认参数
generator->frequency = 200.0f; // 默认200Hz正弦波
generator->amplitude = 1.0f; // 幅值1.0V
generator->sample_rate = sample_rate;
generator->is_running = false;
// 查找表参数
generator->sine_lookup_table = NULL;
generator->table_size = 0;
generator->table_index = 0;
}
// 设置正弦波频率
void sine_generator_set_frequency(sine_generator_t *generator, float frequency) {
if (generator == NULL) return;
// 限制频率范围
if (frequency < 0.1f) frequency = 0.1f;
if (frequency > 10000.0f) frequency = 10000.0f;
generator->frequency = frequency;
// 如果已经运行,重新生成查找表
if (generator->is_running) {
sine_generator_generate_lookup_table(generator);
}
ESP_LOGI("SINE_GEN", "Sine wave frequency set to: %.1f Hz", frequency);
}
// 设置幅值直接输入mV值内部自动转换为DAC输出值
void sine_generator_set_amplitude(sine_generator_t *generator, float amplitude_mv) {
if (generator == NULL) return;
// 硬件衰减系数约38倍 (根据实际测量0.132V → 5mV)
// 对应关系amplitude(V) × 38 ≈ 示波器显示值(mV)
const float attenuation_factor = 38.0f;
// 将mV除以衰减系数得到DAC输出值
float dac_amplitude = amplitude_mv / attenuation_factor;
generator->amplitude = dac_amplitude;
// 如果已经运行,重新生成查找表
if (generator->is_running) {
sine_generator_generate_lookup_table(generator);
}
ESP_LOGI("SINE_GEN", "Sine wave amplitude set to: %.1f mV", amplitude_mv);
}
// 开始生成
void sine_generator_start(sine_generator_t *generator) {
if (generator == NULL) return;
generator->is_running = true;
generator->sample_count = 0;
// 生成查找表
sine_generator_generate_lookup_table(generator);
ESP_LOGI("SINE_GEN", "Sine generator started: %.1f Hz, %.1f mV",
generator->frequency, generator->amplitude * 38.0f);
}
// 停止生成
void sine_generator_stop(sine_generator_t *generator) {
if (generator == NULL) return;
generator->is_running = false;
ESP_LOGI("SINE_GEN", "Sine generator stopped");
}
// 重置生成器
void sine_generator_reset(sine_generator_t *generator) {
if (generator == NULL) return;
generator->sample_count = 0;
generator->table_index = 0;
}
// 获取下一个样本
float sine_generator_get_next_sample(sine_generator_t *generator) {
if (generator == NULL || !generator->is_running) {
return 0.0f;
}
// 使用预计算的查找表,超高速访问
if (generator->sine_lookup_table != NULL && generator->table_size > 0) {
// 从查找表获取预计算的值
float sine_value = generator->sine_lookup_table[generator->table_index];
// 更新索引,循环使用查找表
generator->table_index = (generator->table_index + 1) % generator->table_size;
generator->sample_count++;
return sine_value;
} else {
// 如果查找表未初始化,使用实时计算(备用方案)
float t = (float)generator->sample_count / generator->sample_rate;
float sine_value = generator->amplitude * sinf(2.0f * M_PI * generator->frequency * t);
// 添加偏置电压
float offset = generator->amplitude;
sine_value = sine_value + offset;
// 限制在DAC有效范围内
if (sine_value < 0.0f) sine_value = 0.0f;
if (sine_value > 2.048f) sine_value = 2.048f;
generator->sample_count++;
return sine_value;
}
}
// 生成正弦波查找表
void sine_generator_generate_lookup_table(sine_generator_t *generator) {
if (generator == NULL) return;
// 释放旧的查找表
sine_generator_free_lookup_table(generator);
// 计算查找表大小:一个完整周期的样本数
// 表大小 = 采样率 / 正弦波频率
generator->table_size = (uint32_t)(generator->sample_rate / generator->frequency);
// 确保表大小至少为1
if (generator->table_size < 1) {
generator->table_size = 1;
}
// 分配内存
generator->sine_lookup_table = (float*)malloc(generator->table_size * sizeof(float));
if (generator->sine_lookup_table == NULL) {
ESP_LOGE("SINE_GEN", "Failed to allocate memory for sine lookup table");
generator->table_size = 0;
return;
}
// 预计算正弦波值
for (uint32_t i = 0; i < generator->table_size; i++) {
// 计算时间点
float t = (float)i / generator->sample_rate;
// 计算正弦波值
float sine_value = generator->amplitude * sinf(2.0f * M_PI * generator->frequency * t);
// 添加偏置电压
float offset = generator->amplitude;
sine_value = sine_value + offset;
// 限制在DAC有效范围内
if (sine_value < 0.0f) sine_value = 0.0f;
if (sine_value > 2.048f) sine_value = 2.048f;
generator->sine_lookup_table[i] = sine_value;
}
// 重置索引
generator->table_index = 0;
ESP_LOGI("SINE_GEN", "Generated sine lookup table: %u points, %.1f Hz",
generator->table_size, generator->frequency);
}
// 释放正弦波查找表
void sine_generator_free_lookup_table(sine_generator_t *generator) {
if (generator == NULL) return;
if (generator->sine_lookup_table != NULL) {
free(generator->sine_lookup_table);
generator->sine_lookup_table = NULL;
}
generator->table_size = 0;
generator->table_index = 0;
}
// 清理生成器(释放所有资源)
void sine_generator_cleanup(sine_generator_t *generator) {
if (generator == NULL) return;
generator->is_running = false;
sine_generator_free_lookup_table(generator);
ESP_LOGI("SINE_GEN", "Sine generator cleaned up");
}