using System; using System.Runtime.InteropServices; using System.Collections.Generic; using System.Text; using LibUsbDotNet; using LibUsbDotNet.Usb; using LibUsbDotNet.Usb.Main; using System.Threading; namespace Fusion_Control_Centre_UberMDX { public static class USB_CommunicationClass { private static UsbDeviceList All_FusionBrain_USBDeviceList; //private static string VID_PID = @"USB\VID_04D8&PID_000C\5&6CE8D0A&0&1"; private static List _PossiblePIDs_Version3 = new List(new int[] { 10, 11, 12, 13 }); private static List _PossiblePIDs_Version4 = new List(new int[] { 14 }); 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); All_FusionBrain_USBDeviceList = new UsbDeviceList(); All_FusionBrain_USBDeviceList = LibUsbDotNet.Usb.UsbGlobals.DeviceList; bool[] BrainClaimedArray = new bool[MainMDX.AllBrains.Count]; int indexUSB = -1; foreach (UsbDevice _testDevice in All_FusionBrain_USBDeviceList) { if (_testDevice.Info.ManufacturerString.ToLower().Contains("fusion")) { if (_testDevice.Info.IdVendor == 1240) { if (_PossiblePIDs_Version3.Contains((int)_testDevice.Info.IdProduct) || _PossiblePIDs_Version4.Contains((int)_testDevice.Info.IdProduct)) { /* indexUSB++; if (MainMDX.AllBrains.Count > indexUSB) { if (_PossiblePIDs_Version3.Contains((int)_testDevice.Info.IdProduct)) { MainMDX.AllBrains[indexUSB].InitializeVersion(MainMDX.BrainVersion.Version_03); } else if (_PossiblePIDs_Version4.Contains((int)_testDevice.Info.IdProduct)) { MainMDX.AllBrains[indexUSB].InitializeVersion(MainMDX.BrainVersion.Version_04); } MainMDX.AllBrains[indexUSB].Device = _testDevice; MainMDX.AllBrains[indexUSB].Stream_Reader = _testDevice.OpenInterruptEndpointReader(ReadEndpoints.Ep01); MainMDX.AllBrains[indexUSB].Stream_Writer = _testDevice.OpenInterruptEndpointWriter(WriteEndpoints.Ep01); if (MainMDX.AllBrains[indexUSB].Device.Open()) { int i1 = MainMDX.AllBrains[indexUSB].Device.SetConfiguration(1); int i2 = MainMDX.AllBrains[indexUSB].Device.ClaimInterface(0); } else { } } */ MainMDX.BrainVersion _lookFor = MainMDX.BrainVersion.Version_03; if (_PossiblePIDs_Version3.Contains((int)_testDevice.Info.IdProduct)) { _lookFor = MainMDX.BrainVersion.Version_03; } else if (_PossiblePIDs_Version4.Contains((int)_testDevice.Info.IdProduct)) { _lookFor = MainMDX.BrainVersion.Version_04; } for (int indexBrain = 0; indexBrain < BrainClaimedArray.Length; indexBrain++) { if (BrainClaimedArray[indexBrain]) { continue; } if (MainMDX.AllBrains[indexBrain].version != _lookFor) { continue; } BrainClaimedArray[indexBrain] = true; MainMDX.AllBrains[indexBrain].Device = _testDevice; MainMDX.AllBrains[indexBrain].Stream_Reader = _testDevice.OpenInterruptEndpointReader(ReadEndpoints.Ep01); MainMDX.AllBrains[indexBrain].Stream_Writer = _testDevice.OpenInterruptEndpointWriter(WriteEndpoints.Ep01); if (MainMDX.AllBrains[indexBrain].Device.Open()) { int i1 = MainMDX.AllBrains[indexBrain].Device.SetConfiguration(1); int i2 = MainMDX.AllBrains[indexBrain].Device.ClaimInterface(0); } else { } break; } } } else { } } } //if (indexUSB < 0) //{ // return false; //} _t.IsBackground = true; _t.Start(); return true; } public static void DoUSB() { if (THREAD_SAFETY_SENDOK) { lock (MainMDX.AllBrains) { foreach (MainMDX.BrainID _FB in MainMDX.AllBrains) { bool isVirtual = MainMDX.VirtualBrainClass.isAVirtualBrain(_FB.humanName.ToLower()); if (_FB.Device == null && !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 (_FB.Device == null) { continue; } flipper = !flipper; int successWrite = 0; int successRead = 0; try { if (ByteStreamEvent_Send != null) { ByteStreamEvent_Send(_FB.humanName, _toSend); } } catch (Exception) { } try { 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 (successWrite < 0 || successRead < 0) { _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]].PreviousState = MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].CurrentState; 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]].CurrentState = true; } else { MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].CurrentState = false; } } else if (myVote[1] != 0) { if (myVote[1] > 0) { MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].CurrentState = true; } else { MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].CurrentState = false; } } else if (myVote[0] != 0) { if (myVote[0] > 0) { MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].CurrentState = true; } else { MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].CurrentState = 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; switch (_version) { case MainMDX.BrainVersion.Version_03: byte_address = MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Port; if (flip) { val += 2; } if (MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].CurrentState) { val += 1; } communicationArray[byte_address] = (byte)val; break; case MainMDX.BrainVersion.Version_04: byte_address = (MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].Port * 2); if (MainMDX.AllDigitalOutputs[digitalOutputIndexArray[i]].CurrentState) { 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; } } public static void DisposeOfAllBrains() { for (int i = 0; i < MainMDX.AllBrains.Count; i++) { if (MainMDX.AllBrains[i].Device != null && MainMDX.AllBrains[i].Stream_Reader != null && MainMDX.AllBrains[i].Stream_Writer != null) { MainMDX.AllBrains[i].Stream_Writer.Dispose(); MainMDX.AllBrains[i].Stream_Reader.Dispose(); MainMDX.AllBrains[i].Device.Close(); } } } public static void ShutOffAllOutputs() { foreach (MainMDX.DigitalOutputChannel _doc in MainMDX.AllDigitalOutputs) { _doc.CurrentState = false; _doc.ShouldIChangeState.Clear(); _doc.PreviousState = false; } THREAD_SAFETY_SENDOK = true; DoUSB(); THREAD_SAFETY_SENDOK = false; } private static void SetupPowerModeThread() { Microsoft.Win32.SystemEvents.PowerModeChanged += new Microsoft.Win32.PowerModeChangedEventHandler(SystemEvents_PowerModeChanged); } } }