#include "lcd.h"
#include "lcd_font.h"


// 写命令
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();
}

// 写数据
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();
}

// 写16位数据
static void LCD_WriteData16(uint16_t data) {
    uint8_t buf[2] = {data >> 8, data & 0xFF};
    LCD_DC_HIGH();
    LCD_CS_LOW();
    HAL_SPI_Transmit(&hspi1, buf, 2, HAL_MAX_DELAY);
    LCD_CS_HIGH();
}

// 初始化LCD
void LCD_Init(void) {
    // 复位屏幕
    LCD_RST_LOW();
    HAL_Delay(10);
    LCD_RST_HIGH();
    HAL_Delay(10);

    // 初始化命令序列（以ST7789为例）
    LCD_WriteCommand(0x36); // Memory Data Access Control
    LCD_WriteData(0xC0); // RGB Color Order

    LCD_WriteCommand(0x3A); // Interface Pixel Format
    LCD_WriteData(0x05);    // 16-bit/pixel

    LCD_WriteCommand(0xB2); // Porch Setting
    LCD_WriteData(0x0C);
    LCD_WriteData(0x0C);
    LCD_WriteData(0x00);
    LCD_WriteData(0x33);
    LCD_WriteData(0x33);

    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
    LCD_WriteData(0xD0);
    LCD_WriteData(0x04);
    LCD_WriteData(0x0D);
    LCD_WriteData(0x11);
    LCD_WriteData(0x13);
    LCD_WriteData(0x2B);
    LCD_WriteData(0x3F);
    LCD_WriteData(0x54);
    LCD_WriteData(0x4C);
    LCD_WriteData(0x18);
    LCD_WriteData(0x0D);
    LCD_WriteData(0x0B);
    LCD_WriteData(0x1F);
    LCD_WriteData(0x23);

    LCD_WriteCommand(0xE1); // Negative Voltage Gamma Control
    LCD_WriteData(0xD0);
    LCD_WriteData(0x04);
    LCD_WriteData(0x0C);
    LCD_WriteData(0x11);
    LCD_WriteData(0x13);
    LCD_WriteData(0x2C);
    LCD_WriteData(0x3F);
    LCD_WriteData(0x44);
    LCD_WriteData(0x51);
    LCD_WriteData(0x2F);
    LCD_WriteData(0x1F);
    LCD_WriteData(0x1F);
    LCD_WriteData(0x20);
    LCD_WriteData(0x23);

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

// 清屏
void LCD_Clear(uint16_t color) {
    LCD_WriteCommand(0x2A); // Column Address Set
    LCD_WriteData16(X_OFFSET);    // 起始列地址
    LCD_WriteData16(X_OFFSET + LCD_WIDTH - 1); // 结束列地址

    LCD_WriteCommand(0x2B); // Row Address Set
    LCD_WriteData16(Y_OFFSET);    // 起始行地址
    LCD_WriteData16(Y_OFFSET + LCD_HEIGHT - 1); // 结束行地址

    LCD_WriteCommand(0x2C); // Memory Write
    for (uint32_t i = 0; i < LCD_WIDTH * LCD_HEIGHT; i++) {
        LCD_WriteData16(color);
    }
}

// 绘制单个像素
void LCD_DrawPixel(uint16_t x, uint16_t y, uint16_t color) {
    if (x >= LCD_WIDTH || y >= LCD_HEIGHT) return; // 超出屏幕范围则返回

    LCD_WriteCommand(0x2A); // 设置列地址
    LCD_WriteData16(X_OFFSET + x);
    LCD_WriteData16(X_OFFSET + x);

    LCD_WriteCommand(0x2B); // 设置行地址
    LCD_WriteData16(Y_OFFSET + y);
    LCD_WriteData16(Y_OFFSET + y);

    LCD_WriteCommand(0x2C); // 写入内存
    LCD_WriteData16(color);
}

// 在指定位置显示一个字符
void LCD_DrawChar(uint16_t x, uint16_t y, char ch, uint16_t color, uint16_t bgColor) {
    if (ch < 32 || ch > 126) return; // 字符范围检查 (ASCII 32-126)

    const uint8_t *charData = ascii_1206[ch - 32]; // 获取字符点阵数据
    for (uint8_t i = 0; i < FONT_HEIGHT; i++) { // 遍历字符的高度
        uint8_t line = charData[i]; // 获取字符的每一行数据
        for (uint8_t j = 0; j < FONT_WIDTH; j++) { // 遍历字符的宽度
            if (line & (1 << j)) { // 判断当前像素是否为1
                LCD_DrawPixel(x + j, y + i, color); // 绘制前景色
            } else {
                LCD_DrawPixel(x + j, y + i, bgColor); // 绘制背景色
            }
        }
    }
}

// 在指定位置显示字符串
void LCD_DrawString(uint16_t x, uint16_t y, const char *str, uint16_t color, uint16_t bgColor) {
    while (*str) {
        LCD_DrawChar(x, y, *str, color, bgColor); // 显示单个字符
        x += FONT_WIDTH; // 移动到下一个字符位置
        str++;
    }
}