/*
 * 板子: Generic STM32F4 series -> STM32F407VGT6
 * HSE: 12MHz, 系统时钟: 168MHz
 * 
 * 功能说明:
 * 1. SoftSerial (PA9 TX, PA10 RX) - 115200bps, 接CH340 Type-C, 调试和监控 (软件串口)
 * 2. USART2 (PA2 TX, PA3 RX) - 300bps, 接井下设备 (硬件串口)
 * 3. USART1 (PB6 RX, PB7 TX, PB5 EN) - RS485通信 (硬件串口)
 *    注意:PB6/PB7是USART1的默认复用引脚
 * 4. PA0/PA1 差分输入捕获 - 测量脉冲宽度
 * 
 * 通信流转:
 * - RS485接收 -> SoftSerial输出 + USART2转发
 * - SoftSerial接收 -> RS485发送
 * - USART2接收 -> RS485发送
 */

#include <Arduino.h>
#include <SoftwareSerial.h>

// ==================== 系统配置 ====================
#define SYS_CLOCK_HZ    168000000UL  // 系统时钟168MHz
#define APB1_CLOCK_HZ   42000000UL   // APB1时钟42MHz
#define APB2_CLOCK_HZ   84000000UL   // APB2时钟84MHz

// ==================== 定时器配置 ====================
#define TIMER_CLOCK_HZ  84000000UL   // TIM2时钟84MHz
#define PRESCALER       41           // 预分频 (84M/(41+1)=2MHz)
#define TIMER_STEP_US   0.5f         // 计数步长 0.5μs

// ==================== 波特率配置 ====================
#define SOFT_SERIAL_BAUDRATE  115200 // 软件串口调试口 (高速)
#define USART1_BAUDRATE       4800   // RS485通信
#define USART2_BAUDRATE       300    // 井下设备

// ==================== 引脚定义 ====================
// 软件串口: PA9(TX), PA10(RX) - 115200bps CH340 (软件模拟)
// USART1:   PB6(RX), PB7(TX), PB5(EN) - RS485 (硬件)
// USART2:   PA2(TX), PA3(RX) - 300bps 井下设备 (硬件)

// ==================== 软件串口定义 ====================
SoftwareSerial softSerial(PA10, PA9);  // RX, TX (注意:SoftwareSerial参数顺序是RX, TX)

// ==================== 全局变量 ====================
// 脉冲捕获相关
volatile uint32_t last_capture_ch1 = 0;
volatile uint32_t last_capture_ch2 = 0;
volatile bool new_capture_ready_ch1 = false;
volatile bool new_capture_ready_ch2 = false;
volatile uint32_t overflow_count_ch1 = 0;
volatile uint32_t overflow_count_ch2 = 0;
volatile uint32_t pulse_width_ticks_ch1 = 0;
volatile uint32_t pulse_width_ticks_ch2 = 0;

// RS485控制
volatile bool rs485_tx_mode = false;

// ==================== 中断处理函数 ====================
#ifdef __cplusplus
extern "C" {
#endif

// TIM2_CH1/CH2 捕获中断 (PA0, PA1)
__attribute__((weak)) void TIM2_IRQHandler(void) {
    // 处理CH1捕获中断 (PA0)
    if (TIM2->SR & TIM_SR_CC1IF) {
        TIM2->SR &= ~TIM_SR_CC1IF;
        
        uint32_t current_capture = TIM2->CCR1;
        
        // 计算脉冲宽度(考虑溢出)
        if (overflow_count_ch1 > 0 || current_capture < last_capture_ch1) {
            uint32_t period = TIM2->ARR + 1;
            pulse_width_ticks_ch1 = (period - last_capture_ch1) + current_capture + 
                                    (overflow_count_ch1 - 1) * period;
        } else {
            pulse_width_ticks_ch1 = current_capture - last_capture_ch1;
        }
        
        overflow_count_ch1 = 0;
        last_capture_ch1 = current_capture;
        new_capture_ready_ch1 = true;
    }
    
    // 处理CH2捕获中断 (PA1)
    if (TIM2->SR & TIM_SR_CC2IF) {
        TIM2->SR &= ~TIM_SR_CC2IF;
        
        uint32_t current_capture = TIM2->CCR2;
        
        if (overflow_count_ch2 > 0 || current_capture < last_capture_ch2) {
            uint32_t period = TIM2->ARR + 1;
            pulse_width_ticks_ch2 = (period - last_capture_ch2) + current_capture + 
                                    (overflow_count_ch2 - 1) * period;
        } else {
            pulse_width_ticks_ch2 = current_capture - last_capture_ch2;
        }
        
        overflow_count_ch2 = 0;
        last_capture_ch2 = current_capture;
        new_capture_ready_ch2 = true;
    }
    
    // 处理更新事件(溢出)
    if (TIM2->SR & TIM_SR_UIF) {
        TIM2->SR &= ~TIM_SR_UIF;
        overflow_count_ch1++;
        overflow_count_ch2++;
        
        // 超时保护
        if (overflow_count_ch1 > 1000) {
            overflow_count_ch1 = 0;
            last_capture_ch1 = TIM2->CCR1;
            new_capture_ready_ch1 = false;
        }
        if (overflow_count_ch2 > 1000) {
            overflow_count_ch2 = 0;
            last_capture_ch2 = TIM2->CCR2;
            new_capture_ready_ch2 = false;
        }
    }
}

// USART1 (RS485) 接收中断处理
__attribute__((weak)) void USART1_IRQHandler(void) {
    if (USART1->SR & USART_SR_RXNE) {
        uint8_t data = USART1->DR;
        
        // 转发到软件串口 (调试口)
        softSerial.write(data);
        
        // 转发到USART2 (井下设备)
        while (!(USART2->SR & USART_SR_TXE));
        USART2->DR = data;
    }
}

#ifdef __cplusplus
}
#endif

// ==================== 软件串口发送函数 (调试口) ====================
void soft_serial_send_char(char c) {
    softSerial.write(c);
}

void soft_serial_send_string(const char* str) {
    softSerial.print(str);
}

void soft_serial_send_uint32(uint32_t value) {
    char buffer[16];
    utoa(value, buffer, 10);
    soft_serial_send_string(buffer);
}

void soft_serial_send_float(float value, int decimals) {
    char buffer[32];
    dtostrf(value, 1, decimals, buffer);
    soft_serial_send_string(buffer);
}

void soft_serial_send_hex(uint8_t value) {
    char hex[] = "0123456789ABCDEF";
    soft_serial_send_char(hex[value >> 4]);
    soft_serial_send_char(hex[value & 0x0F]);
}

void soft_serial_send_buffer(uint8_t* buf, uint16_t len) {
    for (uint16_t i = 0; i < len; i++) {
        soft_serial_send_char(buf[i]);
    }
}

// ==================== USART2 发送函数 (300bps井下设备) ====================
void usart2_send_char(char c) {
    while (!(USART2->SR & USART_SR_TXE));
    USART2->DR = c;
}

void usart2_send_buffer(uint8_t* buf, uint16_t len) {
    for (uint16_t i = 0; i < len; i++) {
        usart2_send_char(buf[i]);
    }
}

// ==================== RS485 控制函数 ====================
void rs485_set_mode(bool tx_mode) {
    rs485_tx_mode = tx_mode;
    if (tx_mode) {
        // 发送模式:使能发送,禁用接收
        digitalWrite(PB5, HIGH);
        // 等待使能稳定
        delayMicroseconds(10);
    } else {
        // 接收模式:使能接收,禁用发送
        digitalWrite(PB5, LOW);
        // 等待使能稳定
        delayMicroseconds(10);
    }
}

// ==================== USART1 (RS485) 发送函数 ====================
void usart1_send_char(char c) {
    while (!(USART1->SR & USART_SR_TXE));
    USART1->DR = c;
}

void usart1_send_buffer(uint8_t* buf, uint16_t len) {
    rs485_set_mode(true);  // 切换到发送模式
    for (uint16_t i = 0; i < len; i++) {
        usart1_send_char(buf[i]);
    }
    // 等待发送完成
    while (!(USART1->SR & USART_SR_TC));
    rs485_set_mode(false);  // 切换回接收模式
}

// ==================== 初始化软件串口 (PA9, PA10) ====================
void init_soft_serial() {
    // 初始化SoftwareSerial,波特率115200
    softSerial.begin(SOFT_SERIAL_BAUDRATE);
    
    // 配置引脚模式(SoftwareSerial会自动配置,但手动配置更可靠)
    // PA9 (TX) - 输出
    pinMode(PA9, OUTPUT);
    // PA10 (RX) - 输入
    pinMode(PA10, INPUT);
    
    // 等待稳定
    delay(100);
}

// ==================== 初始化USART1 (RS485) ====================
void init_usart1_rs485() {
    // 启用USART1时钟 (APB2)
    RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
    
    // 配置PB6为复用功能 (RX)
    GPIOB->MODER &= ~GPIO_MODER_MODER6_Msk;
    GPIOB->MODER |= GPIO_MODER_MODER6_1;  // 复用功能
    GPIOB->AFR[0] &= ~GPIO_AFRL_AFSEL6_Msk;
    GPIOB->AFR[0] |= (7 << GPIO_AFRL_AFSEL6_Pos);  // AF7 = USART1
    
    // 配置PB7为复用功能 (TX)
    GPIOB->MODER &= ~GPIO_MODER_MODER7_Msk;
    GPIOB->MODER |= GPIO_MODER_MODER7_1;  // 复用功能
    GPIOB->AFR[0] &= ~GPIO_AFRL_AFSEL7_Msk;
    GPIOB->AFR[0] |= (7 << GPIO_AFRL_AFSEL7_Pos);  // AF7 = USART1
    
    // 配置PB5为485使能控制 (输出)
    GPIOB->MODER &= ~GPIO_MODER_MODER5_Msk;
    GPIOB->MODER |= GPIO_MODER_MODER5_0;  // 输出模式
    GPIOB->OTYPER &= ~GPIO_OTYPER_OT5;    // 推挽输出
    GPIOB->ODR &= ~GPIO_ODR_OD5;          // 初始为接收模式
    
    // 配置USART1: 4800, 8N1
    USART1->BRR = APB2_CLOCK_HZ / USART1_BAUDRATE;
    USART1->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_RXNEIE;  // 使能发送、接收和接收中断
    USART1->CR1 |= USART_CR1_UE;
    
    // 使能USART1接收中断
    NVIC_SetPriority(USART1_IRQn, 2);
    NVIC_EnableIRQ(USART1_IRQn);
}

// ==================== 初始化USART2 (300bps井下设备) ====================
void init_usart2() {
    // 启用USART2时钟 (APB1)
    RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
    
    // 配置PA2为复用功能 (TX)
    GPIOA->MODER &= ~GPIO_MODER_MODER2_Msk;
    GPIOA->MODER |= GPIO_MODER_MODER2_1;  // 复用功能
    GPIOA->AFR[0] &= ~GPIO_AFRL_AFSEL2_Msk;
    GPIOA->AFR[0] |= (7 << GPIO_AFRL_AFSEL2_Pos);  // AF7 = USART2
    
    // 配置PA3为复用功能 (RX)
    GPIOA->MODER &= ~GPIO_MODER_MODER3_Msk;
    GPIOA->MODER |= GPIO_MODER_MODER3_1;  // 复用功能
    GPIOA->AFR[0] &= ~GPIO_AFRL_AFSEL3_Msk;
    GPIOA->AFR[0] |= (7 << GPIO_AFRL_AFSEL3_Pos);  // AF7 = USART2
    
    // 配置USART2: 300, 8N1 (低速通信)
    USART2->BRR = APB1_CLOCK_HZ / USART2_BAUDRATE;
    USART2->CR1 = USART_CR1_TE | USART_CR1_RE;  // 使能发送和接收
    USART2->CR1 |= USART_CR1_UE;  // 使能USART
}

// ==================== 初始化TIM2差分输入捕获 ====================
void init_timer2_capture() {
    // 启用TIM2时钟 (APB1)
    RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
    
    // ===== 配置PA0为TIM2_CH1 (捕获通道1) =====
    GPIOA->MODER &= ~GPIO_MODER_MODER0_Msk;
    GPIOA->MODER |= GPIO_MODER_MODER0_1;  // 复用功能
    GPIOA->AFR[0] &= ~GPIO_AFRL_AFSEL0_Msk;
    GPIOA->AFR[0] |= (1 << GPIO_AFRL_AFSEL0_Pos);  // AF1 = TIM2
    
    // ===== 配置PA1为TIM2_CH2 (捕获通道2) =====
    GPIOA->MODER &= ~GPIO_MODER_MODER1_Msk;
    GPIOA->MODER |= GPIO_MODER_MODER1_1;  // 复用功能
    GPIOA->AFR[0] &= ~GPIO_AFRL_AFSEL1_Msk;
    GPIOA->AFR[0] |= (1 << GPIO_AFRL_AFSEL1_Pos);  // AF1 = TIM2
    
    // ===== 配置TIM2 =====
    TIM2->PSC = PRESCALER;      // 预分频 41
    TIM2->ARR = 0xFFFFFFFF;     // 32位自动重载最大值
    
    // ===== 配置通道1 (PA0) =====
    TIM2->CCMR1 &= ~TIM_CCMR1_CC1S_Msk;
    TIM2->CCMR1 |= (1 << TIM_CCMR1_CC1S_Pos);  // CC1输入, IC1映射到TI1
    TIM2->CCMR1 &= ~(TIM_CCMR1_IC1F_Msk | TIM_CCMR1_IC1PSC_Msk);
    TIM2->CCMR1 |= (0 << TIM_CCMR1_IC1PSC_Pos);  // 无预分频
    TIM2->CCMR1 |= (0 << TIM_CCMR1_IC1F_Pos);    // 无滤波
    
    // ===== 配置通道2 (PA1) =====
    TIM2->CCMR1 &= ~TIM_CCMR1_CC2S_Msk;
    TIM2->CCMR1 |= (1 << TIM_CCMR1_CC2S_Pos);  // CC2输入, IC2映射到TI2
    TIM2->CCMR1 &= ~(TIM_CCMR1_IC2F_Msk | TIM_CCMR1_IC2PSC_Msk);
    TIM2->CCMR1 |= (0 << TIM_CCMR1_IC2PSC_Pos);  // 无预分频
    TIM2->CCMR1 |= (0 << TIM_CCMR1_IC2F_Pos);    // 无滤波
    
    // ===== 配置捕获边沿 =====
    // 通道1: 上升沿捕获
    TIM2->CCER &= ~TIM_CCER_CC1P_Msk;
    TIM2->CCER |= TIM_CCER_CC1E_Msk;
    
    // 通道2: 上升沿捕获
    TIM2->CCER &= ~TIM_CCER_CC2P_Msk;
    TIM2->CCER |= TIM_CCER_CC2E_Msk;
    
    // ===== 使能中断 =====
    TIM2->DIER |= TIM_DIER_CC1IE;  // 通道1捕获中断
    TIM2->DIER |= TIM_DIER_CC2IE;  // 通道2捕获中断
    TIM2->DIER |= TIM_DIER_UIE;    // 更新中断(溢出)
    
    // 设置NVIC中断优先级并启用
    NVIC_SetPriority(TIM2_IRQn, 1);
    NVIC_EnableIRQ(TIM2_IRQn);
    
    // 清除中断标志
    TIM2->SR &= ~(TIM_SR_CC1IF | TIM_SR_CC2IF | TIM_SR_UIF);
    
    // 启动定时器
    TIM2->CR1 |= TIM_CR1_CEN;
}

// ==================== 格式化和输出脉冲宽度 ====================
void output_pulse_width(uint32_t ticks, float step_us, const char* channel_name) {
    float width_us = ticks * step_us;
    float width_ms = width_us / 1000.0f;
    
    soft_serial_send_string(channel_name);
    soft_serial_send_string(": ");
    soft_serial_send_uint32(ticks);
    soft_serial_send_string(" ticks = ");
    soft_serial_send_float(width_us, 2);
    soft_serial_send_string(" us (");
    soft_serial_send_float(width_ms, 3);
    soft_serial_send_string(" ms)");
    
    // 对于串口信号,计算对应的波特率
    if (width_us > 0) {
        float baud_rate = 1000000.0f / width_us;  // 如果是单bit脉宽
        soft_serial_send_string(" (~");
        soft_serial_send_float(baud_rate, 0);
        soft_serial_send_string(" bps)");
    }
    soft_serial_send_string("\r\n");
}

// ==================== setup ====================
void setup() {
    // 初始化软件串口 (PA9, PA10) - 调试口 115200bps
    init_soft_serial();
    
    // 初始化硬件串口
    init_usart1_rs485();  // RS485 (PB6/PB7) - 4800bps
    init_usart2();        // 井下设备 (PA2/PA3) - 300bps
    
    // 初始化定时器捕获
    init_timer2_capture();
    
    // 延时等待稳定
    delay(100);
    
    // 设置RS485为接收模式
    rs485_set_mode(false);
    
    // ===== 发送启动信息到软件串口 =====
    soft_serial_send_string("\r\n");
    soft_serial_send_string("================================================\r\n");
    soft_serial_send_string("STM32F407 Multi-Serial & Pulse Measurement\r\n");
    soft_serial_send_string("================================================\r\n");
    soft_serial_send_string("System Clock: ");
    soft_serial_send_uint32(SYS_CLOCK_HZ);
    soft_serial_send_string(" Hz\r\n");
    soft_serial_send_string("\r\n");
    soft_serial_send_string("Serial Ports:\r\n");
    soft_serial_send_string("  SoftSerial: PA9/PA10, 115200bps (Debug - Software)\r\n");
    soft_serial_send_string("  USART1:     PB6/PB7,  4800bps (RS485 - Hardware)\r\n");
    soft_serial_send_string("  USART2:     PA2/PA3,  300bps (Downhole - Hardware)\r\n");
    soft_serial_send_string("\r\n");
    soft_serial_send_string("RS485 Control:\r\n");
    soft_serial_send_string("  TX: PB7, RX: PB6, EN: PB5\r\n");
    soft_serial_send_string("  Mode: ");
    soft_serial_send_string(rs485_tx_mode ? "TX" : "RX");
    soft_serial_send_string("\r\n");
    soft_serial_send_string("\r\n");
    soft_serial_send_string("Pulse Capture (TIM2):\r\n");
    soft_serial_send_string("  CH1: PA0, CH2: PA1 (Differential)\r\n");
    soft_serial_send_string("  Clock: 84MHz, Prescaler: 41, Step: 0.5us\r\n");
    soft_serial_send_string("================================================\r\n");
    soft_serial_send_string("\r\n");
    soft_serial_send_string("Waiting for data...\r\n\r\n");
}

// ==================== loop ====================
void loop() {
    // ===== 1. 处理RS485接收数据 (已在中断中自动转发) =====
    // USART1接收中断已经将数据转发到SoftSerial和USART2
    
    // ===== 2. 处理软件串口接收 (调试口 -> RS485) =====
    if (softSerial.available()) {
        char c = softSerial.read();
        // 转发到RS485 (USART1)
        usart1_send_buffer((uint8_t*)&c, 1);  // 单字符发送,内部会控制485使能
        // 可选:回显到软件串口
        // soft_serial_send_char(c);
    }
    
    // ===== 3. 处理USART2接收 (井下设备 -> RS485) =====
    if (USART2->SR & USART_SR_RXNE) {
        char c = USART2->DR;
        // 转发到RS485 (USART1)
        usart1_send_buffer((uint8_t*)&c, 1);
        // 可选:转发到调试口监控
        // soft_serial_send_char(c);
    }
    
    // ===== 4. 处理脉冲捕获结果 =====
    // 通道1 (PA0)
    if (new_capture_ready_ch1) {
        new_capture_ready_ch1 = false;
        output_pulse_width(pulse_width_ticks_ch1, TIMER_STEP_US, "CH1(PA0)");
    }
    
    // 通道2 (PA1)
    if (new_capture_ready_ch2) {
        new_capture_ready_ch2 = false;
        output_pulse_width(pulse_width_ticks_ch2, TIMER_STEP_US, "CH2(PA1)");
    }
    
    // 小延时防止过度占用CPU
    delayMicroseconds(100);
}