diff --git a/TBF/Rig/ControlBoard/Uni/UniCB.cs b/TBF/Rig/ControlBoard/Uni/UniCB.cs index dabff3598..e6325cef8 100644 --- a/TBF/Rig/ControlBoard/Uni/UniCB.cs +++ b/TBF/Rig/ControlBoard/Uni/UniCB.cs @@ -83,57 +83,14 @@ namespace TBF.Rig.ControlBoard.Uni const int BUFFER_SIZE = 4000; /// Size of input buffers byte[] buffer; /// Buffer for data received in one attempt in RunDeviceBefore() byte[] rcvdData; /// Buffer for all recevied but nut processed data. May contain data from several read attempts - int[] cumulativeSums; + int[] cumulativeSums; /// Cumulative sums to verify checksums easily int rcvdBytesCount; /// Count of valid bytes in rcvdData buffer int lastReceivedTime; /// StateMachine.Time time stamp of the last received valid frame + bool outputsInitialized; /// Flag indicating that outputs were sent at least once /// - /// Route / digital outputs / states of electromagnetic valves - /// - readonly UInt128 routeMask; /// Set in the constructor, bits of outputs that can be controlled by Action.ChangeRoute are set. - /// Regulation valve control outputs and diverters cannot be controlled by Action.ChangeRoute - /// Depends on the control board configuration - - ulong valvesToInvert; /// From configurations of valve and pump components. Inversion is applied when creating - /// Action.ChangeRoute an dafter obtaining RRoute from the control board - - /// State of digital outputs obtained from the control board - public UInt128 RRoute - { - get - { - if ((StateMachine.Time - lastReceivedTime) < 5) - { - return (UInt128)(Data.Vystupy ^ valvesToInvert); - } - else - { - return ((UInt128)1) << cbCfg.BitNr; /// No connection to control board - } - } - } - - UInt128 displayedRoute; /// A route displayed on the screen (inversions are not applied) - UInt128 bitsChangedByUI; /// Ones in this word indicate which valves/pumpes were changed in UI by mouse clicks - UInt128 displayedRoutePlusUI; /// A route displayed on the screen plus the modifications from UI (inversions are not applied) - UInt128 outputLatch; /// A copy of route sent to physical outputs - UInt128 benchModelRoute; - bool outputsInitialized; - int lastStateMachineTime = 0; - - /// - /// Route: 128-bit word representing the current state of all valves and pumps - /// - public UInt128 Route { get { return benchModelRoute; } } - - - /// UI actions are blocked when true - public bool IsUIBlocked { get; set; } - - /// Message queue - Queue actionQueue; - /// Received data + /// public GeneralData Data; DivTransitionData divTransitionData; ScopeAnalyzerData scopeAnalyzerData; @@ -143,7 +100,7 @@ namespace TBF.Rig.ControlBoard.Uni /// Current flow meter ID public int FlowmeterId { get { return Convert.ToInt32(Data.State & (ulong)StatusP.FlowmtrNrMask); } } - + public UInt64 DigitalInputs { get { return Data.Vstupy; } } /// Digital inputs public Int16 AnalogInput(int channel) @@ -152,10 +109,36 @@ namespace TBF.Rig.ControlBoard.Uni { return Data.AnalogInput[channel]; } - return 0; + else return 0; } - /// Values valid during a test + /// + /// Digital outputs / Route / States of electromagnetic valves + /// + readonly UInt128 routeMask; /// Set in the constructor, bits of outputs that can be controlled by Action.ChangeRoute are set. + /// Regulation valve control outputs and diverters cannot be controlled by Action.ChangeRoute + /// Depends on the control board configuration + ulong valvesToInvert; /// From configurations of valve and pump components. Inversion is applied when creating + /// a message to be sent by serial port + UInt128 displayedRoute; /// A route displayed on the screen (inversions are not applied) + UInt128 bitsChangedByUI; /// Ones in this word indicate which valves/pumpes were changed in UI by mouse clicks + UInt128 displayedRoutePlusUI; /// A route displayed on the screen plus the modifications from UI (inversions are not applied) + UInt128 outputLatch; /// A copy of data sent to physical digital outputs (inversions are not applied) + /// + /// 128-bit word representing the current state of all valves and pumps (inversions are not applied) + /// + UInt128 route; + public UInt128 Route { get { return route; } } + + /// + /// Queue of higher level commands for the control board + /// + Queue actionQueue; + + /// UI actions are blocked when true + public bool IsUIBlocked { get; set; } + + /// Measured values valid during a test public double RefFrequency { get { return Data.ReferenceFreq[0]; } } public double RefFrequency1 { get { return Data.ReferenceFreq[1]; } } public double RefFrequency2 { get { return Data.ReferenceFreq[2]; } } @@ -252,19 +235,14 @@ namespace TBF.Rig.ControlBoard.Uni /// Handler handling mouse clicks on the schematc drawinng - valve or pump state changes TBF.UiBridge.Bridge.RouteChangeHandler += delegate(object sndr, TBF.UiBridge.RouteChangeArgs args) - { - UInt128 oneBitMask = ((UInt128)1) << args.BitNr; - bitsChangedByUI |= oneBitMask; - displayedRoutePlusUI = displayedRoutePlusUI ^ oneBitMask; - //if ((displayedRoutePlusUI & oneBitMask) == 0) - //{ - // displayedRoutePlusUI |= oneBitMask; - //} - //else - //{ - // displayedRoutePlusUI &= (~oneBitMask); - //} - }; + { + UInt128 oneBitMask = ((UInt128)1) << args.BitNr; + lock (this) + { + bitsChangedByUI |= oneBitMask; + displayedRoutePlusUI = displayedRoutePlusUI ^ oneBitMask; + } + }; log.FatalFormat("{0} - Device successfully initialized", Name); } @@ -274,6 +252,9 @@ namespace TBF.Rig.ControlBoard.Uni /// public void RunDeviceBefore() { + /// + /// Read data from the control board + /// if (cbCfg.DebugLevel == DebugMode.Normal && serialPort != null && serialPort.IsOpen) { /// Read new received bytes and append them to a buffer @@ -357,15 +338,25 @@ namespace TBF.Rig.ControlBoard.Uni rcvdBytesCount -= lastValidOffset; } - benchModelRoute = RRoute; /// - if (!IsUIBlocked && bitsChangedByUI != 0) + /// Combine data from the current route, from digital outputs and from UI + /// + lock (this) { - benchModelRoute = (benchModelRoute & ~bitsChangedByUI) | (displayedRoutePlusUI & bitsChangedByUI); - bitsChangedByUI = 0; + route = (UInt128)(Data.Vystupy ^ valvesToInvert); + /// + if (!IsUIBlocked && bitsChangedByUI != 0) + { + route = (route & ~bitsChangedByUI) | (displayedRoutePlusUI & bitsChangedByUI); + bitsChangedByUI = 0; + } + if ((StateMachine.Time - lastReceivedTime) >= 5) + { + /// No connection to control board ... set indicator bit + route += ((UInt128)1) << cbCfg.BitNr; + } } - - log.DebugFormat("Route synced with RRoute and UI changes, new route = {0}", Utils.RouteToStr(benchModelRoute)); + log.DebugFormat("Route synced with RRoute and UI changes, new route = {0}", Utils.RouteToStr(route)); } /// @@ -373,15 +364,20 @@ namespace TBF.Rig.ControlBoard.Uni /// public void RunDeviceAfter() { - /// Synchronize benchModelRoute with RRoute - if (!IsUIBlocked && bitsChangedByUI != 0) + /// + /// Combine data from the current route and from UI + /// + lock (this) { - benchModelRoute = (benchModelRoute & ~bitsChangedByUI) | (displayedRoutePlusUI & bitsChangedByUI); + if (!IsUIBlocked && bitsChangedByUI != 0) + { + route = (route & ~bitsChangedByUI) | (displayedRoutePlusUI & bitsChangedByUI); + bitsChangedByUI = 0; + } + displayedRoute = route; + displayedRoutePlusUI = route; bitsChangedByUI = 0; } - displayedRoute = Route; - displayedRoutePlusUI = Route; - bitsChangedByUI = 0; ProcessData.UpdateMeasuredValuesAndSetpoints(); Bridge.OnStateMachineTick(this, new StateMachineTickEventArgs(displayedRoute, ProcessData.MsrmntAvailableFlags, ProcessData.MeasuredValues, ProcessData.AltStrings, ProcessData.Setpoints)); @@ -405,7 +401,7 @@ namespace TBF.Rig.ControlBoard.Uni } } - if (!outputsInitialized || (outputLatch & routeMask) != (benchModelRoute & routeMask)) /// || (StateMachine.Time - lastStateMachineTime) >= 15) + if (!outputsInitialized || (outputLatch & routeMask) != (route & routeMask)) /// || (StateMachine.Time - lastStateMachineTime) >= 15) { var actionsToModify = actionQueue.Where(x => (x.ActionId == ActionID.ChangeRoute)); bool oneModified = false; @@ -418,14 +414,14 @@ namespace TBF.Rig.ControlBoard.Uni } oneModified = true; - a.Route = (ulong)benchModelRoute; - log.InfoFormat("ChangeRoute(route={0:X}) ... an action in the queue modified", benchModelRoute); + a.Route = (ulong)route; + log.InfoFormat("ChangeRoute(route={0:X}) ... an action in the queue modified", route); } if (!oneModified) { - actionQueue.Enqueue(Action.ChangeRoute(false, (ulong)benchModelRoute)); - log.InfoFormat("ChangeRoute(route={0:X}) ... a new action enqueued", (ulong)benchModelRoute); + actionQueue.Enqueue(Action.ChangeRoute(false, (ulong)route)); + log.InfoFormat("ChangeRoute(route={0:X}) ... a new action enqueued", (ulong)route); } foreach (var a in actionQueue) log.DebugFormat(" {0}", a); @@ -440,10 +436,16 @@ namespace TBF.Rig.ControlBoard.Uni { outputsInitialized = true; outputLatch = combinedAction.Route; - lastStateMachineTime = StateMachine.Time; + if (cbCfg.DebugLevel != DebugMode.Normal) + { + Data.Vystupy = combinedAction.Route ^ valvesToInvert; + } } - if (cbCfg.DebugLevel == DebugMode.Normal) serialPort.Write(outData, 0, outData.Length); + if (cbCfg.DebugLevel == DebugMode.Normal) + { + serialPort.Write(outData, 0, outData.Length); + } string s = Telegram.LogTelegram("Sent: ", outData); Debug.WriteLine(s); @@ -506,11 +508,11 @@ namespace TBF.Rig.ControlBoard.Uni /// Bits of changed valves are set in the return value public UInt128 SetValves(UInt128 valvesToOpen, UInt128 valvesToClose, IList logicalFnValves) { - UInt128 oldRoute = benchModelRoute; - benchModelRoute = (benchModelRoute | valvesToOpen) & (~valvesToClose); - foreach (var logFnV in logicalFnValves) logFnV.UpdateRoute(ref benchModelRoute); - log.DebugFormat("SetValves(x,x), new route = {0}", Utils.RouteToStr(benchModelRoute)); - UInt128 retVal = oldRoute ^ benchModelRoute; + UInt128 oldRoute = route; + route = (route | valvesToOpen) & (~valvesToClose); + foreach (var logFnV in logicalFnValves) logFnV.UpdateRoute(ref route); + log.DebugFormat("SetValves(x,x), new route = {0}", Utils.RouteToStr(route)); + UInt128 retVal = oldRoute ^ route; log.DebugFormat("{0}.SetValves({1}, {2}) returns {3}", Name, valvesToOpen.ToString("X"), valvesToClose.ToString("X"), retVal.ToString("X")); return retVal;