# drivers.py - 硬件驱动整合模块
from machine import Pin, PWM, ADC, I2C, SPI
import time
import math

class HardwareDrivers:
    """硬件驱动类 - 控制电机、传感器和IO端口"""
    
    def __init__(self):
        # 初始化属性
        self.light_sensor = None
        self.thermistor = None
        self.ports = {}
        self.i2c = None
        self.motor_address = 0x40
        self.motor_available = False
        self.spi_sd = None
        self.sd_cs = None
        self.sd_available = False
        
        # 初始化硬件
        self._init_sensors()
        self._init_ports()
        self._init_motor()
        self._init_sd_card()
    
    def _init_sensors(self):
        """初始化传感器"""
        try:
            # 光照传感器 (ADC)
            self.light_sensor = ADC(Pin(36))
            self.light_sensor.atten(ADC.ATTN_11DB)
            
            # 热敏电阻 (ADC)
            self.thermistor = ADC(Pin(39))
            self.thermistor.atten(ADC.ATTN_11DB)
            
        except Exception as e:
            # print(f"传感器初始化失败: {e}")
            self.light_sensor = None
            self.thermistor = None
    
    def _init_ports(self):
        """初始化通用IO端口"""
        try:
            self.ports = {
                'port1': Pin(33, Pin.OUT),
                'port2': Pin(32, Pin.OUT),
                'port3': Pin(26, Pin.OUT),
                'port4': Pin(25, Pin.OUT)
            }
            
            # 初始化所有端口为低电平
            for port in self.ports.values():
                port.value(0)
                
        except Exception as e:
            # print(f"通用端口初始化失败: {e}")
            self.ports = {}
    
    def _init_motor(self):
        """初始化电机驱动"""
        try:
            # 初始化I2C用于电机驱动
            self.i2c = I2C(0, scl=Pin(15), sda=Pin(21), freq=100000)
            self.motor_address = 0x40
            
            # 检查I2C设备
            devices = self.i2c.scan()
            
            if self.motor_address in devices:
                self.motor_available = True
                # 初始化时停止所有电机
                self.motor_stop("ALL")
            else:
                self.motor_available = False
                
        except Exception as e:
            # print(f"电机驱动初始化失败: {e}")
            self.motor_available = False
    
    def _init_sd_card(self):
        """初始化SD卡"""
        try:
            # 初始化SPI2用于SD卡
            self.spi_sd = SPI(2, baudrate=1000000, sck=Pin(18), mosi=Pin(23), miso=Pin(19))
            self.sd_cs = Pin(22, Pin.OUT)
            self.sd_cs.value(1)  # 初始不选中
            
            self.sd_available = True
            
        except Exception as e:
            # print(f"SD卡初始化失败: {e}")
            self.sd_available = False

    # ===== 电机控制方法 =====
    def speed_to_bytes(self, speed):
        """将速度值(0-255)转换为两个字节"""
        if speed < 0 or speed > 255:
            speed = 0
        
        speed_16bit = speed * 16
        sdB = speed_16bit // 256      # 高字节
        sdA = speed_16bit % 256       # 低字节
        return sdA, sdB

    def send_motor_command(self, cmd_byte, sdA, sdB, direction):
        """发送电机控制命令"""
        if not self.motor_available:
            return
            
        try:
            if direction == "CW":  # 顺时针/前进
                data_sequence = [cmd_byte, 0, 0, sdA, sdB, 0, 0, 0, 0]
            elif direction == "CCW":  # 逆时针/后退
                data_sequence = [cmd_byte, 0, 0, 0, 0, 0, 0, sdA, sdB]
            else:  # 停止
                data_sequence = [cmd_byte, 0, 0, 0, 0, 0, 0, 0, 0]
            
            self.i2c.writeto(self.motor_address, bytes(data_sequence))
        except Exception as e:
            pass

    def motor_run(self, motor, direction, speed):
        """
        控制电机运行
        :param motor: 1=电机1, 2=电机2, "ALL"=所有电机
        :param direction: "CW"=顺时针/前进, "CCW"=逆时针/后退
        :param speed: 速度值 0-255
        """
        if not self.motor_available:
            return
            
        sdA, sdB = self.speed_to_bytes(speed)
        
        # 电机命令字节映射
        motor_cmds = {1: 14, 2: 6, "ALL": 0}
        
        if motor == "ALL":
            # 控制所有电机
            self.send_motor_command(motor_cmds[1], sdA, sdB, direction)
            self.send_motor_command(motor_cmds[2], sdA, sdB, direction)
        else:
            # 控制单个电机
            if motor in motor_cmds:
                self.send_motor_command(motor_cmds[motor], sdA, sdB, direction)

    def motor_stop(self, motor):
        """
        停止电机
        :param motor: 1=电机1, 2=电机2, "ALL"=所有电机
        """
        if motor == "ALL":
            # 停止所有电机
            self.send_motor_command(14, 0, 0, "stop")
            self.send_motor_command(6, 0, 0, "stop")
        else:
            # 停止单个电机
            motor_cmds = {1: 14, 2: 6}
            if motor in motor_cmds:
                self.send_motor_command(motor_cmds[motor], 0, 0, "stop")

    # ===== 传感器读取方法 =====
    def light(self):
        """读取光照强度 (0-4095)"""
        if self.light_sensor:
            try:
                return self.light_sensor.read()
            except:
                return 0
        return 0
    
    def temp_raw(self):
        """读取温度传感器原始ADC值"""
        if self.thermistor:
            try:
                return self.thermistor.read()
            except:
                return 0
        return 0

    def temp_c(self):
        """读取转换后的温度值（摄氏度）"""
        # 获取原始ADC值
        adc_value = self.temp_raw()
        
        if adc_value == 0:
            return 0
        
        try:
            # 计算电压值 (ESP32 ADC范围0-4095对应0-3.3V)
            voltage = adc_value * 3.3 / 4095
            
            # 假设使用10k NTC热敏电阻，串联10k电阻分压
            resistance = 10000 * voltage / (3.3 - voltage)
            
            # Steinhart-Hart方程简化版 (B=3950, R0=10k @ 25°C)
            temp_k = 1 / (1/298.15 + 1/3950.0 * math.log(resistance / 10000))
            
            # 转换为摄氏度
            return temp_k - 273.15
        except:
            return 0

    # ===== 端口控制方法 =====
    def port(self, port_num, state=None):
        """
        设置或获取端口状态
        :param port_num: 端口号 (1-4)
        :param state: 设置状态 (True/False)，不传则获取状态
        :return: 如果获取状态，返回当前状态
        """
        port_key = f'port{port_num}'
        if port_key in self.ports:
            try:
                if state is not None:
                    self.ports[port_key].value(1 if state else 0)
                else:
                    return self.ports[port_key].value()
            except:
                return 0
        return 0

# 创建全局驱动实例
drivers = HardwareDrivers()

# ===== 简化访问函数 =====
def motor_run(motor, direction, speed):
    """运行电机"""
    drivers.motor_run(motor, direction, speed)

def motor_stop(motor):
    """停止电机"""
    drivers.motor_stop(motor)

def port(port_num, state=None):
    """设置或获取端口状态"""
    return drivers.port(port_num, state)

def light():
    """读取光照强度"""
    return drivers.light()

def temp_raw():
    """读取温度原始值"""
    return drivers.temp_raw()

def temp_c():
    """读取温度摄氏度"""
    return drivers.temp_c()