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

#include "stm32g0xx_hal.h"
#include "dmx512_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

/* 虚拟节点配置 */
#define MAX_VIRTUAL_NODES       32

typedef struct {
    uint16_t parent_node_id;
    uint8_t  virtual_count;
    uint8_t  channel_per_node;
    uint16_t start_channel;
} VirtualNodeConfig_t;

static VirtualNodeConfig_t virtual_config[MAX_VIRTUAL_NODES];
static uint8_t virtual_config_count = 0;

/* 函数声明 */
static void SystemClock_Config(void);
static void GPIO_Init(void);
static void UART_Init(void);
static void LED_SetRun(uint8_t on);
static void LED_SetComm(uint8_t on);
static void ProcessHostFrame(Host_Frame_t *frame);
static void ProcessVirtualNode(uint16_t parent_id, uint8_t sub_index, Host_Frame_t *frame);

/**
 * @brief 主函数
 */
int main(void)
{
    /* HAL 初始化 */
    HAL_Init();
    
    /* 系统时钟配置 */
    SystemClock_Config();
    
    /* 外设初始化 */
    GPIO_Init();
    UART_Init();
    
    /* 模块初始化 */
    DMX512_Init();
    HostProtocol_Init();
    
    /* 启动指示灯 */
    for (int i = 0; i < 3; i++) {
        LED_SetRun(1);
        HAL_Delay(100);
        LED_SetRun(0);
        HAL_Delay(100);
    }
    
    /* 主循环 */
    while (1) {
        /* 处理主机协议 */
        Host_Frame_t frame;
        if (HostProtocol_Receive(&frame)) {
            LED_SetComm(1);
            ProcessHostFrame(&frame);
            LED_SetComm(0);
        }
        
        /* DMX512 帧发送 */
        DMX512_Process();
        
        /* 运行指示灯 */
        LED_SetRun((HAL_GetTick() / 500) % 2);
    }
}

/**
 * @brief 处理主机帧
 */
static void ProcessHostFrame(Host_Frame_t *frame)
{
    uint16_t node_id = frame->node_id;
    uint16_t channel;
    
    switch (frame->cmd) {
        case HOST_CMD_OFF:
            /* 关闭: 所有通道置 0 */
            channel = (node_id - 1) * 4 + 1;
            DMX512_SetChannel(channel + 0, 0);
            DMX512_SetChannel(channel + 1, 0);
            DMX512_SetChannel(channel + 2, 0);
            DMX512_SetChannel(channel + 3, 0);
            break;
            
        case HOST_CMD_SET_DIM:
            /* 单通道调光 */
            channel = (node_id - 1) + 1;
            DMX512_SetChannel(channel, frame->data[0]);
            break;
            
        case HOST_CMD_SET_CCT:
            /* 双色温: 2 通道 (暖白 + 冷白) */
            {
                uint16_t cct = (frame->data[0] << 8) | frame->data[1];
                uint8_t brightness = frame->data[2];
                
                uint8_t warm, cool;
                
                /* 色温映射到冷暖比例 */
                /* 2700K = 全暖, 6500K = 全冷 */
                if (cct <= 2700) {
                    warm = brightness;
                    cool = 0;
                } else if (cct >= 6500) {
                    warm = 0;
                    cool = brightness;
                } else {
                    /* 线性插值 */
                    uint32_t ratio = ((cct - 2700) * 255) / (6500 - 2700);
                    cool = (brightness * ratio) / 255;
                    warm = brightness - cool;
                }
                
                channel = (node_id - 1) * 2 + 1;
                DMX512_SetChannel(channel + 0, warm);
                DMX512_SetChannel(channel + 1, cool);
            }
            break;
            
        case HOST_CMD_SET_COLOR:
            /* RGBW: 4 通道 */
            {
                uint8_t r = frame->data[0];
                uint8_t g = frame->data[1];
                uint8_t b = frame->data[2];
                uint8_t w = frame->data[3];
                
                channel = (node_id - 1) * 4 + 1;
                DMX512_SetChannel(channel + 0, r);
                DMX512_SetChannel(channel + 1, g);
                DMX512_SetChannel(channel + 2, b);
                DMX512_SetChannel(channel + 3, w);
            }
            break;
            
        case HOST_CMD_SCENE:
            /* DMX512 本身没有场景概念，可扩展 */
            break;
            
        case HOST_CMD_CONFIG:
            /* 节点配置 */
            {
                uint8_t mode = frame->data[0];
                if (mode == HOST_MODE_VIRTUAL_NODES) {
                    /* 配置虚拟节点 */
                    uint8_t count = frame->data[1];
                    uint8_t ch_per_node = frame->data[2];
                    
                    /* 查找或创建配置 */
                    int idx = -1;
                    for (int i = 0; i < virtual_config_count; i++) {
                        if (virtual_config[i].parent_node_id == node_id) {
                            idx = i;
                            break;
                        }
                    }
                    
                    if (idx < 0 && virtual_config_count < MAX_VIRTUAL_NODES) {
                        idx = virtual_config_count++;
                    }
                    
                    if (idx >= 0) {
                        virtual_config[idx].parent_node_id = node_id;
                        virtual_config[idx].virtual_count = count;
                        virtual_config[idx].channel_per_node = ch_per_node;
                        virtual_config[idx].start_channel = (node_id - 1) * 4 + 1;
                    }
                }
            }
            break;
            
        case HOST_CMD_SET_MODE:
            /* 设置工作模式 */
            /* 可扩展: 单节点/虚拟节点 */
            break;
            
        case HOST_CMD_GET_INFO:
            /* 获取模块信息 */
            {
                Host_ModuleInfo_t info;
                info.protocol_type = 2;  /* DMX512 */
                info.version_major = FIRMWARE_VERSION_MAJOR;
                info.version_minor = FIRMWARE_VERSION_MINOR;
                info.version_patch = FIRMWARE_VERSION_PATCH;
                info.max_nodes = 512 / 4;  /* 每节点4通道 */
                info.current_nodes = 0;
                info.uptime = HAL_GetTick() / 1000;
                
                HostProtocol_SendResponse(HOST_CMD_GET_INFO, 
                                         (uint8_t *)&info, sizeof(info));
            }
            break;
            
        default:
            /* 检查是否是虚拟节点控制 */
            /* 命令码高位置1表示虚拟节点 */
            if (frame->cmd & 0x80) {
                uint8_t sub_index = frame->cmd & 0x7F;
                ProcessVirtualNode(node_id, sub_index, frame);
            }
            break;
    }
}

/**
 * @brief 处理虚拟节点
 */
static void ProcessVirtualNode(uint16_t parent_id, uint8_t sub_index, Host_Frame_t *frame)
{
    /* 查找父节点配置 */
    VirtualNodeConfig_t *config = NULL;
    for (int i = 0; i < virtual_config_count; i++) {
        if (virtual_config[i].parent_node_id == parent_id) {
            config = &virtual_config[i];
            break;
        }
    }
    
    if (config == NULL || sub_index >= config->virtual_count) {
        return;
    }
    
    /* 计算实际通道 */
    uint16_t channel = config->start_channel + sub_index * config->channel_per_node;
    
    /* 根据数据类型设置通道 */
    if (frame->data_len >= 4) {
        /* RGBW */
        DMX512_SetChannel(channel + 0, frame->data[0]);
        DMX512_SetChannel(channel + 1, frame->data[1]);
        DMX512_SetChannel(channel + 2, frame->data[2]);
        if (config->channel_per_node >= 4) {
            DMX512_SetChannel(channel + 3, frame->data[3]);
        }
    } else if (frame->data_len >= 2) {
        /* CCT */
        DMX512_SetChannel(channel + 0, frame->data[0]);
        DMX512_SetChannel(channel + 1, frame->data[1]);
    } else if (frame->data_len >= 1) {
        /* DIM */
        DMX512_SetChannel(channel, frame->data[0]);
    }
}

/**
 * @brief 系统时钟配置
 */
static void SystemClock_Config(void)
{
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    
    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();
    }
    
    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};
    
    __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);
    
    /* MAX485 DE 引脚 */
    GPIO_InitStruct.Pin = GPIO_PIN_0;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);  /* 默认接收 */
    
    /* 初始状态 */
    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 (与主机通信)
 * PA0-TX, PA1-RX (DMX512, 250000bps)
 */
static void UART_Init(void)
{
    /* 主机通信 UART1 */
    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();
    }
    
    /* DMX512 UART2 */
    UART_HandleTypeDef huart2;
    __HAL_RCC_USART2_CLK_ENABLE();
    
    huart2.Instance = USART2;
    huart2.Init.BaudRate = 250000;  /* DMX512 标准波特率 */
    huart2.Init.WordLength = UART_WORDLENGTH_8B;
    huart2.Init.StopBits = UART_STOPBITS_2;  /* 2 停止位 */
    huart2.Init.Parity = UART_PARITY_NONE;
    huart2.Init.Mode = UART_MODE_TX_RX;
    huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    huart2.Init.OverSampling = UART_OVERSAMPLING_16;
    
    if (HAL_UART_Init(&huart2) != HAL_OK) {
        Error_Handler();
    }
}

/**
 * @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);
    }
}
