using System.Net;
using DotNext;
using WebProtocol;

namespace Peripherals.CameraClient;

static class CameraAddr
{
    public const UInt32 BASE = 0x7000_0000;

    public const UInt32 DMA0_START_WRITE_ADDR = BASE + 0x0C;
    public const UInt32 DMA0_END_WRITE_ADDR = BASE + 0x0D;
    public const UInt32 DMA0_CAPTURE_CTRL = BASE + 0x0E; //[0]: on, 1 is on. [8]: reset, 1 is reset.
    public const UInt32 EXPECTED_VH = BASE + 0x0F;
    public const UInt32 CAMERA_POWER = BASE + 0x10; //[0]: rstn, 0 is reset. [8]: power down, 1 is down.
}

public class Camera
{
    private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();

    readonly int timeout = 500;
    readonly int taskID;
    readonly int port;
    readonly string address;
    private IPEndPoint ep;


    const uint CAM_I2C_ADDR = 0x3C;
    const Peripherals.I2cClient.I2cProtocol CAM_PROTO = Peripherals.I2cClient.I2cProtocol.SCCB;
    const byte PLL_MUX = 105;
    const UInt32 FrameAddr = 0x00;

    // 动态分辨率参数
    private UInt16 _currentWidth = 640;
    private UInt16 _currentHeight = 480;
    private UInt32 _currentFrameLength = 640 * 480 * 2 / 4; // RGB565格式，2字节/像素，按4字节对齐


    /// <summary>
    /// 初始化摄像头客户端
    /// </summary>
    /// <param name="address">摄像头设备IP地址</param>
    /// <param name="port">摄像头设备端口</param>
    /// <param name="timeout">超时时间（毫秒）</param>
    public Camera(string address, int port, int timeout = 500)
    {
        if (timeout < 0)
            throw new ArgumentException("Timeout couldn't be negative", nameof(timeout));
        this.address = address;
        this.port = port;
        this.ep = new IPEndPoint(IPAddress.Parse(address), port);
        this.timeout = timeout;
    }

    public async ValueTask<Result<bool>> Init()
    {
        await PowerHardwareCamera(true);
        await SleepHardwareCamera(false);
        // 步骤1: 复位
        var resetResult = await Reset();
        if (!resetResult.IsSuccessful) return resetResult;

        var wakeupResult = await Sleep();
        if (!wakeupResult.IsSuccessful) return wakeupResult;

        // 步骤3: 配置基础寄存器
        var basicResult = await ConfigureBasicRegisters();
        if (!basicResult.IsSuccessful) return basicResult;

        // 步骤4: 配置传感器控制
        var sensorResult = await ConfigureSensorControl();
        if (!sensorResult.IsSuccessful) return sensorResult;

        // 步骤5: 配置模拟控制
        var analogResult = await ConfigureAnalogControl();
        if (!analogResult.IsSuccessful) return analogResult;

        // 步骤6: 配置时钟控制
        var clockResult = await ConfigureClockControl();
        if (!clockResult.IsSuccessful) return clockResult;

        // 步骤7: 配置PSRAM控制
        var psramResult = await ConfigurePSRAMControl();
        if (!psramResult.IsSuccessful) return psramResult;

        // 步骤8: 配置DVP时序
        var dvpResult = await ConfigureDVPTiming();
        if (!dvpResult.IsSuccessful) return dvpResult;

        // 步骤9: 配置基础控制
        var baseResult = await ConfigureBaseControl();
        if (!baseResult.IsSuccessful) return baseResult;

        // 步骤10: 配置图像格式
        var formatResult = await ConfigureImageFormat();
        if (!formatResult.IsSuccessful) return formatResult;

        // 步骤11: 配置ISP控制
        var ispResult = await ConfigureISPControl();
        if (!ispResult.IsSuccessful) return ispResult;

        // 步骤12: 配置AEC
        var aecResult = await ConfigureAEC();
        if (!aecResult.IsSuccessful) return aecResult;

        // 步骤13: 配置LENC
        var lencResult = await ConfigureLENC();
        if (!lencResult.IsSuccessful) return lencResult;

        // 步骤14: 配置AWB
        var awbResult = await ConfigureAWB();
        if (!awbResult.IsSuccessful) return awbResult;

        // 步骤15: 配置Gamma
        var gammaResult = await ConfigureGamma();
        if (!gammaResult.IsSuccessful) return gammaResult;

        // 步骤16: 配置CMX
        var cmxResult = await ConfigureCMX();
        if (!cmxResult.IsSuccessful) return cmxResult;

        // 步骤17: 配置SDE
        var sdeResult = await ConfigureSDE();
        if (!sdeResult.IsSuccessful) return sdeResult;

        // 步骤18: 配置CIP
        var cipResult = await ConfigureCIP();
        if (!cipResult.IsSuccessful) return cipResult;

        // 步骤19: 配置时序控制
        var timingResult = await ConfigureTimingControl();
        if (!timingResult.IsSuccessful) return timingResult;

        // 步骤20: 配置测试和闪光灯
        var testResult = await ConfigureTestAndFlash();
        if (!testResult.IsSuccessful) return testResult;

        // 步骤21: 配置分辨率（默认640x480）
        var resolutionResult = await ConfigureResolution640x480();
        // var resolutionResult = await ConfigureResolution1280x720();
        if (!resolutionResult.IsSuccessful) return resolutionResult;

        // var autofocusResult = await InitAutoFocus();
        // if (!autofocusResult.IsSuccessful) return autofocusResult;

        var startResult = await WakeUp();
        if (!startResult.IsSuccessful) return startResult;
        // var sleepResult = await Sleep();
        // if (!sleepResult.IsSuccessful) return sleepResult;
        // var resetResult2 = await Reset();
        // if (!resetResult2.IsSuccessful) return resetResult2;

        return true;
    }

    public async ValueTask<Result<bool>> EnableHardwareTrans(bool isEnable)
    {
        var ret = await UDPClientPool.WriteAddr(this.ep, this.taskID, CameraAddr.DMA0_CAPTURE_CTRL, (isEnable ? 0x00000001u : 0x00000100u));
        if (!ret.IsSuccessful)
        {
            logger.Error($"Failed to write CAPTURE_ON to camera at {this.address}:{this.port}, error: {ret.Error}");
            return new(ret.Error);
        }
        if (!ret.Value)
        {
            logger.Error($"CAPTURE_ON write returned false for camera at {this.address}:{this.port}");
            return false;
        }
        return true;
    }

    public async ValueTask<Result<bool>> PowerHardwareCamera(bool isEnable)
    {
        {
            var ret = await UDPClientPool.WriteAddr(this.ep, this.taskID, CameraAddr.CAMERA_POWER, (isEnable ? 0x00000001u : 0x00000000u));
            if (!ret.IsSuccessful)
            {
                logger.Error($"Failed to write STORE_ADDR: {ret.Error}");
                return new(ret.Error);
            }
            if (!ret.Value)
            {
                logger.Error("STORE_ADDR write returned false");
                return new(new Exception("STORE_ADDR write returned false"));
            }
        }
        await Task.Delay(5); // 确保硬件状态稳定
        return true;
    }

    public async ValueTask<Result<bool>> SleepHardwareCamera(bool isEnable)
    {
        {
            var ret = await UDPClientPool.WriteAddr(this.ep, this.taskID, CameraAddr.CAMERA_POWER, (isEnable ? 0x00000101u : 0x00000001u));
            if (!ret.IsSuccessful)
            {
                logger.Error($"Failed to write STORE_ADDR: {ret.Error}");
                return new(ret.Error);
            }
            if (!ret.Value)
            {
                logger.Error("STORE_ADDR write returned false");
                return new(new Exception("STORE_ADDR write returned false"));
            }
        }
        await Task.Delay(5);
        return true;
    }

    /// <summary>
    /// 读取一帧图像数据
    /// </summary>
    /// <returns>包含图像数据的字节数组</returns>
    public async ValueTask<Result<byte[]>> ReadFrame()
    {
        // 只在第一次或出错时清除UDP缓冲区，避免每帧都清除造成延迟
        // MsgBus.UDPServer.ClearUDPData(this.address, this.taskID);

        logger.Trace($"Reading frame from camera {this.address}");

        // 使用UDPClientPool读取图像帧数据
        var result = await UDPClientPool.ReadAddr4BytesAsync(
            this.ep,
            this.taskID, // taskID
            FrameAddr,
            (int)_currentFrameLength, // 使用当前分辨率的动态大小
            BurstType.ExtendBurst,
            this.timeout);

        if (!result.IsSuccessful)
        {
            logger.Error($"Failed to read frame from camera {this.address}:{this.port}, error: {result.Error}");
            // 读取失败时清除缓冲区，为下次读取做准备
            try
            {
                MsgBus.UDPServer.ClearUDPData(this.address, this.taskID);
            }
            catch (Exception ex)
            {
                logger.Warn($"Failed to clear UDP data after read error: {ex.Message}");
            }
            return new(result.Error);
        }

        logger.Trace($"Successfully read frame from camera {this.address}:{this.port}, data length: {result.Value.Length} bytes");
        return result.Value;
    }

    /// <summary>
    /// 批量配置I2C寄存器
    /// </summary>
    /// <param name="registerTable">寄存器配置表，每个元素格式为：[16位寄存器地址, 数据1, 数据2, ...]，数据按地址递增写入</param>
    /// <param name="customDelayMs">自定义延时时间（毫秒），如果为null则使用默认延时逻辑</param>
    /// <returns>配置结果</returns>
    public async ValueTask<Result<bool>> ConfigureRegisters(UInt16[][] registerTable, int? customDelayMs = null)
    {
        MsgBus.UDPServer.ClearUDPData(this.address, this.taskID);

        var i2c = new Peripherals.I2cClient.I2c(this.address, this.port, this.taskID, this.timeout);

        foreach (var cmd in registerTable)
        {
            if (cmd.Length < 2)
            {
                logger.Error($"Invalid register command length: {cmd.Length}, expected at least 2 elements (address + data)");
                return new(new ArgumentException($"Invalid register command length: {cmd.Length}, expected at least 2 elements"));
            }

            var baseAddress = cmd[0];
            logger.Debug($"ConfigureRegisters: 配置寄存器组，基地址=0x{baseAddress:X4}, 数据数量={cmd.Length - 1}");

            // 为每个数据字节单独写入到连续地址
            for (int i = 1; i < cmd.Length; i++)
            {
                var currentAddress = (UInt16)(baseAddress + i - 1);
                var data = (byte)cmd[i];

                logger.Debug($"ConfigureRegisters: 写入地址=0x{currentAddress:X4}, 数据=0x{data:X2}");

                // 准备I2C数据：16位地址 + 8位数据
                var i2cData = new byte[3];
                i2cData[0] = (byte)(currentAddress >> 8);    // 地址高位
                i2cData[1] = (byte)(currentAddress & 0xFF);  // 地址低位
                i2cData[2] = data;                           // 数据

                var ret = await i2c.WriteData(CAM_I2C_ADDR, i2cData, CAM_PROTO);

                if (!ret.IsSuccessful)
                {
                    logger.Error($"I2C write 0x{CAM_I2C_ADDR:X} failed: Address=0x{currentAddress:X4}, Data=0x{data:X2}, error: {ret.Error}");
                    return new(ret.Error);
                }

                if (!ret.Value)
                {
                    logger.Error($"I2C write 0x{CAM_I2C_ADDR:X} returned false: Address=0x{currentAddress:X4}, Data=0x{data:X2}");
                    return false;
                }

                // 处理延时逻辑
                if (customDelayMs.HasValue)
                {
                    await Task.Delay(customDelayMs.Value);
                }
                else
                {
                    await Task.Delay(1); // 1ms延时
                }
            }
        }

        return true;
    }

    /// <summary>
    /// 读取I2C寄存器字节值
    /// </summary>
    /// <param name="register">要读取的寄存器地址 (16位)</param>
    /// <returns>ret</returns>
    public async ValueTask<Result<byte>> ReadRegister(UInt16 register)
    {
        var i2c = new Peripherals.I2cClient.I2c(this.address, this.port, this.taskID, this.timeout);

        // Convert 16-bit register address to byte array
        var registerBytes = new byte[] { (byte)(register >> 8), (byte)(register & 0xFF) };

        var ret = await i2c.ReadData(CAM_I2C_ADDR, registerBytes, 1, CAM_PROTO);
        if (!ret.IsSuccessful)
            return new(ret.Error);

        return new Result<byte>(ret.Value[0]);
    }

    /// <summary>
    /// 配置摄像头分辨率和相关参数
    /// </summary>
    /// <param name="hStart">水平起始位置</param>
    /// <param name="vStart">垂直起始位置</param>
    /// <param name="dvpHo">输出水平像素数</param>
    /// <param name="dvpVo">输出垂直像素数</param>
    /// <param name="hts">水平总像素数</param>
    /// <param name="vts">垂直总像素数</param>
    /// <param name="hOffset">水平偏移</param>
    /// <param name="vOffset">垂直偏移</param>
    /// <param name="hWindow">水平窗口大小（默认1500）</param>
    /// <param name="vWindow">垂直窗口大小（默认1300）</param>
    /// <returns>配置结果</returns>
    public async ValueTask<Result<bool>> ConfigureResolution(
        UInt16 hStart, UInt16 vStart,
        UInt16 dvpHo, UInt16 dvpVo,
        UInt16 hts, UInt16 vts,
        UInt16 hOffset, UInt16 vOffset,
        UInt16 hWindow = 1500, UInt16 vWindow = 1300)
    {
        // 计算结束位置
        UInt16 hEnd = (UInt16)(hStart + hWindow - 1);
        UInt16 vEnd = (UInt16)(vStart + vWindow - 1);

        // 计算帧长度
        UInt32 frameLength = (UInt32)(dvpHo * dvpVo * 16 / 32);

        // 1. 配置UDP相关寄存器
        {
            var ret = await UDPClientPool.WriteAddr(this.ep, this.taskID, CameraAddr.DMA0_START_WRITE_ADDR, FrameAddr);
            if (!ret.IsSuccessful)
            {
                logger.Error($"Failed to write STORE_ADDR: {ret.Error}");
                return new(ret.Error);
            }
            if (!ret.Value)
            {
                logger.Error("STORE_ADDR write returned false");
                return new(new Exception("STORE_ADDR write returned false"));
            }
        }

        {
            var ret = await UDPClientPool.WriteAddr(this.ep, this.taskID, CameraAddr.DMA0_END_WRITE_ADDR, FrameAddr + frameLength - 1);
            if (!ret.IsSuccessful)
            {
                logger.Error($"Failed to write STORE_NUM: {ret.Error}");
                return new(ret.Error);
            }
            if (!ret.Value)
            {
                logger.Error("STORE_NUM write returned false");
                return new(new Exception("STORE_NUM write returned false"));
            }
        }

        {
            var ret = await UDPClientPool.WriteAddr(this.ep, this.taskID, CameraAddr.EXPECTED_VH, ((uint)dvpVo) << 16 | ((uint)dvpHo * 2));
            if (!ret.IsSuccessful)
            {
                logger.Error($"Failed to write EXPECTED_VH: {ret.Error}");
                return new(ret.Error);
            }
            if (!ret.Value)
            {
                logger.Error("EXPECTED_VH write returned false");
                return new(new Exception("EXPECTED_VH write returned false"));
            }
        }

        // 2. 配置I2C寄存器
        var resolutionRegisters = new UInt16[][]
        {
            // H_START/V_START
            [0x3800, unchecked((byte)((hStart >> 8) & 0xFF))],
            [0x3801, unchecked((byte)(hStart & 0xFF))],
            [0x3802, unchecked((byte)((vStart >> 8) & 0xFF))],
            [0x3803, unchecked((byte)(vStart & 0xFF))],

            // H_END/V_END
            [0x3804, unchecked((byte)((hEnd >> 8) & 0xFF))],
            [0x3805, unchecked((byte)(hEnd & 0xFF))],
            [0x3806, unchecked((byte)((vEnd >> 8) & 0xFF))],
            [0x3807, unchecked((byte)(vEnd & 0xFF))],

            // 输出像素个数
            [0x3808, unchecked((byte)((dvpHo >> 8) & 0xFF))],
            [0x3809, unchecked((byte)(dvpHo & 0xFF))],
            [0x380A, unchecked((byte)((dvpVo >> 8) & 0xFF))],
            [0x380B, unchecked((byte)(dvpVo & 0xFF))],

            // 总像素
            [0x380C, unchecked((byte)((hts >> 8) & 0xFF))],
            [0x380D, unchecked((byte)(hts & 0xFF))],
            [0x380E, unchecked((byte)((vts >> 8) & 0xFF))],
            [0x380F, unchecked((byte)(vts & 0xFF))],

            // H_OFFSET/V_OFFSET
            [0x3810, unchecked((byte)((hOffset >> 8) & 0xFF))],
            [0x3811, unchecked((byte)(hOffset & 0xFF))],
            [0x3812, unchecked((byte)((vOffset >> 8) & 0xFF))],
            // Timing Voffset
            [0x3813, unchecked((byte)(vOffset & 0xFF))]
        };

        var configResult = await ConfigureRegisters(resolutionRegisters, customDelayMs: 1);
        if (!configResult.IsSuccessful)
        {
            logger.Error($"Failed to configure resolution registers: {configResult.Error}");
            return configResult;
        }

        logger.Info($"Successfully configured resolution: {dvpHo}x{dvpVo}, HTS={hts}, VTS={vts}");
        return true;
    }

    /// <summary>
    /// 配置为640x480分辨率（默认配置）
    /// </summary>
    /// <returns>配置结果</returns>
    public async ValueTask<Result<bool>> ConfigureResolution640x480()
    {
        return await ConfigureResolution(
            hStart: 0, vStart: 0,
            dvpHo: 640, dvpVo: 480,
            hts: 1700, vts: 1500,
            hOffset: 16, vOffset: 4
        );
    }

    /// <summary>
    /// 配置为960x540分辨率
    /// </summary>
    /// <returns>配置结果</returns>
    public async ValueTask<Result<bool>> ConfigureResolution960x540()
    {
        return await ConfigureResolution(
            hStart: 0, vStart: 0,
            dvpHo: 960, dvpVo: 540,
            hts: 1700, vts: 1500,
            hOffset: 16, vOffset: 4
        );
    }

    /// <summary>
    /// 配置为320x240分辨率
    /// </summary>
    /// <returns>配置结果</returns>
    public async ValueTask<Result<bool>> ConfigureResolution320x240()
    {
        return await ConfigureResolution(
            hStart: 0, vStart: 0,
            dvpHo: 320, dvpVo: 240,
            hts: 850, vts: 750,
            hOffset: 16, vOffset: 4,
            hWindow: 750, vWindow: 650
        );
    }

    /// <summary>
    /// 配置为1280x720分辨率
    /// </summary>
    /// <returns>配置结果</returns>
    public async ValueTask<Result<bool>> ConfigureResolution1280x720()
    {
        return await ConfigureResolution(
            hStart: 0, vStart: 250,
            dvpHo: 1280, dvpVo: 720,
            hts: 2844, vts: 1968,
            hOffset: 16, vOffset: 4,
            hWindow: 2624, vWindow: 1456
        );
    }

    /// <summary>
    /// 配置为1280x720分辨率
    /// </summary>
    /// <returns>配置结果</returns>
    public async ValueTask<Result<bool>> ConfigureResolution1280x960()
    {
        return await ConfigureResolution(
            hStart: 0, vStart: 250,
            dvpHo: 1280, dvpVo: 960,
            hts: 2844, vts: 1968,
            hOffset: 16, vOffset: 4,
            hWindow: 2624, vWindow: 1456
        );

    }

    /// <summary>
    /// 配置为1920x1080分辨率
    /// </summary>
    /// <returns>配置结果</returns>
    public async ValueTask<Result<bool>> ConfigureResolution1920x1080()
    {
        return await ConfigureResolution(
            hStart: 0, vStart: 250,
            dvpHo: 1920, dvpVo: 1080,
            hts: 2844, vts: 1968,
            hOffset: 16, vOffset: 4,
            hWindow: 2624, vWindow: 1456
        );

    }

    /// <summary>
    /// 切换摄像头分辨率
    /// </summary>
    /// <param name="width">宽度</param>
    /// <param name="height">高度</param>
    /// <returns>配置结果</returns>
    public async ValueTask<Result<bool>> ChangeResolution(int width, int height)
    {
        try
        {
            // await WakeUp();
            logger.Info($"正在切换摄像头分辨率到 {width}x{height}");

            Result<bool> result;
            switch ($"{width}x{height}")
            {
                case "640x480":
                    result = await ConfigureResolution640x480();
                    break;
                case "960x540":
                    result = await ConfigureResolution960x540();
                    break;
                case "1280x720":
                    result = await ConfigureResolution1280x720();
                    break;
                case "1280x960":
                    result = await ConfigureResolution1280x960();
                    break;
                case "1920x1080":
                    result = await ConfigureResolution1920x1080();
                    break;
                default:
                    logger.Error($"不支持的分辨率: {width}x{height}");
                    return new(new ArgumentException($"不支持的分辨率: {width}x{height}"));
            }

            if (result.IsSuccessful)
            {
                _currentWidth = (UInt16)width;
                _currentHeight = (UInt16)height;
                _currentFrameLength = (UInt32)(width * height * 2 / 4); // RGB565格式，按4字节对齐
                logger.Info($"摄像头分辨率已切换到 {width}x{height}");
            }
            // await Sleep();
            return result;
        }
        catch (Exception ex)
        {
            logger.Error(ex, $"切换分辨率到 {width}x{height} 时发生错误");
            return new(ex);
        }
    }

    /// <summary>
    /// 获取当前分辨率
    /// </summary>
    /// <returns>当前分辨率(宽度, 高度)</returns>
    public (int Width, int Height) GetCurrentResolution()
    {
        return (_currentWidth, _currentHeight);
    }

    /// <summary>
    /// 获取当前帧长度
    /// </summary>
    /// <returns>当前帧长度</returns>
    public UInt32 GetCurrentFrameLength()
    {
        return _currentFrameLength;
    }

    /// <summary>
    /// 复位摄像头
    /// </summary>
    /// <returns>配置结果</returns>
    public async ValueTask<Result<bool>> Reset()
    {
        var resetRegisters = new UInt16[][]
        {
            [0x3103, 0x11],// system clock from pad, bit[1]
            [0x3008, 0x82] // 复位命令
        };

        return await ConfigureRegisters(resetRegisters, customDelayMs: 50); // 复位后等待5ms
    }

    /// <summary>
    /// 设置摄像头为休眠模式
    /// </summary>
    /// <returns>配置结果</returns>
    public async ValueTask<Result<bool>> Sleep()
    {
        var sleepRegisters = new UInt16[][]
        {
            [0x3008, 0x42] // 休眠命令
        };

        return await ConfigureRegisters(sleepRegisters, customDelayMs: 50);
    }

    /// <summary>
    /// 配置基础寄存器
    /// </summary>
    /// <returns>配置结果</returns>
    public async ValueTask<Result<bool>> ConfigureBasicRegisters()
    {
        var basicRegisters = new UInt16[][]
        {
            [0x3103, 0x03], // system clock from pad, bit[1] //02
            [0x3017, 0xff],
            [0x3018, 0xff],
            [0x3037, 0x13],
            [0x3108, 0x01]
        };

        return await ConfigureRegisters(basicRegisters);
    }

    /// <summary>
    /// 配置传感器控制寄存器
    /// </summary>
    /// <returns>配置结果</returns>
    public async ValueTask<Result<bool>> ConfigureSensorControl()
    {
        var sensorRegisters = new UInt16[][]
        {
            [0x3630, 0x36],
            [0x3631, 0x0e],
            [0x3632, 0xe2],
            [0x3633, 0x12],
            [0x3621, 0xe0]
        };

        return await ConfigureRegisters(sensorRegisters);
    }

    /// <summary>
    /// 配置模拟控制寄存器
    /// </summary>
    /// <returns>配置结果</returns>
    public async ValueTask<Result<bool>> ConfigureAnalogControl()
    {
        var analogRegisters = new UInt16[][]
        {
            [0x3704, 0xa0],
            [0x3703, 0x5a],
            [0x3715, 0x78],
            [0x3717, 0x01],
            [0x370b, 0x60],
            [0x3705, 0x1a]
        };

        return await ConfigureRegisters(analogRegisters);
    }

    /// <summary>
    /// 配置时钟控制寄存器
    /// </summary>
    /// <returns>配置结果</returns>
    public async ValueTask<Result<bool>> ConfigureClockControl()
    {
        var clockRegisters = new UInt16[][]
        {
            [0x3905, 0x02],
            [0x3906, 0x10],
            [0x3901, 0x0a]
        };

        return await ConfigureRegisters(clockRegisters);
    }

    /// <summary>
    /// 配置PSRAM控制寄存器
    /// </summary>
    /// <returns>配置结果</returns>
    public async ValueTask<Result<bool>> ConfigurePSRAMControl()
    {
        var psramRegisters = new UInt16[][]
        {
            [0x3731, 0x12],
            [0x3600, 0x08],
            [0x3601, 0x33],
            [0x302d, 0x60],
            [0x3620, 0x52],
            [0x371b, 0x20],
            [0x471c, 0x50]
        };

        return await ConfigureRegisters(psramRegisters);
    }

    /// <summary>
    /// 配置DVP时序寄存器
    /// </summary>
    /// <returns>配置结果</returns>
    public async ValueTask<Result<bool>> ConfigureDVPTiming()
    {
        var dvpRegisters = new UInt16[][]
        {
            [0x3a13, 0x43],
            [0x3a18, 0x00],
            [0x3a19, 0xf8],
            [0x3635, 0x13],
            [0x3636, 0x03],
            [0x3634, 0x40],
            [0x3622, 0x01]
        };

        return await ConfigureRegisters(dvpRegisters);
    }

    /// <summary>
    /// 配置基础控制寄存器
    /// </summary>
    /// <returns>配置结果</returns>
    public async ValueTask<Result<bool>> ConfigureBaseControl()
    {
        var baseRegisters = new UInt16[][]
        {
            [0x3c01, 0x34],
            [0x3c04, 0x28],
            [0x3c05, 0x98],
            [0x3c06, 0x00],
            [0x3c07, 0x07],
            [0x3c08, 0x00],
            [0x3c09, 0x1c],
            [0x3c0a, 0x9c],
            [0x3c0b, 0x40],
            [0x3708, 0x64]
        };

        return await ConfigureRegisters(baseRegisters);
    }

    /// <summary>
    /// 配置图像格式寄存器
    /// </summary>
    /// <returns>配置结果</returns>
    public async ValueTask<Result<bool>> ConfigureImageFormat()
    {
        var formatRegisters = new UInt16[][]
        {
            [0x4001, 0x02],
            [0x4005, 0x1a],
            [0x3000, 0x00],
            [0x3004, 0xff],
            [0x4300, 0x6F], // RGB565:first byte:{g[2:0],b[4:0]],second byte:{r[4:0],g[5:3]}
            [0x501f, 0x01], // Format: ISP RGB
            [0x440e, 0x00]
        };

        return await ConfigureRegisters(formatRegisters);
    }

    /// <summary>
    /// 配置ISP控制寄存器
    /// </summary>
    /// <returns>配置结果</returns>
    public async ValueTask<Result<bool>> ConfigureISPControl()
    {
        var ispRegisters = new UInt16[][]
        {
            [0x5000, 0xA7], // ISP控制
            [0x5001, 0xA3]  // ISP控制
        };

        return await ConfigureRegisters(ispRegisters);
    }

    /// <summary>
    /// 配置AEC（自动曝光控制）寄存器
    /// </summary>
    /// <returns>配置结果</returns>
    public async ValueTask<Result<bool>> ConfigureAEC()
    {
        var aecRegisters = new UInt16[][]
        {
            [0x3a0f, 0x30], // AEC控制;stable range in high     //78
            [0x3a10, 0x28], // AEC控制;stable range in low      //68
            [0x3a1b, 0x30], // AEC控制;stable range out high        //78
            [0x3a1e, 0x26], // AEC控制;stable range out low     //68
            [0x3a11, 0x60], // AEC控制; fast zone high      //D0
            [0x3a1f, 0x14], // AEC控制; fast zone low       //40
            [0x3b07, 0x0a]  // 帧曝光模式
        };

        return await ConfigureRegisters(aecRegisters);
    }

    /// <summary>
    /// 配置LENC（镜头校正）寄存器
    /// </summary>
    /// <returns>配置结果</returns>
    public async ValueTask<Result<bool>> ConfigureLENC()
    {
        var lencRegisters = new UInt16[][]
        {
            [0x5800, 0x23], [0x5801, 0x14], [0x5802, 0x0f],
            [0x5803, 0x0f], [0x5804, 0x12], [0x5805, 0x26],
            [0x5806, 0x0c], [0x5807, 0x08], [0x5808, 0x05],
            [0x5809, 0x05], [0x580a, 0x08], [0x580b, 0x0d],
            [0x580c, 0x08], [0x580d, 0x03], [0x580e, 0x00],
            [0x580f, 0x00], [0x5810, 0x03], [0x5811, 0x09],
            [0x5812, 0x07], [0x5813, 0x03], [0x5814, 0x00],
            [0x5815, 0x01], [0x5816, 0x03], [0x5817, 0x08],
            [0x5818, 0x0d], [0x5819, 0x08], [0x581a, 0x05],
            [0x581b, 0x06], [0x581c, 0x08], [0x581d, 0x0e],
            [0x581e, 0x29], [0x581f, 0x17], [0x5820, 0x11],
            [0x5821, 0x11], [0x5822, 0x15], [0x5823, 0x28],
            [0x5824, 0x46], [0x5825, 0x26], [0x5826, 0x08],
            [0x5827, 0x26], [0x5828, 0x64], [0x5829, 0x26],
            [0x582a, 0x24], [0x582b, 0x22], [0x582c, 0x24],
            [0x582d, 0x24], [0x582e, 0x06], [0x582f, 0x22],
            [0x5830, 0x40], [0x5831, 0x42], [0x5832, 0x24],
            [0x5833, 0x26], [0x5834, 0x24], [0x5835, 0x22],
            [0x5836, 0x22], [0x5837, 0x26], [0x5838, 0x44],
            [0x5839, 0x24], [0x583a, 0x26], [0x583b, 0x28],
            [0x583c, 0x42], [0x583d, 0xce]
        };

        return await ConfigureRegisters(lencRegisters);
    }

    /// <summary>
    /// 配置摄像头AWB（自动白平衡）寄存器
    /// </summary>
    /// <returns>配置结果</returns>
    public async ValueTask<Result<bool>> ConfigureAWB()
    {
        var awbRegisters = new UInt16[][]
        {
            [0x5180, 0xff], [0x5181, 0xf2], [0x5182, 0x00],
            [0x5183, 0x14], [0x5184, 0x25], [0x5185, 0x24],
            [0x5186, 0x09], [0x5187, 0x09], [0x5188, 0x09],
            [0x5189, 0x75], [0x518a, 0x54], [0x518b, 0xe0],
            [0x518c, 0xb2], [0x518d, 0x42], [0x518e, 0x3d],
            [0x518f, 0x56], [0x5190, 0x46], [0x5191, 0xf8],
            [0x5192, 0x04], [0x5193, 0x70], [0x5194, 0xf0],
            [0x5195, 0xf0], [0x5196, 0x03], [0x5197, 0x01],
            [0x5198, 0x04], [0x5199, 0x12], [0x519a, 0x04],
            [0x519b, 0x00], [0x519c, 0x06], [0x519d, 0x82],
            [0x519e, 0x38]
        };

        return await ConfigureRegisters(awbRegisters, customDelayMs: 2);
    }

    /// <summary>
    /// 配置摄像头Gamma校正寄存器
    /// </summary>
    /// <returns>配置结果</returns>
    public async ValueTask<Result<bool>> ConfigureGamma()
    {
        var gammaRegisters = new UInt16[][]
        {
            [0x5480, 0x01], [0x5481, 0x08], [0x5482, 0x14],
            [0x5483, 0x28], [0x5484, 0x51], [0x5485, 0x65],
            [0x5486, 0x71], [0x5487, 0x7d], [0x5488, 0x87],
            [0x5489, 0x91], [0x548a, 0x9a], [0x548b, 0xaa],
            [0x548c, 0xb8], [0x548d, 0xcd], [0x548e, 0xdd],
            [0x548f, 0xea], [0x5490, 0x1d]
        };

        return await ConfigureRegisters(gammaRegisters);
    }


    /// <summary>
    /// 配置CMX（色彩矩阵）寄存器
    /// </summary>
    /// <returns>配置结果</returns>
    public async ValueTask<Result<bool>> ConfigureCMX()
    {
        var cmxRegisters = new UInt16[][]
        {
            [0x5381, 0x1e], [0x5382, 0x5b], [0x5383, 0x08],
            [0x5384, 0x0a], [0x5385, 0x7e], [0x5386, 0x88],
            [0x5387, 0x7c], [0x5388, 0x6c], [0x5389, 0x10],
            [0x538a, 0x01], [0x538b, 0x98]
        };

        return await ConfigureRegisters(cmxRegisters);
    }

    /// <summary>
    /// 配置SDE（特殊数字效果）寄存器
    /// </summary>
    /// <returns>配置结果</returns>
    public async ValueTask<Result<bool>> ConfigureSDE()
    {
        var sdeRegisters = new UInt16[][]
        {
            [0x5580, 0x06], [0x5583, 0x40], [0x5584, 0x10],
            [0x5589, 0x10], [0x558a, 0x00], [0x558b, 0xf8],
            [0x501d, 0x40]
        };

        return await ConfigureRegisters(sdeRegisters);
    }

    /// <summary>
    /// 配置CIP（颜色插值处理）寄存器
    /// </summary>
    /// <returns>配置结果</returns>
    public async ValueTask<Result<bool>> ConfigureCIP()
    {
        var cipRegisters = new UInt16[][]
        {
            [0x5300, 0x08], [0x5301, 0x30], [0x5302, 0x10],
            [0x5303, 0x00], [0x5304, 0x08], [0x5305, 0x30],
            [0x5306, 0x08], [0x5307, 0x16], [0x5309, 0x08],
            [0x530a, 0x30], [0x530b, 0x04], [0x530c, 0x06],
            [0x5025, 0x00]
        };

        return await ConfigureRegisters(cipRegisters);
    }

    /// <summary>
    /// 配置时序控制寄存器
    /// </summary>
    /// <returns>配置结果</returns>
    public async ValueTask<Result<bool>> ConfigureTimingControl()
    {
        var timingRegisters = new UInt16[][]
        {
            [0x3035, 0x21], // 60fps
            [0x3036, PLL_MUX],// PLL倍频
            [0x3c07, 0x08],
            [0x3820, 0x40], // vflip
            [0x3821, 0x01], // mirror
            [0x3814, 0x11], // timing X inc
            [0x3815, 0x11]  // timing Y inc
        };

        return await ConfigureRegisters(timingRegisters);
    }

    /// <summary>
    /// 配置测试模式和闪光灯寄存器
    /// </summary>
    /// <returns>配置结果</returns>
    public async ValueTask<Result<bool>> ConfigureTestAndFlash()
    {
        var testRegisters = new UInt16[][]
        {
            [0x3618, 0x00],
            [0x3612, 0x29],
            [0x3709, 0x52],
            [0x370c, 0x03],
            [0x4004, 0x02], // BLC(背光) 2 lines
            [0x4713, 0x03], // JPEG mode 3
            [0x4407, 0x04], // 量化标度
            [0x460c, 0x00],
            [0x3a02, 0x17], // 60Hz max exposure
            [0x3a03, 0x10], // 60Hz max exposure
            [0x3a14, 0x17], // 50Hz max exposure
            [0x3a15, 0x10], // 50Hz max exposure
            [0x4837, 0x22], // DVP CLK divider
            [0x3824, 0x02], // DVP CLK divider
            // 彩条测试禁用
            [0x503d, 0x00],
            [0x4741, 0x00],
            // 闪光灯配置
            [0x3016, 0x02],
            [0x301c, 0x02],
            [0x3019, 0x02], // 开启闪光灯
            [0x3019, 0x00]  // 关闭闪光灯
        };

        return await ConfigureRegisters(testRegisters);
    }

    /// <summary>
    /// 开始流媒体传输
    /// </summary>
    /// <returns>配置结果</returns>
    public async ValueTask<Result<bool>> WakeUp()
    {
        var startRegisters = new UInt16[][]
        {
            [0x3008, 0x02] // 开始流
        };

        return await ConfigureRegisters(startRegisters, customDelayMs: 50);
    }

    #region 自动对焦功能

    /// <summary>
    /// OV5640 自动对焦固件数据
    /// </summary>
    private static readonly UInt16[] OV5640_AF_FIRMWARE =
    [
        0x02, 0x0f, 0xd6, 0x02, 0x0a, 0x39, 0xc2, 0x01, 0x22, 0x22, 0x00, 0x02, 0x0f, 0xb2, 0xe5, 0x1f, //0x8000,
        0x70, 0x72, 0xf5, 0x1e, 0xd2, 0x35, 0xff, 0xef, 0x25, 0xe0, 0x24, 0x4e, 0xf8, 0xe4, 0xf6, 0x08, //0x8010,
        0xf6, 0x0f, 0xbf, 0x34, 0xf2, 0x90, 0x0e, 0x93, 0xe4, 0x93, 0xff, 0xe5, 0x4b, 0xc3, 0x9f, 0x50, //0x8020,
        0x04, 0x7f, 0x05, 0x80, 0x02, 0x7f, 0xfb, 0x78, 0xbd, 0xa6, 0x07, 0x12, 0x0f, 0x04, 0x40, 0x04, //0x8030,
        0x7f, 0x03, 0x80, 0x02, 0x7f, 0x30, 0x78, 0xbc, 0xa6, 0x07, 0xe6, 0x18, 0xf6, 0x08, 0xe6, 0x78, //0x8040,
        0xb9, 0xf6, 0x78, 0xbc, 0xe6, 0x78, 0xba, 0xf6, 0x78, 0xbf, 0x76, 0x33, 0xe4, 0x08, 0xf6, 0x78, //0x8050,
        0xb8, 0x76, 0x01, 0x75, 0x4a, 0x02, 0x78, 0xb6, 0xf6, 0x08, 0xf6, 0x74, 0xff, 0x78, 0xc1, 0xf6, //0x8060,
        0x08, 0xf6, 0x75, 0x1f, 0x01, 0x78, 0xbc, 0xe6, 0x75, 0xf0, 0x05, 0xa4, 0xf5, 0x4b, 0x12, 0x0a, //0x8070,
        0xff, 0xc2, 0x37, 0x22, 0x78, 0xb8, 0xe6, 0xd3, 0x94, 0x00, 0x40, 0x02, 0x16, 0x22, 0xe5, 0x1f, //0x8080,
        0xb4, 0x05, 0x23, 0xe4, 0xf5, 0x1f, 0xc2, 0x01, 0x78, 0xb6, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x78, //0x8090,
        0x4e, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0xa2, 0x37, 0xe4, 0x33, 0xf5, 0x3c, 0x90, 0x30, 0x28, 0xf0, //0x80a0,
        0x75, 0x1e, 0x10, 0xd2, 0x35, 0x22, 0xe5, 0x4b, 0x75, 0xf0, 0x05, 0x84, 0x78, 0xbc, 0xf6, 0x90, //0x80b0,
        0x0e, 0x8c, 0xe4, 0x93, 0xff, 0x25, 0xe0, 0x24, 0x0a, 0xf8, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x78, //0x80c0,
        0xbc, 0xe6, 0x25, 0xe0, 0x24, 0x4e, 0xf8, 0xa6, 0x04, 0x08, 0xa6, 0x05, 0xef, 0x12, 0x0f, 0x0b, //0x80d0,
        0xd3, 0x78, 0xb7, 0x96, 0xee, 0x18, 0x96, 0x40, 0x0d, 0x78, 0xbc, 0xe6, 0x78, 0xb9, 0xf6, 0x78, //0x80e0,
        0xb6, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0x90, 0x0e, 0x8c, 0xe4, 0x93, 0x12, 0x0f, 0x0b, 0xc3, 0x78, //0x80f0,
        0xc2, 0x96, 0xee, 0x18, 0x96, 0x50, 0x0d, 0x78, 0xbc, 0xe6, 0x78, 0xba, 0xf6, 0x78, 0xc1, 0xa6, //0x8100,
        0x06, 0x08, 0xa6, 0x07, 0x78, 0xb6, 0xe6, 0xfe, 0x08, 0xe6, 0xc3, 0x78, 0xc2, 0x96, 0xff, 0xee, //0x8110,
        0x18, 0x96, 0x78, 0xc3, 0xf6, 0x08, 0xa6, 0x07, 0x90, 0x0e, 0x95, 0xe4, 0x18, 0x12, 0x0e, 0xe9, //0x8120,
        0x40, 0x02, 0xd2, 0x37, 0x78, 0xbc, 0xe6, 0x08, 0x26, 0x08, 0xf6, 0xe5, 0x1f, 0x64, 0x01, 0x70, //0x8130,
        0x4a, 0xe6, 0xc3, 0x78, 0xc0, 0x12, 0x0e, 0xdf, 0x40, 0x05, 0x12, 0x0e, 0xda, 0x40, 0x39, 0x12, //0x8140,
        0x0f, 0x02, 0x40, 0x04, 0x7f, 0xfe, 0x80, 0x02, 0x7f, 0x02, 0x78, 0xbd, 0xa6, 0x07, 0x78, 0xb9, //0x8150,
        0xe6, 0x24, 0x03, 0x78, 0xbf, 0xf6, 0x78, 0xb9, 0xe6, 0x24, 0xfd, 0x78, 0xc0, 0xf6, 0x12, 0x0f, //0x8160,
        0x02, 0x40, 0x06, 0x78, 0xc0, 0xe6, 0xff, 0x80, 0x04, 0x78, 0xbf, 0xe6, 0xff, 0x78, 0xbe, 0xa6, //0x8170,
        0x07, 0x75, 0x1f, 0x02, 0x78, 0xb8, 0x76, 0x01, 0x02, 0x02, 0x4a, 0xe5, 0x1f, 0x64, 0x02, 0x60, //0x8180,
        0x03, 0x02, 0x02, 0x2a, 0x78, 0xbe, 0xe6, 0xff, 0xc3, 0x78, 0xc0, 0x12, 0x0e, 0xe0, 0x40, 0x08, //0x8190,
        0x12, 0x0e, 0xda, 0x50, 0x03, 0x02, 0x02, 0x28, 0x12, 0x0f, 0x02, 0x40, 0x04, 0x7f, 0xff, 0x80, //0x81a0,
        0x02, 0x7f, 0x01, 0x78, 0xbd, 0xa6, 0x07, 0x78, 0xb9, 0xe6, 0x04, 0x78, 0xbf, 0xf6, 0x78, 0xb9, //0x81b0,
        0xe6, 0x14, 0x78, 0xc0, 0xf6, 0x18, 0x12, 0x0f, 0x04, 0x40, 0x04, 0xe6, 0xff, 0x80, 0x02, 0x7f, //0x81c0,
        0x00, 0x78, 0xbf, 0xa6, 0x07, 0xd3, 0x08, 0xe6, 0x64, 0x80, 0x94, 0x80, 0x40, 0x04, 0xe6, 0xff, //0x81d0,
        0x80, 0x02, 0x7f, 0x00, 0x78, 0xc0, 0xa6, 0x07, 0xc3, 0x18, 0xe6, 0x64, 0x80, 0x94, 0xb3, 0x50, //0x81e0,
        0x04, 0xe6, 0xff, 0x80, 0x02, 0x7f, 0x33, 0x78, 0xbf, 0xa6, 0x07, 0xc3, 0x08, 0xe6, 0x64, 0x80, //0x81f0,
        0x94, 0xb3, 0x50, 0x04, 0xe6, 0xff, 0x80, 0x02, 0x7f, 0x33, 0x78, 0xc0, 0xa6, 0x07, 0x12, 0x0f, //0x8200,
        0x02, 0x40, 0x06, 0x78, 0xc0, 0xe6, 0xff, 0x80, 0x04, 0x78, 0xbf, 0xe6, 0xff, 0x78, 0xbe, 0xa6, //0x8210,
        0x07, 0x75, 0x1f, 0x03, 0x78, 0xb8, 0x76, 0x01, 0x80, 0x20, 0xe5, 0x1f, 0x64, 0x03, 0x70, 0x26, //0x8220,
        0x78, 0xbe, 0xe6, 0xff, 0xc3, 0x78, 0xc0, 0x12, 0x0e, 0xe0, 0x40, 0x05, 0x12, 0x0e, 0xda, 0x40, //0x8230,
        0x09, 0x78, 0xb9, 0xe6, 0x78, 0xbe, 0xf6, 0x75, 0x1f, 0x04, 0x78, 0xbe, 0xe6, 0x75, 0xf0, 0x05, //0x8240,
        0xa4, 0xf5, 0x4b, 0x02, 0x0a, 0xff, 0xe5, 0x1f, 0xb4, 0x04, 0x10, 0x90, 0x0e, 0x94, 0xe4, 0x78, //0x8250,
        0xc3, 0x12, 0x0e, 0xe9, 0x40, 0x02, 0xd2, 0x37, 0x75, 0x1f, 0x05, 0x22, 0x30, 0x01, 0x03, 0x02, //0x8260,
        0x04, 0xc0, 0x30, 0x02, 0x03, 0x02, 0x04, 0xc0, 0x90, 0x51, 0xa5, 0xe0, 0x78, 0x93, 0xf6, 0xa3, //0x8270,
        0xe0, 0x08, 0xf6, 0xa3, 0xe0, 0x08, 0xf6, 0xe5, 0x1f, 0x70, 0x3c, 0x75, 0x1e, 0x20, 0xd2, 0x35, //0x8280,
        0x12, 0x0c, 0x7a, 0x78, 0x7e, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0x78, 0x8b, 0xa6, 0x09, 0x18, 0x76, //0x8290,
        0x01, 0x12, 0x0c, 0x5b, 0x78, 0x4e, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0x78, 0x8b, 0xe6, 0x78, 0x6e, //0x82a0,
        0xf6, 0x75, 0x1f, 0x01, 0x78, 0x93, 0xe6, 0x78, 0x90, 0xf6, 0x78, 0x94, 0xe6, 0x78, 0x91, 0xf6, //0x82b0,
        0x78, 0x95, 0xe6, 0x78, 0x92, 0xf6, 0x22, 0x79, 0x90, 0xe7, 0xd3, 0x78, 0x93, 0x96, 0x40, 0x05, //0x82c0,
        0xe7, 0x96, 0xff, 0x80, 0x08, 0xc3, 0x79, 0x93, 0xe7, 0x78, 0x90, 0x96, 0xff, 0x78, 0x88, 0x76, //0x82d0,
        0x00, 0x08, 0xa6, 0x07, 0x79, 0x91, 0xe7, 0xd3, 0x78, 0x94, 0x96, 0x40, 0x05, 0xe7, 0x96, 0xff, //0x82e0,
        0x80, 0x08, 0xc3, 0x79, 0x94, 0xe7, 0x78, 0x91, 0x96, 0xff, 0x12, 0x0c, 0x8e, 0x79, 0x92, 0xe7, //0x82f0,
        0xd3, 0x78, 0x95, 0x96, 0x40, 0x05, 0xe7, 0x96, 0xff, 0x80, 0x08, 0xc3, 0x79, 0x95, 0xe7, 0x78, //0x8300,
        0x92, 0x96, 0xff, 0x12, 0x0c, 0x8e, 0x12, 0x0c, 0x5b, 0x78, 0x8a, 0xe6, 0x25, 0xe0, 0x24, 0x4e, //0x8310,
        0xf8, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0x78, 0x8a, 0xe6, 0x24, 0x6e, 0xf8, 0xa6, 0x09, 0x78, 0x8a, //0x8320,
        0xe6, 0x24, 0x01, 0xff, 0xe4, 0x33, 0xfe, 0xd3, 0xef, 0x94, 0x0f, 0xee, 0x64, 0x80, 0x94, 0x80, //0x8330,
        0x40, 0x04, 0x7f, 0x00, 0x80, 0x05, 0x78, 0x8a, 0xe6, 0x04, 0xff, 0x78, 0x8a, 0xa6, 0x07, 0xe5, //0x8340,
        0x1f, 0xb4, 0x01, 0x0a, 0xe6, 0x60, 0x03, 0x02, 0x04, 0xc0, 0x75, 0x1f, 0x02, 0x22, 0x12, 0x0c, //0x8350,
        0x7a, 0x78, 0x80, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0x12, 0x0c, 0x7a, 0x78, 0x82, 0xa6, 0x06, 0x08, //0x8360,
        0xa6, 0x07, 0x78, 0x6e, 0xe6, 0x78, 0x8c, 0xf6, 0x78, 0x6e, 0xe6, 0x78, 0x8d, 0xf6, 0x7f, 0x01, //0x8370,
        0xef, 0x25, 0xe0, 0x24, 0x4f, 0xf9, 0xc3, 0x78, 0x81, 0xe6, 0x97, 0x18, 0xe6, 0x19, 0x97, 0x50, //0x8380,
        0x0a, 0x12, 0x0c, 0x82, 0x78, 0x80, 0xa6, 0x04, 0x08, 0xa6, 0x05, 0x74, 0x6e, 0x2f, 0xf9, 0x78, //0x8390,
        0x8c, 0xe6, 0xc3, 0x97, 0x50, 0x08, 0x74, 0x6e, 0x2f, 0xf8, 0xe6, 0x78, 0x8c, 0xf6, 0xef, 0x25, //0x83a0,
        0xe0, 0x24, 0x4f, 0xf9, 0xd3, 0x78, 0x83, 0xe6, 0x97, 0x18, 0xe6, 0x19, 0x97, 0x40, 0x0a, 0x12, //0x83b0,
        0x0c, 0x82, 0x78, 0x82, 0xa6, 0x04, 0x08, 0xa6, 0x05, 0x74, 0x6e, 0x2f, 0xf9, 0x78, 0x8d, 0xe6, //0x83c0,
        0xd3, 0x97, 0x40, 0x08, 0x74, 0x6e, 0x2f, 0xf8, 0xe6, 0x78, 0x8d, 0xf6, 0x0f, 0xef, 0x64, 0x10, //0x83d0,
        0x70, 0x9e, 0xc3, 0x79, 0x81, 0xe7, 0x78, 0x83, 0x96, 0xff, 0x19, 0xe7, 0x18, 0x96, 0x78, 0x84, //0x83e0,
        0xf6, 0x08, 0xa6, 0x07, 0xc3, 0x79, 0x8c, 0xe7, 0x78, 0x8d, 0x96, 0x08, 0xf6, 0xd3, 0x79, 0x81, //0x83f0,
        0xe7, 0x78, 0x7f, 0x96, 0x19, 0xe7, 0x18, 0x96, 0x40, 0x05, 0x09, 0xe7, 0x08, 0x80, 0x06, 0xc3, //0x8400,
        0x79, 0x7f, 0xe7, 0x78, 0x81, 0x96, 0xff, 0x19, 0xe7, 0x18, 0x96, 0xfe, 0x78, 0x86, 0xa6, 0x06, //0x8410,
        0x08, 0xa6, 0x07, 0x79, 0x8c, 0xe7, 0xd3, 0x78, 0x8b, 0x96, 0x40, 0x05, 0xe7, 0x96, 0xff, 0x80, //0x8420,
        0x08, 0xc3, 0x79, 0x8b, 0xe7, 0x78, 0x8c, 0x96, 0xff, 0x78, 0x8f, 0xa6, 0x07, 0xe5, 0x1f, 0x64, //0x8430,
        0x02, 0x70, 0x69, 0x90, 0x0e, 0x91, 0x93, 0xff, 0x18, 0xe6, 0xc3, 0x9f, 0x50, 0x72, 0x12, 0x0c, //0x8440,
        0x4a, 0x12, 0x0c, 0x2f, 0x90, 0x0e, 0x8e, 0x12, 0x0c, 0x38, 0x78, 0x80, 0x12, 0x0c, 0x6b, 0x7b, //0x8450,
        0x04, 0x12, 0x0c, 0x1d, 0xc3, 0x12, 0x06, 0x45, 0x50, 0x56, 0x90, 0x0e, 0x92, 0xe4, 0x93, 0xff, //0x8460,
        0x78, 0x8f, 0xe6, 0x9f, 0x40, 0x02, 0x80, 0x11, 0x90, 0x0e, 0x90, 0xe4, 0x93, 0xff, 0xd3, 0x78, //0x8470,
        0x89, 0xe6, 0x9f, 0x18, 0xe6, 0x94, 0x00, 0x40, 0x03, 0x75, 0x1f, 0x05, 0x12, 0x0c, 0x4a, 0x12, //0x8480,
        0x0c, 0x2f, 0x90, 0x0e, 0x8f, 0x12, 0x0c, 0x38, 0x78, 0x7e, 0x12, 0x0c, 0x6b, 0x7b, 0x40, 0x12, //0x8490,
        0x0c, 0x1d, 0xd3, 0x12, 0x06, 0x45, 0x40, 0x18, 0x75, 0x1f, 0x05, 0x22, 0xe5, 0x1f, 0xb4, 0x05, //0x84a0,
        0x0f, 0xd2, 0x01, 0xc2, 0x02, 0xe4, 0xf5, 0x1f, 0xf5, 0x1e, 0xd2, 0x35, 0xd2, 0x33, 0xd2, 0x36, //0x84b0,
        0x22, 0xef, 0x8d, 0xf0, 0xa4, 0xa8, 0xf0, 0xcf, 0x8c, 0xf0, 0xa4, 0x28, 0xce, 0x8d, 0xf0, 0xa4, //0x84c0,
        0x2e, 0xfe, 0x22, 0xbc, 0x00, 0x0b, 0xbe, 0x00, 0x29, 0xef, 0x8d, 0xf0, 0x84, 0xff, 0xad, 0xf0, //0x84d0,
        0x22, 0xe4, 0xcc, 0xf8, 0x75, 0xf0, 0x08, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xec, 0x33, 0xfc, //0x84e0,
        0xee, 0x9d, 0xec, 0x98, 0x40, 0x05, 0xfc, 0xee, 0x9d, 0xfe, 0x0f, 0xd5, 0xf0, 0xe9, 0xe4, 0xce, //0x84f0,
        0xfd, 0x22, 0xed, 0xf8, 0xf5, 0xf0, 0xee, 0x84, 0x20, 0xd2, 0x1c, 0xfe, 0xad, 0xf0, 0x75, 0xf0, //0x8500,
        0x08, 0xef, 0x2f, 0xff, 0xed, 0x33, 0xfd, 0x40, 0x07, 0x98, 0x50, 0x06, 0xd5, 0xf0, 0xf2, 0x22, //0x8510,
        0xc3, 0x98, 0xfd, 0x0f, 0xd5, 0xf0, 0xea, 0x22, 0xe8, 0x8f, 0xf0, 0xa4, 0xcc, 0x8b, 0xf0, 0xa4, //0x8520,
        0x2c, 0xfc, 0xe9, 0x8e, 0xf0, 0xa4, 0x2c, 0xfc, 0x8a, 0xf0, 0xed, 0xa4, 0x2c, 0xfc, 0xea, 0x8e, //0x8530,
        0xf0, 0xa4, 0xcd, 0xa8, 0xf0, 0x8b, 0xf0, 0xa4, 0x2d, 0xcc, 0x38, 0x25, 0xf0, 0xfd, 0xe9, 0x8f, //0x8540,
        0xf0, 0xa4, 0x2c, 0xcd, 0x35, 0xf0, 0xfc, 0xeb, 0x8e, 0xf0, 0xa4, 0xfe, 0xa9, 0xf0, 0xeb, 0x8f, //0x8550,
        0xf0, 0xa4, 0xcf, 0xc5, 0xf0, 0x2e, 0xcd, 0x39, 0xfe, 0xe4, 0x3c, 0xfc, 0xea, 0xa4, 0x2d, 0xce, //0x8560,
        0x35, 0xf0, 0xfd, 0xe4, 0x3c, 0xfc, 0x22, 0x75, 0xf0, 0x08, 0x75, 0x82, 0x00, 0xef, 0x2f, 0xff, //0x8570,
        0xee, 0x33, 0xfe, 0xcd, 0x33, 0xcd, 0xcc, 0x33, 0xcc, 0xc5, 0x82, 0x33, 0xc5, 0x82, 0x9b, 0xed, //0x8580,
        0x9a, 0xec, 0x99, 0xe5, 0x82, 0x98, 0x40, 0x0c, 0xf5, 0x82, 0xee, 0x9b, 0xfe, 0xed, 0x9a, 0xfd, //0x8590,
        0xec, 0x99, 0xfc, 0x0f, 0xd5, 0xf0, 0xd6, 0xe4, 0xce, 0xfb, 0xe4, 0xcd, 0xfa, 0xe4, 0xcc, 0xf9, //0x85a0,
        0xa8, 0x82, 0x22, 0xb8, 0x00, 0xc1, 0xb9, 0x00, 0x59, 0xba, 0x00, 0x2d, 0xec, 0x8b, 0xf0, 0x84, //0x85b0,
        0xcf, 0xce, 0xcd, 0xfc, 0xe5, 0xf0, 0xcb, 0xf9, 0x78, 0x18, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, //0x85c0,
        0xed, 0x33, 0xfd, 0xec, 0x33, 0xfc, 0xeb, 0x33, 0xfb, 0x10, 0xd7, 0x03, 0x99, 0x40, 0x04, 0xeb, //0x85d0,
        0x99, 0xfb, 0x0f, 0xd8, 0xe5, 0xe4, 0xf9, 0xfa, 0x22, 0x78, 0x18, 0xef, 0x2f, 0xff, 0xee, 0x33, //0x85e0,
        0xfe, 0xed, 0x33, 0xfd, 0xec, 0x33, 0xfc, 0xc9, 0x33, 0xc9, 0x10, 0xd7, 0x05, 0x9b, 0xe9, 0x9a, //0x85f0,
        0x40, 0x07, 0xec, 0x9b, 0xfc, 0xe9, 0x9a, 0xf9, 0x0f, 0xd8, 0xe0, 0xe4, 0xc9, 0xfa, 0xe4, 0xcc, //0x8600,
        0xfb, 0x22, 0x75, 0xf0, 0x10, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xcc, 0x33, //0x8610,
        0xcc, 0xc8, 0x33, 0xc8, 0x10, 0xd7, 0x07, 0x9b, 0xec, 0x9a, 0xe8, 0x99, 0x40, 0x0a, 0xed, 0x9b, //0x8620,
        0xfd, 0xec, 0x9a, 0xfc, 0xe8, 0x99, 0xf8, 0x0f, 0xd5, 0xf0, 0xda, 0xe4, 0xcd, 0xfb, 0xe4, 0xcc, //0x8630,
        0xfa, 0xe4, 0xc8, 0xf9, 0x22, 0xeb, 0x9f, 0xf5, 0xf0, 0xea, 0x9e, 0x42, 0xf0, 0xe9, 0x9d, 0x42, //0x8640,
        0xf0, 0xe8, 0x9c, 0x45, 0xf0, 0x22, 0xe8, 0x60, 0x0f, 0xec, 0xc3, 0x13, 0xfc, 0xed, 0x13, 0xfd, //0x8650,
        0xee, 0x13, 0xfe, 0xef, 0x13, 0xff, 0xd8, 0xf1, 0x22, 0xe8, 0x60, 0x0f, 0xef, 0xc3, 0x33, 0xff, //0x8660,
        0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xec, 0x33, 0xfc, 0xd8, 0xf1, 0x22, 0xe4, 0x93, 0xfc, 0x74, //0x8670,
        0x01, 0x93, 0xfd, 0x74, 0x02, 0x93, 0xfe, 0x74, 0x03, 0x93, 0xff, 0x22, 0xe6, 0xfb, 0x08, 0xe6, //0x8680,
        0xf9, 0x08, 0xe6, 0xfa, 0x08, 0xe6, 0xcb, 0xf8, 0x22, 0xec, 0xf6, 0x08, 0xed, 0xf6, 0x08, 0xee, //0x8690,
        0xf6, 0x08, 0xef, 0xf6, 0x22, 0xa4, 0x25, 0x82, 0xf5, 0x82, 0xe5, 0xf0, 0x35, 0x83, 0xf5, 0x83, //0x86a0,
        0x22, 0xd0, 0x83, 0xd0, 0x82, 0xf8, 0xe4, 0x93, 0x70, 0x12, 0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, //0x86b0,
        0xa3, 0x93, 0xf8, 0x74, 0x01, 0x93, 0xf5, 0x82, 0x88, 0x83, 0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, //0x86c0,
        0x60, 0xef, 0xa3, 0xa3, 0xa3, 0x80, 0xdf, 0x90, 0x38, 0x04, 0x78, 0x52, 0x12, 0x0b, 0xfd, 0x90, //0x86d0,
        0x38, 0x00, 0xe0, 0xfe, 0xa3, 0xe0, 0xfd, 0xed, 0xff, 0xc3, 0x12, 0x0b, 0x9e, 0x90, 0x38, 0x10, //0x86e0,
        0x12, 0x0b, 0x92, 0x90, 0x38, 0x06, 0x78, 0x54, 0x12, 0x0b, 0xfd, 0x90, 0x38, 0x02, 0xe0, 0xfe, //0x86f0,
        0xa3, 0xe0, 0xfd, 0xed, 0xff, 0xc3, 0x12, 0x0b, 0x9e, 0x90, 0x38, 0x12, 0x12, 0x0b, 0x92, 0xa3, //0x8700,
        0xe0, 0xb4, 0x31, 0x07, 0x78, 0x52, 0x79, 0x52, 0x12, 0x0c, 0x13, 0x90, 0x38, 0x14, 0xe0, 0xb4, //0x8710,
        0x71, 0x15, 0x78, 0x52, 0xe6, 0xfe, 0x08, 0xe6, 0x78, 0x02, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, //0x8720,
        0xf9, 0x79, 0x53, 0xf7, 0xee, 0x19, 0xf7, 0x90, 0x38, 0x15, 0xe0, 0xb4, 0x31, 0x07, 0x78, 0x54, //0x8730,
        0x79, 0x54, 0x12, 0x0c, 0x13, 0x90, 0x38, 0x15, 0xe0, 0xb4, 0x71, 0x15, 0x78, 0x54, 0xe6, 0xfe, //0x8740,
        0x08, 0xe6, 0x78, 0x02, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x79, 0x55, 0xf7, 0xee, 0x19, //0x8750,
        0xf7, 0x79, 0x52, 0x12, 0x0b, 0xd9, 0x09, 0x12, 0x0b, 0xd9, 0xaf, 0x47, 0x12, 0x0b, 0xb2, 0xe5, //0x8760,
        0x44, 0xfb, 0x7a, 0x00, 0xfd, 0x7c, 0x00, 0x12, 0x04, 0xd3, 0x78, 0x5a, 0xa6, 0x06, 0x08, 0xa6, //0x8770,
        0x07, 0xaf, 0x45, 0x12, 0x0b, 0xb2, 0xad, 0x03, 0x7c, 0x00, 0x12, 0x04, 0xd3, 0x78, 0x56, 0xa6, //0x8780,
        0x06, 0x08, 0xa6, 0x07, 0xaf, 0x48, 0x78, 0x54, 0x12, 0x0b, 0xb4, 0xe5, 0x43, 0xfb, 0xfd, 0x7c, //0x8790,
        0x00, 0x12, 0x04, 0xd3, 0x78, 0x5c, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0xaf, 0x46, 0x7e, 0x00, 0x78, //0x87a0,
        0x54, 0x12, 0x0b, 0xb6, 0xad, 0x03, 0x7c, 0x00, 0x12, 0x04, 0xd3, 0x78, 0x58, 0xa6, 0x06, 0x08, //0x87b0,
        0xa6, 0x07, 0xc3, 0x78, 0x5b, 0xe6, 0x94, 0x08, 0x18, 0xe6, 0x94, 0x00, 0x50, 0x05, 0x76, 0x00, //0x87c0,
        0x08, 0x76, 0x08, 0xc3, 0x78, 0x5d, 0xe6, 0x94, 0x08, 0x18, 0xe6, 0x94, 0x00, 0x50, 0x05, 0x76, //0x87d0,
        0x00, 0x08, 0x76, 0x08, 0x78, 0x5a, 0x12, 0x0b, 0xc6, 0xff, 0xd3, 0x78, 0x57, 0xe6, 0x9f, 0x18, //0x87e0,
        0xe6, 0x9e, 0x40, 0x0e, 0x78, 0x5a, 0xe6, 0x13, 0xfe, 0x08, 0xe6, 0x78, 0x57, 0x12, 0x0c, 0x08, //0x87f0,
        0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0x78, 0x5e, 0x12, 0x0b, 0xbe, 0xff, 0xd3, 0x78, 0x59, 0xe6, //0x8800,
        0x9f, 0x18, 0xe6, 0x9e, 0x40, 0x0e, 0x78, 0x5c, 0xe6, 0x13, 0xfe, 0x08, 0xe6, 0x78, 0x59, 0x12, //0x8810,
        0x0c, 0x08, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0xe4, 0xfc, 0xfd, 0x78, 0x62, 0x12, 0x06, 0x99, //0x8820,
        0x78, 0x5a, 0x12, 0x0b, 0xc6, 0x78, 0x57, 0x26, 0xff, 0xee, 0x18, 0x36, 0xfe, 0x78, 0x66, 0x12, //0x8830,
        0x0b, 0xbe, 0x78, 0x59, 0x26, 0xff, 0xee, 0x18, 0x36, 0xfe, 0xe4, 0xfc, 0xfd, 0x78, 0x6a, 0x12, //0x8840,
        0x06, 0x99, 0x12, 0x0b, 0xce, 0x78, 0x66, 0x12, 0x06, 0x8c, 0xd3, 0x12, 0x06, 0x45, 0x40, 0x08, //0x8850,
        0x12, 0x0b, 0xce, 0x78, 0x66, 0x12, 0x06, 0x99, 0x78, 0x54, 0x12, 0x0b, 0xd0, 0x78, 0x6a, 0x12, //0x8860,
        0x06, 0x8c, 0xd3, 0x12, 0x06, 0x45, 0x40, 0x0a, 0x78, 0x54, 0x12, 0x0b, 0xd0, 0x78, 0x6a, 0x12, //0x8870,
        0x06, 0x99, 0x78, 0x61, 0xe6, 0x90, 0x60, 0x01, 0xf0, 0x78, 0x65, 0xe6, 0xa3, 0xf0, 0x78, 0x69, //0x8880,
        0xe6, 0xa3, 0xf0, 0x78, 0x55, 0xe6, 0xa3, 0xf0, 0x7d, 0x01, 0x78, 0x61, 0x12, 0x0b, 0xe9, 0x24, //0x8890,
        0x01, 0x12, 0x0b, 0xa6, 0x78, 0x65, 0x12, 0x0b, 0xe9, 0x24, 0x02, 0x12, 0x0b, 0xa6, 0x78, 0x69, //0x88a0,
        0x12, 0x0b, 0xe9, 0x24, 0x03, 0x12, 0x0b, 0xa6, 0x78, 0x6d, 0x12, 0x0b, 0xe9, 0x24, 0x04, 0x12, //0x88b0,
        0x0b, 0xa6, 0x0d, 0xbd, 0x05, 0xd4, 0xc2, 0x0e, 0xc2, 0x06, 0x22, 0x85, 0x08, 0x41, 0x90, 0x30, //0x88c0,
        0x24, 0xe0, 0xf5, 0x3d, 0xa3, 0xe0, 0xf5, 0x3e, 0xa3, 0xe0, 0xf5, 0x3f, 0xa3, 0xe0, 0xf5, 0x40, //0x88d0,
        0xa3, 0xe0, 0xf5, 0x3c, 0xd2, 0x34, 0xe5, 0x41, 0x12, 0x06, 0xb1, 0x09, 0x31, 0x03, 0x09, 0x35, //0x88e0,
        0x04, 0x09, 0x3b, 0x05, 0x09, 0x3e, 0x06, 0x09, 0x41, 0x07, 0x09, 0x4a, 0x08, 0x09, 0x5b, 0x12, //0x88f0,
        0x09, 0x73, 0x18, 0x09, 0x89, 0x19, 0x09, 0x5e, 0x1a, 0x09, 0x6a, 0x1b, 0x09, 0xad, 0x80, 0x09, //0x8900,
        0xb2, 0x81, 0x0a, 0x1d, 0x8f, 0x0a, 0x09, 0x90, 0x0a, 0x1d, 0x91, 0x0a, 0x1d, 0x92, 0x0a, 0x1d, //0x8910,
        0x93, 0x0a, 0x1d, 0x94, 0x0a, 0x1d, 0x98, 0x0a, 0x17, 0x9f, 0x0a, 0x1a, 0xec, 0x00, 0x00, 0x0a, //0x8920,
        0x38, 0x12, 0x0f, 0x74, 0x22, 0x12, 0x0f, 0x74, 0xd2, 0x03, 0x22, 0xd2, 0x03, 0x22, 0xc2, 0x03, //0x8930,
        0x22, 0xa2, 0x37, 0xe4, 0x33, 0xf5, 0x3c, 0x02, 0x0a, 0x1d, 0xc2, 0x01, 0xc2, 0x02, 0xc2, 0x03, //0x8940,
        0x12, 0x0d, 0x0d, 0x75, 0x1e, 0x70, 0xd2, 0x35, 0x02, 0x0a, 0x1d, 0x02, 0x0a, 0x04, 0x85, 0x40, //0x8950,
        0x4a, 0x85, 0x3c, 0x4b, 0x12, 0x0a, 0xff, 0x02, 0x0a, 0x1d, 0x85, 0x4a, 0x40, 0x85, 0x4b, 0x3c, //0x8960,
        0x02, 0x0a, 0x1d, 0xe4, 0xf5, 0x22, 0xf5, 0x23, 0x85, 0x40, 0x31, 0x85, 0x3f, 0x30, 0x85, 0x3e, //0x8970,
        0x2f, 0x85, 0x3d, 0x2e, 0x12, 0x0f, 0x46, 0x80, 0x1f, 0x75, 0x22, 0x00, 0x75, 0x23, 0x01, 0x74, //0x8980,
        0xff, 0xf5, 0x2d, 0xf5, 0x2c, 0xf5, 0x2b, 0xf5, 0x2a, 0x12, 0x0f, 0x46, 0x85, 0x2d, 0x40, 0x85, //0x8990,
        0x2c, 0x3f, 0x85, 0x2b, 0x3e, 0x85, 0x2a, 0x3d, 0xe4, 0xf5, 0x3c, 0x80, 0x70, 0x12, 0x0f, 0x16, //0x89a0,
        0x80, 0x6b, 0x85, 0x3d, 0x45, 0x85, 0x3e, 0x46, 0xe5, 0x47, 0xc3, 0x13, 0xff, 0xe5, 0x45, 0xc3, //0x89b0,
        0x9f, 0x50, 0x02, 0x8f, 0x45, 0xe5, 0x48, 0xc3, 0x13, 0xff, 0xe5, 0x46, 0xc3, 0x9f, 0x50, 0x02, //0x89c0,
        0x8f, 0x46, 0xe5, 0x47, 0xc3, 0x13, 0xff, 0xfd, 0xe5, 0x45, 0x2d, 0xfd, 0xe4, 0x33, 0xfc, 0xe5, //0x89d0,
        0x44, 0x12, 0x0f, 0x90, 0x40, 0x05, 0xe5, 0x44, 0x9f, 0xf5, 0x45, 0xe5, 0x48, 0xc3, 0x13, 0xff, //0x89e0,
        0xfd, 0xe5, 0x46, 0x2d, 0xfd, 0xe4, 0x33, 0xfc, 0xe5, 0x43, 0x12, 0x0f, 0x90, 0x40, 0x05, 0xe5, //0x89f0,
        0x43, 0x9f, 0xf5, 0x46, 0x12, 0x06, 0xd7, 0x80, 0x14, 0x85, 0x40, 0x48, 0x85, 0x3f, 0x47, 0x85, //0x8a00,
        0x3e, 0x46, 0x85, 0x3d, 0x45, 0x80, 0x06, 0x02, 0x06, 0xd7, 0x12, 0x0d, 0x7e, 0x90, 0x30, 0x24, //0x8a10,
        0xe5, 0x3d, 0xf0, 0xa3, 0xe5, 0x3e, 0xf0, 0xa3, 0xe5, 0x3f, 0xf0, 0xa3, 0xe5, 0x40, 0xf0, 0xa3, //0x8a20,
        0xe5, 0x3c, 0xf0, 0x90, 0x30, 0x23, 0xe4, 0xf0, 0x22, 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, //0x8a30,
        0xd0, 0x90, 0x3f, 0x0c, 0xe0, 0xf5, 0x32, 0xe5, 0x32, 0x30, 0xe3, 0x74, 0x30, 0x36, 0x66, 0x90, //0x8a40,
        0x60, 0x19, 0xe0, 0xf5, 0x0a, 0xa3, 0xe0, 0xf5, 0x0b, 0x90, 0x60, 0x1d, 0xe0, 0xf5, 0x14, 0xa3, //0x8a50,
        0xe0, 0xf5, 0x15, 0x90, 0x60, 0x21, 0xe0, 0xf5, 0x0c, 0xa3, 0xe0, 0xf5, 0x0d, 0x90, 0x60, 0x29, //0x8a60,
        0xe0, 0xf5, 0x0e, 0xa3, 0xe0, 0xf5, 0x0f, 0x90, 0x60, 0x31, 0xe0, 0xf5, 0x10, 0xa3, 0xe0, 0xf5, //0x8a70,
        0x11, 0x90, 0x60, 0x39, 0xe0, 0xf5, 0x12, 0xa3, 0xe0, 0xf5, 0x13, 0x30, 0x01, 0x06, 0x30, 0x33, //0x8a80,
        0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x09, 0x30, 0x02, 0x06, 0x30, 0x33, 0x03, 0xd3, 0x80, 0x01, //0x8a90,
        0xc3, 0x92, 0x0a, 0x30, 0x33, 0x0c, 0x30, 0x03, 0x09, 0x20, 0x02, 0x06, 0x20, 0x01, 0x03, 0xd3, //0x8aa0,
        0x80, 0x01, 0xc3, 0x92, 0x0b, 0x90, 0x30, 0x01, 0xe0, 0x44, 0x40, 0xf0, 0xe0, 0x54, 0xbf, 0xf0, //0x8ab0,
        0xe5, 0x32, 0x30, 0xe1, 0x14, 0x30, 0x34, 0x11, 0x90, 0x30, 0x22, 0xe0, 0xf5, 0x08, 0xe4, 0xf0, //0x8ac0,
        0x30, 0x00, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x08, 0xe5, 0x32, 0x30, 0xe5, 0x12, 0x90, 0x56, //0x8ad0,
        0xa1, 0xe0, 0xf5, 0x09, 0x30, 0x31, 0x09, 0x30, 0x05, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x0d, //0x8ae0,
        0x90, 0x3f, 0x0c, 0xe5, 0x32, 0xf0, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32, 0x90, //0x8af0,
        0x0e, 0x7e, 0xe4, 0x93, 0xfe, 0x74, 0x01, 0x93, 0xff, 0xc3, 0x90, 0x0e, 0x7c, 0x74, 0x01, 0x93, //0x8b00,
        0x9f, 0xff, 0xe4, 0x93, 0x9e, 0xfe, 0xe4, 0x8f, 0x3b, 0x8e, 0x3a, 0xf5, 0x39, 0xf5, 0x38, 0xab, //0x8b10,
        0x3b, 0xaa, 0x3a, 0xa9, 0x39, 0xa8, 0x38, 0xaf, 0x4b, 0xfc, 0xfd, 0xfe, 0x12, 0x05, 0x28, 0x12, //0x8b20,
        0x0d, 0xe1, 0xe4, 0x7b, 0xff, 0xfa, 0xf9, 0xf8, 0x12, 0x05, 0xb3, 0x12, 0x0d, 0xe1, 0x90, 0x0e, //0x8b30,
        0x69, 0xe4, 0x12, 0x0d, 0xf6, 0x12, 0x0d, 0xe1, 0xe4, 0x85, 0x4a, 0x37, 0xf5, 0x36, 0xf5, 0x35, //0x8b40,
        0xf5, 0x34, 0xaf, 0x37, 0xae, 0x36, 0xad, 0x35, 0xac, 0x34, 0xa3, 0x12, 0x0d, 0xf6, 0x8f, 0x37, //0x8b50,
        0x8e, 0x36, 0x8d, 0x35, 0x8c, 0x34, 0xe5, 0x3b, 0x45, 0x37, 0xf5, 0x3b, 0xe5, 0x3a, 0x45, 0x36, //0x8b60,
        0xf5, 0x3a, 0xe5, 0x39, 0x45, 0x35, 0xf5, 0x39, 0xe5, 0x38, 0x45, 0x34, 0xf5, 0x38, 0xe4, 0xf5, //0x8b70,
        0x22, 0xf5, 0x23, 0x85, 0x3b, 0x31, 0x85, 0x3a, 0x30, 0x85, 0x39, 0x2f, 0x85, 0x38, 0x2e, 0x02, //0x8b80,
        0x0f, 0x46, 0xe0, 0xa3, 0xe0, 0x75, 0xf0, 0x02, 0xa4, 0xff, 0xae, 0xf0, 0xc3, 0x08, 0xe6, 0x9f, //0x8b90,
        0xf6, 0x18, 0xe6, 0x9e, 0xf6, 0x22, 0xff, 0xe5, 0xf0, 0x34, 0x60, 0x8f, 0x82, 0xf5, 0x83, 0xec, //0x8ba0,
        0xf0, 0x22, 0x78, 0x52, 0x7e, 0x00, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x02, 0x04, 0xc1, 0xe4, 0xfc, //0x8bb0,
        0xfd, 0x12, 0x06, 0x99, 0x78, 0x5c, 0xe6, 0xc3, 0x13, 0xfe, 0x08, 0xe6, 0x13, 0x22, 0x78, 0x52, //0x8bc0,
        0xe6, 0xfe, 0x08, 0xe6, 0xff, 0xe4, 0xfc, 0xfd, 0x22, 0xe7, 0xc4, 0xf8, 0x54, 0xf0, 0xc8, 0x68, //0x8bd0,
        0xf7, 0x09, 0xe7, 0xc4, 0x54, 0x0f, 0x48, 0xf7, 0x22, 0xe6, 0xfc, 0xed, 0x75, 0xf0, 0x04, 0xa4, //0x8be0,
        0x22, 0x12, 0x06, 0x7c, 0x8f, 0x48, 0x8e, 0x47, 0x8d, 0x46, 0x8c, 0x45, 0x22, 0xe0, 0xfe, 0xa3, //0x8bf0,
        0xe0, 0xfd, 0xee, 0xf6, 0xed, 0x08, 0xf6, 0x22, 0x13, 0xff, 0xc3, 0xe6, 0x9f, 0xff, 0x18, 0xe6, //0x8c00,
        0x9e, 0xfe, 0x22, 0xe6, 0xc3, 0x13, 0xf7, 0x08, 0xe6, 0x13, 0x09, 0xf7, 0x22, 0xad, 0x39, 0xac, //0x8c10,
        0x38, 0xfa, 0xf9, 0xf8, 0x12, 0x05, 0x28, 0x8f, 0x3b, 0x8e, 0x3a, 0x8d, 0x39, 0x8c, 0x38, 0xab, //0x8c20,
        0x37, 0xaa, 0x36, 0xa9, 0x35, 0xa8, 0x34, 0x22, 0x93, 0xff, 0xe4, 0xfc, 0xfd, 0xfe, 0x12, 0x05, //0x8c30,
        0x28, 0x8f, 0x37, 0x8e, 0x36, 0x8d, 0x35, 0x8c, 0x34, 0x22, 0x78, 0x84, 0xe6, 0xfe, 0x08, 0xe6, //0x8c40,
        0xff, 0xe4, 0x8f, 0x37, 0x8e, 0x36, 0xf5, 0x35, 0xf5, 0x34, 0x22, 0x90, 0x0e, 0x8c, 0xe4, 0x93, //0x8c50,
        0x25, 0xe0, 0x24, 0x0a, 0xf8, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x22, 0xe6, 0xfe, 0x08, 0xe6, 0xff, //0x8c60,
        0xe4, 0x8f, 0x3b, 0x8e, 0x3a, 0xf5, 0x39, 0xf5, 0x38, 0x22, 0x78, 0x4e, 0xe6, 0xfe, 0x08, 0xe6, //0x8c70,
        0xff, 0x22, 0xef, 0x25, 0xe0, 0x24, 0x4e, 0xf8, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x22, 0x78, 0x89, //0x8c80,
        0xef, 0x26, 0xf6, 0x18, 0xe4, 0x36, 0xf6, 0x22, 0x75, 0x89, 0x03, 0x75, 0xa8, 0x01, 0x75, 0xb8, //0x8c90,
        0x04, 0x75, 0x34, 0xff, 0x75, 0x35, 0x0e, 0x75, 0x36, 0x15, 0x75, 0x37, 0x0d, 0x12, 0x0e, 0x9a, //0x8ca0,
        0x12, 0x00, 0x09, 0x12, 0x0f, 0x16, 0x12, 0x00, 0x06, 0xd2, 0x00, 0xd2, 0x34, 0xd2, 0xaf, 0x75, //0x8cb0,
        0x34, 0xff, 0x75, 0x35, 0x0e, 0x75, 0x36, 0x49, 0x75, 0x37, 0x03, 0x12, 0x0e, 0x9a, 0x30, 0x08, //0x8cc0,
        0x09, 0xc2, 0x34, 0x12, 0x08, 0xcb, 0xc2, 0x08, 0xd2, 0x34, 0x30, 0x0b, 0x09, 0xc2, 0x36, 0x12, //0x8cd0,
        0x02, 0x6c, 0xc2, 0x0b, 0xd2, 0x36, 0x30, 0x09, 0x09, 0xc2, 0x36, 0x12, 0x00, 0x0e, 0xc2, 0x09, //0x8ce0,
        0xd2, 0x36, 0x30, 0x0e, 0x03, 0x12, 0x06, 0xd7, 0x30, 0x35, 0xd3, 0x90, 0x30, 0x29, 0xe5, 0x1e, //0x8cf0,
        0xf0, 0xb4, 0x10, 0x05, 0x90, 0x30, 0x23, 0xe4, 0xf0, 0xc2, 0x35, 0x80, 0xc1, 0xe4, 0xf5, 0x4b, //0x8d00,
        0x90, 0x0e, 0x7a, 0x93, 0xff, 0xe4, 0x8f, 0x37, 0xf5, 0x36, 0xf5, 0x35, 0xf5, 0x34, 0xaf, 0x37, //0x8d10,
        0xae, 0x36, 0xad, 0x35, 0xac, 0x34, 0x90, 0x0e, 0x6a, 0x12, 0x0d, 0xf6, 0x8f, 0x37, 0x8e, 0x36, //0x8d20,
        0x8d, 0x35, 0x8c, 0x34, 0x90, 0x0e, 0x72, 0x12, 0x06, 0x7c, 0xef, 0x45, 0x37, 0xf5, 0x37, 0xee, //0x8d30,
        0x45, 0x36, 0xf5, 0x36, 0xed, 0x45, 0x35, 0xf5, 0x35, 0xec, 0x45, 0x34, 0xf5, 0x34, 0xe4, 0xf5, //0x8d40,
        0x22, 0xf5, 0x23, 0x85, 0x37, 0x31, 0x85, 0x36, 0x30, 0x85, 0x35, 0x2f, 0x85, 0x34, 0x2e, 0x12, //0x8d50,
        0x0f, 0x46, 0xe4, 0xf5, 0x22, 0xf5, 0x23, 0x90, 0x0e, 0x72, 0x12, 0x0d, 0xea, 0x12, 0x0f, 0x46, //0x8d60,
        0xe4, 0xf5, 0x22, 0xf5, 0x23, 0x90, 0x0e, 0x6e, 0x12, 0x0d, 0xea, 0x02, 0x0f, 0x46, 0xe5, 0x40, //0x8d70,
        0x24, 0xf2, 0xf5, 0x37, 0xe5, 0x3f, 0x34, 0x43, 0xf5, 0x36, 0xe5, 0x3e, 0x34, 0xa2, 0xf5, 0x35, //0x8d80,
        0xe5, 0x3d, 0x34, 0x28, 0xf5, 0x34, 0xe5, 0x37, 0xff, 0xe4, 0xfe, 0xfd, 0xfc, 0x78, 0x18, 0x12, //0x8d90,
        0x06, 0x69, 0x8f, 0x40, 0x8e, 0x3f, 0x8d, 0x3e, 0x8c, 0x3d, 0xe5, 0x37, 0x54, 0xa0, 0xff, 0xe5, //0x8da0,
        0x36, 0xfe, 0xe4, 0xfd, 0xfc, 0x78, 0x07, 0x12, 0x06, 0x56, 0x78, 0x10, 0x12, 0x0f, 0x9a, 0xe4, //0x8db0,
        0xff, 0xfe, 0xe5, 0x35, 0xfd, 0xe4, 0xfc, 0x78, 0x0e, 0x12, 0x06, 0x56, 0x12, 0x0f, 0x9d, 0xe4, //0x8dc0,
        0xff, 0xfe, 0xfd, 0xe5, 0x34, 0xfc, 0x78, 0x18, 0x12, 0x06, 0x56, 0x78, 0x08, 0x12, 0x0f, 0x9a, //0x8dd0,
        0x22, 0x8f, 0x3b, 0x8e, 0x3a, 0x8d, 0x39, 0x8c, 0x38, 0x22, 0x12, 0x06, 0x7c, 0x8f, 0x31, 0x8e, //0x8de0,
        0x30, 0x8d, 0x2f, 0x8c, 0x2e, 0x22, 0x93, 0xf9, 0xf8, 0x02, 0x06, 0x69, 0x00, 0x00, 0x00, 0x00, //0x8df0,
        0x12, 0x01, 0x17, 0x08, 0x31, 0x15, 0x53, 0x54, 0x44, 0x20, 0x20, 0x20, 0x20, 0x20, 0x13, 0x01, //0x8e00,
        0x10, 0x01, 0x56, 0x40, 0x1a, 0x30, 0x29, 0x7e, 0x00, 0x30, 0x04, 0x20, 0xdf, 0x30, 0x05, 0x40, //0x8e10,
        0xbf, 0x50, 0x03, 0x00, 0xfd, 0x50, 0x27, 0x01, 0xfe, 0x60, 0x00, 0x11, 0x00, 0x3f, 0x05, 0x30, //0x8e20,
        0x00, 0x3f, 0x06, 0x22, 0x00, 0x3f, 0x01, 0x2a, 0x00, 0x3f, 0x02, 0x00, 0x00, 0x36, 0x06, 0x07, //0x8e30,
        0x00, 0x3f, 0x0b, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x30, 0x01, 0x40, 0xbf, 0x30, 0x01, 0x00, //0x8e40,
        0xbf, 0x30, 0x29, 0x70, 0x00, 0x3a, 0x00, 0x00, 0xff, 0x3a, 0x00, 0x00, 0xff, 0x36, 0x03, 0x36, //0x8e50,
        0x02, 0x41, 0x44, 0x58, 0x20, 0x18, 0x10, 0x0a, 0x04, 0x04, 0x00, 0x03, 0xff, 0x64, 0x00, 0x00, //0x8e60,
        0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x06, 0x06, 0x00, 0x03, 0x51, 0x00, 0x7a, //0x8e70,
        0x50, 0x3c, 0x28, 0x1e, 0x10, 0x10, 0x50, 0x2d, 0x28, 0x16, 0x10, 0x10, 0x02, 0x00, 0x10, 0x0c, //0x8e80,
        0x10, 0x04, 0x0c, 0x6e, 0x06, 0x05, 0x00, 0xa5, 0x5a, 0x00, 0xae, 0x35, 0xaf, 0x36, 0xe4, 0xfd, //0x8e90,
        0xed, 0xc3, 0x95, 0x37, 0x50, 0x33, 0x12, 0x0f, 0xe2, 0xe4, 0x93, 0xf5, 0x38, 0x74, 0x01, 0x93, //0x8ea0,
        0xf5, 0x39, 0x45, 0x38, 0x60, 0x23, 0x85, 0x39, 0x82, 0x85, 0x38, 0x83, 0xe0, 0xfc, 0x12, 0x0f, //0x8eb0,
        0xe2, 0x74, 0x03, 0x93, 0x52, 0x04, 0x12, 0x0f, 0xe2, 0x74, 0x02, 0x93, 0x42, 0x04, 0x85, 0x39, //0x8ec0,
        0x82, 0x85, 0x38, 0x83, 0xec, 0xf0, 0x0d, 0x80, 0xc7, 0x22, 0x78, 0xbe, 0xe6, 0xd3, 0x08, 0xff, //0x8ed0,
        0xe6, 0x64, 0x80, 0xf8, 0xef, 0x64, 0x80, 0x98, 0x22, 0x93, 0xff, 0x7e, 0x00, 0xe6, 0xfc, 0x08, //0x8ee0,
        0xe6, 0xfd, 0x12, 0x04, 0xc1, 0x78, 0xc1, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0xd3, 0xef, 0x9d, 0xee, //0x8ef0,
        0x9c, 0x22, 0x78, 0xbd, 0xd3, 0xe6, 0x64, 0x80, 0x94, 0x80, 0x22, 0x25, 0xe0, 0x24, 0x0a, 0xf8, //0x8f00,
        0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x22, 0xe5, 0x3c, 0xd3, 0x94, 0x00, 0x40, 0x0b, 0x90, 0x0e, 0x88, //0x8f10,
        0x12, 0x0b, 0xf1, 0x90, 0x0e, 0x86, 0x80, 0x09, 0x90, 0x0e, 0x82, 0x12, 0x0b, 0xf1, 0x90, 0x0e, //0x8f20,
        0x80, 0xe4, 0x93, 0xf5, 0x44, 0xa3, 0xe4, 0x93, 0xf5, 0x43, 0xd2, 0x06, 0x30, 0x06, 0x03, 0xd3, //0x8f30,
        0x80, 0x01, 0xc3, 0x92, 0x0e, 0x22, 0xa2, 0xaf, 0x92, 0x32, 0xc2, 0xaf, 0xe5, 0x23, 0x45, 0x22, //0x8f40,
        0x90, 0x0e, 0x5d, 0x60, 0x0e, 0x12, 0x0f, 0xcb, 0xe0, 0xf5, 0x2c, 0x12, 0x0f, 0xc8, 0xe0, 0xf5, //0x8f50,
        0x2d, 0x80, 0x0c, 0x12, 0x0f, 0xcb, 0xe5, 0x30, 0xf0, 0x12, 0x0f, 0xc8, 0xe5, 0x31, 0xf0, 0xa2, //0x8f60,
        0x32, 0x92, 0xaf, 0x22, 0xd2, 0x01, 0xc2, 0x02, 0xe4, 0xf5, 0x1f, 0xf5, 0x1e, 0xd2, 0x35, 0xd2, //0x8f70,
        0x33, 0xd2, 0x36, 0xd2, 0x01, 0xc2, 0x02, 0xf5, 0x1f, 0xf5, 0x1e, 0xd2, 0x35, 0xd2, 0x33, 0x22, //0x8f80,
        0xfb, 0xd3, 0xed, 0x9b, 0x74, 0x80, 0xf8, 0x6c, 0x98, 0x22, 0x12, 0x06, 0x69, 0xe5, 0x40, 0x2f, //0x8f90,
        0xf5, 0x40, 0xe5, 0x3f, 0x3e, 0xf5, 0x3f, 0xe5, 0x3e, 0x3d, 0xf5, 0x3e, 0xe5, 0x3d, 0x3c, 0xf5, //0x8fa0,
        0x3d, 0x22, 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x90, 0x3f, 0x0d, 0xe0, 0xf5, 0x33, 0xe5, 0x33, //0x8fb0,
        0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32, 0x90, 0x0e, 0x5f, 0xe4, 0x93, 0xfe, 0x74, 0x01, //0x8fc0,
        0x93, 0xf5, 0x82, 0x8e, 0x83, 0x22, 0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0xcd, 0x02, //0x8fd0,
        0x0c, 0x98, 0x8f, 0x82, 0x8e, 0x83, 0x75, 0xf0, 0x04, 0xed, 0x02, 0x06, 0xa5                    //0x8fe0
    ];

    /// <summary>
    /// 写入自动对焦固件到摄像头
    /// </summary>
    /// <returns>写入结果</returns>
    private async ValueTask<Result<bool>> WriteFocusFirmware()
    {
        logger.Info("开始写入OV5640自动对焦固件");

        MsgBus.UDPServer.ClearUDPData(this.address, this.taskID);

        // 组装固件写入命令：地址 + 所有固件数据
        UInt16 firmwareAddr = 0x8000;
        var firmwareCommand = new UInt16[1 + OV5640_AF_FIRMWARE.Length];
        firmwareCommand[0] = firmwareAddr;

        // 将固件数据复制到命令数组中
        for (int i = 0; i < OV5640_AF_FIRMWARE.Length; i++)
        {
            firmwareCommand[i + 1] = OV5640_AF_FIRMWARE[i];
        }

        var result = await ConfigureRegisters([firmwareCommand]);
        if (!result.IsSuccessful)
        {
            logger.Error($"固件写入失败: {result.Error}");
            return result;
        }

        logger.Info($"OV5640自动对焦固件写入完成，总共写入 {OV5640_AF_FIRMWARE.Length} 字节");
        return true;
    }

    /// <summary>
    /// 初始化自动对焦功能
    /// </summary>
    /// <returns>初始化结果</returns>
    public async ValueTask<Result<bool>> InitAutoFocus()
    {
        logger.Info("开始初始化OV5640自动对焦功能");

        // 步骤1: 启动MCU
        var mcuResult = await ConfigureRegisters([[0x3000, 0x20]]);
        if (!mcuResult.IsSuccessful) return mcuResult;

        // 步骤2: 写入自动对焦固件
        var firmwareResult = await WriteFocusFirmware();
        if (!firmwareResult.IsSuccessful) return firmwareResult;

        // 步骤3: 配置对焦相关寄存器
        var focusRegisters = new UInt16[][]
        {
            [0x3022, 0x00], // 清除指令寄存器
            [0x3023, 0x00], // 清除状态寄存器
            [0x3024, 0x00], // 清除参数寄存器
            [0x3025, 0x00],
            [0x3026, 0x00],
            [0x3027, 0x00],
            [0x3028, 0x00],
            [0x3029, 0xFF], // 状态寄存器
            [0x3000, 0x00], // 启动MCU
            [0x3004, 0xFF]  // 使能中断
        };
        var result = await ConfigureRegisters(focusRegisters);
        if (!result.IsSuccessful) return result;

        // // 读取寄存器判断初始化是否完毕
        // for (int iteration = 1000; iteration > 0; iteration--)
        // {
        //     var readResult = await ReadRegister(0x3029);
        //     if (!readResult.IsSuccessful)
        //     {
        //         logger.Error($"读取自动对焦初始化状态失败: {readResult.Error}");
        //         return new(readResult.Error);
        //     }

        //     logger.Debug($"自动对焦初始化状态检查, state=0x{readResult.Value:X2}");

        //     if (readResult.Value != 0x7F)
        //     {
        //         break; // 初始化完成
        //     }

        //     if (iteration == 1)
        //     {
        //         logger.Error($"自动对焦初始化状态检查超时!! state=0x{readResult.Value:X2}");
        //         return new(new Exception($"自动对焦初始化状态检查超时, state=0x{readResult.Value:X2}"));
        //     }

        //     await Task.Delay(1);
        // }

        logger.Info("OV5640自动对焦功能初始化完成");
        return true;
    }

    /// <summary>
    /// 执行一次自动对焦
    /// </summary>
    /// <returns>对焦结果</returns>
    public async ValueTask<Result<bool>> PerformAutoFocus()
    {
        logger.Info("开始执行一次自动对焦");

        // 步骤1: 将 0x3022 寄存器写为 0x03，开始单点对焦过程
        var focusCmdResult = await ConfigureRegisters([[0x3022, 0x03]]);
        if (!focusCmdResult.IsSuccessful)
        {
            logger.Error($"写入对焦命令失败: {focusCmdResult.Error}");
            return focusCmdResult;
        }

        logger.Info("已发送单点对焦命令 (0x3022 = 0x03)");

        // 步骤2: 读取寄存器 0x3029 的状态，如果返回值为 0x10，代表对焦已完成
        for (int iteration = 5000; iteration > 0; iteration--)
        {
            var readResult = await ReadRegister(0x3029);
            if (!readResult.IsSuccessful)
            {
                logger.Error($"读取对焦状态寄存器(0x3029)失败: {readResult.Error}");
                return new(readResult.Error);
            }

            if (readResult.Value == 0x10)
            {
                logger.Info("对焦已完成 (0x3029 = 0x10)");
                break;
            }

            if (iteration == 1)
            {
                logger.Error($"自动对焦超时，状态: 0x{readResult.Value:X2}");
                return new(new Exception($"自动对焦超时，状态: 0x{readResult.Value:X2}"));
            }

            await Task.Delay(100);
        }

        // 步骤3: 写寄存器 0x3022 为 0x06，暂停对焦过程，使镜头将保持在此对焦位置
        var pauseResult = await ConfigureRegisters([[0x3022, 0x06]]);
        if (!pauseResult.IsSuccessful)
        {
            logger.Error($"暂停对焦过程失败: {pauseResult.Error}");
            return pauseResult;
        }

        logger.Info("自动对焦完成并暂停，镜头保持在对焦位置");
        return true;
    }

    #endregion
}
