using Aitex.Core.Common.DeviceData; using Aitex.Core.RT.DataCenter; using Aitex.Core.RT.Device; using Aitex.Core.RT.Log; using Aitex.Core.RT.OperationCenter; using Aitex.Core.RT.SCCore; using Aitex.Core.RT.Tolerance; using Aitex.Core.UI.Control; using Aitex.Core.Util; using MECF.Framework.Common.Communications; using MECF.Framework.Common.DataCenter; using MECF.Framework.Common.Device.Bases; using MECF.Framework.Common.Equipment; using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Net; using Venus_Core; namespace Venus_RT.Devices { public class TruPlasmaRF : RfPowerBase { private readonly AsyncSerialPort _serial; private static byte _ACK = 0x06; private static byte ParamRead = 0x01; private static byte ParamWrite = 0x02; private static byte TelegramError = 0xFE; private static byte MessageRead = 0x04; private static byte CtllnterfaceAct= 0x05; // private bool = 0x05; public TruPlasmaRF(ModuleName mod, VenusDevice device) : base(mod.ToString(), device.ToString()) { var portNum = SC.GetStringValue(device == VenusDevice.Rf ? $"{mod}.Rf.Port" : $"{mod}.BiasRf.Port"); _serial = new AsyncSerialPort(portNum, 9600, 8, System.IO.Ports.Parity.None, System.IO.Ports.StopBits.One, "\r\r"); } public override bool Initialize() { base.Initialize(); DATA.Subscribe($"{Module}.{Name}.DeviceData", () => DeviceData); if (_serial.Open()) { _serial.OnBinaryDataChanged += SerialPortDataReceived; _serial.OnErrorHappened += SerialPortErrorOccurred; } else { LOG.Write(eEvent.ERR_RF, Module, "Tru 射频发生器串口无法打开"); return false; } return true; } public new AITRfData DeviceData => new AITRfData { Module = Module, DeviceName = Name, ScalePower = ScalePower, ForwardPower = ForwardPower, ReflectPower = ReflectPower, IsRfOn = IsPowerOn, PowerSetPoint = PowerSetPoint, }; private void SerialPortDataReceived(byte[] rawMessage) { LOG.Write(eEvent.INFO_RF, Module, $"RF byte"+rawMessage.ToString()); try { if (rawMessage.Length==1&& rawMessage[1]== 0x06) //ACK 指令 { } else if (rawMessage.Length > 1) { parsecmd(rawMessage); } } catch (Exception ex) { LOG.WriteExeption(ex); } } public void parsecmd(byte[] message) { switch (message[4]) { case 0x01://ParamRead int DataValue = BitConverter.ToInt32(new byte[] { message[10], message[11], message[12], message[13] }, 0); ReflectPower = DataValue; break; case 0x02://ParamWrite DataValue = BitConverter.ToInt32(new byte[] { message[10] ,message[11], message[12], message[13] }, 0); ForwardPower = DataValue; break; case 0xFE://TelegramError LOG.Write(eEvent.ERR_RF, Module, "Telegram structure is not correct"); break; default: // 默认代码块 break; } } private void SerialPortErrorOccurred(string obj) { LOG.Write(eEvent.ERR_RF, Module, $"Tru 射频串口出错, [{obj}]"); } public override void SetPower(float val) { //var power = !_scEnableCalibration.BoolValue ? val : CalibrationData(val, true); ForwardPower=val; List baseBytes = new List() { 0xAA, 0x02, 0x0B, 0x00, 0x02, 0x06, 0x00, 0x01, 0x00, 0x04 }; byte[] valueBytes = BitConverter.GetBytes((int)val); baseBytes.AddRange(valueBytes); baseBytes = CRC16(baseBytes.ToArray()); baseBytes.Add(0x55); _serial.Write(baseBytes.ToArray()); } public override bool SetPowerOnOff(bool on, out string str) { str = ""; var _chamber = DEVICE.GetDevice(Module); if (on && !_chamber.CheckGeneratorAndHVInterlock(VenusDevice.Rf)) { return false; } List baseBytes = new List() { 0xAA, 0x02, 0x0B, 0x00, 0x02, 0x6F, 0x00, 0x01, 0x00, 0x07 }; if (on == true) { baseBytes.AddRange(new List { 0x01, 0x00, 0x00, 0x00 }); } else { baseBytes.AddRange(new List { 0x00, 0x00, 0x00, 0x00 }); } baseBytes = CRC16(baseBytes.ToArray()); baseBytes.Add(0x55); _serial.Write(baseBytes.ToArray()); return true; } public override void SetPulseMode(bool on) { List baseBytes = new List() { 0xAA, 0x02, 0x0B, 0x00, 0x02, 0x6A, 0x01, 0x01, 0x00, 0x04 }; if (on == true) { baseBytes.AddRange(new List { 0x01, 0x00, 0x00, 0x00 }); } else { baseBytes.AddRange(new List { 0x00, 0x00, 0x00, 0x00 }); } baseBytes = CRC16(baseBytes.ToArray()); baseBytes.Add(0x55); _serial.Write(baseBytes.ToArray()); } public override void SetPulseRateFreq(int nFreq) { if (nFreq > 0) { List baseBytes = new List() { 0xAA, 0x02, 0x0B, 0x00, 0x02, 0x6C, 0x01, 0x01, 0x00, 0x04 }; byte[] valueBytes = BitConverter.GetBytes(nFreq); baseBytes.AddRange(valueBytes); baseBytes = CRC16(baseBytes.ToArray()); baseBytes.Add(0x55); _serial.Write(baseBytes.ToArray()); } else { LOG.Write(eEvent.ERR_RF, Module, $"{Name},SetPulseRateFreq() parameter error: {nFreq}"); } } public override void SetPulseDutyCycle(int percentage) { if (percentage >= 10 && percentage <= 90) { List baseBytes = new List() { 0xAA, 0x02, 0x0B, 0x00, 0x02, 0x6D, 0x01, 0x01, 0x00, 0x04 }; byte[] valueBytes = BitConverter.GetBytes(percentage); baseBytes.AddRange(valueBytes); baseBytes = CRC16(baseBytes.ToArray()); baseBytes.Add(0x55); _serial.Write(baseBytes.ToArray()); } else { LOG.Write(eEvent.ERR_RF, Module, $"{Name},SetPulseDutyCycle() parameter error: {percentage}"); } } #region 霍廷格RF协议crc-16/CCITT-FALSE校验 private bool CRC16(byte[] buffer, ref byte[] ResCRC16) // crc-16/CCITT-FALSE,判断校验 { bool status = false; ushort crc = 0xFFFF; int size = buffer.Length; //计算待计算的数据长度 int i = 0; if (size > 0) { while (size-- > 0) { crc = (ushort)((crc >> 8) | (crc << 8)); crc ^= buffer[i++]; crc ^= (ushort)(((byte)crc) >> 4); crc ^= (ushort)(crc << 12); crc ^= (ushort)((crc & 0xff) << 5); } } //判断输入的ResCRC16与计算出来的是否一致 if (ResCRC16[0] == (byte)((crc >> 8) & 0xff) && ResCRC16[1] == (byte)(crc & 0xff)) { status = true; } return status; } private List CRC16(byte[] buffer) // crc-16/CCITT-FALSE,补全两个字节 { ushort crc = 0xFFFF; int size = buffer.Length; //计算待计算的数据长度 int i = 0; if (size > 0) { while (size-- > 0) { crc = (ushort)((crc >> 8) | (crc << 8)); crc ^= buffer[i++]; crc ^= (ushort)(((byte)crc) >> 4); crc ^= (ushort)(crc << 12); crc ^= (ushort)((crc & 0xff) << 5); } } var byteList = buffer.ToList(); byteList.Add((byte)(crc & 0xff)); byteList.Add((byte)((crc >> 8) & 0xff)); return byteList; } #endregion } }