/**
 * DALI 转接模块 - 主程序
 * 
 * 功能: 接收主机串口数据，转换为 DALI 协议输出
 * 硬件: STM32G030F6P6 + L6571
 * 
 * 作者: 微智电子智能助手
 * 日期: 2026-06-11
 */

#include "stm32g0xx_hal.h"
#include "dali_driver.h"
#include "host_protocol.h"
#include <string.h>

/* 版本信息 */
#define FIRMWARE_VERSION_MAJOR  1
#define FIRMWARE_VERSION_MINOR  0
#define FIRMWARE_VERSION_PATCH  0

/* LED 引脚定义 */
#define LED_RUN_PIN     GPIO_PIN_1
#define LED_RUN_PORT    GPIOB
#define LED_COMM_PIN    GPIO_PIN_8
#define LED_COMM_PORT   GPIOA

/* 状态机 */
typedef enum {
    STATE_IDLE = 0,
    STATE_RECEIVING,
    STATE_PROCESSING,
    STATE_SENDING_DALI,
    STATE_WAIT_REPLY
} SystemState_t;

static SystemState_t g_state = STATE_IDLE;
static uint32_t g_last_activity = 0;

/* 函数声明 */
static void SystemClock_Config(void);
static void GPIO_Init(void);
static void UART_Init(void);
static void TIM_Init(void);
static void LED_SetRun(uint8_t on);
static void LED_SetComm(uint8_t on);
static void ProcessHostFrame(Host_Frame_t *frame);

/**
 * @brief 主函数
 */
int main(void)
{
    /* HAL 初始化 */
    HAL_Init();
    
    /* 系统时钟配置 */
    SystemClock_Config();
    
    /* 外设初始化 */
    GPIO_Init();
    UART_Init();
    TIM_Init();
    
    /* 模块初始化 */
    DALI_Init();
    HostProtocol_Init();
    
    /* 启动指示灯 */
    for (int i = 0; i < 3; i++) {
        LED_SetRun(1);
        HAL_Delay(100);
        LED_SetRun(0);
        HAL_Delay(100);
    }
    
    g_last_activity = HAL_GetTick();
    
    /* 主循环 */
    while (1) {
        /* 处理主机协议 */
        Host_Frame_t frame;
        if (HostProtocol_Receive(&frame)) {
            LED_SetComm(1);
            ProcessHostFrame(&frame);
            LED_SetComm(0);
            g_last_activity = HAL_GetTick();
        }
        
        /* DALI 状态机处理 */
        DALI_Process();
        
        /* 运行指示灯闪烁 */
        if ((HAL_GetTick() - g_last_activity) > 1000) {
            LED_SetRun((HAL_GetTick() / 500) % 2);
        } else {
            LED_SetRun(1);
        }
    }
}

/**
 * @brief 处理主机帧
 */
static void ProcessHostFrame(Host_Frame_t *frame)
{
    uint8_t dali_addr;
    uint8_t dali_cmd;
    uint8_t dali_data;
    
    /* 节点ID 转换为 DALI 地址 */
    dali_addr = frame->node_id & 0x3F;  /* DALI 短地址 0-63 */
    
    switch (frame->cmd) {
        case HOST_CMD_OFF:
            DALI_SendCommand(dali_addr, DALI_CMD_OFF);
            break;
            
        case HOST_CMD_SET_DIM:
            /* 亮度 0-100 映射到 DALI 0-254 */
            dali_data = (frame->data[0] * 254) / 100;
            DALI_SendDirectArc(dali_addr, dali_data);
            break;
            
        case HOST_CMD_SET_CCT:
            /* 双色温控制 (需要 DT8 支持) */
            {
                uint8_t brightness = frame->data[0];  /* 亮度 */
                uint16_t cct = (frame->data[1] << 8) | frame->data[2];  /* 色温 */
                
                /* 先设置亮度 */
                dali_data = (brightness * 254) / 100;
                DALI_SendDirectArc(dali_addr, dali_data);
                
                /* 再设置色温 (DT8) */
                DALI_SendDT8Temperature(dali_addr, cct);
            }
            break;
            
        case HOST_CMD_SET_COLOR:
            /* RGBW 控制 (需要 DT8 支持) */
            {
                uint8_t r = frame->data[0];
                uint8_t g = frame->data[1];
                uint8_t b = frame->data[2];
                uint8_t w = frame->data[3];
                DALI_SendDT8RGBW(dali_addr, r, g, b, w);
            }
            break;
            
        case HOST_CMD_SCENE:
            /* 调用场景 */
            dali_cmd = DALI_CMD_GO_TO_SCENE(frame->data[0]);
            DALI_SendCommand(dali_addr, dali_cmd);
            break;
            
        case HOST_CMD_DISCOVER:
            /* 启动 DALI 地址分配 */
            DALI_StartCommissioning();
            break;
            
        case HOST_CMD_CONFIG:
            /* 节点配置 */
            /* 可扩展: 设置组地址、最小/最大亮度等 */
            break;
            
        default:
            /* 未知命令 */
            break;
    }
}

/**
 * @brief 系统时钟配置
 * 配置为 64MHz
 */
static void SystemClock_Config(void)
{
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    
    /* 配置 HSI 为系统时钟源 */
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
    RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1;
    RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
    
    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
        Error_Handler();
    }
    
    /* 初始化 CPU、AHB 和 APB 时钟 */
    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK |
                                   RCC_CLOCKTYPE_PCLK1;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
    RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV1;
    
    if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) {
        Error_Handler();
    }
}

/**
 * @brief GPIO 初始化
 */
static void GPIO_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    
    /* GPIO 时钟使能 */
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    
    /* LED 引脚配置 */
    GPIO_InitStruct.Pin = LED_RUN_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(LED_RUN_PORT, &GPIO_InitStruct);
    
    GPIO_InitStruct.Pin = LED_COMM_PIN;
    HAL_GPIO_Init(LED_COMM_PORT, &GPIO_InitStruct);
    
    /* 初始状态 */
    HAL_GPIO_WritePin(LED_RUN_PORT, LED_RUN_PIN, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(LED_COMM_PORT, LED_COMM_PIN, GPIO_PIN_RESET);
}

/**
 * @brief UART 初始化 (与主机通信)
 * PA9-TX, PA10-RX, 115200 8N1
 */
static void UART_Init(void)
{
    UART_HandleTypeDef huart1;
    
    __HAL_RCC_USART1_CLK_ENABLE();
    
    huart1.Instance = USART1;
    huart1.Init.BaudRate = 115200;
    huart1.Init.WordLength = UART_WORDLENGTH_8B;
    huart1.Init.StopBits = UART_STOPBITS_1;
    huart1.Init.Parity = UART_PARITY_NONE;
    huart1.Init.Mode = UART_MODE_TX_RX;
    huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    huart1.Init.OverSampling = UART_OVERSAMPLING_16;
    
    if (HAL_UART_Init(&huart1) != HAL_OK) {
        Error_Handler();
    }
}

/**
 * @brief 定时器初始化
 */
static void TIM_Init(void)
{
    /* 用于 DALI 时序控制 */
    /* 具体实现在 dali_driver.c */
}

/**
 * @brief 设置运行 LED
 */
static void LED_SetRun(uint8_t on)
{
    HAL_GPIO_WritePin(LED_RUN_PORT, LED_RUN_PIN, 
                      on ? GPIO_PIN_SET : GPIO_PIN_RESET);
}

/**
 * @brief 设置通信 LED
 */
static void LED_SetComm(uint8_t on)
{
    HAL_GPIO_WritePin(LED_COMM_PORT, LED_COMM_PIN,
                      on ? GPIO_PIN_SET : GPIO_PIN_RESET);
}

/**
 * @brief 错误处理
 */
void Error_Handler(void)
{
    /* 错误指示灯快速闪烁 */
    while (1) {
        LED_SetRun(1);
        HAL_Delay(100);
        LED_SetRun(0);
        HAL_Delay(100);
    }
}

/**
 * @brief 断言失败回调
 */
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line)
{
    /* 可添加调试输出 */
}
#endif
