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.Diagnostics; 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 } static class TruPlasmaMatchMessage { public const string PRESET = "G"; public const string AUTO = "L"; public const string MANUAL = "M"; public const string PRESET_MEM = "P"; public const string START_QUERY = "S3"; public const string STOP_QUERY = "SP"; public const string WRITE_POS = "$APGR"; public const string READ_POS = "$APRR"; } class TruPlasmaMatch : RfMatchBase { private readonly AsyncSerialPort _serial; private const ushort S3_HEAD_LENGTH = 2; private readonly DeviceTimer _timerQueryStatus = new DeviceTimer(); private int QUERY_INTERVAL = 1000; //private int _scMatchPresetMode; //private int _scMatchMode; //private readonly SCConfigItem _scMatchPositionC1; //private readonly SCConfigItem _scMatchPositionC2; //private readonly bool _scEnableC1C2Position; // --------------------------Properties------------------------ // [Subscription("MatchWorkMode")] public EnumRfMatchTuneMode WorkMode { get; set; } public float C1 { get; set; } public float C2 { get; set; } //[Subscription("VPP")] public ushort VPP { get; set; } public new AITMatchData DeviceData { get { return new AITMatchData { Module = Module, DeviceName = Name, WorkMode = WorkMode.ToString(), C1 = TunePosition1, C2 = TunePosition2, VPP = "", DCBias = DCBias.ToString() }; } } public TruPlasmaMatch(ModuleName mod, VenusDevice device) : base(mod.ToString(), device.ToString()) { var portNum = SC.GetStringValue($"{mod}.{device}.Port"); _serial = new AsyncSerialPort(portNum, 9600, 8); //_scMatchPresetMode = SC.GetValue($"{Module}.Rf.PresetMode"); //_scMatchMode = SC.GetValue($"{Module}.Rf.MatchMode"); //_scMatchPositionC1 = SC.GetConfigItem($"{Module}.Rf.MatchPositionC1"); //_scMatchPositionC2 = SC.GetConfigItem($"{Module}.Rf.MatchPositionC2"); //_scEnableC1C2Position = SC.GetValue($"{Module}.Rf.EnableC1C2Position"); SerachCommandList = new List() { AdTecMatchMessage.READ_POS, AdTecMatchMessage.START_QUERY }; intervalTime = 100; sendDataChangedEvent += TruMatch_sendDataChangedEvent; baseStopwatch.Start(); baseTimer.Enabled = true; } private void TruMatch_sendDataChangedEvent(string obj) { this.SendCmd(obj); } ~TruPlasmaMatch() { _serial?.Close(); } public override bool Initialize() { base.Initialize(); if (_serial.Open()) { _serial.OnBinaryDataChanged += SerialBinaryPortDataReceived; _serial.OnErrorHappened += SerialPortErrorOccurred; } else { LOG.Write(eEvent.ERR_RF, Module, "Match 串口无法打开"); return false; } DATA.Subscribe($"{Module}.{Name}.C1", () => TunePosition1); DATA.Subscribe($"{Module}.{Name}.C2", () => TunePosition2); DATA.Subscribe($"{Module}.{Name}.WorkMode", () => WorkMode.ToString()); OP.Subscribe($"{Module}.{Name}.SetC1", (func, args) => { return true; }); OP.Subscribe($"{Module}.{Name}.SetC2", (func, args) => { return true; }); OP.Subscribe($"{Module}.{Name}.{AITRfOperation.SetMatchPositionC1}", (out string reason, int time, object[] param) => { SetMatchPositionC1((float)Convert.ToDouble(param[0]), out reason); return true; }); OP.Subscribe($"{Module}.{Name}.{AITRfOperation.SetMatchPositionC2}", (out string reason, int time, object[] param) => { SetMatchPositionC2((float)Convert.ToDouble(param[0]), out reason); return true; }); OP.Subscribe($"{Module}.{Name}.{AITRfOperation.SetMatchPosition}", (out string reason, int time, object[] param) => { SetMatchPosition((float)Convert.ToDouble(param[0]), (float)Convert.ToDouble(param[1]), out reason); return true; }); OP.Subscribe($"{Module}.{Name}.{AITRfOperation.SetMatchProcessMode}", (out string reason, int time, object[] param) => { SetMatchMode((string)param[0] == "Auto" ? EnumRfMatchTuneMode.Auto : EnumRfMatchTuneMode.Manual, out reason); return true; }); _timerQueryStatus.Start(QUERY_INTERVAL); this.SendCmd(AdTecMatchMessage.START_QUERY); //LOG.Write(eEvent.ERR_RF, Module, "Initialize done."); return true; } public override void Monitor() { //try //{ // if (_timerQueryStatus.IsTimeout()) // { // this.SendCmd(AdTecMatchMessage.READ_POS); // _timerQueryStatus.Start(QUERY_INTERVAL); // } //} //catch (Exception ex) //{ // LOG.WriteExeption(ex); //} } public override void Terminate() { this.SendCmd(AdTecMatchMessage.STOP_QUERY); } public override void Reset() { //SendCmd(AdTecMatchMessage.STOP_QUERY); } /// /// /// /// 百分比数字 /// /// private void executeMatchPostion(float c1, float c2) { //SetWorkMode(EnumRfMatchTuneMode.Manual); ////await Task.Delay(200); SetPosition(c1, c2); //await Task.Delay(200); //SetPresetMemory(0); //await Task.Delay(200); // SetWorkMode(EnumRfMatchTuneMode.Auto); } public override void SetMatchPosition(float c1, float c2, out string reason) { float DataValue = BitConverter.ToSingle(new byte[] { 0x9A, 0x99, 0x19,0x3F }, 0); byte[] floatAsBytes = BitConverter.GetBytes(DataValue); float DataValue1= BitConverter.ToSingle(new byte[] { floatAsBytes[0], floatAsBytes[1], floatAsBytes[2], floatAsBytes[3] }, 0); //LOG.Write(eEvent.WARN_RF, Module, $"AdTec Match error [{c1}, {c2}]"); base.SetMatchPosition(c1, c2, out reason); executeMatchPostion(c1, c2); reason = ""; } public void SetPresetMode(RfMatchPresetMode mode) { } // -----------------------Private Method------------------------- // private void SerialBinaryPortDataReceived(byte[] message) { if(message.Count()==0) { LOG.Write(eEvent.ERR_RF, Module, "收到 Match 数据为空"); return; } else { if (message[0] ==0x1D && message[6]==0x60 && message[7] == 0x00) { this.TunePosition1 = BitConverter.ToSingle(new byte[] { message[10], message[11], message[12], message[13] }, 0) * 10; this.TunePosition2 = BitConverter.ToSingle(new byte[] { message[14], message[15], message[16], message[17] }, 0) * 10; switch (message[7]) { case 0x01: this.WorkMode = EnumRfMatchTuneMode.Manual; break; case 0x02: this.WorkMode = EnumRfMatchTuneMode.Auto; break; case 0x20: this.WorkMode = EnumRfMatchTuneMode.Undefined; break; default: break; } } } } private void SerialPortErrorOccurred(string str) { LOG.Write(eEvent.ERR_RF, Module, $"AdTec Match error [{str}]"); } private void SendCmd(string str) { _serial?.Write(str + "\r"); //EV.PostInfoLog(Module.ToString(), $"Match send [{str}]"); } private void SetPosition(float c1val, float c2val) { List Len = new List() { 0x16, 0xE9}; List DstSrc = new List() { 0x00, 0x0A, 0x00, 0x00}; List Cmd = new List { 0x60, 0x40 }; byte[] val1Bytes = BitConverter.GetBytes(c1val / 100); byte[] val2Bytes = BitConverter.GetBytes(c2val / 100); List Act = new List() { 0x64 }; List Ctr123 = new List { 0x08, 0x01, 0x80 }; List baseBytes = new List() { }; baseBytes.AddRange(Len); baseBytes.AddRange(DstSrc); baseBytes.AddRange(Cmd); baseBytes.AddRange(val1Bytes); baseBytes.AddRange(val2Bytes); baseBytes.AddRange(Act); baseBytes.AddRange(Ctr123); byte ack=0x00; for (int i=2; i< baseBytes.Count;i++) { ack += baseBytes[i]; } baseBytes.Add(ack); //SetPointCommandQueue.Add(cmd); _serial.Write(baseBytes.ToArray()); } public override bool SetMatchMode(EnumRfMatchTuneMode enumRfMatchTuneMode, out string reason) { reason = string.Empty; SetWorkMode(enumRfMatchTuneMode); return true; } private void SetWorkMode(EnumRfMatchTuneMode mode) { //string data = mode == EnumRfMatchTuneMode.Auto ? AdTecMatchMessage.AUTO : // mode == EnumRfMatchTuneMode.Manual ? AdTecMatchMessage.MANUAL : ""; //this.SendCmd(mode == EnumRfMatchTuneMode.Auto ? AdTecMatchMessage.AUTO : // mode == EnumRfMatchTuneMode.Manual ? AdTecMatchMessage.MANUAL : ""); //SetPointCommandQueue.Add(data); } private void SetPresetMemory(byte gear) { //this.SendCmd(AdTecMatchMessage.PRESET_MEM + gear.ToString()); //SetPointCommandQueue.Add(AdTecMatchMessage.PRESET_MEM + gear.ToString()); } } }