from machine import UART
import time
import _thread
import struct

class DWIN:
    """DWIN 串口屏幕控制类"""
    
    def __init__(self, uart_id=1, tx_pin=10, rx_pin=9, baudrate=115200):
        """
        初始化DWIN显示屏
        
        参数:
            uart_id: UART端口号 (ESP32的UART1)
            tx_pin: 发送引脚 (ESP32 UART1默认TX=10)
            rx_pin: 接收引脚 (ESP32 UART1默认RX=9)
            baudrate: 波特率
        """
        self.uart = UART(uart_id, baudrate)
        self.uart.init(baudrate=baudrate, tx=tx_pin, rx=rx_pin)
        self._lock = _thread.allocate_lock()
        self.rx_buffer = bytearray(20)
        
    def _send_bytes(self, data):
        """发送字节数据到显示屏"""
        with self._lock:
            self.uart.write(bytes(data))
            time.sleep_ms(10)  # 等待数据发送完成
    
    def put_string(self, data, length):
        """发送字符串数据到显示屏"""
        if isinstance(data, (bytes, bytearray)):
            self._send_bytes(data[:length])
        else:
            self._send_bytes(bytes(data[:length]))
    
    def jump_page(self, page_id):
        """
        切换到指定页面
        
        参数:
            page_id: 页面ID
        """
        data = bytearray([0x5A, 0xA5, 0x04, 0x80, 0x03, page_id >> 8, page_id & 0xFF])
        self.put_string(data, len(data))
    
    def read_reg(self, reg_addr):
        """
        读取寄存器值
        
        参数:
            reg_addr: 寄存器地址
        """
        data = bytearray([0x5A, 0xA5, 0x03, 0x81, reg_addr, 0x07])
        self.put_string(data, len(data))
    
    def write_reg(self, reg_addr, value):
        """
        写入寄存器值
        
        参数:
            reg_addr: 寄存器地址
            value: 要写入的值
        """
        data = bytearray([0x5A, 0xA5, 0x04, 0x80, reg_addr, value >> 8, value & 0xFF])
        self.put_string(data, len(data))
    
    def write_var(self, addr, value):
        """
        写入变量值到LCD显示
        
        参数:
            addr: 变量地址
            value: 要写入的值（16位整数）
        """
        data = bytearray([0x5A, 0xA5, 0x05, 0x82, 
                         addr >> 8, addr & 0xFF,
                         value >> 8, value & 0xFF])
        self.put_string(data, len(data))
    
    def write_var_32(self, addr, value):
        """
        写入32位变量值到LCD显示
        
        参数:
            addr: 变量地址
            value: 要写入的值（32位整数）
        """
        data = bytearray([0x5A, 0xA5, 0x07, 0x82,
                         addr >> 8, addr & 0xFF,
                         (value >> 24) & 0xFF,
                         (value >> 16) & 0xFF,
                         (value >> 8) & 0xFF,
                         value & 0xFF])
        self.put_string(data, len(data))
    
    def init_lcd(self, eeprom_data=None):
        """
        初始化LCD显示
        
        参数:
            eeprom_data: EEPROM数据读取函数，如果不提供则跳过EEPROM初始化
        """
        if eeprom_data is None:
            return
            
        data = bytearray([0x5A, 0xA5, 0x05, 0x82, 0x00, 0x00, 0x00, 0x00])
        
        for addr in range(0xFF):
            data[5] = addr
            data[6] = eeprom_data(addr * 2)
            data[7] = eeprom_data(addr * 2 + 1)
            self.put_string(data, 8)
    
    def process_received_data(self):
        bPackStart = False
        bPackEnd = False
        while bPackEnd == False:
            """处理接收到的数据"""
            if self.uart.any():
                # 读取接收到的数据
                received = self.uart.read()
                if received:
                    bPackStart = True
                    print(received)
                    # 保存接收到的数据开始拼接到rx_buffer缓冲区 
                    if len(self.rx_buffer) > 0:
                        self.rx_buffer += received
                    else:
                        self.rx_buffer = received 
                    '''
                    self.rx_buffer = received[:9]  # 最多保存9字节
                    
                    # 检查帧头
                    if self.rx_buffer[0] == 0x5A and self.rx_buffer[1] == 0xA5:
                        # 处理按键消息
                        if self.rx_buffer[3] == 0x83:
                            cmd_addr = (self.rx_buffer[4] << 8) + self.rx_buffer[5]
                            if cmd_addr == 0x00DF:  # 按键消息
                                key_data = self.rx_buffer[8]
                                self._handle_key_press(key_data)
                        
                        # 处理其他消息
                        elif self.rx_buffer[3] == 0x81:
                            self._handle_system_message()
                    '''
                else:
                    pass
            else:
                if bPackStart== True:
                    bPackEnd = True
                    print("received successed!\r\n")
                    return self.rx_buffer
                 
    
    def _handle_key_press(self, key_data):
        """
        处理按键消息
        
        参数:
            key_data: 按键值
        """
        if key_data == 0xCC:
            # 系统复位
            import machine
            machine.reset()
        elif key_data == 0x10:
            # 开始测试
            self._handle_start_test()
        elif key_data == 0x11:
            # 停止测试
            self._handle_stop_test()
        elif key_data == 0x12:
            # 采集背景
            self._handle_capture_background()
        elif key_data == 0x13:
            # 采集样品
            self._handle_capture_sample()
    
    def _handle_system_message(self):
        """处理系统消息"""
        # 在这里添加系统消息处理代码
        pass
    
    def _handle_start_test(self):
        """处理开始测试"""
        # 在这里添加开始测试的代码
        pass
    
    def _handle_stop_test(self):
        """处理停止测试"""
        # 在这里添加停止测试的代码
        self.write_var_32(0x00, 0)  # 清零测试时间
    
    def _handle_capture_background(self):
        """处理采集背景"""
        # 在这里添加采集背景的代码
        pass
    
    def _handle_capture_sample(self):
        """处理采集样品"""
        # 在这里添加采集样品的代码
        pass
    
    def run(self):
        """运行主循环"""
        self.init_lcd()
        # 切换到页面 0
        #self.jump_page(0)  # 跳转到初始页面
        
        while True:
            self.process_received_data()
            # time.sleep_ms(100)  # 适当的延时避免过度占用CPU

# 使用示例
def example():
    # 创建DWIN实例
    dwin = DWIN(uart_id=1)
    
    # 写入一些测试数据
    dwin.write_var(0x10, 250)  		# 写入16位数据
    dwin.write_var(0x11, 251)  		# 写入16位数据
    dwin.write_var_32(0x20, 255255)  	# 写入32位数据
     
    
    # 运行主循环
    dwin.run()

if __name__ == '__main__': 
    example()