/// /// Copyright (c) 2013-2016 Sensus Metering Systems /// using System; using Dirichlet.Numerics; using log4net; namespace TBF.BenchControl.Elde { public class ControlComWrap : IControlCom { private static readonly ILog log = LogManager.GetLogger(typeof(ControlComWrap)); /// Fatal: SendCalibData(), DoSendCalibData() /// Info: SendCommand(), ValveMove(), StatusP /// Debug: Weight[ix] /// /// Properties /// public StatusP StatusP { get { return (StatusP)ctrlBrdComponent.StatusP; } } #if DN100 || MUNICH || FUZHOU_150 public double ReferenceFreq { get { return 1000.0f * ctrlBrdComponent.referenceFreq; } } /// Returns in [Hz] 0..2500, nom.=2000 public double ReferenceFreqs(int i) { return 0; } #else /// All newer benches public double ReferenceFreq { get { return 1000.0 * ctrlBrdComponent.referenceFreq[0]; } } /// Returns in [Hz] 0..2500, nom.=2000 /// /// /// In case of I11, I12 /// cBrd.referenceFreq[0] = I11 + I12 /// cBrd.referenceFreq[1] = I11 /// cBrd.referenceFreq[2] = I12 /// otherwise /// cBrd.referenceFreq[0] = I2 or I3 or I4 /// /// Reference frequency in Hz public double ReferenceFreqs(int i) { return ((i >= 0) && (i < ctrlBrdComponent.referenceFreq.Length)) ? (1000.0 * ctrlBrdComponent.referenceFreq[i]) : 0; } #endif public int EtPulses(int wmNr1) { return (int)ctrlBrdComponent.etPulses[wmNr1]; } #if DN100 || MUNICH || BADGER_MALA_TRAT || BADGER_STREDNA_TRAT || BADGER_VELKA_TRAT || TORINO_50 || TORUN_50 || CEVAK_40 || MURES_40 || IZRAEL_200 || MALTA_WSD25 public int EtPulsesK { get { return 1; } } #else /// all new benches public int EtPulsesK { get { return (int)ctrlBrdComponent.etPulsesK; } } #endif #if DEWA_300 public int EtPulses2 { get { return (int)ctrlBrdComponent.EtPulses2; } } public int EtPulses3 { get { return (int)ctrlBrdComponent.EtPulses3; } } #elif ROMA_200 public int EtPulses2 { get { return (int)ctrlBrdComponent.EtPulses2; } } public int EtPulses3 { get { return 0; } } #else public int EtPulses2 { get { return 0; } } public int EtPulses3 { get { return 0; } } #endif public UInt16 WMeterPulses(int wmNr1) { return (UInt16)ctrlBrdComponent.wMeterPuls[wmNr1]; } public int WMeterReference(int wmNr0) { return (int)ctrlBrdComponent.wMeterReference[wmNr0]; } public uint RegulValveDAC(int rvNr0) { #if CEVAK_200 return ctrlBrdComponent.StavDA[rvNr0]; #else return ctrlBrdComponent.StavDA; #endif } public float Pressure(int prsNr0) { return ctrlBrdComponent.pressure[prsNr0]; } public float Temperature(int tmpNr0) { return (tmpNr0 >= 0 && tmpNr0 < ctrlBrdComponent.temperature.Length) ? ctrlBrdComponent.temperature[tmpNr0] : 0; } public RegulValveState RegulValveState(int rvNr1) { return (RegulValveState)ctrlBrdComponent.rValveStatus[rvNr1 - 1]; } #if GENESIS || BERLIN || PETERSBURG_200 || DEWA_300 || ROMA_200 public UInt128 RRoute { get { return ((UInt128)ctrlBrdComponent.rRouteH << 64) | (UInt128)ctrlBrdComponent.rRoute; } } #else public UInt128 RRoute { get { return ctrlBrdComponent.rRoute; } } #endif #if GENESIS || KEMPNO_50 || KRAKOW_50 || BAHRAIN_50 || BADGER_STREDNA_TRAT || JUZNA_AFRIKA_50 || IZRAEL_25 || ZAMBIA || ZODINO || FEWA_50 || FILIPINY_50 || SENTEC || FUZHOU_100 || CEVAK_200 || IZRAEL_50 || DEWA_300 || ROMA_200 || PUCHONG_200 || TURA_IPERL_NEW || ALZIR_25 public uint DivTime(int id) { return ctrlBrdComponent.divTime[id]; } public void SetDivLimit(int divNo, uint limLoPct, uint limHiPct) { ctrlBrdComponent.DIVLimit[divNo, 0] = limLoPct; ctrlBrdComponent.DIVLimit[divNo, 1] = limHiPct; } #else public uint DivTime(int id) { return ctrlBrdComponent.divTime; } public void SetDivLimit(int divNo, uint limLoPct, uint limHiPct) { } #endif public float TTime { get { return ctrlBrdComponent.Ttime; } } #if DN100 || MUNICH public float ImpulseTime(int wmNr1) { return ctrlBrdComponent.Ttime; } #else public float ImpulseTime(int wmNr1) { return ctrlBrdComponent.ImpulseTime[wmNr1]; } #endif #if DN100 || MUNICH || FUZHOU_150 public uint FmState { get { return ctrlBrdComponent.fMState; } } #else //if everything newer public uint FmState { get { return ctrlBrdComponent.fMState[0]; } } /// TODO: index #endif public uint BeginState(int wmNr0) { return ctrlBrdComponent.beginSt[wmNr0]; } public double ReferenceFlow { get { return (double)ctrlBrdComponent.referenceFlow; } } public float RValvePosition(int rvNr1) { //return ctrlBrdComponent.RValvePosition[rvNr1 - 1]; return ctrlBrdComponent.Analogy[rvNr1 - 1]; /// Fixes bug: RValvePosition returns 0 all the time } public float DivSamples(int time, int divIx0) { #if MUNICH || IZRAEL_200 return ctrlBrdComponent.DIVSamples[time, 0]; #else return ctrlBrdComponent.DIVSamples[time, divIx0]; #endif } /// Time unit is 2 ms public int ScopeSamples(int i, int j, int k) { return ctrlBrdComponent.ScopeSamples[i, j, k]; } public ulong DigitalInputs { get { return (ulong)ctrlBrdComponent.Vstupy; } } public float AnalogInput(int adcNr0) { return ctrlBrdComponent.Analogy[adcNr0]; } public uint AnalogInputRaw(int adcNr0, int bank) { return ctrlBrdComponent.AnalogyRaw[adcNr0, bank]; } /// bank0=RV, bank1=Temp #if DN100 || MUNICH || BADGER_MALA_TRAT || BADGER_VELKA_TRAT || FUZHOU_50 || FUZHOU_150 || FUZHOU_300 || IZRAEL_200 || TORINO_50 || TORUN_50 || CEVAK_40 || MURES_40 public float TotalRefVolume { get { return ctrlBrdComponent.ReferenceVolume; } } public float MassRefVolume { get { return ctrlBrdComponent.ReferenceVolume; } } #else /// all new test benches public float TotalRefVolume { get { return ctrlBrdComponent.ReferenceVolume[0]; } } public float MassRefVolume { get { return ctrlBrdComponent.ReferenceVolume[1]; } } #endif #if SLM_END || WARSAW_END public uint[] CyclePar { get { return ctrlBrdComponent.CyclePar; } set { ctrlBrdComponent.CyclePar = value; } } public uint[] WMeterCont { get { return ctrlBrdComponent.wMeterCont; } } #else public uint[] CyclePar { get { return new uint[163]; } set { return; }} /// Dummy public uint[] WMeterCont { get { return new uint[3]; } } /// Dummy #endif #if KEMPNO_50 || KRAKOW_50 || JUZNA_AFRIKA_50 || IZRAEL_25 || ZAMBIA || ZODINO || FEWA_50 || FILIPINY_50 || FUZHOU_100 || CEVAK_200 || IZRAEL_50 || ALZIR_25 public float ValveOpenCloseTime { get { return ctrlBrdComponent.ValveMoveTime[0]; } } #else public float ValveOpenCloseTime { get { return 0.001f; } } #endif public bool ManualUIAllowed { get { return ctrlBrdComponent.Dovolene; } set { ctrlBrdComponent.Dovolene = value; } } public float VyslExt(int wmNr0, int what) { return ctrlBrdComponent.VyslExt[wmNr0, what]; } public void SetWeight(int pos, double mass) { ctrlBrdComponent.Weight[pos] = (float)mass; log.DebugFormat("SetWeight(pos={0}, mass={1}", pos, mass); } public void SetReservoirTemp(int nr, float temp) { #if GENESIS if (nr > 0 && nr <= 3) ctrlBrdComponent.TankTemp[nr - 1] = temp; #endif } /// /// Reference to the control board component /// #if DN100 private ControlCom2VB.ControlCom2panel ctrlBrdComponent; #elif MUNICH || FUZHOU_150 private ControlComponent3Munich.UserControl1 ctrlBrdComponent; #elif FUZHOU_300 private ControlComponent3F300.UserControl1 ctrlBrdComponent; #elif IZRAEL_200 || PUCHONG_200 || GENESIS || BERLIN || SLM_150 || PETERSBURG_200 private ControlComponent_Izrael2014.UserControl1 ctrlBrdComponent; #else /// newer benches private ControlComponent_Torino2015.UserControl1 ctrlBrdComponent; #endif /// /// Constructor that initializes the control board component reference /// /// #if DN100 public ControlComWrap(ControlCom2VB.ControlCom2panel ctrlBrdComponent) #elif MUNICH || FUZHOU_150 public ControlComWrap(ControlComponent3Munich.UserControl1 ctrlBrdComponent) #elif FUZHOU_300 public ControlComWrap(ControlComponent3F300.UserControl1 ctrlBrdComponent) #elif IZRAEL_200 || PUCHONG_200 || GENESIS || BERLIN || SLM_150 || PETERSBURG_200 public ControlComWrap(ControlComponent_Izrael2014.UserControl1 ctrlBrdComponent) #else /// all newer benches public ControlComWrap(ControlComponent_Torino2015.UserControl1 ctrlBrdComponent) #endif { this.ctrlBrdComponent = ctrlBrdComponent; } /// /// Sends calibration and configuration data to the control board. /// /// Regulating valves calib.coefs, ix1 = valve nr. (1..5), ix2 = coef.nr. (0..1), values typ. c0 = 0, c1 = 0.2 /// Meret address, index = 0..1, value typ. 99 and 100 /// COM port number of the control board (typ. 1) /// Temp.calc.coefs, ix1 = temp.sens.nr. (0..7 ???), ix2 = coef.nr /// Etalon nominal values /// Percentages for switching of diverters, ix = diverter nr.(0,1), typ.value 50 (%) /// Balance range = volume of the tanks on the balaces (ix=0,1) public void SendCalibData(uint[,] rvCalib, byte[] meretA, int usedCom, float[,] tempCalib, float[] etCalib, uint[] divEdge, uint[] balanceRange, byte meretProtocol) { if (Program.MainWnd.InvokeRequired) { /// When SendCalibData(...) called from the worker thread object[] args = new object[] { rvCalib, meretA, usedCom, tempCalib, etCalib, divEdge, balanceRange }; Program.MainWnd.Invoke((SendCalibDataDlgt)DoSendCalibData, args); /// Invoke required as component was created in UI thread } else { /// When SendCalibData(...) called from the UI thread DoSendCalibData(rvCalib, meretA, usedCom, tempCalib, etCalib, divEdge, balanceRange, meretProtocol); } } /// delegate void SendCalibDataDlgt(uint[,] rvCalib, byte[] meretA, int usedCom, float[,] tempCalib, float[] etCalib, uint[] divEdge, uint[] balanceRange, byte meretProtocol); /// private void DoSendCalibData(uint[,] rvCalib, byte[] meretA, int usedCom, float[,] tempCalib, float[] etCalib, uint[] divEdge, uint[] balanceRange, byte meretProtocol) { //TBF.UiBridge.Bridge.OnLog(this, string.Format("{0} SendCalibData(COM{1}) rvCalib[0,0]={2} rvCalib[0,1]={3} rvCalib[1,0]={4} rvCalib[1,1]={5}\r\n", // DateTime.Now.ToLongTimeString(), usedCom, // rvCalib[0,0], rvCalib[0,1], rvCalib[1,0], rvCalib[1,1])); #if DN100 log.FatalFormat("Component: {0}", ControlCom2VB.ControlCom2panel.ProgVersion); #elif MUNICH || FUZHOU_150 log.FatalFormat("Component: {0}", ControlComponent3Munich.UserControl1.ProgVersion); #elif FUZHOU_300 log.FatalFormat("Component: {0}", ControlComponent3F300.UserControl1.ProgVersion); #elif IZRAEL_200 || PUCHONG_200 || GENESIS || BERLIN || SLM_150 || PETERSBURG_200 log.FatalFormat("Component: {0}", ControlComponent_Izrael2014.UserControl1.ProgVersion); #else /// newer benches log.FatalFormat("Component: {0}", ControlComponent_Torino2015.UserControl1.ProgVersion); #endif log.Fatal("SendCalibData(...)"); for (int i = 0; i < rvCalib.GetLength(0); i++) for (int j = 0; j < rvCalib.GetLength(1); j++) log.FatalFormat(" rvCalib[{0},{1}] = {2}", i, j, rvCalib[i,j]); for (int i = 0; i < meretA.Length; i++) log.FatalFormat(" meretA[{0}] = {1}", i, meretA[i]); log.FatalFormat(" usedCom = {0}", usedCom); for (int i = 0; i < tempCalib.GetLength(0); i++) for (int j = 0; j < tempCalib.GetLength(1); j++) log.FatalFormat(" tempCalib[{0},{1}] = {2}", i, j, tempCalib[i, j]); for (int i = 0; i < etCalib.Length; i++) log.FatalFormat(" etCalib[{0}] = {1}", i, etCalib[i]); for (int i = 0; i < divEdge.Length; i++) log.FatalFormat(" divEdge[{0}] = {1}", i, divEdge[i]); for (int i = 0; i < balanceRange.Length; i++) log.FatalFormat(" balanceRange[{0}] = {1}", i, balanceRange[i]); ctrlBrdComponent.ExternalCom = true; #if SENTEC || CEVAK_200 || FUZHOU_100 || IZRAEL_25 || ALZIR_25 ctrlBrdComponent.SendCalibData(rvCalib, meretA, (byte)usedCom, tempCalib, etCalib, divEdge, balanceRange, meretProtocol); #else ctrlBrdComponent.SendCalibData(rvCalib, meretA, (byte)usedCom, tempCalib, etCalib, divEdge, balanceRange); #endif } /// /// Control of regulating valves. /// /// /// Regulating valve nr. (1..5) /// Valve regulation mode, see the enum /// Target position or target frequency or pulse duration /// Stabilization time when setting the flow: 0=200ms, step 50ms, max. 1.5 sec. public void ValveMove(int valveNo, RegulValveMode valveMode, float[] valveValue, int stableTime) { if (Program.MainWnd.InvokeRequired) { /// When ValveMove(...) called from the worker thread object[] args = new object[] { valveNo, valveMode, valveValue, stableTime }; Program.MainWnd.Invoke((ValveMoveDlgt)DoValveMove, args); /// When ValveMove called from a worker thread } else { /// When ValveMove(...) called from the UI thread DoValveMove(valveNo, valveMode, valveValue, stableTime); /// When ValveMove called from the UI thread } } /// delegate void ValveMoveDlgt(int valveNo, RegulValveMode valveMode, float[] valveValue, int stableTime); /// private void DoValveMove(int valveNo, RegulValveMode valveMode, float[] valveValue, int stableTime) { #if DN100 || MUNICH || FUZHOU_150 log.InfoFormat("ValveMove(#={0}, md={1}, [{2}, {3}])", valveNo, valveMode, valveValue[0], valveValue[1]); ctrlBrdComponent.ValveMove((byte)valveNo, (byte)valveMode, valveValue); #else /// all newer benches log.InfoFormat("ValveMove(#={0}, md={1}, [{2}, {3}], {4})", valveNo, valveMode, valveValue[0], valveValue[1], stableTime); ctrlBrdComponent.ValveMove((byte)valveNo, (byte)valveMode, valveValue, stableTime); #endif } /// /// Sends a command to the control board. /// /// Arguments /// State of valves, 128-bit word /// Array with length=8 of filter costants (0..255, 0 = no filtering) /// Freq.inverter control (not applicable in DT100, Munich) /// PID coefficient for flow control /// 0 = default value, 1 = spec. processing of very short pulses public void SendCommand(SendCommandArgs sendCommandArgs, UInt128 route, uint[] filterConstants, float[] fmFreq, int regConst, int shortImp) { if (Program.MainWnd.InvokeRequired) { /// From another thread ... use Invoke() Program.MainWnd.Invoke((SendCommandDlgt)DoSendCommand, new object[] { sendCommandArgs, route, filterConstants, fmFreq, regConst, shortImp }); } else { /// Call DoSendCommand() directly DoSendCommand(sendCommandArgs, route, filterConstants, fmFreq, regConst, shortImp); } } /// delegate void SendCommandDlgt(SendCommandArgs sendCommandArgs, UInt128 route, uint[] filterConstants, float[] fmFreq, int regConst, int shortImp); /// private void DoSendCommand(SendCommandArgs sendCommandArgs, UInt128 route, uint[] filterConstants, float[] fmFreq, int regConst, int shortImp) { #if FUZHOU_300 /// /// The following code deals with the situation that all FM controlled pumps share bit #39. /// In settings the bits of pumps should be sent as follows: P1=50, P2=51, P3=52, P4=53, P5=54 and P7=55 /// (in FUZHOU_300 the FM pump bit should be set to value FMIndex+50). /// bool bit39 = (route & 0x00FC000000000000) != 0; /// true if any of bits 50 through 55 is set route = route & 0xFF03FFFFFFFFFFFF; if (bit39) route = route | 0x0000008000000000; #elif PETERSBURG_200 || ROMA_200 /// /// The following code deals with the situation that all pumps share bit #80. /// In settings the bits of pumps should be sent as follows: P1=64, P2=65, P3=66, P4=67 and P5=68 /// bool bit80 = (route & (((UInt128)0x1F) << 64)) != 0; /// true if any of bits 64 through 68 is set if (bit80) route = route | (((UInt128)1) << 80); else route = route & (~(((UInt128)1) << 80)); #endif log.InfoFormat("DoSendCommand(Cmd={0},Ref#={1},Route={2},TotalPls={3},MassPls={4},TM={5},filt={6},FM=[{7}{8}{9}{10}{11}{12}],Reg={13},ShrtImp={14},Stop={15})", sendCommandArgs.Cmd, /// 0 sendCommandArgs.RefFlowmtrNr, /// 1 Utils.RouteToStr(route), /// 2 sendCommandArgs.TotalRefPulses, sendCommandArgs.MassRefPulses, sendCommandArgs.TestMethods, filterConstants, /// 3, 4, 5, 6 fmFreq[0].ToString(), /// 7 (fmFreq.Length > 1) ? ("," + fmFreq[1].ToString()) : "", /// 8 (fmFreq.Length > 2) ? ("," + fmFreq[2].ToString()) : "", /// 9 (fmFreq.Length > 3) ? ("," + fmFreq[3].ToString()) : "", /// 10 (fmFreq.Length > 4) ? ("," + fmFreq[4].ToString()) : "", /// 11 (fmFreq.Length > 5) ? ("," + fmFreq[5].ToString()) : "", /// 12 regConst, /// 13 shortImp, /// 14 sendCommandArgs.StopDevs); /// 15 #if DN100 || MUNICH ctrlBrdComponent.SendCommand((uint)sendCommandArgs.Cmd, (byte)sendCommandArgs.RefFlowmtrNr, (ulong)route, (uint)sendCommandArgs.TotalRefPulses, (uint)sendCommandArgs.TestMethods, Convert.ToSingle(filterConstants[0]), fmFreq[0], (uint)regConst, (uint)shortImp, (uint)sendCommandArgs.StopDevs); #elif BADGER_MALA_TRAT || BADGER_VELKA_TRAT || FUZHOU_50 || FUZHOU_150 || FUZHOU_300 || IZRAEL_200 || TORINO_50 || TORUN_50 || CEVAK_40 || MURES_40 ctrlBrdComponent.SendCommand((uint)sendCommandArgs.Cmd, (byte)sendCommandArgs.RefFlowmtrNr, (ulong)route, (uint)sendCommandArgs.TotalRefPulses, (uint)sendCommandArgs.TestMethods, Convert.ToSingle(filterConstants[0]), fmFreq, (uint)regConst, (uint)shortImp, (uint)sendCommandArgs.StopDevs); #elif BERLIN || SLM_150 || PETERSBURG_200 ctrlBrdComponent.SendCommand((uint)sendCommandArgs.Cmd, (byte)sendCommandArgs.RefFlowmtrNr, (ulong)(route & (UInt128)0xFFFFFFFFFFFFFFFF), (ulong)(route >> 64), new uint[] { (uint)sendCommandArgs.TotalRefPulses, (uint)sendCommandArgs.MassRefPulses }, (uint)sendCommandArgs.TestMethods, Convert.ToSingle(filterConstants[0]), fmFreq, (uint)regConst, (uint)shortImp, (uint)sendCommandArgs.StopDevs); #elif GENESIS || DEWA_300 || ROMA_200 ctrlBrdComponent.SendCommand((uint)sendCommandArgs.Cmd, (byte)sendCommandArgs.RefFlowmtrNr, (ulong)(route & (UInt128)0xFFFFFFFFFFFFFFFF), (ulong)(route >> 64), new uint[] { (uint)sendCommandArgs.TotalRefPulses, (uint)sendCommandArgs.MassRefPulses }, (uint)sendCommandArgs.TestMethods, filterConstants, fmFreq, (uint)regConst, (uint)shortImp, (uint)sendCommandArgs.StopDevs); #elif JUZNA_AFRIKA_50 || IZRAEL_25 || ZAMBIA || ZODINO || FEWA_50 || FILIPINY_50 || SENTEC || FUZHOU_100 || CEVAK_200 || IZRAEL_50 || ALZIR_25 ctrlBrdComponent.SendCommand((uint)sendCommandArgs.Cmd, (byte)sendCommandArgs.RefFlowmtrNr, (ulong)route, new uint[] { (uint)sendCommandArgs.TotalRefPulses, (uint)sendCommandArgs.MassRefPulses }, (uint)sendCommandArgs.TestMethods, filterConstants, fmFreq, (uint)regConst, (uint)shortImp, (uint)sendCommandArgs.StopDevs); #else /// if TURA_IPERL || TURA_IPERL_NEW || TURA_SPECIAL || MALTA_WSD25 || SLM_50 || SLM_END || WARSAW_END || PETERSBURG_50 || KEMPNO_50 || BAHRAIN_50 || RUM_MOB || KRAKOW_50 || BADGER_STREDNA_TRAT || PUCHONG_200 ctrlBrdComponent.SendCommand((uint)sendCommandArgs.Cmd, (byte)sendCommandArgs.RefFlowmtrNr, (ulong)route, new uint[] { (uint)sendCommandArgs.TotalRefPulses, (uint)sendCommandArgs.MassRefPulses }, (uint)sendCommandArgs.TestMethods, Convert.ToSingle(filterConstants[0]), fmFreq, (uint)regConst, (uint)shortImp, (uint)sendCommandArgs.StopDevs); #endif log.DebugFormat("DoSendCommand() Route = {0}", Utils.RouteToStr(route)); if (lastRoute != route) /// This is to update the MainWnd status bar on changes only { UInt128 rRoute = RRoute; Program.MainWnd.UpdateRoute(string.Format("{0} ({1})", Utils.RouteToStr(route), Utils.RouteToStr(rRoute))); lastRoute = route; } } enum CommType { Rx, /// Receive data only TxRx, /// Transmit and receive data } private StatusP lastStatusP; /// This is to update the MainWnd status bar on changes only private UInt128 lastRoute; /// This is to update the MainWnd status bar on changes only public void RunDeviceBefore() { object[] args = new object[] { CommType.Rx }; MakeCommDlgt dlgt = MakeComm; Program.MainWnd.Invoke(dlgt, args); /// Invoke MakeExtComm(.) in the UI thread StatusP bufferedStatusP = StatusP; if (lastStatusP != bufferedStatusP) { string statusPStr = ((ulong)bufferedStatusP).ToString("x16"); log.DebugFormat("RunDeviceBefore() StatusP = {0}", statusPStr); //Program.MainWnd.UpdateStatusP(statusPStr); /// TODO 170309 lastStatusP = bufferedStatusP; } } public void RunDeviceAfter() { object[] args = new object[] { CommType.TxRx }; MakeCommDlgt dlgt = MakeComm; Program.MainWnd.Invoke(dlgt, args); /// Invoke MakeExtComm(.) in the UI thread StatusP bufferedStatusP = StatusP; if (lastStatusP != bufferedStatusP) { string statusPStr = ((ulong)bufferedStatusP).ToString("x16"); log.DebugFormat("RunDeviceAfter() StatusP = {0}", statusPStr); //Program.MainWnd.UpdateStatusP(statusPStr); /// TODO 170309 lastStatusP = bufferedStatusP; } } /// /// A delegate to execute the SendCommand() in the UI thread /// delegate void MakeCommDlgt(CommType extComm); /// /// Executes the SendCommand(...) and MakeExtCom() in the UI thread /// void MakeComm(CommType commType) { if (ctrlBrdComponent.ExternalCom) { ctrlBrdComponent.MakeExtCom((commType == CommType.Rx) ? false : true); } } } }