diff --git a/server/src/Peripherals/CameraClient.cs b/server/src/Peripherals/CameraClient.cs index 855808a..1f0e54d 100644 --- a/server/src/Peripherals/CameraClient.cs +++ b/server/src/Peripherals/CameraClient.cs @@ -483,49 +483,6 @@ class Camera /// 配置结果 public async ValueTask> ConfigureResolution1280x720() { - // var Registers = new UInt16[][] - // { - // // 1280x720, 15fps - // // input clock 24Mhz, PCLK 42Mhz - // // [0x3035, 0x41], // PLL - // // [0x3036, 0x69], // PLL - // [0x3c07, 0x07], // lightmeter 1 threshold[7:0] - // [0x3820, 0x41], // flip - // [0x3821, 0x07], // mirror - // [0x3814, 0x31], // timing X inc - // [0x3815, 0x31], // timing Y inc - // [0x3800, 0x00], // HS - // [0x3801, 0x00], // HS - // [0x3802, 0x00], // VS - // [0x3803, 0xfa], // VS - // [0x3804, 0x0a], // HW (HE) - // [0x3805, 0x3f], // HW (HE) - // [0x3806, 0x06], // VH (VE) - // [0x3807, 0xa9], // VH (VE) - // [0x3808, 0x05], // DVPHO - // [0x3809, 0x00], // DVPHO - // [0x380a, 0x02], // DVPVO - // [0x380b, 0xd0], // DVPVO - // [0x380c, 0x0B], // HTS - // [0x380d, 0x1C], // HTS - // [0x380e, 0x07], // VTS - // [0x380f, 0xB0], // VTS - // [0x3810, 0x00], // Timing Hoffset[11:8] - // [0x3811, 0x10], // Timing Hoffset[7:0] - // [0x3812, 0x00], // Timing Voffset[10:8] - // [0x3813, 0x04], // timing V offset - // [0x3618, 0x00], - // [0x3612, 0x29], - // [0x3709, 0x52], - // [0x370c, 0x03] - // // [0x3a02, 0x02], // 60Hz max exposure - // // [0x3a03, 0xe0], // 60Hz max exposure - // // [0x3a14, 0x02], // 50Hz max exposure - // // [0x3a15, 0xe0] // 50Hz max exposure - // }; - - // await ConfigureRegisters(Registers); - return await ConfigureResolution( hStart: 0, vStart: 250, dvpHo: 1280, dvpVo: 720, @@ -533,6 +490,37 @@ class Camera hOffset: 16, vOffset: 4, hWindow: 2624, vWindow: 1456 ); + } + + /// + /// 配置为1280x720分辨率 + /// + /// 配置结果 + public async ValueTask> ConfigureResolution1280x960() + { + return await ConfigureResolution( + hStart: 0, vStart: 250, + dvpHo: 1280, dvpVo: 960, + hts: 2844, vts: 1968, + hOffset: 16, vOffset: 4, + hWindow: 2624, vWindow: 1456 + ); + + } + + /// + /// 配置为1920x1080分辨率 + /// + /// 配置结果 + public async ValueTask> ConfigureResolution1920x1080() + { + return await ConfigureResolution( + hStart: 0, vStart: 250, + dvpHo: 1920, dvpVo: 1080, + hts: 2844, vts: 1968, + hOffset: 16, vOffset: 4, + hWindow: 2624, vWindow: 1456 + ); } @@ -558,6 +546,12 @@ class Camera 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}")); @@ -956,8 +950,8 @@ class Camera [0x3035, 0x21], // 60fps [0x3036, PLL_MUX],// PLL倍频 [0x3c07, 0x08], - [0x3820, 0x41], // vflip - [0x3821, 0x00], // mirror + [0x3820, 0x40], // vflip + [0x3821, 0x01], // mirror [0x3814, 0x11], // timing X inc [0x3815, 0x11] // timing Y inc }; @@ -1336,37 +1330,38 @@ class Camera [0x3026, 0x00], [0x3027, 0x00], [0x3028, 0x00], - [0x3029, 0x7F], // 状态寄存器 - [0x3000, 0x00] // 启动MCU + [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); - } + // // 读取寄存器判断初始化是否完毕 + // 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}"); + // logger.Debug($"自动对焦初始化状态检查, state=0x{readResult.Value:X2}"); - if (readResult.Value != 0x7F) - { - break; // 初始化完成 - } + // if (readResult.Value != 0x7F) + // { + // break; // 初始化完成 + // } - if (iteration == 1) - { - logger.Error($"自动对焦初始化状态检查超时!! state=0x{readResult.Value:X2}"); - return new(new Exception($"自动对焦初始化状态检查超时, state=0x{readResult.Value:X2}")); - } + // if (iteration == 1) + // { + // logger.Error($"自动对焦初始化状态检查超时!! state=0x{readResult.Value:X2}"); + // return new(new Exception($"自动对焦初始化状态检查超时, state=0x{readResult.Value:X2}")); + // } - await Task.Delay(1); - } + // await Task.Delay(1); + // } logger.Info("OV5640自动对焦功能初始化完成"); return true; diff --git a/server/src/Peripherals/I2cClient.cs b/server/src/Peripherals/I2cClient.cs index f47afa2..878e891 100644 --- a/server/src/Peripherals/I2cClient.cs +++ b/server/src/Peripherals/I2cClient.cs @@ -174,7 +174,7 @@ public class I2c // 等待I2C命令完成 { - var ret = await UDPClientPool.ReadAddrWithWait(this.ep, this.taskID, I2cAddr.Flag, 0x0000_0001, 0xFFFF_FFFF); + var ret = await UDPClientPool.ReadAddrWithWait(this.ep, this.taskID, I2cAddr.Flag, 0x0000_0001, 0xFFFF_FFFF, 10); if (!ret.IsSuccessful) { logger.Error($"Failed to wait for I2C command completion: {ret.Error}"); @@ -280,7 +280,7 @@ public class I2c // 等待I2C命令完成 { - var ret = await UDPClientPool.ReadAddrWithWait(this.ep, this.taskID, I2cAddr.Flag, 0x0000_0001, 0xFFFF_FFFF); + var ret = await UDPClientPool.ReadAddrWithWait(this.ep, this.taskID, I2cAddr.Flag, 0x0000_0001, 0xFFFF_FFFF, 10); if (!ret.IsSuccessful) { logger.Error($"Failed to wait for I2C command completion: {ret.Error}"); diff --git a/server/src/Peripherals/JtagClient.cs b/server/src/Peripherals/JtagClient.cs index cae8873..6a6f581 100644 --- a/server/src/Peripherals/JtagClient.cs +++ b/server/src/Peripherals/JtagClient.cs @@ -452,7 +452,7 @@ public class Jtag await Task.Delay(TimeSpan.FromMilliseconds(delayMilliseconds)); { - var ret = await UDPClientPool.ReadAddrWithWait(this.ep, 0, JtagAddr.STATE, result, resultMask, this.timeout); + var ret = await UDPClientPool.ReadAddrWithWait(this.ep, 0, JtagAddr.STATE, result, resultMask, 0, this.timeout); if (!ret.IsSuccessful) return new(ret.Error); return ret.Value; } @@ -471,7 +471,7 @@ public class Jtag await Task.Delay(TimeSpan.FromMilliseconds(delayMilliseconds)); { - var ret = await UDPClientPool.ReadAddrWithWait(this.ep, 0, JtagAddr.STATE, result, resultMask, this.timeout); + var ret = await UDPClientPool.ReadAddrWithWait(this.ep, 0, JtagAddr.STATE, result, resultMask, 0, this.timeout); if (!ret.IsSuccessful) return new(ret.Error); return ret.Value; } diff --git a/server/src/Peripherals/RemoteUpdateClient.cs b/server/src/Peripherals/RemoteUpdateClient.cs index e17cad9..296afb8 100644 --- a/server/src/Peripherals/RemoteUpdateClient.cs +++ b/server/src/Peripherals/RemoteUpdateClient.cs @@ -99,7 +99,7 @@ public class RemoteUpdater const int FLASH_SECTOR_LENGTH = 4 * 1024; readonly int timeout = 2000; - readonly int timeoutForWait = 60 * 1000; + readonly int timeoutForWait = 20 * 1000; readonly int port; readonly string address; @@ -152,7 +152,7 @@ public class RemoteUpdater { var ret = await UDPClientPool.ReadAddrWithWait( this.ep, 0, RemoteUpdaterAddr.WriteSign, - 0x00_00_00_01, 0x00_00_00_01, this.timeoutForWait); + 0x00_00_00_01, 0x00_00_00_01, 100, this.timeoutForWait); if (!ret.IsSuccessful) return new(ret.Error); if (!ret.Value) return new(new Exception( $"Flash clear failed after {this.timeoutForWait} milliseconds")); @@ -167,7 +167,7 @@ public class RemoteUpdater { var ret = await UDPClientPool.ReadAddrWithWait( this.ep, 0, RemoteUpdaterAddr.WriteSign, - 0x00_00_01_00, 0x00_00_01_00, this.timeoutForWait); + 0x00_00_01_00, 0x00_00_01_00, 100, this.timeoutForWait); if (!ret.IsSuccessful) return new(ret.Error); return ret.Value; } @@ -332,7 +332,7 @@ public class RemoteUpdater { var ret = await UDPClientPool.ReadAddrWithWait( this.ep, 0, RemoteUpdaterAddr.ReadSign, - 0x00_00_01_00, 0x00_00_01_00, this.timeoutForWait); + 0x00_00_01_00, 0x00_00_01_00, 10, this.timeoutForWait); if (!ret.IsSuccessful) return new(ret.Error); if (!ret.Value) return new(new Exception( $"Read bitstream failed after {this.timeoutForWait} milliseconds")); diff --git a/server/src/Services/HttpVideoStreamService.cs b/server/src/Services/HttpVideoStreamService.cs index db63890..3fec4ad 100644 --- a/server/src/Services/HttpVideoStreamService.cs +++ b/server/src/Services/HttpVideoStreamService.cs @@ -946,14 +946,6 @@ public class HttpVideoStreamService : BackgroundService { logger.Info($"正在设置视频流分辨率为 {width}x{height}"); - // 验证分辨率 - if (!IsSupportedResolution(width, height)) - { - var message = $"不支持的分辨率: {width}x{height},支持的分辨率: 640x480, 1280x720"; - logger.Error(message); - return (false, message); - } - Camera? currentCamera = null; lock (_cameraLock) { @@ -1007,18 +999,6 @@ public class HttpVideoStreamService : BackgroundService } } - /// - /// 检查是否支持该分辨率 - /// - /// 宽度 - /// 高度 - /// 是否支持 - private bool IsSupportedResolution(int width, int height) - { - var resolution = $"{width}x{height}"; - return resolution == "640x480" || resolution == "1280x720"; - } - /// /// 获取支持的分辨率列表 /// @@ -1028,7 +1008,9 @@ public class HttpVideoStreamService : BackgroundService return new List<(int, int, string)> { (640, 480, "640x480 (VGA)"), - (1280, 720, "1280x720 (HD)") + (1280, 720, "1280x720 (HD)"), + (1280, 960, "1280x960 (SXGA)"), + (1920, 1080, "1920x1080 (Full HD)") }; } diff --git a/server/src/UdpClientPool.cs b/server/src/UdpClientPool.cs index 4b7712b..23e4501 100644 --- a/server/src/UdpClientPool.cs +++ b/server/src/UdpClientPool.cs @@ -306,10 +306,11 @@ public class UDPClientPool /// 设备地址 /// 期望的结果值 /// 结果掩码,用于位校验 + /// 等待间隔时间(毫秒) /// 超时时间(毫秒) /// 校验结果,true表示在超时前数据匹配期望值 public static async ValueTask> ReadAddrWithWait( - IPEndPoint endPoint, int taskID, uint devAddr, UInt32 result, UInt32 resultMask, int timeout = 1000) + IPEndPoint endPoint, int taskID, uint devAddr, UInt32 result, UInt32 resultMask, int waittime = 100, int timeout = 1000) { var address = endPoint.Address.ToString(); @@ -319,7 +320,7 @@ public class UDPClientPool var elapsed = DateTime.Now - startTime; if (elapsed >= TimeSpan.FromMilliseconds(timeout)) break; var timeleft = TimeSpan.FromMilliseconds(timeout) - elapsed; - + await Task.Delay(waittime); try { var ret = await ReadAddr(endPoint, taskID, devAddr, Convert.ToInt32(timeleft.TotalMilliseconds)); @@ -637,21 +638,23 @@ public class UDPClientPool IsWrite = true, }; + var max4BytesPerRead = 128; // 1024 bytes per read + // Check Msg Bus if (!MsgBus.IsRunning) return new(new Exception("Message bus not working!")); - var hasRest = dataArray.Length % (256 * (32 / 8)) != 0; + var hasRest = dataArray.Length % (max4BytesPerRead * (32 / 8)) != 0; var writeTimes = hasRest ? - dataArray.Length / (256 * (32 / 8)) + 1 : - dataArray.Length / (256 * (32 / 8)); + dataArray.Length / (max4BytesPerRead * (32 / 8)) + 1 : + dataArray.Length / (max4BytesPerRead * (32 / 8)); for (var i = 0; i < writeTimes; i++) { // Sperate Data Array var isLastData = i == writeTimes - 1; var sendDataArray = isLastData ? - dataArray[(i * (256 * (32 / 8)))..] : - dataArray[(i * (256 * (32 / 8)))..((i + 1) * (256 * (32 / 8)))]; + dataArray[(i * (max4BytesPerRead * (32 / 8)))..] : + dataArray[(i * (max4BytesPerRead * (32 / 8)))..((i + 1) * (max4BytesPerRead * (32 / 8)))]; // Calculate BurstLength opts.BurstLength = ((byte)(