using LFP_Manager.Utils; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace LFP_Manager.Function { internal class CsModbusFunction { static public byte[] MakeWriteRegisterData(ushort devId, ushort writeAddr, short[] writeData) { if (writeData == null || writeData.Length == 0) return Array.Empty(); // 부호 확장 없이 캐스팅 (2’s complement 그대로 0..65535 범위로 들어갑니다) Span regs = writeData.Length <= 16 ? stackalloc ushort[writeData.Length] : new ushort[writeData.Length]; // 길면 힙 사용 for (int k = 0; k < writeData.Length; k++) regs[k] = unchecked((ushort)writeData[k]); return MakeWriteRegisterData(devId, writeAddr, regs); } static private byte[] MakeWriteRegisterData(ushort devId, ushort writeAddr, ReadOnlySpan writeData) { if (writeData.Length <= 0) return Array.Empty(); const byte Func = 0x10; // PRESET_MULTI_REG int regCount = writeData.Length; int payloadLen = 7 + regCount * 2; // CRC 제외 길이 byte[] frame = new byte[payloadLen + 2]; int i = 0; frame[i++] = (byte)devId; // Device ID frame[i++] = Func; // Function Code (0x10) frame[i++] = (byte)(writeAddr >> 8); // Addr Hi frame[i++] = (byte)writeAddr; // Addr Lo frame[i++] = (byte)(regCount >> 8); // Count Hi frame[i++] = (byte)regCount; // Count Lo frame[i++] = (byte)(regCount * 2); // ByteCount // 데이터: 각 레지스터를 Hi → Lo 바이트로 for (int j = 0; j < regCount; j++) { ushort v = writeData[j]; frame[i++] = (byte)(v >> 8); frame[i++] = (byte)v; } // CRC (CRCL → CRCH) 부착 if (!CsCRC16.TryAppendCrcLowHigh(frame, payloadLen, 0)) return Array.Empty(); return frame; } } }