diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.AnalogMux/Datasheet/74HC_HCT4051.pdf b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.AnalogMux/Datasheet/74HC_HCT4051.pdf new file mode 100644 index 0000000000..2ee219a892 Binary files /dev/null and b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.AnalogMux/Datasheet/74HC_HCT4051.pdf differ diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.AnalogMux/Datasheet/cd74hct4067.pdf b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.AnalogMux/Datasheet/cd74hct4067.pdf new file mode 100644 index 0000000000..ddd877f8d0 Binary files /dev/null and b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.AnalogMux/Datasheet/cd74hct4067.pdf differ diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.AnalogMux/Driver/AnalogInputMultiplexerBase.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.AnalogMux/Driver/AnalogInputMultiplexerBase.cs new file mode 100644 index 0000000000..fdb0538e59 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.AnalogMux/Driver/AnalogInputMultiplexerBase.cs @@ -0,0 +1,55 @@ +using Meadow.Hardware; + +namespace Meadow.Foundation.ICs.IOExpanders +{ + public abstract class AnalogInputMultiplexerBase : IAnalogInputMultiplexer + { + protected object SyncRoot { get; } = new object(); + + /// + /// The port connected to the Enable pin of the mux (otherwise must be tied low) + /// + public IDigitalOutputPort? EnablePort { get; } + + /// + /// The analog input connected to the Mux output pin (Z) + /// + public IAnalogInputPort Signal { get; } + + public abstract void SetInputChannel(int channel); + + internal AnalogInputMultiplexerBase(IAnalogInputPort signalPort, IDigitalOutputPort? enablePort) + { + Signal = signalPort; + EnablePort = enablePort; + } + + /// + /// Enables the multiplexer (if an enable port was provided) + /// + public void Enable() + { + if (EnablePort != null) + { + lock (SyncRoot) + { + EnablePort.State = false; // active low + } + } + } + + /// + /// Disables the multiplexer (if an enable port was provided) + /// + public void Disable() + { + if (EnablePort != null) + { + lock (SyncRoot) + { + EnablePort.State = true; + } + } + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.AnalogMux/Driver/Drivers/Hp4067.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.AnalogMux/Driver/Drivers/Hp4067.cs new file mode 100644 index 0000000000..c79ff98a15 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.AnalogMux/Driver/Drivers/Hp4067.cs @@ -0,0 +1,19 @@ +using Meadow.Hardware; + +namespace Meadow.Foundation.ICs.IOExpanders +{ + /// + /// Represents an Ti HP4067 16-channel analog multiplexer. + /// + /// This part is identical to the Nxp74HC4067 + public class Hp4067 : Nxp74HC4067 + { + /// + /// Creates a new Hp4067 object + /// + public Hp4067(IAnalogInputPort z, IDigitalOutputPort s0, IDigitalOutputPort? s1 = null, IDigitalOutputPort? s2 = null, IDigitalOutputPort? s3 = null, IDigitalOutputPort? enable = null) + : base(z, s0, s1, s2, s3, enable) + { + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.AnalogMux/Driver/Drivers/Nxp74HC4051.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.AnalogMux/Driver/Drivers/Nxp74HC4051.cs new file mode 100644 index 0000000000..4cb7d77f51 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.AnalogMux/Driver/Drivers/Nxp74HC4051.cs @@ -0,0 +1,138 @@ +using Meadow.Hardware; +using System; + +namespace Meadow.Foundation.ICs.IOExpanders +{ + /// + /// Represents an NXP 74HC4051 8-channel analog multiplexer + /// + public class Nxp74HC4051 : AnalogInputMultiplexerBase + { + /// + /// The port connected to the mux's S0 selection pin + /// + public IDigitalOutputPort S0 { get; } + /// + /// The port connected to the mux's S1 selection pin + /// + public IDigitalOutputPort? S1 { get; } + /// + /// The port connected to the mux's S2 selection pin + /// + public IDigitalOutputPort? S2 { get; } + + /// + /// Creates a new Nxp74HC4051 object using the default parameters + /// + public Nxp74HC4051(IAnalogInputPort z, IDigitalOutputPort s0, IDigitalOutputPort? s1 = null, IDigitalOutputPort? s2 = null, IDigitalOutputPort? enable = null) + : base (z, enable) + { + S0 = s0; + S1 = s1; + S2 = s2; + } + + /// + /// Sets the channel input (Y pin) that will be routed to the mux output (Z pin) + /// + /// + /// + public override void SetInputChannel(int channel) + { + if (channel < 0 || channel > 7) throw new ArgumentOutOfRangeException(); + + lock (SyncRoot) + { + var reenable = false; + + if (EnablePort != null) + { + if (EnablePort.State) + { + reenable = true; + + // disable before switching to prevent possible mis-routing + + Disable(); + } + } + + /* + Truth Table + E S2 S1 S0 + -- -- -- -- + L L L L Y0 to Z + L L L H Y1 to Z + L L H L Y2 to Z + L L H H Y3 to Z + L H L L Y4 to Z + L H L H Y5 to Z + L H H L Y6 to Z + L H H H Y7 to Z + H X X X switches of + */ + + switch (channel) + { + case 0: + S0.State = false; + if (S1 != null) { S1.State = false; } + if (S2 != null) { S2.State = false; } + break; + case 1: + S0.State = true; + if (S1 != null) { S1.State = false; } + if (S2 != null) { S2.State = false; } + break; + case 2: + if (S1 == null) throw new ArgumentException("You must have an S1 connected to access channels > 1"); + S0.State = false; + S1.State = true; + if (S2 != null) { S2.State = false; } + break; + case 3: + if (S1 == null) throw new ArgumentException("You must have an S1 connected to access channels > 1"); + S0.State = true; + S1.State = true; + if (S2 != null) { S2.State = false; } + break; + case 4: + if (S1 == null) throw new ArgumentException("You must have an S1 connected to access channels > 1"); + if (S2 == null) throw new ArgumentException("You must have an S2 connected to access channels > 3"); + S0.State = false; + S1.State = false; + S2.State = true; + break; + case 5: + if (S1 == null) throw new ArgumentException("You must have an S1 connected to access channels > 1"); + if (S2 == null) throw new ArgumentException("You must have an S2 connected to access channels > 3"); + S0.State = true; + S1.State = false; + S2.State = true; + break; + case 6: + if (S1 == null) throw new ArgumentException("You must have an S1 connected to access channels > 1"); + if (S2 == null) throw new ArgumentException("You must have an S2 connected to access channels > 3"); + S0.State = false; + S1.State = true; + S2.State = true; + break; + case 7: + if (S1 == null) throw new ArgumentException("You must have an S1 connected to access channels > 1"); + if (S2 == null) throw new ArgumentException("You must have an S2 connected to access channels > 3"); + S0.State = true; + S1.State = true; + S2.State = true; + break; + + } + + if (reenable) + { + Enable(); + } + } + + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.AnalogMux/Driver/Drivers/Nxp74HC4067.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.AnalogMux/Driver/Drivers/Nxp74HC4067.cs new file mode 100644 index 0000000000..706e473e67 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.AnalogMux/Driver/Drivers/Nxp74HC4067.cs @@ -0,0 +1,230 @@ +using Meadow.Hardware; +using System; + +namespace Meadow.Foundation.ICs.IOExpanders +{ + /// + /// Represents an NXP 74HC4067 16-channel analog multiplexer + /// + public class Nxp74HC4067 : AnalogInputMultiplexerBase + { + /// + /// The port connected to the mux's S0 selection pin + /// + public IDigitalOutputPort S0 { get; } + /// + /// The port connected to the mux's S1 selection pin + /// + public IDigitalOutputPort? S1 { get; } + /// + /// The port connected to the mux's S2 selection pin + /// + public IDigitalOutputPort? S2 { get; } + /// + /// The port connected to the mux's S3 selection pin + /// + public IDigitalOutputPort? S3 { get; } + + /// + /// Creates a new Nxp74HC4051 object + /// + public Nxp74HC4067(IAnalogInputPort z, IDigitalOutputPort s0, IDigitalOutputPort? s1 = null, IDigitalOutputPort? s2 = null, IDigitalOutputPort? s3 = null, IDigitalOutputPort? enable = null) + : base(z, enable) + { + S0 = s0; + S1 = s1; + S2 = s2; + S3 = s3; + } + + /// + /// Sets the channel input (Y pin) that will be routed to the mux output (Z pin) + /// + /// + /// + public override void SetInputChannel(int channel) + { + if (channel < 0 || channel > 7) throw new ArgumentOutOfRangeException(); + + lock (SyncRoot) + { + var reenable = false; + + if (EnablePort != null) + { + if (EnablePort.State) + { + reenable = true; + + // disable before switching to prevent possible mis-routing + + Disable(); + } + } + + /* + Truth Table + E S3 S2 S1 S0 + -- -- -- -- + L L L L L C0 to Z + L L L L H C1 to Z + L L L H L C2 to Z + L L L H H C3 to Z + L L H L L C4 to Z + L L H L H C5 to Z + L L H H L C6 to Z + L L H H H C7 to Z + L L L L L C8 to Z + L H L L H C9 to Z + L H L H L C10 to Z + L H L H H C11 to Z + L H H L L C12 to Z + L H H L H C13 to Z + L H H H L C14 to Z + L H H H H C15 to Z + H X X X X switches of + */ + + switch (channel) + { + case 0: + S0.State = false; + if (S1 != null) { S1.State = false; } + if (S2 != null) { S2.State = false; } + if (S3 != null) { S3.State = false; } + break; + case 1: + S0.State = true; + if (S1 != null) { S1.State = false; } + if (S2 != null) { S2.State = false; } + if (S3 != null) { S3.State = false; } + break; + case 2: + if (S1 == null) throw new ArgumentException("You must have an S1 connected to access channels > 1"); + S0.State = false; + S1.State = true; + if (S2 != null) { S2.State = false; } + if (S3 != null) { S3.State = false; } + break; + case 3: + if (S1 == null) throw new ArgumentException("You must have an S1 connected to access channels > 1"); + S0.State = true; + S1.State = true; + if (S2 != null) { S2.State = false; } + if (S3 != null) { S3.State = false; } + break; + case 4: + if (S1 == null) throw new ArgumentException("You must have an S1 connected to access channels > 1"); + if (S2 == null) throw new ArgumentException("You must have an S2 connected to access channels > 3"); + S0.State = false; + S1.State = false; + S2.State = true; + if (S3 != null) { S3.State = false; } + break; + case 5: + if (S1 == null) throw new ArgumentException("You must have an S1 connected to access channels > 1"); + if (S2 == null) throw new ArgumentException("You must have an S2 connected to access channels > 3"); + S0.State = true; + S1.State = false; + S2.State = true; + if (S3 != null) { S3.State = false; } + break; + case 6: + if (S1 == null) throw new ArgumentException("You must have an S1 connected to access channels > 1"); + if (S2 == null) throw new ArgumentException("You must have an S2 connected to access channels > 3"); + S0.State = false; + S1.State = true; + S2.State = true; + if (S3 != null) { S3.State = false; } + break; + case 7: + if (S1 == null) throw new ArgumentException("You must have an S1 connected to access channels > 1"); + if (S2 == null) throw new ArgumentException("You must have an S2 connected to access channels > 3"); + S0.State = true; + S1.State = true; + S2.State = true; + if (S3 != null) { S3.State = false; } + break; + + case 8: + if (S1 == null) throw new ArgumentException("You must have an S1 connected to access channels > 1"); + if (S2 == null) throw new ArgumentException("You must have an S2 connected to access channels > 3"); + if (S3 == null) throw new ArgumentException("You must have an S3 connected to access channels > 7"); + S0.State = false; + S1.State = false; + S2.State = false; + S3.State = true; + break; + case 9: + if (S1 == null) throw new ArgumentException("You must have an S1 connected to access channels > 1"); + if (S2 == null) throw new ArgumentException("You must have an S2 connected to access channels > 3"); + if (S3 == null) throw new ArgumentException("You must have an S3 connected to access channels > 7"); + S0.State = true; + S1.State = false; + S2.State = false; + S3.State = true; + break; + case 10: + if (S1 == null) throw new ArgumentException("You must have an S1 connected to access channels > 1"); + if (S2 == null) throw new ArgumentException("You must have an S2 connected to access channels > 3"); + if (S3 == null) throw new ArgumentException("You must have an S3 connected to access channels > 7"); + S0.State = false; + S1.State = true; + S2.State = false; + S3.State = true; + break; + case 11: + if (S1 == null) throw new ArgumentException("You must have an S1 connected to access channels > 1"); + if (S2 == null) throw new ArgumentException("You must have an S2 connected to access channels > 3"); + if (S3 == null) throw new ArgumentException("You must have an S3 connected to access channels > 7"); + S0.State = true; + S1.State = true; + S2.State = false; + S3.State = true; + break; + case 12: + if (S1 == null) throw new ArgumentException("You must have an S1 connected to access channels > 1"); + if (S2 == null) throw new ArgumentException("You must have an S2 connected to access channels > 3"); + if (S3 == null) throw new ArgumentException("You must have an S3 connected to access channels > 7"); + S0.State = false; + S1.State = false; + S2.State = true; + S3.State = true; + break; + case 13: + if (S1 == null) throw new ArgumentException("You must have an S1 connected to access channels > 1"); + if (S2 == null) throw new ArgumentException("You must have an S2 connected to access channels > 3"); + if (S3 == null) throw new ArgumentException("You must have an S3 connected to access channels > 7"); + S0.State = true; + S1.State = false; + S2.State = true; + S3.State = true; + break; + case 14: + if (S1 == null) throw new ArgumentException("You must have an S1 connected to access channels > 1"); + if (S2 == null) throw new ArgumentException("You must have an S2 connected to access channels > 3"); + if (S3 == null) throw new ArgumentException("You must have an S3 connected to access channels > 7"); + S0.State = false; + S1.State = true; + S2.State = true; + S3.State = true; + break; + case 15: + if (S1 == null) throw new ArgumentException("You must have an S1 connected to access channels > 1"); + if (S2 == null) throw new ArgumentException("You must have an S2 connected to access channels > 3"); + if (S3 == null) throw new ArgumentException("You must have an S3 connected to access channels > 7"); + S0.State = true; + S1.State = true; + S2.State = true; + S3.State = true; + break; + } + + if (reenable) + { + Enable(); + } + } + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.AnalogMux/Driver/IAnalogInputMultiplexer.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.AnalogMux/Driver/IAnalogInputMultiplexer.cs new file mode 100644 index 0000000000..910862ed58 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.AnalogMux/Driver/IAnalogInputMultiplexer.cs @@ -0,0 +1,35 @@ +using Meadow.Hardware; +using System; + +namespace Meadow.Foundation.ICs.IOExpanders +{ + public interface IAnalogInputMultiplexer + { + /// + /// The port connected to the Enable pin of the mux (otherwise must be tied low) + /// + IDigitalOutputPort EnablePort { get; } + + /// + /// The analog input connected to the Mux output pin (Z) + /// + IAnalogInputPort Signal { get; } + + /// + /// Disables the multiplexer (if an enable port was provided) + /// + void Disable(); + + /// + /// Enables the multiplexer (if an enable port was provided) + /// + void Enable(); + + /// + /// Sets the channel input that will be routed to the mux Signal output + /// + /// + /// + void SetInputChannel(int channel); + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.AnalogMux/Driver/ICs.IOExpanders.AnalogMux.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.AnalogMux/Driver/ICs.IOExpanders.AnalogMux.csproj new file mode 100644 index 0000000000..ab2d086bd2 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.AnalogMux/Driver/ICs.IOExpanders.AnalogMux.csproj @@ -0,0 +1,25 @@ + + + true + icon.png + Wilderness Labs, Inc + netstandard2.1 + Library + AnalogMux + Wilderness Labs, Inc + http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ + Meadow.Foundation.ICs.IOExpanders.AnalogMux + https://github.com/WildernessLabs/Meadow.Foundation + Meadow.Foundation, IOExpanders, Analog, Input, Multiplexer, 74HC4051, 74HC4067, HP4067 + 0.1.0 + true + Library for various analog multiplexers + enable + + + + + + + + \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.AnalogMux/Samples/Nxp74HC4051_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.AnalogMux/Samples/Nxp74HC4051_Sample/MeadowApp.cs new file mode 100644 index 0000000000..78d5e630b6 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.AnalogMux/Samples/Nxp74HC4051_Sample/MeadowApp.cs @@ -0,0 +1,56 @@ +using Meadow; +using Meadow.Devices; +using Meadow.Foundation.ICs.IOExpanders; +using System.Threading.Tasks; + +namespace ICs.IOExpanders.Nxp74HC4051_Sample +{ + public class MeadowApp : App + { + // + + private Nxp74HC4051 _mux; + + public MeadowApp() + { + } + + public override Task Initialize() + { + Resolver.Log.Info("Initialize..."); + + _mux = new Nxp74HC4051( + Device.CreateAnalogInputPort(Device.Pins.A00), // input + Device.CreateDigitalOutputPort(Device.Pins.D00), // s0 + Device.CreateDigitalOutputPort(Device.Pins.D01), // s1 + Device.CreateDigitalOutputPort(Device.Pins.D02), // s2 + Device.CreateDigitalOutputPort(Device.Pins.D03) // enable + ); + + return base.Initialize(); + } + + public override Task Run() + { + Task.Run(ReadRoundRobin); + + return base.Run(); + } + + public async Task ReadRoundRobin() + { + while (true) + { + for (var channel = 0; channel < 8; channel++) + { + _mux.SetInputChannel(channel); + var read = await _mux.Signal.Read(); + Resolver.Log.Info($"ADC Channel {channel} = {read.Volts:0.0}V"); + await Task.Delay(1000); + } + } + } + + // + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.AnalogMux/Samples/Nxp74HC4051_Sample/Nxp74HC4051_Sample.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.AnalogMux/Samples/Nxp74HC4051_Sample/Nxp74HC4051_Sample.csproj new file mode 100644 index 0000000000..ab34b38ae8 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.AnalogMux/Samples/Nxp74HC4051_Sample/Nxp74HC4051_Sample.csproj @@ -0,0 +1,15 @@ + + + https://github.com/WildernessLabs/Meadow.Foundation + Wilderness Labs, Inc + Wilderness Labs, Inc + true + netstandard2.1 + Library + App + + + + + + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sgp40/Samples/Sgp40_Sample/Program.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sgp40/Samples/Sgp40_Sample/Program.cs deleted file mode 100644 index 1d765cd8d3..0000000000 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sgp40/Samples/Sgp40_Sample/Program.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Meadow; -using System.Threading; - -namespace BasicSensors.Atmospheric.SI7021_Sample -{ - class Program - { - static IApp? app; - - public static void Main(string[] args) - { - app = new MeadowApp(); - - Thread.Sleep(Timeout.Infinite); - } - } -} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sgp40/Samples/Sgp40_Sample/Sgp40_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sgp40/Samples/Sgp40_Sample/Sgp40_Sample.csproj index beffd4fcaf..b553836c9f 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sgp40/Samples/Sgp40_Sample/Sgp40_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sgp40/Samples/Sgp40_Sample/Sgp40_Sample.csproj @@ -5,7 +5,7 @@ Wilderness Labs, Inc true netstandard2.1 - Exe + Library App enable diff --git a/Source/Meadow.Foundation.sln b/Source/Meadow.Foundation.sln index 329392da13..0b516d961c 100644 --- a/Source/Meadow.Foundation.sln +++ b/Source/Meadow.Foundation.sln @@ -1054,6 +1054,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sensors.Atmospheric.Sgp40", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sgp40_Sample", "Meadow.Foundation.Peripherals\Sensors.Atmospheric.Sgp40\Samples\Sgp40_Sample\Sgp40_Sample.csproj", "{1ACC6BA0-8108-4BFA-9A75-9063B5E07493}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Ics.IOExpanders.AnalogMux", "Ics.IOExpanders.AnalogMux", "{643EF07C-36AD-4796-9748-2F630631CF16}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{27443DF5-9D37-47E8-A350-4AFD103913CC}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ICs.IOExpanders.AnalogMux", "Meadow.Foundation.Peripherals\ICs.IOExpanders.AnalogMux\Driver\ICs.IOExpanders.AnalogMux.csproj", "{D80EB935-8B49-4D46-8474-F457C5BFB27C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nxp74HC4051_Sample", "Meadow.Foundation.Peripherals\ICs.IOExpanders.AnalogMux\Samples\Nxp74HC4051_Sample\Nxp74HC4051_Sample.csproj", "{212208FF-76E1-4864-ADA4-AAC7AE0F2981}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -2466,6 +2474,18 @@ Global {1ACC6BA0-8108-4BFA-9A75-9063B5E07493}.Release|Any CPU.ActiveCfg = Release|Any CPU {1ACC6BA0-8108-4BFA-9A75-9063B5E07493}.Release|Any CPU.Build.0 = Release|Any CPU {1ACC6BA0-8108-4BFA-9A75-9063B5E07493}.Release|Any CPU.Deploy.0 = Release|Any CPU + {D80EB935-8B49-4D46-8474-F457C5BFB27C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D80EB935-8B49-4D46-8474-F457C5BFB27C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D80EB935-8B49-4D46-8474-F457C5BFB27C}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {D80EB935-8B49-4D46-8474-F457C5BFB27C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D80EB935-8B49-4D46-8474-F457C5BFB27C}.Release|Any CPU.Build.0 = Release|Any CPU + {D80EB935-8B49-4D46-8474-F457C5BFB27C}.Release|Any CPU.Deploy.0 = Release|Any CPU + {212208FF-76E1-4864-ADA4-AAC7AE0F2981}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {212208FF-76E1-4864-ADA4-AAC7AE0F2981}.Debug|Any CPU.Build.0 = Debug|Any CPU + {212208FF-76E1-4864-ADA4-AAC7AE0F2981}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {212208FF-76E1-4864-ADA4-AAC7AE0F2981}.Release|Any CPU.ActiveCfg = Release|Any CPU + {212208FF-76E1-4864-ADA4-AAC7AE0F2981}.Release|Any CPU.Build.0 = Release|Any CPU + {212208FF-76E1-4864-ADA4-AAC7AE0F2981}.Release|Any CPU.Deploy.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -2990,6 +3010,10 @@ Global {F2ECD777-3B3B-4EF1-B68C-E31AAADBF2B5} = {B98533B9-CA48-4F0D-961B-C95BD5158391} {71EBC24D-5B32-4E76-ADF3-DE0017946108} = {B98533B9-CA48-4F0D-961B-C95BD5158391} {1ACC6BA0-8108-4BFA-9A75-9063B5E07493} = {F2ECD777-3B3B-4EF1-B68C-E31AAADBF2B5} + {643EF07C-36AD-4796-9748-2F630631CF16} = {64623FCA-6086-4F0A-A59D-2BF372EA38AA} + {27443DF5-9D37-47E8-A350-4AFD103913CC} = {643EF07C-36AD-4796-9748-2F630631CF16} + {D80EB935-8B49-4D46-8474-F457C5BFB27C} = {643EF07C-36AD-4796-9748-2F630631CF16} + {212208FF-76E1-4864-ADA4-AAC7AE0F2981} = {27443DF5-9D37-47E8-A350-4AFD103913CC} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {AF7CA16F-8C38-4546-87A2-5DAAF58A1520}