Stimulate/main/main.c

310 lines
11 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <stdio.h>
#include "esp32_s3_szp.h"
#include "app_ui.h"
#include <esp_system.h>
#include <math.h>
#include "ecg_generator.h"
#include "sine_generator.h"
#include "esp_timer.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
EventGroupHandle_t my_event_group;
// 按键定义
#define BUTTON_PIN GPIO_NUM_0 // 使用GPIO0作为按键输入
#define BUTTON_DEBOUNCE_MS 200 // 防抖时间
static const char *TAG = "MAIN";
// 信号生成器相关
static ecg_generator_t g_ecg_gen_i; // I导联ECG生成器
static ecg_generator_t g_ecg_gen_ii; // II导联ECG生成器
static ecg_generator_t g_ecg_gen_v1; // V1导联ECG生成器
static ecg_generator_t g_ecg_gen_v2; // V2导联ECG生成器
static ecg_generator_t g_ecg_gen_v3; // V3导联ECG生成器
static ecg_generator_t g_ecg_gen_v4; // V4导联ECG生成器
static ecg_generator_t g_ecg_gen_v5; // V5导联ECG生成器
static ecg_generator_t g_ecg_gen_v6; // V6导联ECG生成器
static sine_generator_t g_sine_gen;
static esp_timer_handle_t signal_timer = NULL;
static uint32_t signal_sample_count = 0;
static uint32_t signal_last_log_time = 0;
static bool use_sine_wave = true; // true=正弦波, false=ECG
// 移除use_lead_i变量因为现在同时输出两个导联
// 信号生成器定时器回调函数
static void signal_timer_callback(void* arg) {
float signal_voltage = 0.0f;
if (use_sine_wave) {
// 生成正弦波样本
signal_voltage = sine_generator_get_next_sample(&g_sine_gen);
// 输出到DAC通道2
set_channel_voltage(2, signal_voltage);
} else {
// ECG模式同时输出多个导联
// I导联输出到通道2
signal_voltage = ecg_generator_get_next_sample(&g_ecg_gen_i);
set_channel_voltage(2, signal_voltage);
// II导联输出到通道3
signal_voltage = ecg_generator_get_next_sample(&g_ecg_gen_ii);
set_channel_voltage(3, signal_voltage);
// V1导联输出到通道4
signal_voltage = ecg_generator_get_next_sample(&g_ecg_gen_v1);
set_channel_voltage(4, signal_voltage);
// V2导联输出到通道5
signal_voltage = ecg_generator_get_next_sample(&g_ecg_gen_v2);
set_channel_voltage(5, signal_voltage);
// V3导联输出到通道6
signal_voltage = ecg_generator_get_next_sample(&g_ecg_gen_v3);
set_channel_voltage(6, signal_voltage);
// V4导联输出到通道7
signal_voltage = ecg_generator_get_next_sample(&g_ecg_gen_v4);
set_channel_voltage(7, signal_voltage);
// V5、V6导联生成器已实现但不输出到通道
ecg_generator_get_next_sample(&g_ecg_gen_v5);
ecg_generator_get_next_sample(&g_ecg_gen_v6);
}
signal_sample_count++;
// 减少日志输出频率,避免影响高频中断性能
// 每20000个样本输出一次统计信息约1秒
if (signal_sample_count >= 20000) {
if (use_sine_wave) {
ESP_LOGI(TAG, "Generated %u samples at 20kHz (Sine Wave)", signal_sample_count);
} else {
ESP_LOGI(TAG, "Generated %u samples at 20kHz (ECG I+II+V1+V2+V3+V4)", signal_sample_count);
}
signal_sample_count = 0;
signal_last_log_time = esp_timer_get_time() / 1000;
}
}
// 函数声明
void displayMemoryUsage(void);
void test_signal_generation(void);
void switch_to_ecg_mode(void);
void switch_to_sine_mode(void);
void switch_ecg_lead(void);
// 信号生成器测试函数
void test_signal_generation(void) {
ESP_LOGI(TAG, "=== Signal Generation Test ===");
// 初始化ECG生成器
ecg_generator_init(&g_ecg_gen_i, 20000.0f, ECG_LEAD_I); // I导联20kHz生成率
ecg_param_set(&g_ecg_gen_i, 5.0f, 75.0f);
ecg_generator_init(&g_ecg_gen_ii, 20000.0f, ECG_LEAD_II); // II导联20kHz生成率
ecg_param_set(&g_ecg_gen_ii, 5.0f, 75.0f);
ecg_generator_init(&g_ecg_gen_v1, 20000.0f, ECG_LEAD_V1); // V1导联20kHz生成率
ecg_param_set(&g_ecg_gen_v1, 5.0f, 75.0f);
ecg_generator_init(&g_ecg_gen_v2, 20000.0f, ECG_LEAD_V2); // V2导联20kHz生成率
ecg_param_set(&g_ecg_gen_v2, 5.0f, 75.0f);
ecg_generator_init(&g_ecg_gen_v3, 20000.0f, ECG_LEAD_V3); // V3导联20kHz生成率
ecg_param_set(&g_ecg_gen_v3, 5.0f, 75.0f);
ecg_generator_init(&g_ecg_gen_v4, 20000.0f, ECG_LEAD_V4); // V4导联20kHz生成率
ecg_param_set(&g_ecg_gen_v4, 5.0f, 75.0f);
ecg_generator_init(&g_ecg_gen_v5, 20000.0f, ECG_LEAD_V5); // V5导联20kHz生成率
ecg_param_set(&g_ecg_gen_v5, 5.0f, 75.0f);
ecg_generator_init(&g_ecg_gen_v6, 20000.0f, ECG_LEAD_V6); // V6导联20kHz生成率
ecg_param_set(&g_ecg_gen_v6, 5.0f, 75.0f);
// 初始化正弦波生成器
sine_generator_init(&g_sine_gen, 20000.0f); // 20kHz生成率
sine_generator_set_frequency(&g_sine_gen, 10.0f); // 10Hz正弦波
sine_generator_set_amplitude(&g_sine_gen, 5.0f); // 5mV
// 创建定时器配置
const esp_timer_create_args_t timer_args = {
.callback = &signal_timer_callback,
.name = "signal_timer"
};
// 创建定时器
esp_err_t ret = esp_timer_create(&timer_args, &signal_timer);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to create signal timer: %s", esp_err_to_name(ret));
return;
}
// 启动信号生成器
if (use_sine_wave) {
sine_generator_start(&g_sine_gen);
ESP_LOGI(TAG, "Started sine wave generator: 10Hz, 5mV");
} else {
// 同时启动多个ECG导联
ecg_generator_start(&g_ecg_gen_i);
ecg_generator_start(&g_ecg_gen_ii);
ecg_generator_start(&g_ecg_gen_v1);
ecg_generator_start(&g_ecg_gen_v2);
ecg_generator_start(&g_ecg_gen_v3);
ecg_generator_start(&g_ecg_gen_v4);
ecg_generator_start(&g_ecg_gen_v5);
ecg_generator_start(&g_ecg_gen_v6);
ESP_LOGI(TAG, "Started ECG generators: I+II+V1+V2+V3+V4+V5+V6, 75 BPM, 5mV");
}
// 启动定时器 (50us = 20kHz)
ret = esp_timer_start_periodic(signal_timer, 50); // 50微秒 = 20kHz
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to start signal timer: %s", esp_err_to_name(ret));
esp_timer_delete(signal_timer);
return;
}
ESP_LOGI(TAG, "Signal timer started at 20kHz (50us period)");
}
// 切换到ECG模式
void switch_to_ecg_mode(void) {
if (use_sine_wave) {
sine_generator_stop(&g_sine_gen);
// 同时启动多个ECG导联
ecg_generator_start(&g_ecg_gen_i);
ecg_generator_start(&g_ecg_gen_ii);
ecg_generator_start(&g_ecg_gen_v1);
ecg_generator_start(&g_ecg_gen_v2);
ecg_generator_start(&g_ecg_gen_v3);
ecg_generator_start(&g_ecg_gen_v4);
ecg_generator_start(&g_ecg_gen_v5);
ecg_generator_start(&g_ecg_gen_v6);
ESP_LOGI(TAG, "Switched to ECG mode (I+SII+V1+V2+V3+V4)");
use_sine_wave = false;
}
}
// 切换到正弦波模式
void switch_to_sine_mode(void) {
if (!use_sine_wave) {
// 停止所有ECG导联
ecg_generator_stop(&g_ecg_gen_i);
ecg_generator_stop(&g_ecg_gen_ii);
ecg_generator_stop(&g_ecg_gen_v1);
ecg_generator_stop(&g_ecg_gen_v2);
ecg_generator_stop(&g_ecg_gen_v3);
ecg_generator_stop(&g_ecg_gen_v4);
ecg_generator_stop(&g_ecg_gen_v5);
ecg_generator_stop(&g_ecg_gen_v6);
sine_generator_start(&g_sine_gen);
use_sine_wave = true;
ESP_LOGI(TAG, "Switched to sine wave mode");
}
}
// 切换ECG导联现在不需要因为同时输出两个导联
void switch_ecg_lead(void) {
// 此函数保留但不使用因为现在同时输出I导联和II导联
ESP_LOGI(TAG, "ECG mode: Both I导联 and II导联 are active simultaneously");
}
// 按键初始化
void button_init(void) {
gpio_config_t io_conf = {};
io_conf.intr_type = GPIO_INTR_DISABLE;
io_conf.mode = GPIO_MODE_INPUT;
io_conf.pin_bit_mask = (1ULL << BUTTON_PIN);
io_conf.pull_down_en = 0;
io_conf.pull_up_en = 1; // 启用上拉电阻
gpio_config(&io_conf);
ESP_LOGI(TAG, "Button initialized on GPIO %d", BUTTON_PIN);
}
// 检测按键按下
bool button_pressed(void) {
static uint32_t last_press_time = 0;
uint32_t current_time = esp_timer_get_time() / 1000; // 转换为毫秒
// 检测按键按下(低电平)
if (gpio_get_level(BUTTON_PIN) == 0) {
// 防抖处理
if (current_time - last_press_time > BUTTON_DEBOUNCE_MS) {
last_press_time = current_time;
return true;
}
}
return false;
}
// 打印内存使用情况
void displayMemoryUsage() {
size_t totalDRAM = heap_caps_get_total_size(MALLOC_CAP_INTERNAL);
size_t freeDRAM = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
size_t usedDRAM = totalDRAM - freeDRAM;
size_t totalPSRAM = heap_caps_get_total_size(MALLOC_CAP_SPIRAM);
size_t freePSRAM = heap_caps_get_free_size(MALLOC_CAP_SPIRAM);
size_t usedPSRAM = totalPSRAM - freePSRAM;
size_t DRAM_largest_block = heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL);
size_t PSRAM_largest_block = heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM);
float dramUsagePercentage = (float)usedDRAM / totalDRAM * 100;
float psramUsagePercentage = (float)usedPSRAM / totalPSRAM * 100;
ESP_LOGI(TAG, "DRAM Total: %zu bytes, Used: %zu bytes, Free: %zu bytes, DRAM_Largest_block: %zu bytes", totalDRAM, usedDRAM, freeDRAM, DRAM_largest_block);
ESP_LOGI(TAG, "DRAM Used: %.2f%%", dramUsagePercentage);
ESP_LOGI(TAG, "PSRAM Total: %zu bytes, Used: %zu bytes, Free: %zu bytes, PSRAM_Largest_block: %zu bytes", totalPSRAM, usedPSRAM, freePSRAM, PSRAM_largest_block);
ESP_LOGI(TAG, "PSRAM Used: %.2f%%", psramUsagePercentage);
}
// 主函数
void app_main(void)
{
ESP_LOGI(TAG, "Starting ECG application...");
// 硬件初始化
bsp_i2c_init(); // I2C初始化
LED_init(); // LED初始化
init_ad5328(); // DAC初始化
button_init(); // 按键初始化
my_event_group = xEventGroupCreate();
ESP_LOGI(TAG, "Hardware initialization completed.");
// 启动信号生成
test_signal_generation();
// LED状态指示
ESP_LOGI(TAG, "Starting LED status indicator...");
int led_count = 0;
while (true) {
// 检测按键按下
if (button_pressed()) {
if (use_sine_wave) {
switch_to_ecg_mode();
} else {
// 在ECG模式下按键切换回正弦波
switch_to_sine_mode();
}
}
// LED闪烁指示系统运行
gpio_set_level(LED_PIN, 1); // LED亮
vTaskDelay(pdMS_TO_TICKS(1000));
gpio_set_level(LED_PIN, 0); // LED灭
vTaskDelay(pdMS_TO_TICKS(1000));
// 每10次循环显示一次内存使用情况
if (++led_count % 10 == 0) {
displayMemoryUsage();
}
}
}