/*
 * @Author: mypx
 * @Date: 2025-10-15 13:03:38
 * @LastEditTime: 2025-10-17 13:37:16
 * @LastEditors: mypx mypx_coder@163.com
 * @Description: 
 */
#include "bsp_tec.h"
#include "main.h"
#include "spi.h"
#include "tim.h"
/*
 * 当前板子存在的问题：
 * PE8-TEC-IN1(left) TIM1_CH1N默认为PE8
 * PA8-TEC-IN2(right) TIM1_CH1默认为PA9,需要映射到PA8
 * 问题：
 * 映射只能成对映射，也就是PE8也要做映射，所以一次配置，同时使能两个管脚做不到
 * 解决方法：
 * 1. 分别配置PE8和PA8为TIM1_CH1N和TIM1_CH1
 * 2. 分别使能PE8和PA8的TIM1_CH1N和TIM1_CH1
 * stm32cubemx 使能TIM1_CH1N和TIM1_CH1默认的管脚为REMAP后的管脚，感觉是bug
 * 
*/

static void stop_tec_pwm(void)
{
    // 一块关闭，避免左右搞混没关掉
    HAL_TIM_PWM_Stop(&TEC_TIM, TIM_CHANNEL_1);
    HAL_TIMEx_PWMN_Stop(&TEC_TIM, TIM_CHANNEL_1);
}

static void tec_sd_disable(void)
{
    HAL_GPIO_WritePin(GPIOA, TEC_LEFT_SD_Pin | TEC_RIGHT_SD_Pin, GPIO_PIN_RESET);
}

static void left_tec_sd_enable(void)
{
    HAL_GPIO_WritePin(GPIOA, TEC_LEFT_SD_Pin, GPIO_PIN_SET);
}

static void right_tec_sd_enable(void)
{
    HAL_GPIO_WritePin(GPIOA, TEC_RIGHT_SD_Pin, GPIO_PIN_SET);
}

// PE8-TEC-IN1(left) TIM1_CH1N, 需要做full remap
static void left_tec_reconfig_pwm(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    /* Stop PWM outputs first to avoid both outputs being active during transition */
    stop_tec_pwm();

    /* Ensure GPIO clocks */
    __HAL_RCC_GPIOE_CLK_ENABLE();

    /* Enable TIM1 full remap if you need the remapped mapping (CubeMX generated code might expect this)
       Note: remap affects mapping for all TIM1 channels - do this before initializing the GPIOs */
    __HAL_AFIO_REMAP_TIM1_ENABLE();

    /* Deinit any previous GPIO config on PE8/PA8 to be safe */
    HAL_GPIO_DeInit(GPIOE, GPIO_PIN_8);
    HAL_GPIO_DeInit(GPIOA, TEC_RIGHT_IN_Pin);

    /**TIM1 GPIO Configuration
    PE8     ------> TIM1_CH1N
    */
    GPIO_InitStruct.Pin   = GPIO_PIN_8;
    GPIO_InitStruct.Mode  = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

    /*
     * Hardware note: main output (CH1) and complementary output (CH1N) cannot
     * be enabled at the same time on this board. For the 'left' mapping (PE8)
     * we only enable the complementary output (CH1N) and ensure CH1 is stopped.
     */
    /* Ensure main channel is off, then start complementary output only */
    HAL_TIMEx_PWMN_Start(&TEC_TIM, TIM_CHANNEL_1);
}

// PA8-TEC-IN2(right) TIM1_CH1,默认CH1，不需要映射
void right_tec_reconfig_pwm(void)
{
    stop_tec_pwm();

    /* Disable TIM1 remap so TIM1_CH1 maps to the default (PA8/PA9 depending on device)
       Do this before re-initializing the GPIO so HAL init uses the correct port/pin */
    __HAL_AFIO_REMAP_TIM1_DISABLE();

    /* Deinit any previous GPIO config on PE8/PA8 to be safe */
    HAL_GPIO_DeInit(GPIOE, GPIO_PIN_8);
    HAL_GPIO_DeInit(GPIOA, TEC_RIGHT_IN_Pin);

    /* Re-run the post-init which will configure PA8 as AF (HAL_TIM_MspPostInit uses TEC_RIGHT_IN_Pin) */
    HAL_TIM_MspPostInit(&TEC_TIM);

    /*
     * For the 'right' mapping (PA8) we only enable the main output (CH1) and
     * ensure the complementary output (CH1N) is stopped to avoid hardware conflict.
     */
    HAL_TIM_PWM_Start(&TEC_TIM, TIM_CHANNEL_1);
}

void bsp_fan_start(void)
{
    HAL_GPIO_WritePin(FAN_CONTROL_GPIO_Port, FAN_CONTROL_Pin, GPIO_PIN_SET);
}

void bsp_fan_stop(void)
{
    HAL_GPIO_WritePin(FAN_CONTROL_GPIO_Port, FAN_CONTROL_Pin, GPIO_PIN_RESET);
}

void bsp_left_tec_open(void)
{
    tec_sd_disable();
    left_tec_reconfig_pwm();
    left_tec_sd_enable();
}

void bsp_right_tec_open(void)
{
    tec_sd_disable();
    right_tec_reconfig_pwm();
    right_tec_sd_enable();
}

static void left_tec_adjust_duty_cycle(uint32_t duty_cycle)
{
    __HAL_TIM_SET_COMPARE(&TEC_TIM, TIM_CHANNEL_1, duty_cycle);
}

static void right_tec_adjust_duty_cycle(uint32_t duty_cycle)
{
    __HAL_TIM_SET_COMPARE(&TEC_TIM, TIM_CHANNEL_1, duty_cycle);
}

void bsp_tec_cooling_open(void)
{
    bsp_left_tec_open();
}

void bsp_tec_heating_open(void)
{
    bsp_right_tec_open();
}

// pwm: 0.0 ~ 1.0
void bsp_tec_cooling_adjust(float pwm)
{
    extern TIM_HandleTypeDef TEC_TIM;
    uint32_t                 max_period = __HAL_TIM_GET_AUTORELOAD(&TEC_TIM);
    left_tec_adjust_duty_cycle((uint32_t)(pwm * max_period));
}

// pwm: 0.0 ~ 1.0
void bsp_tec_heating_adjust(float pwm)
{
    extern TIM_HandleTypeDef TEC_TIM;
    uint32_t                 max_period = __HAL_TIM_GET_AUTORELOAD(&TEC_TIM);
    right_tec_adjust_duty_cycle((uint32_t)(pwm * max_period));
}

void bsp_tec_close(void)
{
    stop_tec_pwm();
    tec_sd_disable();
}


void bsp_tec_init(void)
{
    MX_SPI3_Init();
    MX_TIM1_Init();
}

