/*
*Copyright (C),2023 , NANOCHAP
*File name:   ENS1_WAVEGEN.C
*Author:
*Version:     V1.0
*Date:        2023-11-
*Description: 波形生成器电刺激功能实现
*Function List:
     1  int wavegen_driverA_sine_test(CMSDK_WAVE_GEN_TypeDef *CMSDK_WAVEGEN_DRVA, uint16_t incount);
     2  void wavegen_Stop(CMSDK_WAVE_GEN_TypeDef *CMSDK_WAVEGEN_DRVA);
     3  void wavegen_Init(void);
     4  void wavegen_Start(void);
History:
1.V1.0
Date:
Author:
Modification: 初版
*/

#include <stdio.h>
#include "ENS1_WAVEGEN.h"
#include "ENS1_CLOCK.h"
#include "ENS1_BOOST.h"

// 全局变量
static EMS_Config_TypeDef g_ems_config = {0};
static volatile uint8_t g_ems_running = 0;
static volatile uint32_t g_ems_count = 0;

// 缓进缓出控制变量
static volatile uint16_t g_current_intensity = 0; // 当前强度
static volatile uint8_t g_ramp_phase = 0;         // 渐进阶段：0=缓进, 1=保持, 2=缓出
static volatile uint32_t g_wave_counter = 0;      // 方波周期计数器
static volatile uint32_t g_ramp_step_counter = 0; // 缓进步进计数器

/* --------------------------------------------------------------- */
/*  波形生成器驱动器A正弦波测试                                      */
/* --------------------------------------------------------------- */
int wavegen_driverA_sine_test(CMSDK_WAVE_GEN_TypeDef *CMSDK_WAVEGEN_DRVA, uint16_t incount)
{
    int return_val = 0;
    int err_code = 0;

    printf("\n驱动器A正弦波测试\n");

    CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_REST_T_REG = 100; // 死区时间10ms //交替模式下，死区时间失效，即使CONFIG_REG使能了死区时间也无效
    // CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_SILENT_T_REG = 200;  //静默时间20ms
    CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_CLK_FREQ_REG = 0x00000020; // 32MHz ==PCLK

    CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_CLK_FREQ_REG = 32;          // 32MHz ==PCLK  //MHz为单位
    CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_HLF_WAVE_PRD_REG = 100;     // 正半周期脉宽10ms，有交替方波
    CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_NEG_HLF_WAVE_PRD_REG = 100; // 负半周期脉宽10ms，无交替方波

#if 1                                                         // 无需静默时间
    CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_CONFIG_REG = 0x00000050; // bit 0:rest enable  ， 正半周期和负半周期中间的休息时间
                                                              // 1:negative enable  ， 负半周期发生使能，如果不使能，则没有负半周期的波形（注意交替模式只会对正半周期起作用）
                                                              // 2: silent enable   ， 负半周期结束后的静默时间
    // 3: source B enable ，负脉宽方向使能位，1负脉宽在负半周期，0负脉宽在正半周期

    // 4: alternating the positive side ,正极交替产生包络
    // 5: continue mode   ，连续模式
    // 6: multi-electrode ，多电极模式
#else // 需要静默时间
    /*交替模式下config寄存器说明：
    正脉宽交替，无负脉宽，无死区时间，无静默时间：0x50 或 0x51 或 0x58 或 0x59
    正脉宽交替，无死区时间，无负脉宽，有静默时间：0x54	或 0x55 或 0x5C 或 0x5D
    正脉宽交替，无死区时间，负脉宽不交替但有波形，无静默时间 ：0x5A	或 0x5B
  正脉宽交替，无死区时间，负脉宽不交替但有波形且波形在正脉宽上（因为源B失能了），无静默时间 ：0x52 或 0x53
    正脉宽交替，无死区时间，负脉宽不交替但有波形且波形在正脉宽上（因为源B失能了），有静默时间 ：0x56 或 0x57
    正脉宽交替，无死区时间，负脉宽不交替但有波形，有静默时间 ： 0x5E 或 0x5F
        */
    //   CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_CONFIG_REG = 0x5F; 		//bit 0:rest enable  ， 正半周期和负半周期中间的死区时间
    // 1:negative enable  ， 负半周期发生使能，如果不使能，则没有负半周期的波形
    // 2: silent enable   ， 负半周期结束后的静默时间
    // 3: source B enable
    // 4: alternating the positive side ,正极交替产生包络
    // 5: continue mode   ，连续模式
    CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_CONFIG_REG = 0x34; // 静默时间、交替模式和多电极使能                                                  //6: multi-electrode ，多电极模式

#endif

    CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_ISEL_REG = 0x04; // 总电流 = 单元电流ISEL * WAVE_GEN_DRV_IN_WAVE_REG

    for (int i = 0; i < 64; i++)
    {
        CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_IN_WAVE_ADDR_REG = i;
        // CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_IN_WAVE_REG = sine_data[i];  //正弦波数据数组，根据数组中的点描绘正半周期的波形
        //  CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_IN_WAVE_REG = saw_data[i];  //三角波数据
        CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_IN_WAVE_REG = incount; // 方波数据（固定值0x80）
    }

    CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_ALT_LIM_REG = 3200;         //  3200  需要设置一个正半周期下需要再生成多少个周期波形。设置10kHz=0.1ms=100us，100us=A*(1/32us),所以A=3200。
    CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_ALT_SILENT_LIM_REG = 0;     // 交替后静默的时钟数（无死区时间设置）。在这种情况下，驱动器B连续交替。//包络下波形的静默时间
    CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_DELAY_LIM_REG = 0x00000000; // 延迟时钟数

    CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_NEG_SCALE_REG = 0x00000001;  // 负半周期幅值倍乘系数，如超过255，则从0开始增长
    CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_NEG_OFFSET_REG = 0x00000000; // 负半周期幅值偏移量，如超过255，则从0开始增长，
                                                                  // 如正半周期幅值为250，此处设置为10，则负半周期幅值为5 ！！！

    CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_INT_REG = 0x0;         //  中断寄存器设置为0
    CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_CTRL_REG = 0x00000001; // 使能驱动器

    /* 生成返回值 */
    if (err_code != 0)
    {
        printf("\n错误 : 驱动器A测试失败\n");
        return_val = 1;
        err_code = 0;
    }

    return (return_val);
}

void wavegen_Stop(CMSDK_WAVE_GEN_TypeDef *CMSDK_WAVEGEN_DRVA)
{
    CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_ISEL_REG = 0; // 范围 0x00 - 0x07

    for (int i = 0; i < 64; i++)
    {
        CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_IN_WAVE_ADDR_REG = i;
        CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_IN_WAVE_REG = 0; // 最大值0xff
    }
}

// 初始化波形生成器
void wavegen_Init(void)
{
    // 设置MTP等待周期
    CMSDK_MTPREG->MTP_CR = 0x00000002;

    // 注意：时钟配置已在ClockInit()中完成，这里不再重复配置
    // 使用HSI作为主频 32MHz
    // CMSDK_SYSCON->HSI_CTRL = (CMSDK_SYSCON->HSI_CTRL & ~CMSDK_SYSCON_HSI_FREQ_Msk) | (0x3 << CMSDK_SYSCON_HSI_FREQ_Pos); //HSI=32MHz

    // 使能UART和WAVE_GEN外设时钟（不覆盖TIMER0时钟）
    CMSDK_SYSCON->APB_CLKEN |= 0x1003 | 0x4000; // 使用|=而不是=，避免覆盖其他时钟使能

    // 升压电压选择
    //boost_voltage_select_11V();
    //boost_voltage_select_15V();
    //boost_voltage_select_26V();
    //boost_voltage_select_45V();
    boost_voltage_select_55V();
}

// 启动波形生成器
void wavegen_Start(void)
{
    g_ems_running = 1;
    g_ems_count = 0;

    // 初始化缓进缓出控制
    if (g_ems_config.enable_ramp)
    {
        g_current_intensity = 0; // 从0开始
        g_ramp_phase = 0;        // 缓进阶段
        g_wave_counter = 0;      // 重置方波计数器
        g_ramp_step_counter = 0; // 重置步进计数器
    }
    else
    {
        g_current_intensity = g_ems_config.intensity; // 直接使用设定强度
    }
}

// 电刺激参数配置
void EMS_Configure(EMS_Config_TypeDef *config)
{
    if (config != NULL)
    {
        g_ems_config = *config;
    }
}

// 启动电刺激
void EMS_Start(void)
{
    wavegen_Start();
}

// 停止电刺激
void EMS_Stop(void)
{
    g_ems_running = 0;
    g_ems_count = 0;         // 重置计数器
    g_current_intensity = 0; // 重置强度
    g_ramp_phase = 0;        // 重置渐进阶段
    g_wave_counter = 0;      // 重置方波计数器
    g_ramp_step_counter = 0; // 重置步进计数器
    wavegen_Stop(WAVE_GEN_DRVA_BLK0);
}

// 更新电刺激强度
void EMS_UpdateIntensity(uint16_t intensity)
{
    g_ems_config.intensity = intensity;
}

// 缓进缓出处理函数（在电刺激处理中调用）
void EMS_Process_Ramp(void)
{
    if (!g_ems_config.enable_ramp || !g_ems_running)
    {
        return; // 如果未启用缓进缓出或未运行，直接返回
    }

    // 计算每个强度步进需要的方波周期数
    // 2秒 = 2000000微秒，每个方波周期100微秒，所以2秒内有20000个方波周期
    // 需要从0增加到128，所以每156.25个方波周期增加1个强度单位
    uint32_t waves_per_step = 0;
    uint32_t total_waves_ramp_up = g_ems_config.ramp_up_time * 5; // 缓进阶段总方波周期数
    uint32_t total_waves_ramp_down = g_ems_config.ramp_down_time * 1; // 缓出阶段总方波周期数
    uint32_t total_waves_hold = g_ems_config.hold_time * 5; // 保持阶段总方波周期数
    
    if (g_ems_config.intensity > 0)
    {
        waves_per_step = total_waves_ramp_up / g_ems_config.intensity; // 每个强度步进需要的方波周期数
    }

    g_wave_counter++; // 每次调用增加一个方波周期计数

    switch (g_ramp_phase)
    {
    case 0: // 缓进阶段
        if (g_ramp_step_counter < total_waves_ramp_up)
        {
            // 检查是否需要增加强度
            if (g_wave_counter >= waves_per_step)
            {
                g_wave_counter = 0; // 重置方波计数器
                if (g_current_intensity < g_ems_config.intensity)
                {
                    g_current_intensity++;
                }
            }
            g_ramp_step_counter++;
        }
        else
        {
            // 缓进完成，进入保持阶段
            g_ramp_phase = 1;
            g_ramp_step_counter = 0;
            g_current_intensity = g_ems_config.intensity; // 确保达到最大强度
        }
        break;

    case 1: // 保持阶段
        if (g_ramp_step_counter < total_waves_hold)
        {
            // 保持最大强度
            g_current_intensity = g_ems_config.intensity;
            g_ramp_step_counter++;
        }
        else
        {
            // 保持完成，进入缓出阶段
            g_ramp_phase = 2;
            g_ramp_step_counter = 0;
            g_wave_counter = 0; // 重置方波计数器
        }
        break;

    case 2: // 缓出阶段
        if (g_ramp_step_counter < total_waves_ramp_down)
        {
            // 检查是否需要减少强度
            if (g_wave_counter >= waves_per_step)
            {
                g_wave_counter = 0; // 重置方波计数器
                if (g_current_intensity > 0)
                {
                    g_current_intensity--;
                }
            }
            g_ramp_step_counter++;
        }
        else
        {
            // 缓出完成，停止电刺激
            g_current_intensity = 0;

            // 这里不直接停止，让主循环控制停止
        }
        break;
    }
}

// 电刺激主循环处理函数（在主循环中调用）
void EMS_Process(void)
{
    if (g_ems_running)
    {
        g_ems_count++;

        // 处理缓进缓出控制
        EMS_Process_Ramp();

        // 使用当前缓进缓出的强度
        uint16_t current_intensity = g_current_intensity;

        // 根据配置生成不同强度的方波
        if (g_ems_count < 1280)
        {
            wavegen_driverA_sine_test(WAVE_GEN_DRVA_BLK0, current_intensity);
        }
        else if (g_ems_count < 1280 * 256)
        {
            // 休息时间
        }
        else if (g_ems_count < 1280 * 2)
        {
            wavegen_driverA_sine_test(WAVE_GEN_DRVA_BLK0, current_intensity);
        }
        else
        {
            // 重置计数器，开始新的周期
            g_ems_count = 0;
        }
    }
}
