#include "lcd.h"
#include "lcd_font.h"
#include <stdlib.h> // 添加标准库以使用 malloc 和 free
#include "lv_port_disp.h"


// 写命令到LCD
static void LCD_WriteCommand(uint8_t cmd) {
    LCD_DC_LOW();
    LCD_CS_LOW();
    HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY);
    LCD_CS_HIGH();
}

// 写数据到LCD
static void LCD_WriteData(uint8_t data) {
    LCD_DC_HIGH();
    LCD_CS_LOW();
    HAL_SPI_Transmit(&hspi1, &data, 1, HAL_MAX_DELAY);
    LCD_CS_HIGH();
}


// 使用 DMA 写多个数据到 LCD
static void LCD_WriteDataBuffer_DMA(uint8_t *data, uint16_t size) {
    LCD_DC_HIGH();
    LCD_CS_LOW();
    HAL_SPI_Transmit_DMA(&hspi1, data, size); // 使用 DMA 传输
    while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY); // 等待传输完成
    LCD_CS_HIGH();
}

// 修改原来的 LCD_WriteDataBuffer，增加 DMA 支持
static void LCD_WriteDataBuffer(uint8_t *data, uint16_t size) {
    if (size > 64) { // 如果数据量较大，使用 DMA
        LCD_WriteDataBuffer_DMA(data, size);
    } else { // 否则使用普通传输
        LCD_DC_HIGH();
        LCD_CS_LOW();
        HAL_SPI_Transmit(&hspi1, data, size, HAL_MAX_DELAY);
        LCD_CS_HIGH();
    }
}

// 初始化LCD
void LCD_Init(void) {
    LCD_RST_LOW();
    HAL_Delay(50);
    LCD_RST_HIGH();
    HAL_Delay(50);

    LCD_WriteCommand(0x36); // Memory Data Access Control
    LCD_WriteData(0x60);    // 横屏模式，向右旋转90度

    LCD_WriteCommand(0x3A); // Interface Pixel Format
    LCD_WriteData(0x05);    // 16位色

    LCD_WriteCommand(0xB2); // Porch Setting
    uint8_t porch[] = {0x0C, 0x0C, 0x00, 0x33, 0x33};
    LCD_WriteDataBuffer(porch, sizeof(porch));

    LCD_WriteCommand(0xB7); // Gate Control
    LCD_WriteData(0x35);

    LCD_WriteCommand(0xBB); // VCOM Setting
    LCD_WriteData(0x19);

    LCD_WriteCommand(0xC0); // LCM Control
    LCD_WriteData(0x2C);

    LCD_WriteCommand(0xC2); // VDV and VRH Command Enable
    LCD_WriteData(0x01);

    LCD_WriteCommand(0xC3); // VRH Set
    LCD_WriteData(0x12);

    LCD_WriteCommand(0xC4); // VDV Set
    LCD_WriteData(0x20);

    LCD_WriteCommand(0xC6); // Frame Rate Control
    LCD_WriteData(0x0F);

    LCD_WriteCommand(0xD0); // Power Control 1
    LCD_WriteData(0xA4);
    LCD_WriteData(0xA1);

    LCD_WriteCommand(0xE0); // Positive Voltage Gamma Control
    uint8_t gamma_pos[] = {0xD0, 0x04, 0x0D, 0x11, 0x13, 0x2B, 0x3F, 0x54, 0x4C, 0x18, 0x0D, 0x0B, 0x1F, 0x23};
    LCD_WriteDataBuffer(gamma_pos, sizeof(gamma_pos));

    LCD_WriteCommand(0xE1); // Negative Voltage Gamma Control
    uint8_t gamma_neg[] = {0xD0, 0x04, 0x0C, 0x11, 0x13, 0x2C, 0x3F, 0x44, 0x51, 0x2F, 0x1F, 0x1F, 0x20, 0x23};
    LCD_WriteDataBuffer(gamma_neg, sizeof(gamma_neg));

    LCD_WriteCommand(0x21); // Display Inversion On
    LCD_WriteCommand(0x11); // Sleep Out
    HAL_Delay(120);
    LCD_WriteCommand(0x29); // Display On
}

// 设置显示窗口
static void LCD_SetAddressWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h) {
    uint16_t x_start = x + X_OFFSET;
    uint16_t x_end = x_start + w - 1;
    uint16_t y_start = y + Y_OFFSET;
    uint16_t y_end = y_start + h - 1;

    LCD_WriteCommand(0x2A); // Column Address Set
    uint8_t data_x[] = {x_start >> 8, x_start & 0xFF, x_end >> 8, x_end & 0xFF};
    LCD_WriteDataBuffer(data_x, sizeof(data_x));

    LCD_WriteCommand(0x2B); // Row Address Set
    uint8_t data_y[] = {y_start >> 8, y_start & 0xFF, y_end >> 8, y_end & 0xFF};
    LCD_WriteDataBuffer(data_y, sizeof(data_y));

    LCD_WriteCommand(0x2C); // Memory Write
}

// 清屏
// void LCD_Clear(uint16_t color) {
//     uint8_t color_data[] = {color >> 8, color & 0xFF};
//     LCD_SetAddressWindow(0, 0, LCD_WIDTH, LCD_HEIGHT);

//     for (uint32_t i = 0; i < LCD_WIDTH * LCD_HEIGHT; i++) {
//         LCD_WriteDataBuffer(color_data, 2);
//     }
// }

void LCD_Clear(uint16_t color) {
    uint8_t color_data[] = {color >> 8, color & 0xFF};
    LCD_SetAddressWindow(0, 0, LCD_WIDTH, LCD_HEIGHT); // 设置整个屏幕为绘制窗口

    // 创建一个缓冲区，用于存储一行的颜色数据
    uint32_t row_size = LCD_WIDTH * 2; // 每行像素占用 2 字节
    uint8_t *row_buffer = (uint8_t *)malloc(row_size);
    if (row_buffer == NULL) return; // 分配失败，直接返回

    // 填充缓冲区为目标颜色
    for (uint32_t i = 0; i < row_size; i += 2) {
        row_buffer[i] = color_data[0];
        row_buffer[i + 1] = color_data[1];
    }

    // 按行传输数据，覆盖整个屏幕
    for (uint32_t y = 0; y < LCD_HEIGHT; y++) {
        LCD_WriteDataBuffer_DMA(row_buffer, row_size);
    }

    free(row_buffer); // 释放缓冲区
}

// 绘制像素
// void LCD_DrawPixel(uint16_t x, uint16_t y, uint16_t color) {
//     LCD_SetAddressWindow(x, y, 1, 1);
//     uint8_t color_data[] = {color >> 8, color & 0xFF};
//     LCD_WriteDataBuffer(color_data, 2);
// }

// 绘制像素（旋转 90°）
void LCD_DrawPixel(uint16_t x, uint16_t y, uint16_t color) {
    // 旋转 90° 的坐标映射
    uint16_t new_x = y;
    uint16_t new_y = LCD_HEIGHT - 1 - x;

    LCD_SetAddressWindow(new_x, new_y, 1, 1);
    uint8_t color_data[] = {color >> 8, color & 0xFF};
    LCD_WriteDataBuffer(color_data, 2);
}

// void LCD_DrawChar(uint16_t x, uint16_t y, char ch, uint16_t color, uint16_t bgColor) {
//     const unsigned char *font = ascii_1206[ch - ' '];
//     uint8_t char_buffer[FONT_WIDTH * FONT_HEIGHT * 2]; // 每个像素 2 字节
//     uint32_t index = 0;

//     // 将字符数据按列存储到缓冲区（逆时针旋转 90 度 + 左右镜像）
//     for (uint8_t i = 0; i < FONT_WIDTH; i++) { // 遍历字体宽度（列）
//         for (uint8_t j = 0; j < FONT_HEIGHT; j++) { // 遍历字体高度（行）
//             // 左右镜像：将列索引从 FONT_WIDTH - 1 - i 开始
//             if (font[j] & (1 << (FONT_WIDTH - 1 - i))) { // 判断像素是否为前景色
//                 char_buffer[index++] = color >> 8;
//                 char_buffer[index++] = color & 0xFF;
//             } else { // 背景色
//                 char_buffer[index++] = bgColor >> 8;
//                 char_buffer[index++] = bgColor & 0xFF;
//             }
//         }
//     }

//     // 设置显示窗口（注意旋转后宽高互换）
//     LCD_SetAddressWindow(x, y, FONT_HEIGHT, FONT_WIDTH);

//     // 使用 DMA 传输字符像素数据
//     LCD_WriteDataBuffer_DMA(char_buffer, sizeof(char_buffer));
// }



// 绘制字符串（沿y轴绘制）
// void LCD_DrawString(uint16_t x, uint16_t y, const char *str, uint16_t color, uint16_t bgColor) {
//     y = LCD_HEIGHT-7 -y;
//     while (*str) {
//         LCD_DrawChar(x, y, *str, color, bgColor);
//         y -= FONT_WIDTH; // 每个字符向下移动一个字符宽度
//         str++;
//     }
// }
