158 lines
5.7 KiB
C
158 lines
5.7 KiB
C
#include "ecg_generator.h"
|
||
#include <math.h>
|
||
#include <string.h>
|
||
#include "esp_log.h"
|
||
|
||
// 初始化ECG生成器
|
||
void ecg_generator_init(ecg_generator_t *generator, float sample_rate) {
|
||
if (generator == NULL) return;
|
||
|
||
memset(generator, 0, sizeof(ecg_generator_t));
|
||
|
||
// 设置默认参数
|
||
generator->heart_rate = 75.0f; // 心率75次/分
|
||
generator->amplitude = 1.0f; // 幅值1.0V
|
||
generator->sample_rate = sample_rate;
|
||
generator->is_running = false;
|
||
|
||
// 固定波形参数 (保持正常ECG比例)
|
||
generator->p_amp_ratio = 0.2f; // P波幅度比例
|
||
generator->q_amp_ratio = 0.3f; // Q波幅度比例
|
||
generator->r_amp_ratio = 1.0f; // R波幅度比例
|
||
generator->s_amp_ratio = 0.4f; // S波幅度比例
|
||
generator->t_amp_ratio = 0.4f; // T波幅度比例
|
||
|
||
// 固定时间参数 (保持正常ECG时序)
|
||
generator->p_width = 0.03f; // P波宽度
|
||
generator->qrs_width = 0.01f; // QRS波群宽度
|
||
generator->t_width = 0.05f; // T波宽度
|
||
}
|
||
|
||
// 设置心率
|
||
void ecg_generator_set_heart_rate(ecg_generator_t *generator, float heart_rate) {
|
||
if (generator == NULL) return;
|
||
|
||
// 限制心率范围
|
||
if (heart_rate < 30.0f) heart_rate = 30.0f;
|
||
if (heart_rate > 200.0f) heart_rate = 200.0f;
|
||
|
||
generator->heart_rate = heart_rate;
|
||
}
|
||
|
||
// 设置幅值(直接输入mV值,内部自动转换为DAC输出值)
|
||
void ecg_generator_set_amplitude(ecg_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;
|
||
}
|
||
|
||
// 开始生成
|
||
void ecg_generator_start(ecg_generator_t *generator) {
|
||
if (generator == NULL) return;
|
||
|
||
generator->is_running = true;
|
||
generator->sample_count = 0;
|
||
}
|
||
|
||
// 停止生成
|
||
void ecg_generator_stop(ecg_generator_t *generator) {
|
||
if (generator == NULL) return;
|
||
|
||
generator->is_running = false;
|
||
}
|
||
|
||
// 重置生成器
|
||
void ecg_generator_reset(ecg_generator_t *generator) {
|
||
if (generator == NULL) return;
|
||
|
||
generator->sample_count = 0;
|
||
}
|
||
|
||
// 获取下一个样本 - 修正时间参数为相对比例
|
||
float ecg_generator_get_next_sample(ecg_generator_t *generator) {
|
||
if (generator == NULL || !generator->is_running) {
|
||
return 0.0f;
|
||
}
|
||
|
||
// 计算RR间期 (秒)
|
||
float rr_interval = 60.0f / generator->heart_rate;
|
||
|
||
// 计算当前时间
|
||
float t = (float)generator->sample_count / generator->sample_rate;
|
||
|
||
// 周期内时间
|
||
float t_mod = fmodf(t, rr_interval);
|
||
|
||
// 归一化时间到0-1范围(相对于RR间期的比例)
|
||
float t_norm = t_mod / rr_interval;
|
||
|
||
// 计算各波幅度
|
||
float p_amp = generator->amplitude * generator->p_amp_ratio;
|
||
float q_amp = generator->amplitude * generator->q_amp_ratio;
|
||
float r_amp = generator->amplitude * generator->r_amp_ratio;
|
||
float s_amp = generator->amplitude * generator->s_amp_ratio;
|
||
float t_amp = generator->amplitude * generator->t_amp_ratio;
|
||
|
||
// 时间参数(相对于RR间期的比例) - 根据Python代码修正
|
||
float p_time_ratio = 0.125f; // P波位置:12.5%
|
||
float q_time_ratio = 0.3125f; // Q波位置:31.25%
|
||
float r_time_ratio = 0.3375f; // R波位置:33.75%
|
||
float s_time_ratio = 0.3625f; // S波位置:36.25%
|
||
float t_time_ratio = 0.625f; // T波位置:62.5%
|
||
|
||
// 宽度参数(相对于RR间期的比例) - 修正QRS宽度使其充分重叠
|
||
float p_width_ratio = 0.0375f; // P波宽度:0.03/0.8 = 3.75%
|
||
float qrs_width_ratio = 0.0125f; // QRS宽度:增加到2.5%,确保Q、R、S充分重叠
|
||
float t_width_ratio = 0.0625f; // T波宽度:0.05/0.8 = 6.25%
|
||
|
||
// P波 - 修正后的计算
|
||
float p = p_amp * expf(-(t_norm - p_time_ratio) * (t_norm - p_time_ratio) / (2.0f * p_width_ratio * p_width_ratio));
|
||
|
||
// QRS波群 - 修正后的计算
|
||
float q = -q_amp * expf(-(t_norm - q_time_ratio) * (t_norm - q_time_ratio) / (2.0f * qrs_width_ratio * qrs_width_ratio));
|
||
float r = r_amp * expf(-(t_norm - r_time_ratio) * (t_norm - r_time_ratio) / (2.0f * qrs_width_ratio * qrs_width_ratio));
|
||
float s = -s_amp * expf(-(t_norm - s_time_ratio) * (t_norm - s_time_ratio) / (2.0f * qrs_width_ratio * qrs_width_ratio));
|
||
float qrs = q + r + s;
|
||
|
||
// T波 - 修正后的计算
|
||
float t_wave = t_amp * expf(-(t_norm - t_time_ratio) * (t_norm - t_time_ratio) / (2.0f * t_width_ratio * t_width_ratio));
|
||
|
||
// 组合波形
|
||
float ecg_value = p + qrs + t_wave;
|
||
|
||
// 调试信息:每1000个样本输出一次最大值
|
||
static float max_ecg_value = 0.0f;
|
||
static uint32_t debug_counter = 0;
|
||
debug_counter++;
|
||
|
||
if (fabsf(ecg_value) > max_ecg_value) {
|
||
max_ecg_value = fabsf(ecg_value);
|
||
}
|
||
|
||
if (debug_counter >= 1000) {
|
||
ESP_LOGI("ECG_DEBUG", "Max ECG value before offset: %.3fV", max_ecg_value);
|
||
debug_counter = 0;
|
||
max_ecg_value = 0.0f;
|
||
}
|
||
|
||
// 添加偏置电压,将ECG波形平移到DAC有效范围
|
||
// ECG波形范围约为 -amplitude 到 +amplitude
|
||
// 需要平移到 0 到 2*amplitude,然后限制在DAC范围内
|
||
float offset = generator->amplitude; // 偏置电压
|
||
ecg_value = ecg_value + offset;
|
||
|
||
// 限制在DAC有效范围内 (0V 到 2.048V)
|
||
if (ecg_value < 0.0f) ecg_value = 0.0f;
|
||
if (ecg_value > 2.048f) ecg_value = 2.048f;
|
||
|
||
generator->sample_count++;
|
||
return ecg_value;
|
||
}
|