#include "common.h"
#include "stm32f10x.h"
#include "parking_sensor.h"
#include "distance_switch.h"
#include "photoelectric_switch.h"
#include "emergency_stop.h"
#include "uart_log.h"


void Delay(uint32_t time, char unit) {
    uint32_t cycles = 0;

    const uint32_t SYSCLK_FREQ = 72000000;  // 72 MHz

    // 根据单位选择不同的延时计算
    switch (unit) {
    case 'n':  // 纳秒延时
        // 每个时钟周期为 13.89 纳秒
        cycles = (time * SYSCLK_FREQ) / 1000000000;  // 纳秒转为时钟周期
        break;
    case 'u':  // 微秒延时
        cycles = (time * SYSCLK_FREQ) / 1000000;  // 微秒转为时钟周期
        break;
    case 'm':  // 毫秒延时
        cycles = (time * SYSCLK_FREQ) / 1000;  // 毫秒转为时钟周期
        break;
    case 's':  // 秒延时
        cycles = time * SYSCLK_FREQ;  // 秒转为时钟周期
        break;
    default:
        // 无效的单位，直接返回
        return;
    }

    // 使用空操作进行延时
    for (volatile uint32_t i = 0; i < cycles; i++) {
        __NOP();  // 空操作
    }
}


void Total_GPIO_Init(void) {
    //RCC->APB2ENR |= 1 << 0;
    //电机配置01
    // 使能 GPIOC 和 GPIOF 的时钟
    RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;
    RCC->APB2ENR |= RCC_APB2ENR_IOPFEN;

    RCC->APB2ENR |= RCC_APB2ENR_IOPGEN; // 启用GPIOG时钟
    RCC->APB2ENR |= RCC_APB2ENR_IOPEEN; // 启用GPIOE时钟

    // 使能GPIOE和GPIOD时钟，同时使能AFIO时钟
    RCC->APB2ENR |= RCC_APB2ENR_IOPDEN;
    // 使能GPIOB
    RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;


    // 使能 AFIO 时钟，用于重映射
    RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;

    // 配置 PC6 引脚为复用推挽输出 (50 MHz)
    GPIOC->CRL &= ~(0xF << 24); // 清空 PC6 配置
    GPIOC->CRL |= (0xB << 24);  // 配置为复用推挽输出 (0xB = 1011)

    // 配置 PC5 为通用推挽输出 (方向)
    GPIOC->CRL &= ~(0xF << 20); // 清空 PC5 配置
    GPIOC->CRL |= (0x3 << 20);  // 配置为通用推挽输出 (0x3 = 0011)

    // 配置 PF11 为通用推挽输出 (使能)
    GPIOF->CRH &= ~(0xF <<12); // 清空 PF11 配置
    GPIOF->CRH |= (0x3 << 12);  // 配置为通用推挽输出 (0x3 = 0011)



    //电机配置02
    // 配置 PC7 引脚为复用推挽输出 (50 MHz)
    GPIOC->CRL &= ~((uint32_t)0xF << (4*7)); // 清空 PC7 配置
    GPIOC->CRL |= ((uint32_t)0xB << (4*7));  // 配置为复用推挽输出 (0xB = 1011)

    // 配置 PF12 为通用推挽输出 (方向)
    GPIOF->CRH &= ~(0xF << (4*4)); // 清空 PF12 配置
    GPIOF->CRH |= (0x3 <<(4*4));  // 配置为通用推挽输出 (0x3 = 0011)


    // 配置 PC4 为通用推挽输出 (使能)
    GPIOC->CRL &= ~(0xF <<(4*4)); // 清空 PC4 配置
    GPIOC->CRL |= (0x3 << (4*4));  // 配置为通用推挽输出 (0x3 = 0011)

    // 重映射 TIM3_CH1 到 PC6 TIM3_CH2 到 PC7
    AFIO->MAPR |= AFIO_MAPR_TIM3_REMAP_FULLREMAP;

    //气动电磁阀GPIO配置
    // 配置 PF13, PF14, PF15 为复用推挽输出 (50 MHz)
    GPIOF->CRH &= ~(0xF <<(4*5)); // 清空 PF13 配置 (位20-23)
    GPIOF->CRH |= (0x3 <<(4*5));  // 配置 PF13 为通用推挽输出

    GPIOF->CRH &= ~(0xF <<(4*6)); // 清空 PF14 配置 (位24-27)
    GPIOF->CRH |= (0x3 << (4*6));  // 配置 PF14 为通用推挽输出

    GPIOF->CRH &= ~((uint32_t)0x3 <<(4*7)); // 清空 PF15 配置 (位28-31)
    GPIOF->CRH |= ((uint32_t)0x3 << (4*7));  // 配置 PF15 为通用推挽输出

    // 配置 PG0, PG1 为复用推挽输出 (50 MHz)
    GPIOG->CRL &= ~(0xF << (4*0)); // 清空 PG0 配置 (位0-3)
    GPIOG->CRL |= (0x3 << (4*0));  // 配置 PG0 为通用推挽输出

    GPIOG->CRL &= ~(0xF << (4*1)); // 清空 PG1 配置 (位4-7)
    GPIOG->CRL |= (0x3 << (4*1));  // 配置 PG1 为通用推挽输出

    // 配置 PE7, PE8 为复用推挽输出 (50 MHz)
    GPIOE->CRL &= ~(0xF << (4*7)); // 清空 PE7 配置 (位20-23)
    GPIOE->CRL |= (0x3 << (4*7));  // 配置 PE7 为通用推挽输出

    GPIOE->CRH &= ~(0xF << (4*0)); // 清空 PE8 配置 (位24-27)
    GPIOE->CRH |= (0x3 << (4*0));  // 配置 PE8 为通用推挽输出

    //倒车雷达

    // 配置PE10-PE15为推挽输出，默认为低电平
    //GPIOE->CRH &= ~(0xFFFFF << 8);  // 清空PE10-PE15配置
    //GPIOE->CRH |= 0x11111 << 8;     // 设置PE10-PE15为推挽输出
    //GPIOE->BRR = 0xFC00;            // 默认低电平（PE10到PE15）
		

    // 配置 PD14 为上拉输入模式
    GPIOD->CRH &= ~(0xF << 24);  // 清空 PD14 的配置
    GPIOD->CRH |= (0x4 << 24);   // 设置为输入模式，并且配置为下拉模式
    //GPIOD->ODR &= ~(1 << 14);    // 配置 PD14 为下拉


    //行走距离开关 distance_switch

    // 配置PG15为输入模式（浮空输入）
    GPIOG->CRH &= ~((uint32_t)0xF << (4*7));   // 清除PG15的配置
    GPIOG->CRH |= ((uint32_t)0x4 << (4*7));    // 设置为浮空输入模式

    // 配置PD6为输入模式（浮空输入）
    GPIOD->CRL &= ~(0xF << 24);   // 清除PD6的配置
    GPIOD->CRL |= (0x4 << 24);    // 设置为浮空输入模式

    //旋转光电开关 photoelectric_switch

    // 配置PB9为输入模式（浮空输入）
    GPIOB->CRH &= ~(0xF << 4);   // 清除PB9的配置
    GPIOB->CRH |= (0x4 << 4);    // 设置为浮空输入模式

    // 配置PE0为输入模式（浮空输入）
    GPIOE->CRL &= ~(0xF << 0);   // 清除PE0的配置
    GPIOE->CRL |= (0x4 << 0);    // 设置为浮空输入模式

    //Onewire_Init
    // 配置 PE1 为推挽输出（初始为高电平）
    GPIOD->CRH &= ~(0xF << 4*4);   // 清除PD12的配置
    GPIOD->CRH |= (0x3 << 4*4);    // 设置为推挽输出模式

    //急停按钮 emergency_stop
    // 配置 PE2 为输入上拉
    GPIOE->CRL &= ~(0xF << (2 * 4));  // 清除 PE2 配置位
    GPIOE->CRL |= (0x8 << (2 * 4));   // 配置 PE2 为上拉输入模式
    GPIOE->ODR |= (1 << 2);

    //蜂鸣器 buzzer
    GPIOE->CRH &= ~(0xF << (4 * 1));
    GPIOE->CRH |= (0x03 << (4 * 1));
}

void Total_EXTI_Init(void) {
    // 设置优先级组为组2 (2位抢占优先级 + 2位子优先级)
    SCB->AIRCR = (0x05FA << 16) | (2 << 8);  // 设置优先级分组

    // 倒车雷达中断
    AFIO->EXTICR[3] &= ~AFIO_EXTICR4_EXTI14;  // 清除EXTI14
    AFIO->EXTICR[3] |= AFIO_EXTICR4_EXTI14_PD;  // 将PD14连接到EXTI14
    EXTI->RTSR |= EXTI_RTSR_TR14;  // 上升沿触发
    EXTI->FTSR |= EXTI_FTSR_TR14;  // 下降沿触发
    EXTI->IMR |= EXTI_IMR_MR14;    // 使能中断


    NVIC_EnableIRQ(EXTI15_10_IRQn);  // 注意：EXTI10-15 共享一个中断向量
    NVIC_SetPriority(EXTI15_10_IRQn, 0x06); // 设置中断优先级

    // 行走距离开关中断
    AFIO->EXTICR[1] &= ~(AFIO_EXTICR2_EXTI6);  // 清除EXTI6的配置
    AFIO->EXTICR[1] |= AFIO_EXTICR2_EXTI6_PD;  // 连接PD6到EXTI6
    AFIO->EXTICR[3] &= ~(AFIO_EXTICR4_EXTI15);  // 清除EXTI15的配置
    AFIO->EXTICR[3] |= AFIO_EXTICR4_EXTI15_PG;  // 连接PG15到EXTI15


    EXTI->RTSR |= EXTI_RTSR_TR6 | EXTI_RTSR_TR15;  // 配置上升沿触发
    EXTI->FTSR |= EXTI_FTSR_TR6 | EXTI_FTSR_TR15;  // 配置下降沿触发
    EXTI->IMR |= EXTI_IMR_MR6 | EXTI_IMR_MR15;  // 使能中断线6和15

    // 使能EXTI9_5_IRQn中断
    //NVIC_EnableIRQ(EXTI9_5_IRQn);  // PD6 属于 EXTI9_5_IRQn
    //NVIC_SetPriority(EXTI9_5_IRQn, 0x0B);  // 设置中断优先级

    // 使能EXTI15_10_IRQn中断
    //NVIC_EnableIRQ(EXTI15_10_IRQn);  // EXTI15 属于 EXTI15_10_IRQn
    //NVIC_SetPriority(EXTI15_10_IRQn, 0x06);  // 设置中断优先级



    // 旋转光电开关中断
    AFIO->EXTICR[2] &= ~(AFIO_EXTICR3_EXTI9);    // 清除EXTI9的配置
    AFIO->EXTICR[2] |= AFIO_EXTICR3_EXTI9_PB;    // 连接PB9到EXTI9
    AFIO->EXTICR[0] &= ~(AFIO_EXTICR1_EXTI0);    // 清除EXTI0的配置
    AFIO->EXTICR[0] |= AFIO_EXTICR1_EXTI0_PE;    // 连接PE0到EXTI0

    EXTI->RTSR |= EXTI_RTSR_TR9 | EXTI_RTSR_TR0;  // 配置上升沿触发
    EXTI->FTSR |= EXTI_FTSR_TR9 | EXTI_FTSR_TR0;  // 配置下降沿触发
    EXTI->IMR |= EXTI_IMR_MR9 | EXTI_IMR_MR0;     // 使能中断线9和0

    // 使能EXTI9_5_IRQn中断
    NVIC_EnableIRQ(EXTI9_5_IRQn);   // PB9 属于 EXTI9_5 中断
    NVIC_SetPriority(EXTI9_5_IRQn, 0x0C);  // 设置优先级

    // 使能EXTI0_IRQn中断
    NVIC_EnableIRQ(EXTI0_IRQn);     // PE0 属于 EXTI0 中断
    NVIC_SetPriority(EXTI0_IRQn, 0x0D);    // 设置优先级

    // 急停按钮中断
    //AFIO->EXTICR[0] = (AFIO->EXTICR[0] & ~0xF) | 0x4;  // PE2
    AFIO->EXTICR[0] &= ~(AFIO_EXTICR1_EXTI2);    // 清除EXTI9的配置
    AFIO->EXTICR[0] |= AFIO_EXTICR1_EXTI2_PE;    // 连接PE2到EXTI2

    EXTI->FTSR &= ~EXTI_FTSR_TR2;  // 清除上升沿触发
    EXTI->RTSR &= ~EXTI_RTSR_TR2;  // 清除上升沿触发
    EXTI->FTSR |= EXTI_FTSR_TR2;   // 使能下降沿触发
    EXTI->IMR |= EXTI_IMR_MR2;
    NVIC_EnableIRQ(EXTI2_IRQn);
    NVIC_SetPriority(EXTI2_IRQn, 0x00); // 设置急停按钮中断优先级为最高

}
// 状态处理函数
void StateMachineHandler(SystemState currentState) {
    switch (currentState) {
    case STATE_IDLE:
        // 处理IDLE状态
        break;
    case STATE_MOTOR_RUNNING:
        // 处理MOTOR_RUNNING状态
        break;
    case STATE_EMERGENCY_STOP:
        // 处理EMERGENCY_STOP状态
        Emergency_Stop_Interrupt();
        break;
    case STATE_PARKING_SENSOR_ACTIVE:
        Parking_Sensor_Interruption();
        break;
    case STATE_DISTANCE_SWITCH_ACTIVE:
        Distance_Switch_Interruption();
        // 处理DISTANCE_SWITCH_ACTIVE状态
        break;
    case STATE_PHOTOELECTRIC_SWITCH_ACTIVE:
        // 处理PHOTOELECTRIC_SWITCH_ACTIVE状态
        Photoelectric_Switch_Interrupt();
        break;
    default:
        // 默认处理
        break;
    }
}

// 中断服务例程
void EXTI9_5_IRQHandler(void) {
    if (EXTI->PR & EXTI_PR_PR6) {  // 检查是否是 EXTI 线 6 触发了中断
        // 处理 PD6 中断
        StateMachineHandler(STATE_DISTANCE_SWITCH_ACTIVE);
        // 清除中断标志位
        EXTI->PR |= EXTI_PR_PR6;
    }
    if (EXTI->PR & EXTI_PR_PR9) {  // 检查是否是 EXTI 线 9 触发了中断
        // 处理 PB9 中断
        StateMachineHandler(STATE_PHOTOELECTRIC_SWITCH_ACTIVE);
        // 清除中断标志位
        EXTI->PR |= EXTI_PR_PR9;
    }
}

// 中断服务例程
void EXTI0_IRQHandler(void) {
    if (EXTI->PR & EXTI_PR_PR0) {  // 检查是否是EXTI线0触发了中断
        // 处理PE0中断
        StateMachineHandler(STATE_PHOTOELECTRIC_SWITCH_ACTIVE);
        // 清除中断标志位
        EXTI->PR |= EXTI_PR_PR0;
    }
}



//STATE_PARKING_SENSOR_ACTIVE
void EXTI15_10_IRQHandler(void) {
    // 处理 PD14 中断
    if (EXTI->PR & EXTI_PR_PR14) {  // 检查是否是EXTI线14触发了中断
       StateMachineHandler(STATE_PARKING_SENSOR_ACTIVE);
			 //EXTI->PR |= EXTI_PR_PR14;  // 清除中断标志位

    }
    if (EXTI->PR & EXTI_PR_PR15) {  // 检查是否是EXTI线15触发了中断
        Serial_Print("EXTI15 triggered\n");
        StateMachineHandler(STATE_DISTANCE_SWITCH_ACTIVE);
        EXTI->PR |= EXTI_PR_PR15;  // 清除中断标志位
    }
}


void EXTI2_IRQHandler(void) {
    if (EXTI->PR & EXTI_PR_PR2) {  // 检查是否是EXTI线2触发了中断
        // 处理PE2中断（急停按钮）
        StateMachineHandler(STATE_EMERGENCY_STOP);
        // 清除中断标志位
        EXTI->PR |= EXTI_PR_PR2;
    }
}


void TIM7_Init(void) {
    // 使能TIM7时钟
    RCC->APB1ENR |= RCC_APB1ENR_TIM7EN;
    
    // 设定预分频器，让定时器的时钟为1MHz（假设系统时钟为16MHz）
    // 16MHz / 16 = 1MHz
    TIM7->PSC = 71; 
    
    // 自动重装载值（最大值）
    TIM7->ARR = 0xFFFF;
    
    // 计数器从0开始
    TIM7->CNT = 0;
    
    // 不启动定时器（启动时可以调用`TIM7->CR1 |= TIM_CR1_CEN;`）
}
void delay_us(uint16_t us)
{
    uint16_t differ = 0xFFFF - us - 5;
    TIM7->CNT = differ;

    // 使能定时器
    TIM7->CR1 |= TIM_CR1_CEN;

    while (TIM7->CNT < 0xFFFF - 5)
    {
        // 等待计数器达到目标值
    }

    // 停止定时器
    TIM7->CR1 &= ~TIM_CR1_CEN;
}
