from machine import Pin, SPI
import time
import framebuf

# 定义颜色
RED   = 0xf800
GREEN = 0x07e0
BLUE  = 0x001f
WHITE = 0xffff
BLACK = 0x0000
YELLOW = 0xFFE0

LCD_WIDTH  = 128
LCD_HEIGHT = 128

class LCD_0inch85(framebuf.FrameBuffer):
    def __init__(self):
        self.width  = LCD_WIDTH
        self.height = LCD_HEIGHT

        self.cs  = Pin(13, Pin.OUT)
        self.rst = Pin(10, Pin.OUT)
        self.dc  = Pin(12, Pin.OUT)

        self.spi = SPI(1, baudrate=40000000, polarity=0, phase=0,
                       sck=Pin(14), mosi=Pin(15), miso=None)

        self.buffer = bytearray(self.height * self.width * 2)
        super().__init__(self.buffer, self.width, self.height, framebuf.RGB565)

        self.init_lcd()

    def write_cmd(self, cmd):
        self.cs.off()
        self.dc.off()
        self.spi.write(bytearray([cmd]))
        self.cs.on()

    def write_data(self, data):
        self.cs.off()
        self.dc.on()
        self.spi.write(bytearray([data]))
        self.cs.on()

    def write_data16(self, data):
        self.cs.off()
        self.dc.on()
        self.spi.write(bytearray([data >> 8, data & 0xFF]))
        self.cs.on()

    def reset(self):
        self.rst.off()
        time.sleep_ms(100)
        self.rst.on()
        time.sleep_ms(100)

    def init_lcd(self):
        self.reset()
        self.write_cmd(0x11)
        time.sleep_ms(120)
        self.write_cmd(0x29)
        time.sleep_ms(120)

        self.write_cmd(0xFE)
        self.write_cmd(0xFE)
        self.write_cmd(0xEF)

        self.write_cmd(0xB0); self.write_data(0xC0)
        self.write_cmd(0xB2); self.write_data(0x24)
        self.write_cmd(0xB3); self.write_data(0x03)
        self.write_cmd(0xB7); self.write_data(0x01)
        self.write_cmd(0xB6); self.write_data(0x19)

        self.write_cmd(0xAC); self.write_data(0xDB)
        self.write_cmd(0xAB); self.write_data(0x0F)
        self.write_cmd(0x3A); self.write_data(0x05)

        self.write_cmd(0xB4); self.write_data(0x04)
        self.write_cmd(0xA8); self.write_data(0x0C)
        self.write_cmd(0xB8); self.write_data(0x08)

        self.write_cmd(0xED); self.write_data(0x03)
        self.write_cmd(0xEA); self.write_data(0x9F)
        self.write_cmd(0xC6); self.write_data(0x2A)
        self.write_cmd(0xC7); self.write_data(0x10)

    def set_window(self, x0, y0, x1, y1):
        x_offset = 0
        y_offset = 32
        self.write_cmd(0x2A)
        self.write_data(0x00)
        self.write_data(x0 + x_offset)
        self.write_data(0x00)
        self.write_data(x1 + x_offset)

        self.write_cmd(0x2B)
        self.write_data(0x00)
        self.write_data(y0 + y_offset)
        self.write_data(0x00)
        self.write_data(y1 + y_offset)

        self.write_cmd(0x2C)

    def fill_color(self, color):
        self.set_window(0, 0, self.width - 1, self.height - 1)
        for _ in range(self.width * self.height):
            self.write_data16(color)
    
    def show(self):
        self.set_window(0, 0, self.width - 1, self.height - 1)
        self.cs.off()
        self.dc.on()
        self.spi.write(self.buffer)
        self.cs.on()
    
    def draw_bmp(self, filename):
        try:
            with open(filename, "rb") as f:
                # BMP 头部解析
                if f.read(2) != b'BM':
                    print("Not a BMP file.")
                    return
                f.seek(10)
                start_pos = int.from_bytes(f.read(4), "little")
                f.seek(18)
                width = int.from_bytes(f.read(4), "little")
                height = int.from_bytes(f.read(4), "little")
                f.seek(28)
                bpp = int.from_bytes(f.read(2), "little")

                if bpp != 24:
                    print("Only 24-bit BMP supported.")
                    return

                # 设定窗口
                self.set_window(0, 0, width - 1, height - 1)

                # BMP 文件像素是 bottom-up 的
                row_size = (width * 3 + 3) & ~3
                for y in range(height - 1, -1, -1):
                    f.seek(start_pos + y * row_size)
                    for _ in range(width):
                        b, g, r = f.read(3)
                        # 将 RGB888 转换为 RGB565
                        color = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3)
                        self.write_data16(color)
        except Exception as e:
            print("Failed to draw BMP:", e)
