using System; using System.Runtime.InteropServices; using System.Collections.Generic; using System.Text; using System.Threading; using FusionBrain_WinUSB; namespace Fusion_Control_Centre_UberMDX { public static class USB_CommunicationClass { public static bool THREAD_SAFETY_SENDOK = true; private static bool flipper; public static event MainMDX.Debug_Delegate_Byte_Stream ByteStreamEvent_Send; public static event MainMDX.Debug_Delegate_Byte_Stream ByteStreamEvent_Received; public static bool Setup_USB_CommunicationClass() { Thread _t = new Thread(SetupPowerModeThread); bool[] BrainClaimedArray = new bool[MainMDX.AllBrains.Count]; int[] BrainTries = new int[MainMDX.AllBrains.Count]; for (int i = 0; i < MainMDX.AllBrains.Count; i++) { int _version = 4; switch (MainMDX.AllBrains[i].version) { case MainMDX.BrainVersion.Version_03: _version = 3; break; case MainMDX.BrainVersion.Version_04: _version = 4; break; } bool _success = FusionBrain_WinUSB.MainUSBClass.FindMyDevice(i, _version); if (_success) { MainMDX.AllBrains[i].isAPhysicalBrain = true; } else { continue; // For testing ignore // Try to free, and retry int _FB_Internal_Index = MainUSBClass.AllUSBDevicesIndexSearch(i); if (_FB_Internal_Index >= 0) { bool success = MainUSBClass.AllUSBDevices[_FB_Internal_Index].Internal_Zombie(); if (success) { MainUSBClass.AllUSBDevices.RemoveAt(_FB_Internal_Index); if (BrainTries[i] < 2) { BrainTries[i]++; i--; } else { } } } } } _t.IsBackground = true; _t.Start(); return true; } public static void DoUSB() { if (THREAD_SAFETY_SENDOK) { lock (MainMDX.AllBrains) { int _FB_index = -1; foreach (MainMDX.BrainID _FB in MainMDX.AllBrains) { _FB_index++; bool isPhysical = _FB.isAPhysicalBrain; //bool isPhysical = false; //int isPhysical_Index = MainUSBClass.AllUSBDevicesIndexSearch(_FB_index); //if (isPhysical_Index >= 0) //{ // string _path = MainUSBClass.AllUSBDevices[isPhysical_Index].myDevicePathName; // if (_path != null) // { // isPhysical = true; // } //} bool isVirtual = MainMDX.VirtualBrainClass.isAVirtualBrain(_FB.humanName.ToLower()); if (!isPhysical && !isVirtual) { continue; } byte[] _toSend = new byte[64]; switch (_FB.version) { case MainMDX.BrainVersion.Version_03: _toSend[61] = (byte)255; break; case MainMDX.BrainVersion.Version_04: int val_of_initialize = 2; if (flipper) { val_of_initialize += 1; } _toSend[61] = (byte)val_of_initialize; break; } try { lock (MainMDX.AllDigitalOutputs) { _toSend = Update_DigitalOutputChannels(_toSend, flipper, _FB.DigitalOutputIndexArray_EX, _FB.version); } } catch (Exception e) { //System.Windows.Forms.MessageBox.Show("TEMPORARY ERROR CATCH: FAILED UPDATING DIGITAL OUTPUTS:\r\n" + e.ToString()); } if (!isPhysical) { continue; } flipper = !flipper; //int successWrite = 0; //int successRead = 0; try { if (ByteStreamEvent_Send != null) { ByteStreamEvent_Send(_FB.humanName, _toSend); } } catch (Exception) { } bool _transferSuccess = false; try { _transferSuccess = MainUSBClass.SendAndReceiveViaInterruptTransfers(ref _toSend, _FB_index, (int)_FB.version); //if (_FB.Stream_Reader != null && _FB.Stream_Writer != null) //{ // successWrite = _FB.Stream_Writer.Write(_toSend, 1000); // successRead = _FB.Stream_Reader.Read(_toSend, 1000); //} } catch (Exception e) { //System.Windows.Forms.MessageBox.Show("TEMPORARY ERROR CATCH: FAILED USB COMMUNICATION FOR BRAIN[" + _FB.humanName + "]\r\n" + e.ToString()); } try { if (ByteStreamEvent_Received != null) { ByteStreamEvent_Received(_FB.humanName, _toSend); } } catch (Exception) { } try { lock (MainMDX.AllAnalogueInputs) { for (int i = 0; i < _FB.AnalogueInputIndexArray_EX.Length; i++) { if (_FB.AnalogueInputIndexArray_EX[i] >= 0 && _FB.AnalogueInputIndexArray_EX[i] < MainMDX.AllAnalogueInputs.Count) { int byte_address_lower = -1; int byte_address_higher = -1; switch (_FB.version) { case MainMDX.BrainVersion.Version_03: byte_address_lower = (12 + (i * 2)); byte_address_higher = (12 + (i * 2) + 1); break; case MainMDX.BrainVersion.Version_04: byte_address_lower = (32 + (i * 2)); byte_address_higher = (32 + (i * 2) + 1); break; default: continue; } Update_AnalogueInputChannel(MainMDX.AllAnalogueInputs[_FB.AnalogueInputIndexArray_EX[i]], Parse_AnalogueInput(_toSend[byte_address_lower], _toSend[byte_address_higher], _FB.version, _FB.Accurate_AnalogueScalingInput_Index), _FB.version); } } } } catch (Exception e) { //System.Windows.Forms.MessageBox.Show("TEMPORARY ERROR CATCH: FAILED ANALOGUE INPUT PARSE\r\n" + e.ToString()); } int max_digital_inputs = 0; switch (_FB.version) { case MainMDX.BrainVersion.Version_03: max_digital_inputs = 4; break; case MainMDX.BrainVersion.Version_04: max_digital_inputs = 0; break; } bool[] DigitalInputs = new bool[max_digital_inputs]; try { lock (MainMDX.AllDigitalInputs) { int byte_address = 0; DigitalInputs = Parse_DigitalInputs(_toSend[31]); for (int i = 0; i < max_digital_inputs; i++) { if (_FB.DigitalInputIndexArray_EX[i] >= 0 && _FB.DigitalInputIndexArray_EX[i] < MainMDX.AllDigitalInputs.Count) { Update_DigitalInputChannel(MainMDX.AllDigitalInputs[_FB.DigitalInputIndexArray_EX[i]], DigitalInputs[i], _FB.version); } } } } catch (Exception e) { //System.Windows.Forms.MessageBox.Show("TEMPORARY ERROR CATCH: FAILED DIGITAL INPUT PARSE\r\n" + e.ToString()); } if (!_transferSuccess) { int _FB_Internal_Index = MainUSBClass.AllUSBDevicesIndexSearch(_FB_index); if (_FB_Internal_Index >= 0) { bool success = MainUSBClass.AllUSBDevices[_FB_Internal_Index].Internal_Zombie(); } MainUSBClass.FindMyDevice(_FB_index, (int)_FB.version); //_FB.Stream_Writer.Dispose(); //_FB.Stream_Reader.Dispose(); //_FB.Stream_Reader = _FB.Device.OpenInterruptEndpointReader(ReadEndpoints.Ep01); //_FB.Stream_Writer = _FB.Device.OpenInterruptEndpointWriter(WriteEndpoints.Ep01); } } } } } public static void USB_CommunicationClass_LOOP() { while (true) { DoUSB(); Thread.Sleep(MainMDX.THREAD_IO_SLEEP_INTERVAL); } } private static byte[] Update_DigitalOutputChannels(byte[] communicationArray, bool flip, int[] digitalOutputIndexArray, MainMDX.BrainVersion _version) { for (int i = 0; i < digitalOutputIndexArray.Length; i++) { try { if (digitalOutputIndexArray[i] >= 0 && digitalOutputIndexArray[i] < MainMDX.AllDigitalOutputs.Count) { #region Tally the Votes int[] myVote = { 0, 0, 0 }; MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].PreviousEnabledState = MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].CurrentEnabledState; foreach (MainMDX.LogicalVote individualVote in MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].ShouldIChangeState) { myVote[MainMDX.Vote_Priority_To_Integer(individualVote.MyLogicalPriority)] += MainMDX.Vote_Opinion_To_Integer(individualVote.MyLogicalOpinion); } MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].ShouldIChangeState.Clear(); if (myVote[2] != 0) { if (myVote[2] > 0) { MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].CurrentEnabledState = true; } else { MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].CurrentEnabledState = false; } } else if (myVote[1] != 0) { if (myVote[1] > 0) { MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].CurrentEnabledState = true; } else { MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].CurrentEnabledState = false; } } else if (myVote[0] != 0) { if (myVote[0] > 0) { MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].CurrentEnabledState = true; } else { MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].CurrentEnabledState = false; } } #endregion if (MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Port >= 0 && MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Port < MainMDX.FUSIONBRAIN_NUMBER_OF_DIGITAL_OUTPUTS(_version)) { int byte_address = -1; int val = 0; int val_2 = 0; bool beOn = MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].CurrentEnabledState; switch (MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Mode) { case MainMDX.DigitalOutputChannel.DigitalOutputChannel_Mode.STANDARD: #region Long Pulse if (MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_LongPulse._period > 0 && MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_LongPulse._duty > 0 && MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_LongPulse._duty < 1) { if (beOn) { if (MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_LongPulse.FLAG_DonePulse) { MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_LongPulse._PulseStart = DateTime.Now; MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_LongPulse.FLAG_DonePulse = false; } if (MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_LongPulse._PulseStart == DateTime.MinValue) { MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_LongPulse._PulseStart = DateTime.Now; } int _time = MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_LongPulse.TimeSinceStart(); if (_time < ((float)MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_LongPulse._period * MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_LongPulse._duty)) { beOn = true; } else { beOn = false; } if (_time >= MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_LongPulse._period) { MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_LongPulse.FLAG_DonePulse = true; } } else { MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_LongPulse._PulseStart = DateTime.MinValue; MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_LongPulse.FLAG_DonePulse = false; } } #endregion #region Sequence if (MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_Sequence._state_list.Count > 0 && MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_Sequence._iterations >= 0) { if (beOn) { if (MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_Sequence._LastIteration == DateTime.MinValue || MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_Sequence.FLAG_NextIteration) { MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_Sequence._LastIteration = DateTime.Now; MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_Sequence.FLAG_NextIteration = false; } if (MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_Sequence._current_iteration < MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_Sequence._state_list.Count) { beOn = MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_Sequence._state_list[MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_Sequence._current_iteration]._state; } int _time = MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_Sequence.TimeSinceStart(); if (_time >= MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_Sequence._period) { MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_Sequence._current_iteration++; MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_Sequence.FLAG_NextIteration = true; if (MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_Sequence._current_iteration >= MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_Sequence._state_list.Count) { MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_Sequence._current_iteration %= MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_Sequence._state_list.Count; MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_Sequence._total_iterations++; if (MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_Sequence._iterations > 0 && MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_Sequence._total_iterations >= MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_Sequence._iterations) { MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_Sequence._current_iteration = 0; MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_Sequence._total_iterations = 0; MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].CurrentEnabledState = false; } } } } else { MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_Sequence._current_iteration = 0; MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_Sequence._LastIteration = DateTime.MinValue; MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_Sequence._total_iterations = 0; MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_Sequence.FLAG_NextIteration = false; } } #endregion #region Relatively Timed Sequence if (MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_RelativeSequence._relative_state_list.Count > 0 && MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_RelativeSequence._iterations >= 0) { if (beOn) { if (MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_RelativeSequence._StartSequence == DateTime.MinValue) //|| MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_RelativeSequence.FLAG_NextIteration) { MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_RelativeSequence._StartSequence = DateTime.Now; //MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_RelativeSequence.FLAG_NextIteration = false; } if (MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_RelativeSequence._current_iteration < MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_RelativeSequence._relative_state_list.Count) { beOn = MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_RelativeSequence._relative_state_list[MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_RelativeSequence._current_iteration]._state; } int _time = MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_RelativeSequence.TimeSinceStart(); if (_time >= MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_RelativeSequence._relative_state_list[MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_RelativeSequence._current_iteration]._time) { MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_RelativeSequence._current_iteration++; //MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_RelativeSequence.FLAG_NextIteration = true; if (MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_RelativeSequence._current_iteration >= MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_RelativeSequence._relative_state_list.Count) { MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_RelativeSequence._current_iteration %= MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_RelativeSequence._relative_state_list.Count; MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_RelativeSequence._total_iterations++; MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_RelativeSequence._StartSequence = DateTime.MinValue; if (MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_RelativeSequence._iterations > 0 && MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_RelativeSequence._total_iterations >= MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_RelativeSequence._iterations) { MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_RelativeSequence._current_iteration = 0; MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_RelativeSequence._total_iterations = 0; MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].CurrentEnabledState = false; } } } } else { MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_RelativeSequence._current_iteration = 0; MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_RelativeSequence._StartSequence = DateTime.MinValue; MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_RelativeSequence._total_iterations = 0; //MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Optional_RelativeSequence.FLAG_NextIteration = false; } } #endregion break; } MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].CurrentActualState = beOn; switch (_version) { case MainMDX.BrainVersion.Version_03: byte_address = MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Port; if (flip) { val += 2; } if (beOn) { val += 1; } communicationArray[byte_address] = (byte)val; break; case MainMDX.BrainVersion.Version_04: byte_address = (MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Port * 2); if (beOn) { val += 1; } val_2 += ((MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].TimerValue % 64) * 4); val_2 += (int)MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Mode; val += (MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].PWM_Value * 2); communicationArray[byte_address] = (byte)val; communicationArray[byte_address + 1] = (byte)val_2; break; default: continue; } } } else { } } catch (Exception e) { System.Windows.Forms.MessageBox.Show("TEMPORARY ERROR INSIDE DIGITAL OUTPUT LOOP: \r\n" + e.ToString()); continue; } } return communicationArray; } private static void Update_AnalogueInputChannel(MainMDX.AnalogueInputChannel _channel, double _newValue, MainMDX.BrainVersion _version) { int max_port = 0; if (_channel.Port < 0 || _channel.Port > MainMDX.FUSIONBRAIN_NUMBER_OF_ANALOGUE_INPUTS(_version)) { return; } _channel.HistoryValues.Add(_newValue); if (_channel.HistoryValues.Count > _channel.maximumHistory) { _channel.HistoryValues.RemoveAt(0); } _channel.CurrentValue = _newValue; if (_channel.autoAverage && _channel.HistoryValues.Count > 0) { _channel.CurrentValue = 0; foreach (double history_value_double in _channel.HistoryValues) { _channel.CurrentValue += history_value_double; } _channel.CurrentValue /= (double)_channel.HistoryValues.Count; } } private static void Update_DigitalInputChannel(MainMDX.DigitalInputChannel _channel, bool _newValue, MainMDX.BrainVersion _version) { int max_ports = 0; if (_version == MainMDX.BrainVersion.Version_03) { max_ports = 4; } if (_channel.Port < 0 || _channel.Port > max_ports) { return; } _channel.PreviousState = _channel.CurrentState; _channel.CurrentState = _newValue; } private static double Parse_AnalogueInput(byte input_byte1, byte input_byte2, MainMDX.BrainVersion _version, int accurate_index) { int digital_value = 0; switch (_version) { case MainMDX.BrainVersion.Version_03: { int byte1Int = (int)input_byte1; for (int i = 7; i >= 0; i--) { if (byte1Int == 0) { break; } int r = (byte1Int / (int)(Math.Pow(2.0, (double)i))); digital_value += r * ((int)(Math.Pow(2.0, (double)(i + 2)))); byte1Int -= (r * (int)(Math.Pow(2.0, (double)i))); } switch ((int)input_byte2) { case 0: break; case 64: digital_value += 1; break; case 128: digital_value += 2; break; case 192: digital_value += 3; break; default: break; } } break; case MainMDX.BrainVersion.Version_04: { digital_value = (int)(input_byte1 * 256) + (int)input_byte2; } break; } double scaling_reF = 5.0; if (accurate_index >= 0 && accurate_index < MainMDX.AllAnalogueInputs.Count) { scaling_reF = MainMDX.AllAnalogueInputs[accurate_index].CurrentValue; if (scaling_reF == 0) { scaling_reF = 5.0; } } double reF = ((double)digital_value / 1023.0f) * scaling_reF; return reF; } private static bool[] Parse_DigitalInputs(byte input_byte) { bool[] _digInputs = new bool[4]; /* int byteInt = (int)input_byte; for (int i = 7; i >= 0; i--) { if (byteInt == 0) { break; } int r = (byteInt / (int)(Math.Pow(2.0, (double)i))); switch(i) { case byteInt -= (r * (int)(Math.Pow(2.0, (double)i))); } */ return _digInputs; } static void SystemEvents_PowerModeChanged(object sender, Microsoft.Win32.PowerModeChangedEventArgs e) { if (e.Mode == Microsoft.Win32.PowerModes.Suspend) { THREAD_SAFETY_SENDOK = false; ShutOffAllOutputs(); } else if (e.Mode == Microsoft.Win32.PowerModes.Resume) { THREAD_SAFETY_SENDOK = true; RestoreAllOutputs(); } } public static void DisposeOfAllBrains() { bool success = MainUSBClass.Zombie(); } public static void ShutOffAllOutputs() { foreach (MainMDX.DigitalOutputChannel _doc in MainMDX.AllDigitalOutputs) { _doc.PreviousEnabledState = _doc.CurrentActualState; _doc.CurrentActualState = false; _doc.ShouldIChangeState.Clear(); } THREAD_SAFETY_SENDOK = true; DoUSB(); THREAD_SAFETY_SENDOK = false; } public static void RestoreAllOutputs() { foreach (MainMDX.DigitalOutputChannel _doc in MainMDX.AllDigitalOutputs) { _doc.CurrentActualState = _doc.PreviousEnabledState; _doc.ShouldIChangeState.Clear(); } THREAD_SAFETY_SENDOK = true; DoUSB(); } private static void SetupPowerModeThread() { Microsoft.Win32.SystemEvents.PowerModeChanged += new Microsoft.Win32.PowerModeChangedEventHandler(SystemEvents_PowerModeChanged); } } }