200 lines
6.2 KiB
C
200 lines
6.2 KiB
C
#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");
|
||
}
|