From 750ff5304ebbe9cff4f07997f05fe6274b3a2e22 Mon Sep 17 00:00:00 2001
From: wanshenmean <cathay_xy@163.com>
Date: 星期五, 13 三月 2026 12:54:50 +0800
Subject: [PATCH] feat: implement I/Q/T/C regions

---
 Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Core/Memory/IRegion.cs |  106 +++++++++++++++
 Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Core/Memory/TRegion.cs |   83 +++++++++++
 Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Core/Memory/QRegion.cs |  106 +++++++++++++++
 Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Core/Memory/CRegion.cs |   83 +++++++++++
 4 files changed, 378 insertions(+), 0 deletions(-)

diff --git a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Core/Memory/CRegion.cs b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Core/Memory/CRegion.cs
new file mode 100644
index 0000000..f5a7b62
--- /dev/null
+++ b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Core/Memory/CRegion.cs
@@ -0,0 +1,83 @@
+using System;
+using WIDESEAWCS_S7Simulator.Core.Interfaces;
+
+namespace WIDESEAWCS_S7Simulator.Core.Memory
+{
+    /// <summary>
+    /// C鍖猴紙璁℃暟鍣ㄥ尯/Counter锛夊疄鐜�
+    /// 鐢ㄤ簬妯℃嫙瑗块棬瀛怱7 PLC鐨勮鏁板櫒鍖哄煙
+    /// 姣忎釜璁℃暟鍣ㄥ崰鐢�2瀛楄妭锛屽瓨鍌ㄨ鏁板櫒鐨勫綋鍓嶅��
+    /// </summary>
+    public class CRegion : MemoryRegion, IMemoryRegion
+    {
+        /// <summary>
+        /// 鏍囪瘑瀵硅薄鏄惁宸茶閲婃斁
+        /// </summary>
+        private bool _disposed = false;
+
+        /// <summary>
+        /// 鍖哄煙绫诲瀷
+        /// </summary>
+        public override string RegionType => "C";
+
+        /// <summary>
+        /// 姣忎釜璁℃暟鍣ㄥ崰鐢ㄧ殑瀛楄妭鏁帮紙S7璁℃暟鍣ㄤ负2瀛楄妭锛�
+        /// </summary>
+        private const int CounterSize = 2;
+
+        /// <summary>
+        /// 鏋勯�犲嚱鏁�
+        /// </summary>
+        /// <param name="counterCount">璁℃暟鍣ㄦ暟閲�</param>
+        public CRegion(int counterCount) : base(counterCount * CounterSize)
+        {
+        }
+
+        /// <summary>
+        /// 璇诲彇璁℃暟鍣ㄥ��
+        /// </summary>
+        /// <param name="counterNumber">璁℃暟鍣ㄥ彿锛堜粠1寮�濮嬶級</param>
+        /// <returns>璁℃暟鍣ㄥ��</returns>
+        public ushort ReadCounter(ushort counterNumber)
+        {
+            if (_disposed)
+                throw new ObjectDisposedException(nameof(CRegion));
+
+            ushort offset = (ushort)((counterNumber - 1) * CounterSize);
+            var data = Read(offset, CounterSize);
+            return (ushort)((data[0] << 8) | data[1]);
+        }
+
+        /// <summary>
+        /// 鍐欏叆璁℃暟鍣ㄥ��
+        /// </summary>
+        /// <param name="counterNumber">璁℃暟鍣ㄥ彿锛堜粠1寮�濮嬶級</param>
+        /// <param name="value">璁℃暟鍣ㄥ��</param>
+        public void WriteCounter(ushort counterNumber, ushort value)
+        {
+            if (_disposed)
+                throw new ObjectDisposedException(nameof(CRegion));
+
+            ushort offset = (ushort)((counterNumber - 1) * CounterSize);
+            var data = new byte[] { (byte)(value >> 8), (byte)(value & 0xFF) };
+            Write(offset, data);
+        }
+
+        /// <summary>
+        /// 閲婃斁璧勬簮
+        /// </summary>
+        /// <param name="disposing">鏄惁姝e湪閲婃斁鎵樼璧勬簮</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (!_disposed)
+            {
+                if (disposing)
+                {
+                    // 閲婃斁鎵樼璧勬簮
+                }
+                _disposed = true;
+            }
+            base.Dispose(disposing);
+        }
+    }
+}
diff --git a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Core/Memory/IRegion.cs b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Core/Memory/IRegion.cs
new file mode 100644
index 0000000..b82a8f3
--- /dev/null
+++ b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Core/Memory/IRegion.cs
@@ -0,0 +1,106 @@
+using System;
+using WIDESEAWCS_S7Simulator.Core.Interfaces;
+
+namespace WIDESEAWCS_S7Simulator.Core.Memory
+{
+    /// <summary>
+    /// I鍖猴紙杈撳叆鍖�/Input锛夊疄鐜�
+    /// 鐢ㄤ簬妯℃嫙瑗块棬瀛怱7 PLC鐨勮緭鍏ヨ繃绋嬫槧鍍忓尯
+    /// </summary>
+    public class IRegion : MemoryRegion, IMemoryRegion
+    {
+        /// <summary>
+        /// 鏍囪瘑瀵硅薄鏄惁宸茶閲婃斁
+        /// </summary>
+        private bool _disposed = false;
+
+        /// <summary>
+        /// 鍖哄煙绫诲瀷
+        /// </summary>
+        public override string RegionType => "I";
+
+        /// <summary>
+        /// 鏋勯�犲嚱鏁�
+        /// </summary>
+        /// <param name="size">鍖哄煙澶у皬锛堝瓧鑺傦級</param>
+        public IRegion(int size) : base(size)
+        {
+        }
+
+        /// <summary>
+        /// 璇诲彇浣�
+        /// </summary>
+        /// <param name="byteOffset">瀛楄妭鍋忕Щ閲�</param>
+        /// <param name="bitOffset">浣嶅亸绉婚噺锛�0-7锛�</param>
+        /// <returns>浣嶇姸鎬侊紙true/false锛�</returns>
+        public bool ReadBit(ushort byteOffset, byte bitOffset)
+        {
+            if (_disposed)
+                throw new ObjectDisposedException(nameof(IRegion));
+
+            if (bitOffset > 7)
+                throw new ArgumentOutOfRangeException(nameof(bitOffset), "浣嶅亸绉诲繀椤诲湪0-7涔嬮棿");
+
+            _lock.EnterReadLock();
+            try
+            {
+                if (byteOffset >= Size)
+                    throw new ArgumentOutOfRangeException(nameof(byteOffset), "瀛楄妭鍋忕Щ瓒呭嚭I鍖鸿寖鍥�");
+
+                return (_memory[byteOffset] & (1 << bitOffset)) != 0;
+            }
+            finally
+            {
+                _lock.ExitReadLock();
+            }
+        }
+
+        /// <summary>
+        /// 鍐欏叆浣�
+        /// </summary>
+        /// <param name="byteOffset">瀛楄妭鍋忕Щ閲�</param>
+        /// <param name="bitOffset">浣嶅亸绉婚噺锛�0-7锛�</param>
+        /// <param name="value">浣嶅�硷紙true/false锛�</param>
+        public void WriteBit(ushort byteOffset, byte bitOffset, bool value)
+        {
+            if (_disposed)
+                throw new ObjectDisposedException(nameof(IRegion));
+
+            if (bitOffset > 7)
+                throw new ArgumentOutOfRangeException(nameof(bitOffset), "浣嶅亸绉诲繀椤诲湪0-7涔嬮棿");
+
+            _lock.EnterWriteLock();
+            try
+            {
+                if (byteOffset >= Size)
+                    throw new ArgumentOutOfRangeException(nameof(byteOffset), "瀛楄妭鍋忕Щ瓒呭嚭I鍖鸿寖鍥�");
+
+                if (value)
+                    _memory[byteOffset] |= (byte)(1 << bitOffset);
+                else
+                    _memory[byteOffset] &= (byte)~(1 << bitOffset);
+            }
+            finally
+            {
+                _lock.ExitWriteLock();
+            }
+        }
+
+        /// <summary>
+        /// 閲婃斁璧勬簮
+        /// </summary>
+        /// <param name="disposing">鏄惁姝e湪閲婃斁鎵樼璧勬簮</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (!_disposed)
+            {
+                if (disposing)
+                {
+                    // 閲婃斁鎵樼璧勬簮
+                }
+                _disposed = true;
+            }
+            base.Dispose(disposing);
+        }
+    }
+}
diff --git a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Core/Memory/QRegion.cs b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Core/Memory/QRegion.cs
new file mode 100644
index 0000000..9760a0c
--- /dev/null
+++ b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Core/Memory/QRegion.cs
@@ -0,0 +1,106 @@
+using System;
+using WIDESEAWCS_S7Simulator.Core.Interfaces;
+
+namespace WIDESEAWCS_S7Simulator.Core.Memory
+{
+    /// <summary>
+    /// Q鍖猴紙杈撳嚭鍖�/Output锛夊疄鐜�
+    /// 鐢ㄤ簬妯℃嫙瑗块棬瀛怱7 PLC鐨勮緭鍑鸿繃绋嬫槧鍍忓尯
+    /// </summary>
+    public class QRegion : MemoryRegion, IMemoryRegion
+    {
+        /// <summary>
+        /// 鏍囪瘑瀵硅薄鏄惁宸茶閲婃斁
+        /// </summary>
+        private bool _disposed = false;
+
+        /// <summary>
+        /// 鍖哄煙绫诲瀷
+        /// </summary>
+        public override string RegionType => "Q";
+
+        /// <summary>
+        /// 鏋勯�犲嚱鏁�
+        /// </summary>
+        /// <param name="size">鍖哄煙澶у皬锛堝瓧鑺傦級</param>
+        public QRegion(int size) : base(size)
+        {
+        }
+
+        /// <summary>
+        /// 璇诲彇浣�
+        /// </summary>
+        /// <param name="byteOffset">瀛楄妭鍋忕Щ閲�</param>
+        /// <param name="bitOffset">浣嶅亸绉婚噺锛�0-7锛�</param>
+        /// <returns>浣嶇姸鎬侊紙true/false锛�</returns>
+        public bool ReadBit(ushort byteOffset, byte bitOffset)
+        {
+            if (_disposed)
+                throw new ObjectDisposedException(nameof(QRegion));
+
+            if (bitOffset > 7)
+                throw new ArgumentOutOfRangeException(nameof(bitOffset), "浣嶅亸绉诲繀椤诲湪0-7涔嬮棿");
+
+            _lock.EnterReadLock();
+            try
+            {
+                if (byteOffset >= Size)
+                    throw new ArgumentOutOfRangeException(nameof(byteOffset), "瀛楄妭鍋忕Щ瓒呭嚭Q鍖鸿寖鍥�");
+
+                return (_memory[byteOffset] & (1 << bitOffset)) != 0;
+            }
+            finally
+            {
+                _lock.ExitReadLock();
+            }
+        }
+
+        /// <summary>
+        /// 鍐欏叆浣�
+        /// </summary>
+        /// <param name="byteOffset">瀛楄妭鍋忕Щ閲�</param>
+        /// <param name="bitOffset">浣嶅亸绉婚噺锛�0-7锛�</param>
+        /// <param name="value">浣嶅�硷紙true/false锛�</param>
+        public void WriteBit(ushort byteOffset, byte bitOffset, bool value)
+        {
+            if (_disposed)
+                throw new ObjectDisposedException(nameof(QRegion));
+
+            if (bitOffset > 7)
+                throw new ArgumentOutOfRangeException(nameof(bitOffset), "浣嶅亸绉诲繀椤诲湪0-7涔嬮棿");
+
+            _lock.EnterWriteLock();
+            try
+            {
+                if (byteOffset >= Size)
+                    throw new ArgumentOutOfRangeException(nameof(byteOffset), "瀛楄妭鍋忕Щ瓒呭嚭Q鍖鸿寖鍥�");
+
+                if (value)
+                    _memory[byteOffset] |= (byte)(1 << bitOffset);
+                else
+                    _memory[byteOffset] &= (byte)~(1 << bitOffset);
+            }
+            finally
+            {
+                _lock.ExitWriteLock();
+            }
+        }
+
+        /// <summary>
+        /// 閲婃斁璧勬簮
+        /// </summary>
+        /// <param name="disposing">鏄惁姝e湪閲婃斁鎵樼璧勬簮</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (!_disposed)
+            {
+                if (disposing)
+                {
+                    // 閲婃斁鎵樼璧勬簮
+                }
+                _disposed = true;
+            }
+            base.Dispose(disposing);
+        }
+    }
+}
diff --git a/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Core/Memory/TRegion.cs b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Core/Memory/TRegion.cs
new file mode 100644
index 0000000..a406bef
--- /dev/null
+++ b/Code/WCS/WIDESEAWCS_S7Simulator/WIDESEAWCS_S7Simulator.Core/Memory/TRegion.cs
@@ -0,0 +1,83 @@
+using System;
+using WIDESEAWCS_S7Simulator.Core.Interfaces;
+
+namespace WIDESEAWCS_S7Simulator.Core.Memory
+{
+    /// <summary>
+    /// T鍖猴紙瀹氭椂鍣ㄥ尯/Timer锛夊疄鐜�
+    /// 鐢ㄤ簬妯℃嫙瑗块棬瀛怱7 PLC鐨勫畾鏃跺櫒鍖哄煙
+    /// 姣忎釜瀹氭椂鍣ㄥ崰鐢�2瀛楄妭锛屽瓨鍌ㄥ畾鏃跺櫒鐨勬椂闂村�硷紙姣锛�
+    /// </summary>
+    public class TRegion : MemoryRegion, IMemoryRegion
+    {
+        /// <summary>
+        /// 鏍囪瘑瀵硅薄鏄惁宸茶閲婃斁
+        /// </summary>
+        private bool _disposed = false;
+
+        /// <summary>
+        /// 鍖哄煙绫诲瀷
+        /// </summary>
+        public override string RegionType => "T";
+
+        /// <summary>
+        /// 姣忎釜瀹氭椂鍣ㄥ崰鐢ㄧ殑瀛楄妭鏁帮紙S7瀹氭椂鍣ㄤ负2瀛楄妭锛�
+        /// </summary>
+        private const int TimerSize = 2;
+
+        /// <summary>
+        /// 鏋勯�犲嚱鏁�
+        /// </summary>
+        /// <param name="timerCount">瀹氭椂鍣ㄦ暟閲�</param>
+        public TRegion(int timerCount) : base(timerCount * TimerSize)
+        {
+        }
+
+        /// <summary>
+        /// 璇诲彇瀹氭椂鍣ㄥ��
+        /// </summary>
+        /// <param name="timerNumber">瀹氭椂鍣ㄥ彿锛堜粠1寮�濮嬶級</param>
+        /// <returns>瀹氭椂鍣ㄥ�硷紙姣锛�</returns>
+        public ushort ReadTimer(ushort timerNumber)
+        {
+            if (_disposed)
+                throw new ObjectDisposedException(nameof(TRegion));
+
+            ushort offset = (ushort)((timerNumber - 1) * TimerSize);
+            var data = Read(offset, TimerSize);
+            return (ushort)((data[0] << 8) | data[1]);
+        }
+
+        /// <summary>
+        /// 鍐欏叆瀹氭椂鍣ㄥ��
+        /// </summary>
+        /// <param name="timerNumber">瀹氭椂鍣ㄥ彿锛堜粠1寮�濮嬶級</param>
+        /// <param name="value">瀹氭椂鍣ㄥ�硷紙姣锛�</param>
+        public void WriteTimer(ushort timerNumber, ushort value)
+        {
+            if (_disposed)
+                throw new ObjectDisposedException(nameof(TRegion));
+
+            ushort offset = (ushort)((timerNumber - 1) * TimerSize);
+            var data = new byte[] { (byte)(value >> 8), (byte)(value & 0xFF) };
+            Write(offset, data);
+        }
+
+        /// <summary>
+        /// 閲婃斁璧勬簮
+        /// </summary>
+        /// <param name="disposing">鏄惁姝e湪閲婃斁鎵樼璧勬簮</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (!_disposed)
+            {
+                if (disposing)
+                {
+                    // 閲婃斁鎵樼璧勬簮
+                }
+                _disposed = true;
+            }
+            base.Dispose(disposing);
+        }
+    }
+}

--
Gitblit v1.9.3