/*
 * 自然写智能点阵笔嵌入式固件软件 V1.0
 * main.c - 主函数入口与RTOS任务创建
 *
 * 功能说明：
 * 1. 系统硬件初始化（GPIO/SPI/I2C/ADC/DMA）
 * 2. FreeRTOS内核启动与任务创建
 * 3. 各功能模块初始化协调
 * 4. 看门狗定时器配置
 * 5. 系统错误处理与故障恢复
 *
 * 硬件平台：ARM Cortex-M4F MCU
 * RTOS：FreeRTOS 10.x
 */

#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <stdio.h>

/* FreeRTOS头文件 */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#include "timers.h"
#include "event_groups.h"

/* 硬件抽象层头文件 */
#include "hal_gpio.h"
#include "hal_spi.h"
#include "hal_i2c.h"
#include "hal_adc.h"
#include "hal_dma.h"
#include "hal_wdt.h"
#include "hal_flash.h"
#include "hal_rtc.h"

/* 功能模块头文件 */
#include "camera_driver.h"
#include "pressure_sensor.h"
#include "led_driver.h"
#include "ble_gatt_server.h"
#include "dot_decoder.h"
#include "power_manager.h"
#include "offline_storage.h"

/* ========== 任务优先级定义 ========== */

/* 图像采集任务（最高优先级，需要精确的100Hz定时） */
#define TASK_IMAGE_CAPTURE_PRIORITY     (configMAX_PRIORITIES - 1)

/* 坐标计算任务 */
#define TASK_COORDINATE_PRIORITY        (configMAX_PRIORITIES - 2)

/* BLE发送任务 */
#define TASK_BLE_SEND_PRIORITY          (configMAX_PRIORITIES - 3)

/* 电源监测任务（较低优先级） */
#define TASK_POWER_MONITOR_PRIORITY     (tskIDLE_PRIORITY + 2)

/* 看门狗喂狗任务 */
#define TASK_WATCHDOG_PRIORITY          (tskIDLE_PRIORITY + 1)

/* ========== 任务栈大小定义（单位：字） ========== */

#define TASK_IMAGE_CAPTURE_STACK_SIZE   512
#define TASK_COORDINATE_STACK_SIZE      1024
#define TASK_BLE_SEND_STACK_SIZE        512
#define TASK_POWER_MONITOR_STACK_SIZE   256
#define TASK_WATCHDOG_STACK_SIZE        128

/* ========== 全局队列与信号量 ========== */

/* 图像数据队列（采集任务 → 坐标计算任务） */
QueueHandle_t g_image_data_queue;

/* 坐标数据队列（坐标计算 → BLE发送） */
QueueHandle_t g_coordinate_queue;

/* BLE连接状态事件组 */
EventGroupHandle_t g_ble_event_group;

/* 系统状态互斥锁 */
SemaphoreHandle_t g_system_mutex;

/* ========== 事件位定义 ========== */
#define EVT_BLE_CONNECTED       (1 << 0)
#define EVT_BLE_DISCONNECTED    (1 << 1)
#define EVT_PEN_DOWN            (1 << 2)
#define EVT_PEN_UP              (1 << 3)
#define EVT_LOW_BATTERY         (1 << 4)
#define EVT_CHARGING            (1 << 5)
#define EVT_OTA_START           (1 << 6)

/* ========== 全局系统状态 ========== */

typedef struct {
    bool pen_is_down;              /* 笔尖是否接触纸面 */
    bool ble_connected;            /* BLE是否已连接 */
    bool is_charging;              /* 是否正在充电 */
    uint8_t battery_percent;       /* 电量百分比 */
    uint32_t total_strokes;        /* 累计笔画数 */
    uint32_t uptime_seconds;       /* 运行时长 */
    uint8_t error_flags;           /* 错误标志位 */
} SystemState;

static SystemState g_system_state;

/* ========== 任务句柄 ========== */

static TaskHandle_t g_task_image_capture;
static TaskHandle_t g_task_coordinate;
static TaskHandle_t g_task_ble_send;
static TaskHandle_t g_task_power_monitor;
static TaskHandle_t g_task_watchdog;

/* ========== 函数前向声明 ========== */

static void hardware_init(void);
static void create_rtos_objects(void);
static void create_tasks(void);
static void watchdog_task(void *pvParameters);

/* 外部任务函数（各功能模块中实现） */
extern void image_capture_task(void *pvParameters);
extern void coordinate_task(void *pvParameters);
extern void ble_send_task(void *pvParameters);
extern void power_monitor_task(void *pvParameters);

/* ========== 主函数 ========== */

/**
 * 系统入口点
 * 完成硬件初始化后启动FreeRTOS调度器
 */
int main(void) {
    /* 步骤1：系统时钟配置（PLL → 168MHz） */
    SystemClock_Config();

    /* 步骤2：基础硬件初始化 */
    hardware_init();

    /* 步骤3：LED指示启动中（蓝色闪烁） */
    led_set_mode(LED_MODE_BLINK_BLUE);

    /* 步骤4：初始化全局状态 */
    memset(&g_system_state, 0, sizeof(g_system_state));

    /* 步骤5：创建RTOS同步对象 */
    create_rtos_objects();

    /* 步骤6：创建功能任务 */
    create_tasks();

    /* 步骤7：启动看门狗定时器（超时8秒） */
    hal_wdt_init(8000);
    hal_wdt_start();

    /* 步骤8：启动FreeRTOS调度器（不应返回） */
    vTaskStartScheduler();

    /* 如果到达这里说明调度器启动失败 */
    led_set_mode(LED_MODE_SOLID_RED);
    while (1) {
        /* 系统错误，死循环 */
    }

    return 0;
}

/* ========== 硬件初始化 ========== */

/**
 * 初始化所有硬件外设
 */
static void hardware_init(void) {
    /* GPIO初始化（笔尖接触检测引脚、充电检测引脚） */
    hal_gpio_init();

    /* SPI初始化（连接CMOS图像传感器，主模式 8MHz） */
    hal_spi_init(SPI_PORT_1, SPI_MODE_MASTER, 8000000);

    /* I2C初始化（连接压力传感器和IMU） */
    hal_i2c_init(I2C_PORT_1, 400000);  /* 400kHz快速模式 */

    /* ADC初始化（电池电压检测，12位分辨率） */
    hal_adc_init(ADC_CHANNEL_BATTERY, ADC_RESOLUTION_12BIT);

    /* DMA初始化（SPI图像数据DMA传输） */
    hal_dma_init(DMA_CHANNEL_SPI_RX);

    /* Flash初始化（离线缓存存储） */
    hal_flash_init();

    /* RTC初始化（时间戳生成） */
    hal_rtc_init();

    /* 摄像头传感器初始化 */
    camera_driver_init();

    /* 压力传感器校准 */
    pressure_sensor_init();
    pressure_sensor_calibrate();

    /* LED驱动初始化 */
    led_driver_init();

    /* BLE协议栈初始化 */
    ble_gatt_server_init();

    /* 点阵码解码器初始化 */
    dot_decoder_init();

    /* 电源管理初始化 */
    power_manager_init();

    /* 离线存储初始化 */
    offline_storage_init();
}

/* ========== RTOS对象创建 ========== */

/**
 * 创建队列、信号量、事件组等RTOS同步对象
 */
static void create_rtos_objects(void) {
    /*
     * 图像数据队列：采集任务以100Hz频率产生数据
     * 队列深度10帧，每帧包含图像元数据（不含原始像素）
     */
    g_image_data_queue = xQueueCreate(10, sizeof(ImageFrameMetadata));
    configASSERT(g_image_data_queue != NULL);

    /*
     * 坐标数据队列：坐标计算结果 → BLE发送
     * 队列深度20，容纳突发计算结果
     */
    g_coordinate_queue = xQueueCreate(20, sizeof(CoordinatePacket));
    configASSERT(g_coordinate_queue != NULL);

    /* BLE事件组 */
    g_ble_event_group = xEventGroupCreate();
    configASSERT(g_ble_event_group != NULL);

    /* 系统状态互斥锁 */
    g_system_mutex = xSemaphoreCreateMutex();
    configASSERT(g_system_mutex != NULL);
}

/* ========== 任务创建 ========== */

/**
 * 创建所有FreeRTOS任务
 */
static void create_tasks(void) {
    BaseType_t ret;

    /* 图像采集任务（100Hz定时采集CMOS图像） */
    ret = xTaskCreate(image_capture_task, "ImgCap",
                      TASK_IMAGE_CAPTURE_STACK_SIZE, NULL,
                      TASK_IMAGE_CAPTURE_PRIORITY, &g_task_image_capture);
    configASSERT(ret == pdPASS);

    /* 坐标计算任务（点阵码解码+坐标计算） */
    ret = xTaskCreate(coordinate_task, "CoordCalc",
                      TASK_COORDINATE_STACK_SIZE, NULL,
                      TASK_COORDINATE_PRIORITY, &g_task_coordinate);
    configASSERT(ret == pdPASS);

    /* BLE发送任务（坐标数据打包+BLE通知发送） */
    ret = xTaskCreate(ble_send_task, "BLESend",
                      TASK_BLE_SEND_STACK_SIZE, NULL,
                      TASK_BLE_SEND_PRIORITY, &g_task_ble_send);
    configASSERT(ret == pdPASS);

    /* 电源监测任务（电池电压/充电状态/低功耗管理） */
    ret = xTaskCreate(power_monitor_task, "PwrMon",
                      TASK_POWER_MONITOR_STACK_SIZE, NULL,
                      TASK_POWER_MONITOR_PRIORITY, &g_task_power_monitor);
    configASSERT(ret == pdPASS);

    /* 看门狗喂狗任务 */
    ret = xTaskCreate(watchdog_task, "WDT",
                      TASK_WATCHDOG_STACK_SIZE, NULL,
                      TASK_WATCHDOG_PRIORITY, &g_task_watchdog);
    configASSERT(ret == pdPASS);
}

/* ========== 看门狗任务 ========== */

/**
 * 看门狗喂狗任务
 * 周期性喂狗，防止系统死锁导致的假死
 * 如果各功能任务异常停止，看门狗将触发系统复位
 */
static void watchdog_task(void *pvParameters) {
    (void)pvParameters;

    TickType_t last_wake_time = xTaskGetTickCount();

    while (1) {
        /* 每2秒喂一次狗（看门狗超时8秒，留足余量） */
        hal_wdt_feed();

        /* 更新运行时长 */
        if (xSemaphoreTake(g_system_mutex, pdMS_TO_TICKS(100)) == pdTRUE) {
            g_system_state.uptime_seconds += 2;
            xSemaphoreGive(g_system_mutex);
        }

        /* 检查各任务是否正常运行 */
        if (eTaskGetState(g_task_image_capture) == eSuspended &&
            g_system_state.pen_is_down) {
            /* 图像采集任务异常挂起但笔在书写，尝试恢复 */
            vTaskResume(g_task_image_capture);
        }

        vTaskDelayUntil(&last_wake_time, pdMS_TO_TICKS(2000));
    }
}

/* ========== FreeRTOS回调函数 ========== */

/**
 * 栈溢出钩子函数
 * 任何任务发生栈溢出时被调用
 */
void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName) {
    /* 记录错误信息到Flash */
    g_system_state.error_flags |= 0x01;

    /* LED红色快闪指示严重错误 */
    led_set_mode(LED_MODE_FAST_BLINK_RED);

    /* 触发系统复位 */
    hal_system_reset();
}

/**
 * Malloc失败钩子函数
 */
void vApplicationMallocFailedHook(void) {
    g_system_state.error_flags |= 0x02;
    led_set_mode(LED_MODE_FAST_BLINK_RED);
    hal_system_reset();
}

/**
 * 空闲任务钩子函数
 * 在CPU空闲时进入低功耗模式以节省电量
 */
void vApplicationIdleHook(void) {
    /* 如果笔没有在书写且BLE空闲，进入轻度睡眠 */
    if (!g_system_state.pen_is_down && !g_system_state.ble_connected) {
        power_enter_light_sleep();
    }
}
