diff --git a/Source/Meadow.Foundation.Core.Samples/Audio.PiezoSpeaker_Sample/Audio.PiezoSpeaker_Sample.csproj b/Source/Meadow.Foundation.Core.Samples/Audio.PiezoSpeaker_Sample/Audio.PiezoSpeaker_Sample.csproj index ea265c2bc9..5232cdbf91 100644 --- a/Source/Meadow.Foundation.Core.Samples/Audio.PiezoSpeaker_Sample/Audio.PiezoSpeaker_Sample.csproj +++ b/Source/Meadow.Foundation.Core.Samples/Audio.PiezoSpeaker_Sample/Audio.PiezoSpeaker_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Core.Samples/Generators.SoftPwmPort_Sample/Generators.SoftPwmPort_Sample.csproj b/Source/Meadow.Foundation.Core.Samples/Generators.SoftPwmPort_Sample/Generators.SoftPwmPort_Sample.csproj index ea265c2bc9..5232cdbf91 100644 --- a/Source/Meadow.Foundation.Core.Samples/Generators.SoftPwmPort_Sample/Generators.SoftPwmPort_Sample.csproj +++ b/Source/Meadow.Foundation.Core.Samples/Generators.SoftPwmPort_Sample/Generators.SoftPwmPort_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Core.Samples/Leds.LedBarGraph_Sample/Leds.LedBarGraph_Sample.csproj b/Source/Meadow.Foundation.Core.Samples/Leds.LedBarGraph_Sample/Leds.LedBarGraph_Sample.csproj index ea265c2bc9..5232cdbf91 100644 --- a/Source/Meadow.Foundation.Core.Samples/Leds.LedBarGraph_Sample/Leds.LedBarGraph_Sample.csproj +++ b/Source/Meadow.Foundation.Core.Samples/Leds.LedBarGraph_Sample/Leds.LedBarGraph_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Core.Samples/Leds.LedBarGraph_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Core.Samples/Leds.LedBarGraph_Sample/MeadowApp.cs index 988f075e79..12e4e052b7 100644 --- a/Source/Meadow.Foundation.Core.Samples/Leds.LedBarGraph_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Core.Samples/Leds.LedBarGraph_Sample/MeadowApp.cs @@ -48,9 +48,9 @@ public override async Task Run() Resolver.Log.Info("Turning them on and off for 200ms using SetLed..."); for (int i = 0; i < ledBarGraph.Count; i++) { - ledBarGraph.SetLed(i, true); + await ledBarGraph.SetLed(i, true); await Task.Delay(100); - ledBarGraph.SetLed(i, false); + await ledBarGraph.SetLed(i, false); } await Task.Delay(1000); @@ -59,8 +59,7 @@ public override async Task Run() while (percentage < 1) { percentage += 0.10f; - Resolver.Log.Info($"{percentage}"); - ledBarGraph.Percentage = Math.Min(1.0f, percentage); + await ledBarGraph.SetPercentage(Math.Min(1.0f, percentage)); await Task.Delay(100); } @@ -70,8 +69,7 @@ public override async Task Run() while (percentage > 0) { percentage -= 0.10f; - Resolver.Log.Info($"{percentage}"); - ledBarGraph.Percentage = Math.Max(0.0f, percentage); + await ledBarGraph.SetPercentage(Math.Max(0.0f, percentage)); await Task.Delay(100); } @@ -81,9 +79,8 @@ public override async Task Run() while (percentage < 1) { percentage += 0.10f; - Resolver.Log.Info($"{percentage}"); - ledBarGraph.Percentage = Math.Min(1.0f, percentage); - ledBarGraph.StartBlink(ledBarGraph.GetTopLedForPercentage()); + await ledBarGraph.SetPercentage(Math.Min(1.0f, percentage)); + await ledBarGraph.StartBlink(ledBarGraph.GetTopLedForPercentage()); await Task.Delay(2000); } @@ -93,25 +90,24 @@ public override async Task Run() while (percentage > 0) { percentage -= 0.10f; - Resolver.Log.Info($"{percentage}"); - ledBarGraph.Percentage = Math.Max(0.0f, percentage); - ledBarGraph.StartBlink(ledBarGraph.GetTopLedForPercentage()); + await ledBarGraph.SetPercentage(Math.Max(0.0f, percentage)); + await ledBarGraph.StartBlink(ledBarGraph.GetTopLedForPercentage()); await Task.Delay(2000); } await Task.Delay(1000); Resolver.Log.Info("Blinking for 5 seconds at 500ms on/off..."); - ledBarGraph.StartBlink(); + await ledBarGraph.StartBlink(); await Task.Delay(5000); - ledBarGraph.Stop(); + await ledBarGraph.StopAnimation(); await Task.Delay(1000); Resolver.Log.Info("Blinking for 5 seconds at 200ms on/off..."); - ledBarGraph.StartBlink(TimeSpan.FromMilliseconds(200), TimeSpan.FromMilliseconds(200)); + await ledBarGraph.StartBlink(TimeSpan.FromMilliseconds(200), TimeSpan.FromMilliseconds(200)); await Task.Delay(5000); - ledBarGraph.Stop(); + await ledBarGraph.StopAnimation(); await Task.Delay(1000); } diff --git a/Source/Meadow.Foundation.Core.Samples/Leds.Led_Sample/Leds.Led_Sample.csproj b/Source/Meadow.Foundation.Core.Samples/Leds.Led_Sample/Leds.Led_Sample.csproj index ea265c2bc9..5232cdbf91 100644 --- a/Source/Meadow.Foundation.Core.Samples/Leds.Led_Sample/Leds.Led_Sample.csproj +++ b/Source/Meadow.Foundation.Core.Samples/Leds.Led_Sample/Leds.Led_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Core.Samples/Leds.Led_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Core.Samples/Leds.Led_Sample/MeadowApp.cs index bf4f9a81b9..a1303f7ee4 100644 --- a/Source/Meadow.Foundation.Core.Samples/Leds.Led_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Core.Samples/Leds.Led_Sample/MeadowApp.cs @@ -1,7 +1,6 @@ using Meadow; using Meadow.Devices; using Meadow.Foundation.Leds; -using Meadow.Peripherals.Leds; using System; using System.Collections.Generic; using System.Threading.Tasks; @@ -74,17 +73,17 @@ public override async Task Run() Resolver.Log.Info("Blinking the LEDs for a second each"); foreach (var led in leds) { - led.StartBlink(); + await led.StartBlink(); await Task.Delay(3000); - led.Stop(); + await led.StopAnimation(); } Resolver.Log.Info("Blinking the LEDs for a second each with on (1s) and off (1s)"); foreach (var led in leds) { - led.StartBlink(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1)); + await led.StartBlink(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1)); await Task.Delay(3000); - led.Stop(); + await led.StopAnimation(); } await Task.Delay(3000); diff --git a/Source/Meadow.Foundation.Core.Samples/Leds.PwmLedBarGraph_Sample/Leds.PwmLedBarGraph_Sample.csproj b/Source/Meadow.Foundation.Core.Samples/Leds.PwmLedBarGraph_Sample/Leds.PwmLedBarGraph_Sample.csproj index ea265c2bc9..5232cdbf91 100644 --- a/Source/Meadow.Foundation.Core.Samples/Leds.PwmLedBarGraph_Sample/Leds.PwmLedBarGraph_Sample.csproj +++ b/Source/Meadow.Foundation.Core.Samples/Leds.PwmLedBarGraph_Sample/Leds.PwmLedBarGraph_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Core.Samples/Leds.PwmLedBarGraph_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Core.Samples/Leds.PwmLedBarGraph_Sample/MeadowApp.cs index aad8f9dce8..9432f55a9f 100644 --- a/Source/Meadow.Foundation.Core.Samples/Leds.PwmLedBarGraph_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Core.Samples/Leds.PwmLedBarGraph_Sample/MeadowApp.cs @@ -2,7 +2,6 @@ using Meadow.Devices; using Meadow.Foundation.Leds; using Meadow.Hardware; -using Meadow.Peripherals.Leds; using Meadow.Units; using System; using System.Threading.Tasks; @@ -50,9 +49,9 @@ public override async Task Run() Resolver.Log.Info("Turning them on and off for 200ms using SetLed..."); for (int i = 0; i < pwmLedBarGraph.Count; i++) { - pwmLedBarGraph.SetLed(i, true); + await pwmLedBarGraph.SetLed(i, true); await Task.Delay(100); - pwmLedBarGraph.SetLed(i, false); + await pwmLedBarGraph.SetLed(i, false); } await Task.Delay(1000); @@ -61,7 +60,7 @@ public override async Task Run() while (percentage < 1) { percentage += 0.01f; - pwmLedBarGraph.Percentage = Math.Min(1.0f, percentage); + await pwmLedBarGraph.SetPercentage(Math.Min(1.0f, percentage)); await Task.Delay(100); } @@ -71,30 +70,34 @@ public override async Task Run() while (percentage > 0) { percentage -= 0.01f; - pwmLedBarGraph.Percentage = Math.Max(0.0f, percentage); + await pwmLedBarGraph.SetPercentage(Math.Max(0.0f, percentage)); await Task.Delay(100); } await Task.Delay(1000); Resolver.Log.Info("Blinking for 5 seconds at 500ms on/off..."); - pwmLedBarGraph.StartBlink(); + await pwmLedBarGraph.StartBlink(); await Task.Delay(5000); - pwmLedBarGraph.Stop(); + await pwmLedBarGraph.StopAnimation(); await Task.Delay(1000); Resolver.Log.Info("Bar blinking with high and low brightness for 5 seconds..."); - pwmLedBarGraph.StartBlink(TimeSpan.FromMilliseconds(200), TimeSpan.FromMilliseconds(200), 0.75f, 0.25f); + await pwmLedBarGraph.StartBlink(TimeSpan.FromMilliseconds(200), TimeSpan.FromMilliseconds(200), 0.75f, 0.25f); await Task.Delay(5000); - pwmLedBarGraph.Stop(); + await pwmLedBarGraph.StopAnimation(); await Task.Delay(1000); Resolver.Log.Info("Bar pulsing for 5 seconds..."); - pwmLedBarGraph.StartPulse(); + await pwmLedBarGraph.StartPulse(); await Task.Delay(5000); - pwmLedBarGraph.Stop(); + await pwmLedBarGraph.StopAnimation(); + + await Task.Delay(1000); + + await pwmLedBarGraph.SetBrightness(0); await Task.Delay(1000); } diff --git a/Source/Meadow.Foundation.Core.Samples/Leds.PwmLed_Onboard_Sample/Leds.PwmLed_Onboard_Sample.csproj b/Source/Meadow.Foundation.Core.Samples/Leds.PwmLed_Onboard_Sample/Leds.PwmLed_Onboard_Sample.csproj index ea265c2bc9..5232cdbf91 100644 --- a/Source/Meadow.Foundation.Core.Samples/Leds.PwmLed_Onboard_Sample/Leds.PwmLed_Onboard_Sample.csproj +++ b/Source/Meadow.Foundation.Core.Samples/Leds.PwmLed_Onboard_Sample/Leds.PwmLed_Onboard_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Core.Samples/Leds.PwmLed_Onboard_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Core.Samples/Leds.PwmLed_Onboard_Sample/MeadowApp.cs index 4db48f0ac5..34b36e656a 100644 --- a/Source/Meadow.Foundation.Core.Samples/Leds.PwmLed_Onboard_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Core.Samples/Leds.PwmLed_Onboard_Sample/MeadowApp.cs @@ -21,7 +21,7 @@ public override Task Initialize() redPwmLed = new PwmLed(Device.Pins.OnboardLedRed, TypicalForwardVoltage.ResistorLimited, CircuitTerminationType.High); greenPwmLed = new PwmLed(Device.Pins.OnboardLedGreen, TypicalForwardVoltage.ResistorLimited, CircuitTerminationType.High); bluePwmLed = new PwmLed(Device.Pins.OnboardLedBlue, TypicalForwardVoltage.ResistorLimited, CircuitTerminationType.High); - + return Task.CompletedTask; } @@ -29,51 +29,51 @@ public override Task Run() { return PulseLeds(); } - + public async Task BrightnessTest(int loopCount) { - for (int i = 0; i < loopCount; i++) { + for (int i = 0; i < loopCount; i++) + { Resolver.Log.Info("Blue On @ 1.0"); - bluePwmLed.Brightness = 1; + bluePwmLed.SetBrightness(1); await Task.Delay(1000); Resolver.Log.Info("Blue at 98.5%"); - bluePwmLed.Brightness = 0.985f; + bluePwmLed.SetBrightness(0.985f); await Task.Delay(1000); Resolver.Log.Info("Blue Off"); - bluePwmLed.Brightness = 0; + bluePwmLed.SetBrightness(0); await Task.Delay(1000); Resolver.Log.Info("Blue 50%"); - bluePwmLed.Brightness = 0.5f; + bluePwmLed.SetBrightness(0.5f); await Task.Delay(1000); - bluePwmLed.Stop(); + await bluePwmLed.StopAnimation(); } } public async Task PulseLeds() { - while (true) + while (true) { Resolver.Log.Info("Pulse Red."); - redPwmLed.StartPulse(TimeSpan.FromMilliseconds(500), lowBrightness: 0.05f); + await redPwmLed.StartPulse(TimeSpan.FromMilliseconds(500), lowBrightness: 0.05f); await Task.Delay(1000); Resolver.Log.Info("Stop Red."); - redPwmLed.Stop(); + await redPwmLed.StopAnimation(); Resolver.Log.Info("Pulse Blue."); - bluePwmLed.StartPulse(TimeSpan.FromMilliseconds(500), lowBrightness: 0.05f); + await bluePwmLed.StartPulse(TimeSpan.FromMilliseconds(500), lowBrightness: 0.05f); await Task.Delay(2000); Resolver.Log.Info("Stop Blue."); - bluePwmLed.Stop(); + await bluePwmLed.StopAnimation(); Resolver.Log.Info("Pulse Green."); - greenPwmLed.StartPulse(TimeSpan.FromMilliseconds(500), lowBrightness: 0.0f); + await greenPwmLed.StartPulse(TimeSpan.FromMilliseconds(500), lowBrightness: 0.0f); await Task.Delay(2000); Resolver.Log.Info("Stop Green."); - greenPwmLed.Stop(); - + await greenPwmLed.StopAnimation(); } } diff --git a/Source/Meadow.Foundation.Core.Samples/Leds.PwmLed_Sample/Leds.PwmLed_Sample.csproj b/Source/Meadow.Foundation.Core.Samples/Leds.PwmLed_Sample/Leds.PwmLed_Sample.csproj index ea265c2bc9..5232cdbf91 100644 --- a/Source/Meadow.Foundation.Core.Samples/Leds.PwmLed_Sample/Leds.PwmLed_Sample.csproj +++ b/Source/Meadow.Foundation.Core.Samples/Leds.PwmLed_Sample/Leds.PwmLed_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Core.Samples/Leds.PwmLed_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Core.Samples/Leds.PwmLed_Sample/MeadowApp.cs index 0778b2a917..c1e511c8a9 100644 --- a/Source/Meadow.Foundation.Core.Samples/Leds.PwmLed_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Core.Samples/Leds.PwmLed_Sample/MeadowApp.cs @@ -1,7 +1,6 @@ using Meadow; using Meadow.Devices; using Meadow.Foundation.Leds; -using Meadow.Peripherals.Leds; using Meadow.Units; using System; using System.Collections.Generic; @@ -62,42 +61,33 @@ public override async Task Run() await Task.Delay(1000); - Resolver.Log.Info("Blinking the LED for a bit."); + Resolver.Log.Info("Blinking each LED (on 500ms / off 500ms)"); foreach (var pwmLed in pwmLeds) { - pwmLed.StartBlink(); + await pwmLed.StartBlink(); await Task.Delay(3000); - pwmLed.Stop(); + await pwmLed.StopAnimation(); } await Task.Delay(1000); - Resolver.Log.Info("Blinking the LED for a bit."); + Resolver.Log.Info("Blinking each LED (on 1s / off 1s)"); foreach (var pwmLed in pwmLeds) { - pwmLed.StartBlink(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1)); + await pwmLed.StartBlink(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1)); await Task.Delay(3000); - pwmLed.Stop(); + await pwmLed.StopAnimation(); } await Task.Delay(1000); - Resolver.Log.Info("Pulsing the LED for a bit."); + Resolver.Log.Info("Pulsing each LED (600ms pulse duration)"); foreach (var pwmLed in pwmLeds) { - pwmLed.StartPulse(); + await pwmLed.StartPulse(); await Task.Delay(1000); - pwmLed.Stop(); - } - - await Task.Delay(1000); - - Resolver.Log.Info("Pulsing the LED for a bit."); - foreach (var pwmLed in pwmLeds) - { - pwmLed.StartPulse(); - await Task.Delay(1000); - pwmLed.Stop(); + await pwmLed.StopAnimation(); + pwmLed.IsOn = false; } await Task.Delay(1000); @@ -105,15 +95,15 @@ public override async Task Run() Resolver.Log.Info("Set brightness the LED for a bit."); foreach (var pwmLed in pwmLeds) { - pwmLed.Brightness = 0.25f; + pwmLed.SetBrightness(0.25f); await Task.Delay(250); - pwmLed.Brightness = 0.5f; + pwmLed.SetBrightness(0.5f); await Task.Delay(250); - pwmLed.Brightness = 0.75f; + pwmLed.SetBrightness(0.75f); await Task.Delay(250); - pwmLed.Brightness = 1.0f; + pwmLed.SetBrightness(1.0f); await Task.Delay(250); - pwmLed.Stop(); + pwmLed.IsOn = false; } await Task.Delay(1000); diff --git a/Source/Meadow.Foundation.Core.Samples/Leds.RgbLed_Sample/Leds.RgbLed_Sample.csproj b/Source/Meadow.Foundation.Core.Samples/Leds.RgbLed_Sample/Leds.RgbLed_Sample.csproj index ea265c2bc9..5232cdbf91 100644 --- a/Source/Meadow.Foundation.Core.Samples/Leds.RgbLed_Sample/Leds.RgbLed_Sample.csproj +++ b/Source/Meadow.Foundation.Core.Samples/Leds.RgbLed_Sample/Leds.RgbLed_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Core.Samples/Leds.RgbLed_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Core.Samples/Leds.RgbLed_Sample/MeadowApp.cs index 4db222ffd5..e5ecbdae97 100644 --- a/Source/Meadow.Foundation.Core.Samples/Leds.RgbLed_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Core.Samples/Leds.RgbLed_Sample/MeadowApp.cs @@ -1,10 +1,9 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Meadow; +using Meadow; using Meadow.Devices; using Meadow.Foundation.Leds; -using Meadow.Peripherals.Leds; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; namespace Leds.RgbLed_Sample { @@ -18,12 +17,6 @@ public override Task Initialize() { Resolver.Log.Info("Initializing..."); - var onRgbLed = new RgbLed( - redPin: Device.Pins.OnboardLedRed, - greenPin: Device.Pins.OnboardLedGreen, - bluePin: Device.Pins.OnboardLedBlue); - onRgbLed.SetColor(RgbLedColors.Red); - rgbLeds = new List { new RgbLed( @@ -44,8 +37,6 @@ public override Task Initialize() Device.CreateDigitalOutputPort(Device.Pins.D13)) }; - onRgbLed.SetColor(RgbLedColors.Green); - return Task.CompletedTask; } @@ -67,25 +58,29 @@ public override async Task Run() await Task.Delay(1000); - Resolver.Log.Info("Blinking through each color on each RGB LED..."); + Resolver.Log.Info("Blinking through each color on each RGB LED (on 500ms / off 500ms)..."); foreach (var rgbLed in rgbLeds) { for (int i = 0; i < (int)RgbLedColors.count; i++) { - rgbLed.StartBlink((RgbLedColors)i); + await rgbLed.StartBlink((RgbLedColors)i); await Task.Delay(3000); + await rgbLed.StopAnimation(); + rgbLed.IsOn = false; } } await Task.Delay(1000); - Resolver.Log.Info("Blinking through each color on each RGB LED..."); + Resolver.Log.Info("Blinking through each color on each RGB LED (on 1s / off 1s)..."); foreach (var rgbLed in rgbLeds) { for (int i = 0; i < (int)RgbLedColors.count; i++) { - rgbLed.StartBlink((RgbLedColors)i, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1)); + await rgbLed.StartBlink((RgbLedColors)i, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1)); await Task.Delay(3000); + await rgbLed.StopAnimation(); + rgbLed.IsOn = false; } } diff --git a/Source/Meadow.Foundation.Core.Samples/Leds.RgbPwmLed_Onboard_Sample/Leds.RgbPwmLed_Onboard_Sample.csproj b/Source/Meadow.Foundation.Core.Samples/Leds.RgbPwmLed_Onboard_Sample/Leds.RgbPwmLed_Onboard_Sample.csproj index ea265c2bc9..5232cdbf91 100644 --- a/Source/Meadow.Foundation.Core.Samples/Leds.RgbPwmLed_Onboard_Sample/Leds.RgbPwmLed_Onboard_Sample.csproj +++ b/Source/Meadow.Foundation.Core.Samples/Leds.RgbPwmLed_Onboard_Sample/Leds.RgbPwmLed_Onboard_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Core.Samples/Leds.RgbPwmLed_Onboard_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Core.Samples/Leds.RgbPwmLed_Onboard_Sample/MeadowApp.cs index 102597f7cd..3ba32b9303 100644 --- a/Source/Meadow.Foundation.Core.Samples/Leds.RgbPwmLed_Onboard_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Core.Samples/Leds.RgbPwmLed_Onboard_Sample/MeadowApp.cs @@ -2,9 +2,7 @@ using Meadow.Devices; using Meadow.Foundation; using Meadow.Foundation.Leds; -using Meadow.Peripherals.Leds; using System; -using System.Threading; using System.Threading.Tasks; namespace Leds.RgbPwmLed_Onboard_Sample @@ -18,48 +16,45 @@ public class MeadowApp : App public override Task Initialize() { Resolver.Log.Info("Creating peripherals..."); - + onboardLed = new RgbPwmLed( Device.Pins.OnboardLedRed, Device.Pins.OnboardLedGreen, - Device.Pins.OnboardLedBlue, - commonType: CommonType.CommonAnode); + Device.Pins.OnboardLedBlue); return Task.CompletedTask; } public override Task Run() { - TestColors(); - - RunColors(); - - return Task.CompletedTask; + return TestColors(); } - public void TestColors() + public async Task TestColors() { - onboardLed.SetColor(Color.Crimson); - Thread.Sleep(3000); - onboardLed.SetColor(Color.MediumPurple); - Thread.Sleep(3000); - onboardLed.SetColor(Color.FromHex("#23abe3")); - } + while (true) + { + Console.WriteLine("SetColor(RgbLedColors.Red);"); + onboardLed.SetColor(Color.Red); + await Task.Delay(3000); - public void RunColors() - { - while (true) { + Console.WriteLine("StartPulse();"); + await onboardLed.StartPulse(); + await Task.Delay(3000); + + Console.WriteLine("StartPulse(RgbLedColors.Green);"); + await onboardLed.StartPulse(Color.Green); + await Task.Delay(3000); - // loop through the entire hue spectrum (360 degrees) - for (int i = 0; i < 360; i++) { - var hue = ((double)i / 360F); - Resolver.Log.Info($"Hue: {hue}"); + Console.WriteLine("SetColor(RgbLedColors.Yellow);"); + onboardLed.SetColor(Color.Yellow); + await Task.Delay(3000); - // set the color of the RGB - onboardLed.SetColor(Color.FromHsba((hue), 1, 1)); + Console.WriteLine("StartPulse(RgbLedColors.Cyan, 200, 200);"); + await onboardLed.StartPulse(Color.Cyan, TimeSpan.FromMilliseconds(400)); + await Task.Delay(3000); - Thread.Sleep(18); - } + await onboardLed.StopAnimation(); } } diff --git a/Source/Meadow.Foundation.Core.Samples/Leds.RgbPwmLed_Sample/Leds.RgbPwmLed_Sample.csproj b/Source/Meadow.Foundation.Core.Samples/Leds.RgbPwmLed_Sample/Leds.RgbPwmLed_Sample.csproj index ea265c2bc9..5232cdbf91 100644 --- a/Source/Meadow.Foundation.Core.Samples/Leds.RgbPwmLed_Sample/Leds.RgbPwmLed_Sample.csproj +++ b/Source/Meadow.Foundation.Core.Samples/Leds.RgbPwmLed_Sample/Leds.RgbPwmLed_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Core.Samples/Leds.RgbPwmLed_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Core.Samples/Leds.RgbPwmLed_Sample/MeadowApp.cs index fa3e6c945e..d544f220f6 100644 --- a/Source/Meadow.Foundation.Core.Samples/Leds.RgbPwmLed_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Core.Samples/Leds.RgbPwmLed_Sample/MeadowApp.cs @@ -2,8 +2,6 @@ using Meadow.Devices; using Meadow.Foundation; using Meadow.Foundation.Leds; -using Meadow.Peripherals.Leds; -using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; @@ -20,22 +18,16 @@ public override Task Initialize() { Resolver.Log.Info("Initializing..."); - var onRgbLed = new RgbLed( - redPin: Device.Pins.OnboardLedRed, - greenPin: Device.Pins.OnboardLedGreen, - bluePin: Device.Pins.OnboardLedBlue); - onRgbLed.SetColor(RgbLedColors.Red); - rgbPwmLeds = new List() { new RgbPwmLed( Device.Pins.D02, Device.Pins.D03, Device.Pins.D04), - new RgbPwmLed( - Device.Pins.D05, - Device.Pins.D06, - Device.Pins.D07), + //new RgbPwmLed( + // Device.Pins.D05, + // Device.Pins.D06, + // Device.Pins.D07), new RgbPwmLed( Device.Pins.D08, Device.Pins.D09, @@ -46,12 +38,10 @@ public override Task Initialize() Device.Pins.D13) }; - onRgbLed.SetColor(RgbLedColors.Green); - return Task.CompletedTask; } - public override Task Run() + public override async Task Run() { Resolver.Log.Info("TestRgbPwmLed..."); @@ -77,7 +67,7 @@ public override Task Run() Resolver.Log.Info($"Red brightness: {i * 0.1f}"); Thread.Sleep(500); } - rgbPwmLed.Stop(); + await rgbPwmLed.StopAnimation(); for (int i = 0; i < 10; i++) { @@ -85,7 +75,7 @@ public override Task Run() Resolver.Log.Info($"Green brightness: {i * 0.1f}"); Thread.Sleep(500); } - rgbPwmLed.Stop(); + await rgbPwmLed.StopAnimation(); for (int i = 0; i < 10; i++) { @@ -93,39 +83,33 @@ public override Task Run() Resolver.Log.Info($"Blue brightness: {i * 0.1f}"); Thread.Sleep(500); } - rgbPwmLed.Stop(); + await rgbPwmLed.StopAnimation(); // Blink - rgbPwmLed.StartBlink(Color.Red, TimeSpan.FromMilliseconds(500), TimeSpan.FromMilliseconds(500), 1f, 0f); + await rgbPwmLed.StartBlink(Color.Red); Resolver.Log.Info("Blinking Red"); Thread.Sleep(3000); - rgbPwmLed.Stop(); - rgbPwmLed.StartBlink(Color.Green, TimeSpan.FromMilliseconds(500), TimeSpan.FromMilliseconds(500), 1f, 0f); + await rgbPwmLed.StartBlink(Color.Green); Resolver.Log.Info("Blinking Green"); Thread.Sleep(3000); - rgbPwmLed.Stop(); - rgbPwmLed.StartBlink(Color.Blue, TimeSpan.FromMilliseconds(500), TimeSpan.FromMilliseconds(500), 1f, 0f); + await rgbPwmLed.StartBlink(Color.Blue); Resolver.Log.Info("Blinking Blue"); Thread.Sleep(3000); - rgbPwmLed.Stop(); // Pulse - rgbPwmLed.StartPulse(Color.Red); + await rgbPwmLed.StartPulse(Color.Red); Resolver.Log.Info("Pulsing Red"); Thread.Sleep(3000); - rgbPwmLed.Stop(); - rgbPwmLed.StartPulse(Color.Green); + await rgbPwmLed.StartPulse(Color.Green); Resolver.Log.Info("Pulsing Green"); Thread.Sleep(3000); - rgbPwmLed.Stop(); - rgbPwmLed.StartPulse(Color.Blue); + await rgbPwmLed.StartPulse(Color.Blue); Resolver.Log.Info("Pulsing Blue"); Thread.Sleep(3000); - rgbPwmLed.Stop(); } } } diff --git a/Source/Meadow.Foundation.Core.Samples/Motor.HBridgeMotor_Sample/Motor.HBridgeMotor_Sample.csproj b/Source/Meadow.Foundation.Core.Samples/Motor.HBridgeMotor_Sample/Motor.HBridgeMotor_Sample.csproj index ea265c2bc9..5232cdbf91 100644 --- a/Source/Meadow.Foundation.Core.Samples/Motor.HBridgeMotor_Sample/Motor.HBridgeMotor_Sample.csproj +++ b/Source/Meadow.Foundation.Core.Samples/Motor.HBridgeMotor_Sample/Motor.HBridgeMotor_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Core.Samples/Relays.Relay_Sample/Relays.Relay_Sample.csproj b/Source/Meadow.Foundation.Core.Samples/Relays.Relay_Sample/Relays.Relay_Sample.csproj index ea265c2bc9..5232cdbf91 100644 --- a/Source/Meadow.Foundation.Core.Samples/Relays.Relay_Sample/Relays.Relay_Sample.csproj +++ b/Source/Meadow.Foundation.Core.Samples/Relays.Relay_Sample/Relays.Relay_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Core.Samples/Sensors.Buttons.PushButton_BasicSample/Sensors.Buttons.PushButton_BasicSample.csproj b/Source/Meadow.Foundation.Core.Samples/Sensors.Buttons.PushButton_BasicSample/Sensors.Buttons.PushButton_BasicSample.csproj index ea265c2bc9..5232cdbf91 100644 --- a/Source/Meadow.Foundation.Core.Samples/Sensors.Buttons.PushButton_BasicSample/Sensors.Buttons.PushButton_BasicSample.csproj +++ b/Source/Meadow.Foundation.Core.Samples/Sensors.Buttons.PushButton_BasicSample/Sensors.Buttons.PushButton_BasicSample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Core.Samples/Sensors.Buttons.PushButton_Sample/Sensors.Buttons.PushButton_Sample.csproj b/Source/Meadow.Foundation.Core.Samples/Sensors.Buttons.PushButton_Sample/Sensors.Buttons.PushButton_Sample.csproj index ea265c2bc9..5232cdbf91 100644 --- a/Source/Meadow.Foundation.Core.Samples/Sensors.Buttons.PushButton_Sample/Sensors.Buttons.PushButton_Sample.csproj +++ b/Source/Meadow.Foundation.Core.Samples/Sensors.Buttons.PushButton_Sample/Sensors.Buttons.PushButton_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Core.Samples/Sensors.Environmental.AnalogWaterLevel_Sample/Sensors.Environmental.AnalogWaterLevel_Sample.csproj b/Source/Meadow.Foundation.Core.Samples/Sensors.Environmental.AnalogWaterLevel_Sample/Sensors.Environmental.AnalogWaterLevel_Sample.csproj index ea265c2bc9..5232cdbf91 100644 --- a/Source/Meadow.Foundation.Core.Samples/Sensors.Environmental.AnalogWaterLevel_Sample/Sensors.Environmental.AnalogWaterLevel_Sample.csproj +++ b/Source/Meadow.Foundation.Core.Samples/Sensors.Environmental.AnalogWaterLevel_Sample/Sensors.Environmental.AnalogWaterLevel_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Core.Samples/Sensors.HID.AnalogJoystick_Sample/Sensors.HID.AnalogJoystick_Sample.csproj b/Source/Meadow.Foundation.Core.Samples/Sensors.HID.AnalogJoystick_Sample/Sensors.HID.AnalogJoystick_Sample.csproj index da9f61d7ac..54ea931c17 100644 --- a/Source/Meadow.Foundation.Core.Samples/Sensors.HID.AnalogJoystick_Sample/Sensors.HID.AnalogJoystick_Sample.csproj +++ b/Source/Meadow.Foundation.Core.Samples/Sensors.HID.AnalogJoystick_Sample/Sensors.HID.AnalogJoystick_Sample.csproj @@ -14,7 +14,7 @@ - + diff --git a/Source/Meadow.Foundation.Core.Samples/Sensors.HallEffect_Sample/Sensors.HallEffect_Sample.csproj b/Source/Meadow.Foundation.Core.Samples/Sensors.HallEffect_Sample/Sensors.HallEffect_Sample.csproj index ea265c2bc9..5232cdbf91 100644 --- a/Source/Meadow.Foundation.Core.Samples/Sensors.HallEffect_Sample/Sensors.HallEffect_Sample.csproj +++ b/Source/Meadow.Foundation.Core.Samples/Sensors.HallEffect_Sample/Sensors.HallEffect_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Core.Samples/Sensors.Light.AnalogLightSensor_Sample/Sensors.Light.AnalogLightSensor_Sample.csproj b/Source/Meadow.Foundation.Core.Samples/Sensors.Light.AnalogLightSensor_Sample/Sensors.Light.AnalogLightSensor_Sample.csproj index d49a10589f..92c62f04f6 100644 --- a/Source/Meadow.Foundation.Core.Samples/Sensors.Light.AnalogLightSensor_Sample/Sensors.Light.AnalogLightSensor_Sample.csproj +++ b/Source/Meadow.Foundation.Core.Samples/Sensors.Light.AnalogLightSensor_Sample/Sensors.Light.AnalogLightSensor_Sample.csproj @@ -14,7 +14,7 @@ - + diff --git a/Source/Meadow.Foundation.Core.Samples/Sensors.Rotary.RotaryEncoderWithButton_Sample/Sensors.Rotary.RotaryEncoderWithButton_Sample.csproj b/Source/Meadow.Foundation.Core.Samples/Sensors.Rotary.RotaryEncoderWithButton_Sample/Sensors.Rotary.RotaryEncoderWithButton_Sample.csproj index 2c2803bf16..36fca71b8f 100644 --- a/Source/Meadow.Foundation.Core.Samples/Sensors.Rotary.RotaryEncoderWithButton_Sample/Sensors.Rotary.RotaryEncoderWithButton_Sample.csproj +++ b/Source/Meadow.Foundation.Core.Samples/Sensors.Rotary.RotaryEncoderWithButton_Sample/Sensors.Rotary.RotaryEncoderWithButton_Sample.csproj @@ -11,7 +11,7 @@ - + diff --git a/Source/Meadow.Foundation.Core.Samples/Sensors.Rotary.RotaryEncoder_Sample/Sensors.Rotary.RotaryEncoder_Sample.csproj b/Source/Meadow.Foundation.Core.Samples/Sensors.Rotary.RotaryEncoder_Sample/Sensors.Rotary.RotaryEncoder_Sample.csproj index 2c2803bf16..36fca71b8f 100644 --- a/Source/Meadow.Foundation.Core.Samples/Sensors.Rotary.RotaryEncoder_Sample/Sensors.Rotary.RotaryEncoder_Sample.csproj +++ b/Source/Meadow.Foundation.Core.Samples/Sensors.Rotary.RotaryEncoder_Sample/Sensors.Rotary.RotaryEncoder_Sample.csproj @@ -11,7 +11,7 @@ - + diff --git a/Source/Meadow.Foundation.Core.Samples/Sensors.Switches.DipSwitch_Sample/Sensors.Switches.DipSwitch_Sample.csproj b/Source/Meadow.Foundation.Core.Samples/Sensors.Switches.DipSwitch_Sample/Sensors.Switches.DipSwitch_Sample.csproj index ea265c2bc9..5232cdbf91 100644 --- a/Source/Meadow.Foundation.Core.Samples/Sensors.Switches.DipSwitch_Sample/Sensors.Switches.DipSwitch_Sample.csproj +++ b/Source/Meadow.Foundation.Core.Samples/Sensors.Switches.DipSwitch_Sample/Sensors.Switches.DipSwitch_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Core.Samples/Sensors.Switches.SpdtSwitch_Sample/Sensors.Switches.SpdtSwitch_Sample.csproj b/Source/Meadow.Foundation.Core.Samples/Sensors.Switches.SpdtSwitch_Sample/Sensors.Switches.SpdtSwitch_Sample.csproj index ea265c2bc9..5232cdbf91 100644 --- a/Source/Meadow.Foundation.Core.Samples/Sensors.Switches.SpdtSwitch_Sample/Sensors.Switches.SpdtSwitch_Sample.csproj +++ b/Source/Meadow.Foundation.Core.Samples/Sensors.Switches.SpdtSwitch_Sample/Sensors.Switches.SpdtSwitch_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Core.Samples/Sensors.Switches.SpstSwitch_Sample/Sensors.Switches.SpstSwitch_Sample.csproj b/Source/Meadow.Foundation.Core.Samples/Sensors.Switches.SpstSwitch_Sample/Sensors.Switches.SpstSwitch_Sample.csproj index ea265c2bc9..5232cdbf91 100644 --- a/Source/Meadow.Foundation.Core.Samples/Sensors.Switches.SpstSwitch_Sample/Sensors.Switches.SpstSwitch_Sample.csproj +++ b/Source/Meadow.Foundation.Core.Samples/Sensors.Switches.SpstSwitch_Sample/Sensors.Switches.SpstSwitch_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Core.Samples/Sensors.Temperature.AnalogTemperature_Sample/Sensors.Temperature.AnalogTemperature_Sample.csproj b/Source/Meadow.Foundation.Core.Samples/Sensors.Temperature.AnalogTemperature_Sample/Sensors.Temperature.AnalogTemperature_Sample.csproj index d49a10589f..92c62f04f6 100644 --- a/Source/Meadow.Foundation.Core.Samples/Sensors.Temperature.AnalogTemperature_Sample/Sensors.Temperature.AnalogTemperature_Sample.csproj +++ b/Source/Meadow.Foundation.Core.Samples/Sensors.Temperature.AnalogTemperature_Sample/Sensors.Temperature.AnalogTemperature_Sample.csproj @@ -14,7 +14,7 @@ - + diff --git a/Source/Meadow.Foundation.Core/Communications/ByteCommsSensorBase.cs b/Source/Meadow.Foundation.Core/Communications/ByteCommsSensorBase.cs index 2019c3706d..e183cf4a70 100644 --- a/Source/Meadow.Foundation.Core/Communications/ByteCommsSensorBase.cs +++ b/Source/Meadow.Foundation.Core/Communications/ByteCommsSensorBase.cs @@ -1,5 +1,6 @@ -using System; -using Meadow.Hardware; +using Meadow.Hardware; +using Meadow.Units; +using System; namespace Meadow.Foundation { @@ -11,9 +12,9 @@ public abstract class ByteCommsSensorBase : PollingSensorBase, IDisposable where UNIT : struct { /// - /// Peripheral object, i.e. an I2CPeripheral or SpiPeripheral + /// Bus communications object, i.e. an I2cCommunications or SpiCommunications /// - protected IByteCommunications? Peripheral { get; set; } + protected IByteCommunications? BusComms { get; set; } /// /// The read buffer @@ -36,7 +37,7 @@ protected ByteCommsSensorBase( II2cBus i2cBus, byte address, int readBufferSize = 8, int writeBufferSize = 8) { - Peripheral = new I2cPeripheral(i2cBus, address, readBufferSize, writeBufferSize); + BusComms = new I2cCommunications(i2cBus, address, readBufferSize, writeBufferSize); Init(readBufferSize, writeBufferSize); } @@ -45,15 +46,21 @@ protected ByteCommsSensorBase( /// /// SPI bus object /// Chip select port + /// The SPI bus speed + /// The SPI bus mode (0-3) /// Read buffer size /// Write buffer size /// Chip select mode protected ByteCommsSensorBase( - ISpiBus spiBus, IDigitalOutputPort? chipSelect, - int readBufferSize = 8, int writeBufferSize = 8, + ISpiBus spiBus, + IDigitalOutputPort? chipSelect, + Frequency busSpeed, + SpiClockConfiguration.Mode busMode = SpiClockConfiguration.Mode.Mode0, + int readBufferSize = 8, + int writeBufferSize = 8, ChipSelectMode chipSelectMode = ChipSelectMode.ActiveLow) { - Peripheral = new SpiPeripheral(spiBus, chipSelect, readBufferSize, writeBufferSize, chipSelectMode); + BusComms = new SpiCommunications(spiBus, chipSelect, busSpeed, busMode, readBufferSize, writeBufferSize, chipSelectMode); Init(readBufferSize, writeBufferSize); } diff --git a/Source/Meadow.Foundation.Core/Communications/I2cPeripheral.cs b/Source/Meadow.Foundation.Core/Communications/I2cCommunications.cs similarity index 61% rename from Source/Meadow.Foundation.Core/Communications/I2cPeripheral.cs rename to Source/Meadow.Foundation.Core/Communications/I2cCommunications.cs index e95e797965..0a1796ec37 100644 --- a/Source/Meadow.Foundation.Core/Communications/I2cPeripheral.cs +++ b/Source/Meadow.Foundation.Core/Communications/I2cCommunications.cs @@ -1,30 +1,41 @@ using System; -using System.Collections.Generic; -using System.Linq; namespace Meadow.Hardware { /// - /// Defines a contract for a peripheral that communicates via the IIC/I2C - /// protocol. + /// Helper class for I2C communications, handles registers, endian, etc. /// - public class I2cPeripheral : II2cPeripheral + public class I2cCommunications : II2cCommunications { + /// + /// The I2C address + /// public byte Address { get; protected set; } + + /// + /// The I2C bus + /// public II2cBus Bus { get; protected set; } /// - /// Internal write buffer. Used in methods in which the buffers aren't + /// Internal write buffer - used in methods in which the buffers aren't /// passed in. /// protected Memory WriteBuffer { get; } /// - /// Internal read buffer. Used in methods in which the buffers aren't + /// Internal read buffer - used in methods in which the buffers aren't /// passed in. /// protected Memory ReadBuffer { get; } - public I2cPeripheral(II2cBus bus, byte peripheralAddress, int readBufferSize = 8, int writeBufferSize = 8) + /// + /// Initializes a new instance of the I2cCommunications class + /// + /// The II2cBus used for communication with the peripheral + /// The address of the peripheral on the I2C bus + /// The size of the buffer used for reading data from the peripheral. Defaults to 8 bytes + /// The size of the buffer used for writing data to the peripheral. Defaults to 8 bytes + public I2cCommunications(II2cBus bus, byte peripheralAddress, int readBufferSize = 8, int writeBufferSize = 8) { Bus = bus; Address = peripheralAddress; @@ -42,7 +53,7 @@ public I2cPeripheral(II2cBus bus, byte peripheralAddress, int readBufferSize = 8 /// public void Read(Span readBuffer) { - Bus.Read(this.Address, readBuffer); + Bus.Read(Address, readBuffer); } /// @@ -50,20 +61,20 @@ public void Read(Span readBuffer) /// /// /// - public void ReadRegister(byte address, Span readBuffer) + public virtual void ReadRegister(byte address, Span readBuffer) { WriteBuffer.Span[0] = address; - Bus.Exchange(this.Address, WriteBuffer.Span[0..1], readBuffer); + Bus.Exchange(Address, WriteBuffer.Span[0..1], readBuffer); } /// /// Read a register from the peripheral. /// /// Address of the register to read. - public byte ReadRegister(byte address) + public virtual byte ReadRegister(byte address) { WriteBuffer.Span[0] = address; - Bus.Exchange(this.Address, WriteBuffer.Span[0..1], ReadBuffer.Span[0..1]); + Bus.Exchange(Address, WriteBuffer.Span[0..1], ReadBuffer.Span[0..1]); return ReadBuffer.Span[0]; } @@ -73,13 +84,16 @@ public byte ReadRegister(byte address) /// Register address of the low byte (the high byte will follow). /// Order of the bytes in the register (little endian is the default). /// Value read from the register. - public ushort ReadRegisterAsUShort(byte address, ByteOrder order = ByteOrder.LittleEndian) + public virtual ushort ReadRegisterAsUShort(byte address, ByteOrder order = ByteOrder.LittleEndian) { WriteBuffer.Span[0] = address; - Bus.Exchange(this.Address, WriteBuffer[0..1].Span, ReadBuffer[0..2].Span); - if (order == ByteOrder.LittleEndian) { + Bus.Exchange(Address, WriteBuffer[0..1].Span, ReadBuffer[0..2].Span); + if (order == ByteOrder.LittleEndian) + { return (ushort)(ReadBuffer.Span[0] | (ReadBuffer.Span[1] << 8)); - } else { + } + else + { return (ushort)(ReadBuffer.Span[0] << 8 | ReadBuffer.Span[1]); } } @@ -88,33 +102,28 @@ public ushort ReadRegisterAsUShort(byte address, ByteOrder order = ByteOrder.Lit /// Write a single byte to the peripheral. /// /// Value to be written (8-bits). - public void Write(byte value) + public virtual void Write(byte value) { - // stuff the value into the write buffer WriteBuffer.Span[0] = value; - this.Bus.Write(this.Address, WriteBuffer.Span[0..1]); + Bus.Write(Address, WriteBuffer.Span[0..1]); } /// /// Write an array of bytes to the peripheral. /// /// Values to be written. - public void Write(Span data) - { - this.Bus.Write(this.Address, data); - } + public virtual void Write(Span data) => Bus.Write(Address, data); /// /// Write data a register in the peripheral. /// /// Address of the register to write to. /// Data to write into the register. - public void WriteRegister(byte address, byte value) + public virtual void WriteRegister(byte address, byte value) { - // stuff the address and value into the write buffer WriteBuffer.Span[0] = address; WriteBuffer.Span[1] = value; - this.Bus.Write(this.Address, WriteBuffer.Span[0..2]); + Bus.Write(Address, WriteBuffer.Span[0..2]); } /// @@ -123,11 +132,9 @@ public void WriteRegister(byte address, byte value) /// Address to write the first byte to. /// Value to be written (16-bits). /// Indicate if the data should be written as big or little endian. - public void WriteRegister(byte address, ushort value, ByteOrder order = ByteOrder.LittleEndian) + public virtual void WriteRegister(byte address, ushort value, ByteOrder order = ByteOrder.LittleEndian) { - // split the 16 bit ushort into two bytes var bytes = BitConverter.GetBytes(value); - // call the helper method WriteRegister(address, bytes, order); } @@ -137,11 +144,9 @@ public void WriteRegister(byte address, ushort value, ByteOrder order = ByteOrde /// Address to write the first byte to. /// Value to be written. /// Indicate if the data should be written as big or little endian. - public void WriteRegister(byte address, uint value, ByteOrder order = ByteOrder.LittleEndian) + public virtual void WriteRegister(byte address, uint value, ByteOrder order = ByteOrder.LittleEndian) { - // split the 32 bit uint into four bytes var bytes = BitConverter.GetBytes(value); - // call the helper method WriteRegister(address, bytes, order); } @@ -151,11 +156,9 @@ public void WriteRegister(byte address, uint value, ByteOrder order = ByteOrder. /// Address to write the first byte to. /// Value to be written. /// Indicate if the data should be written as big or little endian. - public void WriteRegister(byte address, ulong value, ByteOrder order = ByteOrder.LittleEndian) + public virtual void WriteRegister(byte address, ulong value, ByteOrder order = ByteOrder.LittleEndian) { - // split the 64 bit ulong into 8 bytes var bytes = BitConverter.GetBytes(value); - // call the helper method WriteRegister(address, bytes, order); } @@ -165,42 +168,50 @@ public void WriteRegister(byte address, ulong value, ByteOrder order = ByteOrder /// Address of the register to write to. /// A buffer of byte values to be written. /// Indicate if the data should be written as big or little endian. - public void WriteRegister(byte address, Span writeBuffer, ByteOrder order = ByteOrder.LittleEndian) + public virtual void WriteRegister(byte address, Span writeBuffer, ByteOrder order = ByteOrder.LittleEndian) { - if (WriteBuffer.Length < writeBuffer.Length + 1) { + if (WriteBuffer.Length < writeBuffer.Length + 1) + { throw new ArgumentException("Data to write is too large for the write buffer. " + "Must be less than WriteBuffer.Length + 1 (to allow for address). " + "Instantiate this class with a larger WriteBuffer, or send a smaller" + "amount of data to fix."); } - // stuff the register address into the write buffer + // add the register address to the start of the write buffer WriteBuffer.Span[0] = address; - // stuff the bytes into the write buffer (starting at `1` index, - // because `0` is the register address. - switch (order) { + switch (order) + { case ByteOrder.LittleEndian: - for (int i = 0; i < writeBuffer.Length; i++) { + for (int i = 0; i < writeBuffer.Length; i++) + { WriteBuffer.Span[i + 1] = writeBuffer[i]; } break; case ByteOrder.BigEndian: - for (int i = 0; i < writeBuffer.Length; i++) { - // stuff them backwards + for (int i = 0; i < writeBuffer.Length; i++) + { WriteBuffer.Span[i + 1] = writeBuffer[writeBuffer.Length - (i + 1)]; } break; } - // write it - this.Bus.Write(this.Address, WriteBuffer.Span[0..(writeBuffer.Length + 1)]); + Bus.Write(Address, WriteBuffer.Span[0..(writeBuffer.Length + 1)]); } - public void Exchange(Span writeBuffer, Span readBuffer, DuplexType duplex = DuplexType.Half) + /// + /// Exchanges data with an I2C device through a specified write and read buffer + /// + /// A span of bytes that represents the data to be written to the device + /// A span of bytes where the data read from the device will be stored + /// An optional parameter that specifies the duplex type of the communication. + /// It defaults to half-duplex. + /// Thrown when duplex is set to full-duplex, as I2C only supports half-duplex communication + public virtual void Exchange(Span writeBuffer, Span readBuffer, DuplexType duplex = DuplexType.Half) { if (duplex == DuplexType.Full) { throw new ArgumentException("I2C doesn't support full-duplex communications. Only half-duplex is available because it only has a single data line."); } - Bus.Exchange(this.Address, writeBuffer, readBuffer); + Bus.Exchange(Address, writeBuffer, readBuffer); } } -} +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Core/Communications/SpiPeripheral.cs b/Source/Meadow.Foundation.Core/Communications/SpiCommunications.cs similarity index 70% rename from Source/Meadow.Foundation.Core/Communications/SpiPeripheral.cs rename to Source/Meadow.Foundation.Core/Communications/SpiCommunications.cs index faf07fc748..f943895430 100644 --- a/Source/Meadow.Foundation.Core/Communications/SpiPeripheral.cs +++ b/Source/Meadow.Foundation.Core/Communications/SpiCommunications.cs @@ -1,12 +1,13 @@ -using System; +using Meadow.Units; +using System; namespace Meadow.Hardware { /// - /// Represents an SPI peripheral object + /// Helper class for SPI communications, handles registers, endian, etc. /// This encapsulates and synchronizes the SPI bus and chip select ports /// - public class SpiPeripheral : ISpiPeripheral + public class SpiCommunications : ISpiCommunications { /// /// The SPI chip select port @@ -16,13 +17,23 @@ public class SpiPeripheral : ISpiPeripheral /// /// The chip select mode (active high or active low) /// - ChipSelectMode chipSelectMode; + readonly ChipSelectMode chipSelectMode; /// /// the ISpiBus object /// public ISpiBus Bus { get; } + /// + /// SPI bus speed + /// + public Frequency BusSpeed { get; set; } + + /// + /// SPI bus mode + /// + public SpiClockConfiguration.Mode BusMode { get; set; } + /// /// Internal write buffer. Used in methods in which the buffers aren't /// passed in. @@ -35,22 +46,28 @@ public class SpiPeripheral : ISpiPeripheral protected Memory ReadBuffer { get; } /// - /// Creates a new SpiPeripheral instance + /// Creates a new SpiCommunications instance /// /// The spi bus connected to the peripheral /// The chip select port + /// The SPI bus speed + /// The SPI bus mode (0-3) /// The size of the read buffer in bytes /// The size of the write buffer in bytes /// The chip select mode, active high or active low - public SpiPeripheral( + public SpiCommunications( ISpiBus bus, IDigitalOutputPort? chipSelect, + Frequency busSpeed, + SpiClockConfiguration.Mode busMode = SpiClockConfiguration.Mode.Mode0, int readBufferSize = 8, int writeBufferSize = 8, ChipSelectMode csMode = ChipSelectMode.ActiveLow) { - this.Bus = bus; - this.ChipSelect = chipSelect; - this.chipSelectMode = csMode; + Bus = bus; + BusMode = busMode; + BusSpeed = busSpeed; + ChipSelect = chipSelect; + chipSelectMode = csMode; WriteBuffer = new byte[writeBufferSize]; ReadBuffer = new byte[readBufferSize]; } @@ -63,9 +80,11 @@ public SpiPeripheral( /// The number of bytes to be read is determined by the length of the /// `readBuffer`. /// - public void Read(Span readBuffer) + public virtual void Read(Span readBuffer) { - Bus.Read(this.ChipSelect, readBuffer, this.chipSelectMode); + AutoSetBusSpeedAndMode(); + + Bus.Read(ChipSelect, readBuffer, chipSelectMode); } /// @@ -73,10 +92,12 @@ public void Read(Span readBuffer) /// /// The register address /// The buffer to hold the data - public void ReadRegister(byte address, Span readBuffer) + public virtual void ReadRegister(byte address, Span readBuffer) { + AutoSetBusSpeedAndMode(); + WriteBuffer.Span[0] = address; - Bus.Exchange(this.ChipSelect, WriteBuffer.Span[0..readBuffer.Length], readBuffer, this.chipSelectMode); + Bus.Exchange(ChipSelect, WriteBuffer.Span[0..readBuffer.Length], readBuffer, chipSelectMode); } /// @@ -84,10 +105,12 @@ public void ReadRegister(byte address, Span readBuffer) /// /// Address to read /// The byte read - public byte ReadRegister(byte address) + public virtual byte ReadRegister(byte address) { + AutoSetBusSpeedAndMode(); + WriteBuffer.Span[0] = address; - Bus.Exchange(this.ChipSelect, WriteBuffer.Span[0..1], ReadBuffer.Span[0..1], this.chipSelectMode); + Bus.Exchange(ChipSelect, WriteBuffer.Span[0..1], ReadBuffer.Span[0..1], chipSelectMode); return ReadBuffer.Span[0]; } @@ -97,7 +120,7 @@ public byte ReadRegister(byte address) /// Address of the read /// Endianness of the value read /// The value read - public ushort ReadRegisterAsUShort(byte address, ByteOrder order = ByteOrder.LittleEndian) + public virtual ushort ReadRegisterAsUShort(byte address, ByteOrder order = ByteOrder.LittleEndian) { ReadRegister(address, ReadBuffer[0..2].Span); if (order == ByteOrder.LittleEndian) @@ -116,17 +139,21 @@ public ushort ReadRegisterAsUShort(byte address, ByteOrder order = ByteOrder.Lit /// Value to write public void Write(byte value) { + AutoSetBusSpeedAndMode(); + WriteBuffer.Span[0] = value; - Bus.Write(ChipSelect, WriteBuffer.Span[0..1], this.chipSelectMode); + Bus.Write(ChipSelect, WriteBuffer.Span[0..1], chipSelectMode); } /// /// Write a span of bytes to the peripheral. /// /// Data to be written. - public void Write(Span data) + public virtual void Write(Span data) { - Bus.Write(this.ChipSelect, data, this.chipSelectMode); + AutoSetBusSpeedAndMode(); + + Bus.Write(ChipSelect, data, chipSelectMode); } /// @@ -134,12 +161,13 @@ public void Write(Span data) /// /// The target write register address /// Value to write - public void WriteRegister(byte address, byte value) + public virtual void WriteRegister(byte address, byte value) { - // stuff the address and value into the write buffer + AutoSetBusSpeedAndMode(); + WriteBuffer.Span[0] = address; WriteBuffer.Span[1] = value; - Bus.Write(ChipSelect, WriteBuffer.Span[0..2], this.chipSelectMode); + Bus.Write(ChipSelect, WriteBuffer.Span[0..2], chipSelectMode); } /// @@ -148,11 +176,10 @@ public void WriteRegister(byte address, byte value) /// The target write register address /// Value to write /// Endianness of the value to be written - public void WriteRegister(byte address, ushort value, ByteOrder order = ByteOrder.LittleEndian) + public virtual void WriteRegister(byte address, ushort value, ByteOrder order = ByteOrder.LittleEndian) { // split the 16 bit ushort into two bytes var bytes = BitConverter.GetBytes(value); - // call the helper method WriteRegister(address, bytes, order); } @@ -162,11 +189,9 @@ public void WriteRegister(byte address, ushort value, ByteOrder order = ByteOrde /// Address to write the first byte to. /// Value to be written. /// Indicate if the data should be written as big or little endian. - public void WriteRegister(byte address, uint value, ByteOrder order = ByteOrder.LittleEndian) + public virtual void WriteRegister(byte address, uint value, ByteOrder order = ByteOrder.LittleEndian) { - // split the 32 bit ushort into four bytes var bytes = BitConverter.GetBytes(value); - // call the helper method WriteRegister(address, bytes, order); } @@ -176,11 +201,9 @@ public void WriteRegister(byte address, uint value, ByteOrder order = ByteOrder. /// Address to write the first byte to. /// Value to be written. /// Indicate if the data should be written as big or little endian. - public void WriteRegister(byte address, ulong value, ByteOrder order = ByteOrder.LittleEndian) + public virtual void WriteRegister(byte address, ulong value, ByteOrder order = ByteOrder.LittleEndian) { - // split the 64 bit ushort into eight bytes var bytes = BitConverter.GetBytes(value); - // call the helper method WriteRegister(address, bytes, order); } @@ -190,7 +213,7 @@ public void WriteRegister(byte address, ulong value, ByteOrder order = ByteOrder /// Address of the register to write to. /// A buffer of byte values to be written. /// Indicate if the data should be written as big or little endian. - public void WriteRegister(byte address, Span writeBuffer, ByteOrder order = ByteOrder.LittleEndian) + public virtual void WriteRegister(byte address, Span writeBuffer, ByteOrder order = ByteOrder.LittleEndian) { if (WriteBuffer.Length < writeBuffer.Length + 1) { @@ -200,11 +223,10 @@ public void WriteRegister(byte address, Span writeBuffer, ByteOrder order "amount of data to fix."); } - // stuff the register address into the write buffer + AutoSetBusSpeedAndMode(); + WriteBuffer.Span[0] = address; - // stuff the bytes into the write buffer (starting at `1` index, - // because `0` is the register address. switch (order) { case ByteOrder.LittleEndian: @@ -216,13 +238,24 @@ public void WriteRegister(byte address, Span writeBuffer, ByteOrder order case ByteOrder.BigEndian: for (int i = 0; i < writeBuffer.Length; i++) { - // stuff them backwards WriteBuffer.Span[i + 1] = writeBuffer[writeBuffer.Length - (i + 1)]; } break; } - // write it - this.Bus.Write(this.ChipSelect, WriteBuffer.Span[0..(writeBuffer.Length + 1)], this.chipSelectMode); + Bus.Write(ChipSelect, WriteBuffer.Span[0..(writeBuffer.Length + 1)], chipSelectMode); + } + + private void AutoSetBusSpeedAndMode() + { + if (Bus.Configuration.SpiMode != BusMode) + { + Bus.Configuration.SetBusMode(BusMode); + } + + if (Bus.Configuration.Speed != BusSpeed) + { + Bus.Configuration.Speed = BusSpeed; + } } /// @@ -231,36 +264,25 @@ public void WriteRegister(byte address, Span writeBuffer, ByteOrder order /// The buffer holding the data to write /// The buffer to receieve data /// The duplex mode - half or full - public void Exchange(Span writeBuffer, Span readBuffer, DuplexType duplex = DuplexType.Half) + public virtual void Exchange(Span writeBuffer, Span readBuffer, DuplexType duplex = DuplexType.Half) { + AutoSetBusSpeedAndMode(); + if (duplex == DuplexType.Half) { - // Todo: we should move this functionality deeper into the stack - // and have nuttx write the write buffer, then continue clocking out - // 0x00's until it's hit writeBuffer.Length + readBuffer.Lenght - // and ignore the input until it hits writeBuffer.Length, and then - // start writing directly into the readBuffer starting at 0. - // that will prevent all the allocations and copying we're doing - // here. - - // clock in and clock out data means that the buffers have to be as - // long as both tx and rx together int length = writeBuffer.Length + readBuffer.Length; Span txBuffer = stackalloc byte[length]; Span rxBuffer = stackalloc byte[length]; - // copy the write into tx writeBuffer.CopyTo(txBuffer); - // write/read the data - Bus.Exchange(ChipSelect, txBuffer, rxBuffer, this.chipSelectMode); + Bus.Exchange(ChipSelect, txBuffer, rxBuffer, chipSelectMode); - // move the rx data into the read buffer, starting it at zero rxBuffer[writeBuffer.Length..length].CopyTo(readBuffer); } else { - Bus.Exchange(ChipSelect, writeBuffer, readBuffer, this.chipSelectMode); + Bus.Exchange(ChipSelect, writeBuffer, readBuffer, chipSelectMode); } } } diff --git a/Source/Meadow.Foundation.Core/Leds/Led.Animations.cs b/Source/Meadow.Foundation.Core/Leds/Led.Animations.cs new file mode 100644 index 0000000000..4383f184a9 --- /dev/null +++ b/Source/Meadow.Foundation.Core/Leds/Led.Animations.cs @@ -0,0 +1,69 @@ +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace Meadow.Foundation.Leds +{ + /// + /// Utility functions to provide blinking for Led + /// + public partial class Led + { + private object syncRoot = new object(); + + private Task? animationTask = null; + private CancellationTokenSource? cancellationTokenSource = null; + + + /// + /// Stops the current LED animation + /// + public async Task StopAnimation() + { + if (animationTask != null) + { + cancellationTokenSource?.Cancel(); + await animationTask; + animationTask = null; + cancellationTokenSource = null; + } + } + + /// + /// Start the Blink animation which sets turns the LED on and off on an interval of 1 second (500ms on, 500ms off) + /// + public Task StartBlink() + { + return StartBlink(TimeSpan.FromMilliseconds(500), TimeSpan.FromMilliseconds(500)); + } + + /// + /// Start the Blink animation which sets turns the LED on and off with the especified durations + /// + /// The duration the LED stays on + /// The duration the LED stays off + public async Task StartBlink(TimeSpan onDuration, TimeSpan offDuration) + { + await StopAnimation(); + + lock (syncRoot) + { + cancellationTokenSource = new CancellationTokenSource(); + + animationTask = new Task(() => + { + while (cancellationTokenSource.Token.IsCancellationRequested == false) + { + IsOn = true; + Thread.Sleep(onDuration); + + IsOn = false; + Thread.Sleep(offDuration); + } + }, cancellationTokenSource.Token, TaskCreationOptions.LongRunning); + + animationTask.Start(); + } + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Core/Leds/Led.cs b/Source/Meadow.Foundation.Core/Leds/Led.cs index 5da6a0d833..89a8c161c9 100644 --- a/Source/Meadow.Foundation.Core/Leds/Led.cs +++ b/Source/Meadow.Foundation.Core/Leds/Led.cs @@ -1,29 +1,19 @@ using Meadow.Hardware; using Meadow.Peripherals.Leds; using System; -using System.Threading; -using System.Threading.Tasks; namespace Meadow.Foundation.Leds { /// /// Represents a simple LED /// - public class Led : ILed + public partial class Led : ILed, IDisposable { - private Task? animationTask; - private CancellationTokenSource? cancellationTokenSource; + readonly bool createdPort = false; /// - /// Gets the port that is driving the LED - /// - /// The port - protected IDigitalOutputPort Port { get; set; } - - /// - /// Gets or sets a value indicating whether this is on. + /// Turns on LED with current color or turns it off /// - /// true if is on; otherwise, false. public bool IsOn { get => isOn; @@ -36,89 +26,58 @@ public bool IsOn bool isOn; /// - /// Creates a LED through a pin directly from the Digital IO of the board + /// Gets the port that is driving the LED /// - /// - public Led(IPin pin) : - this(pin.CreateDigitalOutputPort(false)) - { } + protected IDigitalOutputPort Port { get; set; } /// - /// Creates a LED through a DigitalOutPutPort from an IO Expander + /// Is the object disposed /// - /// - public Led(IDigitalOutputPort port) - { - Port = port; - } + public bool IsDisposed { get; private set; } /// - /// Stops the LED when its blinking and/or turns it off. + /// Create instance of Led /// - public void Stop() + /// The Output Pin + public Led(IPin pin) : + this(pin.CreateDigitalOutputPort(false)) { - cancellationTokenSource?.Cancel(); - IsOn = false; + createdPort = true; } /// - /// Blink animation that turns the LED on (500ms) and off (500ms) + /// Create instance of Led /// - public void StartBlink() + /// The Output Port + public Led(IDigitalOutputPort port) { - var onDuration = TimeSpan.FromMilliseconds(500); - var offDuration = TimeSpan.FromMilliseconds(500); - - Stop(); - - animationTask = new Task(async () => - { - cancellationTokenSource = new CancellationTokenSource(); - await StartBlinkAsync(onDuration, offDuration, cancellationTokenSource.Token); - }); - animationTask.Start(); + Port = port; } /// - /// Blink animation that turns the LED on and off based on the OnDuration and offDuration values in ms + /// Dispose of the object /// - /// - /// - public void StartBlink(TimeSpan onDuration, TimeSpan offDuration) + public void Dispose() { - Stop(); - - animationTask = new Task(async () => - { - cancellationTokenSource = new CancellationTokenSource(); - await StartBlinkAsync(onDuration, offDuration, cancellationTokenSource.Token); - }); - animationTask.Start(); + Dispose(disposing: true); + GC.SuppressFinalize(this); } /// - /// Set LED to blink + /// Dispose of the object /// - /// on duration in ms - /// off duration in ms - /// cancellation token used to cancel blink - /// - protected async Task StartBlinkAsync(TimeSpan onDuration, TimeSpan offDuration, CancellationToken cancellationToken) + /// Is disposing + protected virtual void Dispose(bool disposing) { - while (true) + if (!IsDisposed) { - if (cancellationToken.IsCancellationRequested) + if (disposing && createdPort) { - break; + Port.Dispose(); } - Port.State = true; - await Task.Delay(onDuration); - Port.State = false; - await Task.Delay(offDuration); + IsDisposed = true; } - - Port.State = IsOn; } } } \ No newline at end of file diff --git a/Source/Meadow.Foundation.Core/Leds/LedBarGraph.Animations.cs b/Source/Meadow.Foundation.Core/Leds/LedBarGraph.Animations.cs new file mode 100644 index 0000000000..12c8c3e57f --- /dev/null +++ b/Source/Meadow.Foundation.Core/Leds/LedBarGraph.Animations.cs @@ -0,0 +1,122 @@ +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace Meadow.Foundation.Leds +{ + public partial class LedBarGraph + { + private object syncRoot = new object(); + + private Task? animationTask; + private CancellationTokenSource? cancellationTokenSource; + + /// + /// Stops the LED bar graph when its blinking + /// + public async Task StopAnimation() + { + if (animationTask != null) + { + cancellationTokenSource?.Cancel(); + await animationTask; + animationTask = null; + cancellationTokenSource = null; + } + } + + /// + /// Stops the blinking animation on an individual LED + /// + public Task StopAnimation(int index) + { + if (index < 0 || index >= Count) + { + throw new ArgumentOutOfRangeException(); + } + + return leds[index].StopAnimation(); + } + + /// + /// Blink animation that turns the LED bar graph on (500ms) and off (500ms) + /// + public Task StartBlink() + { + return StartBlink(TimeSpan.FromMilliseconds(500), TimeSpan.FromMilliseconds(500)); + } + + /// + /// Blink animation that turns the LED bar graph on and off based on the OnDuration and offDuration values + /// + /// The duration the LED bar graph stays on + /// The duration the LED bar graph stays off + public async Task StartBlink(TimeSpan onDuration, TimeSpan offDuration) + { + await StopAnimation(); + + lock (syncRoot) + { + cancellationTokenSource = new CancellationTokenSource(); + + animationTask = new Task(() => + { + while (cancellationTokenSource.Token.IsCancellationRequested == false) + { + foreach (var led in leds) + { + led.IsOn = true; + } + Thread.Sleep(onDuration); + + foreach (var led in leds) + { + led.IsOn = false; + } + Thread.Sleep(offDuration); + } + }, cancellationTokenSource.Token, TaskCreationOptions.LongRunning); + + animationTask.Start(); + } + } + + /// + /// Starts a blink animation on an individual LED on (500ms) and off (500ms) + /// + /// Index of the LED + public Task StartBlink(int index) + { + if (index < 0 || index >= Count) + { + throw new ArgumentOutOfRangeException(); + } + + return leds[index].StartBlink(); + } + + /// + /// Starts a blink animation on an individual LED + /// + /// Index of the LED + /// The duration the LED stays on + /// The duration the LED stays off + public Task StartBlink(int index, TimeSpan onDuration, TimeSpan offDuration) + { + if (index < 0 || index >= Count) + { + throw new ArgumentOutOfRangeException(); + } + + return leds[index].StartBlink(onDuration, offDuration); + } + + /// + /// Returns the index of the last LED turned on + /// + public int GetTopLedForPercentage() + { + return (int)Math.Max(0, Percentage * Count - 0.5); + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Core/Leds/LedBarGraph.cs b/Source/Meadow.Foundation.Core/Leds/LedBarGraph.cs index 674c353d69..c30c507ccb 100644 --- a/Source/Meadow.Foundation.Core/Leds/LedBarGraph.cs +++ b/Source/Meadow.Foundation.Core/Leds/LedBarGraph.cs @@ -1,6 +1,5 @@ using Meadow.Hardware; using System; -using System.Threading; using System.Threading.Tasks; namespace Meadow.Foundation.Leds @@ -8,11 +7,8 @@ namespace Meadow.Foundation.Leds /// /// Represents an LED bar graph composed on multiple LEDs /// - public class LedBarGraph + public partial class LedBarGraph { - private Task? animationTask; - private CancellationTokenSource? cancellationTokenSource; - /// /// Array to hold LED objects for bar /// @@ -26,17 +22,12 @@ public class LedBarGraph /// /// A value between 0 and 1 that controls the number of LEDs that are activated /// - public float Percentage - { - get => percentage; - set => SetPercentage(percentage = value); - } - float percentage; + public float Percentage { get; protected set; } /// /// Create an LedBarGraph instance from an array of IPins /// - /// + /// The Digital Output Pins public LedBarGraph(IPin[] pins) { leds = new Led[pins.Length]; @@ -50,7 +41,7 @@ public LedBarGraph(IPin[] pins) /// /// Create an LedBarGraph instance from an array of IDigitalOutputPort /// - /// + /// The Digital Output Ports public LedBarGraph(IDigitalOutputPort[] ports) { leds = new Led[ports.Length]; @@ -64,16 +55,16 @@ public LedBarGraph(IDigitalOutputPort[] ports) /// /// Set the LED state /// - /// index of the LED - /// - public void SetLed(int index, bool isOn) + /// Index of the LED + /// True for on, False for off + public async Task SetLed(int index, bool isOn) { if (index >= Count) { throw new ArgumentOutOfRangeException(); } - leds[index].Stop(); + await leds[index].StopAnimation(); leds[index].IsOn = isOn; } @@ -81,162 +72,22 @@ public void SetLed(int index, bool isOn) /// Set the percentage of LEDs that are on starting from index 0 /// /// Percentage (Range from 0 - 1) - protected void SetPercentage(float percentage) + public async Task SetPercentage(float percentage) { if (percentage < 0 || percentage > 1) { throw new ArgumentOutOfRangeException(); } + Percentage = percentage; + var value = percentage * Count; value += 0.5f; for (int i = 1; i <= Count; i++) { - if (i <= value) - { - SetLed(i - 1, true); - } - else - { - SetLed(i - 1, false); - } - } - } - - /// - /// Returns the index of the last LED turned on - /// - /// - public int GetTopLedForPercentage() - { - return (int)Math.Max(0, percentage * Count - 0.5); - } - - /// - /// Starts a blink animation on an individual LED on (500ms) and off (500ms) - /// - /// - public void StartBlink(int index) - { - if (index < 0 || index >= Count) - { - throw new ArgumentOutOfRangeException(); + await SetLed(i - 1, i <= value); } - - leds[index].StartBlink(); - } - - /// - /// Starts a blink animation on an individual LED - /// - /// - /// - /// - public void StartBlink(int index, TimeSpan onDuration, TimeSpan offDuration) - { - if (index < 0 || index >= Count) - { - throw new ArgumentOutOfRangeException(); - } - - leds[index].StartBlink(onDuration, offDuration); - } - - /// - /// Blink animation that turns the LED bar graph on (500ms) and off (500ms) - /// - public void StartBlink() - { - var onDuration = TimeSpan.FromMilliseconds(500); - var offDuration = TimeSpan.FromMilliseconds(500); - - Stop(); - - animationTask = new Task(async () => - { - cancellationTokenSource = new CancellationTokenSource(); - await StartBlinkAsync(onDuration, offDuration, cancellationTokenSource.Token); - }); - animationTask.Start(); - } - - /// - /// Blink animation that turns the LED bar graph on and off based on the OnDuration and offDuration values in ms - /// - /// - /// - public void StartBlink(TimeSpan onDuration, TimeSpan offDuration) - { - Stop(); - - animationTask = new Task(async () => - { - cancellationTokenSource = new CancellationTokenSource(); - await StartBlinkAsync(onDuration, offDuration, cancellationTokenSource.Token); - }); - animationTask.Start(); - } - - /// - /// Set LED to blink - /// - /// on duration in ms - /// off duration in ms - /// cancellation token used to cancel blink - /// - protected async Task StartBlinkAsync(TimeSpan onDuration, TimeSpan offDuration, CancellationToken cancellationToken) - { - while (true) - { - if (cancellationToken.IsCancellationRequested) - { - break; - } - - foreach (var led in leds) - { - led.IsOn = true; - } - await Task.Delay(onDuration); - - if (cancellationToken.IsCancellationRequested) - { - break; - } - - foreach (var led in leds) - { - led.IsOn = false; - } - await Task.Delay(offDuration); - } - } - - /// - /// Stops the LED bar graph when its blinking and/or turns it off. - /// - public void Stop() - { - cancellationTokenSource?.Cancel(); - - foreach (var led in leds) - { - led.Stop(); - } - } - - /// - /// Stops the blinking animation on an individual LED and/or turns it off - /// - public void Stop(int index) - { - if (index < 0 || index >= Count) - { - throw new ArgumentOutOfRangeException(); - } - - leds[index].Stop(); } } } \ No newline at end of file diff --git a/Source/Meadow.Foundation.Core/Leds/PwmLed.Animations.cs b/Source/Meadow.Foundation.Core/Leds/PwmLed.Animations.cs new file mode 100644 index 0000000000..f44e9912fc --- /dev/null +++ b/Source/Meadow.Foundation.Core/Leds/PwmLed.Animations.cs @@ -0,0 +1,173 @@ +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace Meadow.Foundation.Leds +{ + public partial class PwmLed + { + private object syncRoot = new object(); + + private Task? animationTask = null; + private CancellationTokenSource? cancellationTokenSource = null; + + /// + /// Stops any running animations. + /// + public async Task StopAnimation() + { + if (animationTask != null) + { + cancellationTokenSource?.Cancel(); + await animationTask; + animationTask = null; + cancellationTokenSource = null; + } + } + + /// + /// Start a Blink animation which sets the brightness of the LED alternating between a low and high brightness setting. + /// + /// The maximum brightness of the animation + /// The minimum brightness of the animation + public async Task StartBlink(float highBrightness = 1f, float lowBrightness = 0f) + { + ValidateBrightness(highBrightness, lowBrightness); + + await StopAnimation(); + + await StartBlink(TimeSpan.FromMilliseconds(500), TimeSpan.FromMilliseconds(500)); + } + + /// + /// Start the Blink animation which sets the brightness of the LED alternating between a low and high brightness setting, using the durations provided. + /// + /// The duration the LED stays in high brightness + /// The duration the LED stays in low brightness + /// The maximum brightness of the animation + /// The minimum brightness of the animation + public async Task StartBlink( + TimeSpan highBrightnessDuration, + TimeSpan lowBrightnessDuration, + float highBrightness = 1f, + float lowBrightness = 0f) + { + ValidateBrightness(highBrightness, lowBrightness); + + await StopAnimation(); + + lock (syncRoot) + { + cancellationTokenSource = new CancellationTokenSource(); + + animationTask = new Task(() => + { + while (cancellationTokenSource.Token.IsCancellationRequested == false) + { + SetBrightness(highBrightness); + Thread.Sleep(highBrightnessDuration); + + SetBrightness(lowBrightness); + Thread.Sleep(lowBrightnessDuration); + } + }, cancellationTokenSource.Token, TaskCreationOptions.LongRunning); + + animationTask.Start(); + } + } + + /// + /// Start the Pulse animation which gradually alternates the brightness of the LED between a low and high brightness setting. + /// + /// The maximum brightness of the animation + /// The minimum brightness of the animation + public async Task StartPulse(float highBrightness = 1, float lowBrightness = 0.15F) + { + ValidateBrightness(highBrightness, lowBrightness); + + await StopAnimation(); + + await StartPulse(TimeSpan.FromMilliseconds(600), highBrightness, lowBrightness); + } + + /// + /// Start the Pulse animation which gradually alternates the brightness of the LED between a low and high brightness setting, using the durations provided. + /// + /// The pulse animation duration + /// The maximum brightness of the animation + /// The minimum brightness of the animation + public async Task StartPulse( + TimeSpan pulseDuration, + float highBrightness = 1, + float lowBrightness = 0.15F) + { + ValidateBrightness(highBrightness, lowBrightness); + + await StopAnimation(); + + lock (syncRoot) + { + cancellationTokenSource = new CancellationTokenSource(); + + animationTask = new Task(() => + { + float brightness = lowBrightness; + bool ascending = true; + var intervalTime = TimeSpan.FromMilliseconds(60); // 60 miliseconds is probably the fastest update we want to do, given that threads are given 20 miliseconds by default. + float steps = (float)(pulseDuration.TotalMilliseconds / intervalTime.TotalMilliseconds); + float delta = (highBrightness - lowBrightness) / steps; + + while (cancellationTokenSource.Token.IsCancellationRequested == false) + { + if (brightness <= lowBrightness) + { + ascending = true; + } + else if (brightness >= highBrightness) + { + ascending = false; + } + + brightness += delta * (ascending ? 1 : -1); + + if (brightness < lowBrightness) + { + brightness = lowBrightness; + } + else if (brightness > highBrightness) + { + brightness = highBrightness; + } + + SetBrightness(brightness); + + Thread.Sleep(intervalTime); + } + }, cancellationTokenSource.Token, TaskCreationOptions.LongRunning); + + animationTask.Start(); + } + } + + /// + /// Validates LED brightness to ensure they're within the range 0 (off) - 1 (full brighness) + /// + /// The maximum brightness of the animation + /// The minimum brightness of the animation + protected void ValidateBrightness(float highBrightness, float lowBrightness) + { + if (highBrightness > 1 || highBrightness <= 0) + { + throw new ArgumentOutOfRangeException(nameof(highBrightness), "onBrightness must be > 0 and <= 1"); + } + if (lowBrightness >= 1 || lowBrightness < 0) + { + throw new ArgumentOutOfRangeException(nameof(lowBrightness), "lowBrightness must be >= 0 and < 1"); + } + if (lowBrightness >= highBrightness) + { + throw new Exception("offBrightness must be less than onBrightness"); + } + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Core/Leds/PwmLed.cs b/Source/Meadow.Foundation.Core/Leds/PwmLed.cs index 2395a3e988..5487ec2594 100644 --- a/Source/Meadow.Foundation.Core/Leds/PwmLed.cs +++ b/Source/Meadow.Foundation.Core/Leds/PwmLed.cs @@ -2,8 +2,6 @@ using Meadow.Peripherals.Leds; using Meadow.Units; using System; -using System.Threading; -using System.Threading.Tasks; namespace Meadow.Foundation.Leds { @@ -11,47 +9,24 @@ namespace Meadow.Foundation.Leds /// Represents an LED whose voltage is limited by the duty-cycle of a PWM /// signal. /// - public class PwmLed : IPwmLed, IDisposable + public partial class PwmLed : IPwmLed, IDisposable { - Task? animationTask; - CancellationTokenSource? cancellationTokenSource; readonly bool createdPwm = false; float maximumPwmDuty = 1; - bool inverted; /// - /// Is the object disposed + /// Maximum forward voltage (3.3 Volts) /// - public bool IsDisposed { get; private set; } + public Voltage MAX_FORWARD_VOLTAGE => new Voltage(3.3); /// - /// Gets the brightness of the LED, controlled by a PWM signal, and limited by the - /// calculated maximum voltage. Valid values are from 0 to 1, inclusive. + /// Minimum forward voltage (0 Volts) /// - public float Brightness - { - get => _brightness; - set - { - if (value < 0 || value > 1) - { - throw new ArgumentOutOfRangeException("Brightness must be between 0 and 1, inclusive."); - } - - _brightness = value; - Port.DutyCycle = maximumPwmDuty * Brightness; - - if (!Port.State) - { - Port.Start(); - } - } - } - float _brightness = 0; + public Voltage MIN_FORWARD_VOLTAGE => new Voltage(0); /// - /// Gets or Sets the state of the LED + /// Turns on LED with current color or turns it off /// public bool IsOn { @@ -74,6 +49,16 @@ public bool IsOn /// public Voltage ForwardVoltage { get; protected set; } + /// + /// The brightness value assigned to the LED + /// + public float Brightness { get; protected set; } = 1f; + + /// + /// Is the object disposed + /// + public bool IsDisposed { get; private set; } + /// /// Initializes a new instance PwmLed class /// @@ -86,12 +71,10 @@ public bool IsOn public PwmLed( IPin pin, Voltage forwardVoltage, - CircuitTerminationType terminationType = CircuitTerminationType.CommonGround) + CircuitTerminationType terminationType = CircuitTerminationType.CommonGround) : + this(pin.CreatePwmPort(new Frequency(100, Frequency.UnitType.Hertz)), forwardVoltage, terminationType) { - Port = pin.CreatePwmPort(new Frequency(100, Frequency.UnitType.Hertz)); - createdPwm = true; // signal that we created it, so we should dispose of it - Port.DutyCycle = 0; - Initialize(forwardVoltage, terminationType); + createdPwm = true; } /// @@ -107,60 +90,35 @@ public PwmLed( Voltage forwardVoltage, CircuitTerminationType terminationType = CircuitTerminationType.CommonGround) { - Port = pwmPort; - Initialize(forwardVoltage, terminationType); - } + ValidateForwardVoltages(forwardVoltage); - private void Initialize( - Voltage forwardVoltage, - CircuitTerminationType terminationType = CircuitTerminationType.CommonGround) - { - if (forwardVoltage < new Voltage(0) || forwardVoltage > new Voltage(3.3)) - { - throw new ArgumentOutOfRangeException(nameof(forwardVoltage), "error, forward voltage must be between 0, and 3.3"); - } + Port = pwmPort; ForwardVoltage = forwardVoltage; - inverted = terminationType == CircuitTerminationType.High; - maximumPwmDuty = Helpers.CalculateMaximumDutyCycle(forwardVoltage); + IsOn = false; - Port.Inverted = inverted; + Port.Inverted = terminationType == CircuitTerminationType.High; Port.Start(); } /// - /// Dispose of the object + /// Validates forward voltages to ensure they're within the range MIN_FORWARD_VOLTAGE to MAX_FORWARD_VOLTAGE /// - /// Is disposing - protected virtual void Dispose(bool disposing) + /// The forward voltage for the LED + protected void ValidateForwardVoltages(Voltage forwardVoltage) { - if (!IsDisposed) + if (forwardVoltage < MIN_FORWARD_VOLTAGE || forwardVoltage > MAX_FORWARD_VOLTAGE) { - if (disposing && createdPwm) - { - Port.Dispose(); - } - - IsDisposed = true; + throw new ArgumentOutOfRangeException(nameof(forwardVoltage), "error, forward voltage must be between 0, and 3.3"); } } - /// - /// Dispose of the object - /// - public void Dispose() - { - Dispose(disposing: true); - GC.SuppressFinalize(this); - } - /// /// Sets the LED to a specific brightness. /// /// Valid values are from 0 to 1, inclusive - [Obsolete("Use Brightness property instead")] public void SetBrightness(float brightness) { if (brightness < 0 || brightness > 1) @@ -168,7 +126,7 @@ public void SetBrightness(float brightness) throw new ArgumentOutOfRangeException(nameof(brightness), "brightness must be between 0 and 1, inclusive."); } - _brightness = brightness; + Brightness = brightness; Port.DutyCycle = maximumPwmDuty * Brightness; @@ -179,218 +137,29 @@ public void SetBrightness(float brightness) } /// - /// Start a Blink animation which sets the brightness of the LED alternating between a low and high brightness setting. - /// - /// - /// - /// - /// - public void StartBlink(float highBrightness = 1f, float lowBrightness = 0f) - { - var onDuration = TimeSpan.FromMilliseconds(500); - var offDuration = TimeSpan.FromMilliseconds(500); - - if (highBrightness > 1 || highBrightness <= 0) - { - throw new ArgumentOutOfRangeException(nameof(highBrightness), "onBrightness must be > 0 and <= 1"); - } - if (lowBrightness >= 1 || lowBrightness < 0) - { - throw new ArgumentOutOfRangeException(nameof(lowBrightness), "lowBrightness must be >= 0 and < 1"); - } - if (lowBrightness >= highBrightness) - { - throw new Exception("offBrightness must be less than onBrightness"); - } - - Stop(); - - animationTask = new Task(async () => - { - cancellationTokenSource = new CancellationTokenSource(); - await StartBlinkAsync(onDuration, offDuration, highBrightness, lowBrightness, cancellationTokenSource.Token); - }); - animationTask.Start(); - } - - /// - /// Start the Blink animation which sets the brightness of the LED alternating between a low and high brightness setting, using the durations provided. - /// - /// - /// - /// - /// - /// - /// - public void StartBlink(TimeSpan onDuration, TimeSpan offDuration, float highBrightness = 1f, float lowBrightness = 0f) - { - if (highBrightness > 1 || highBrightness <= 0) - { - throw new ArgumentOutOfRangeException(nameof(highBrightness), "onBrightness must be > 0 and <= 1"); - } - if (lowBrightness >= 1 || lowBrightness < 0) - { - throw new ArgumentOutOfRangeException(nameof(lowBrightness), "lowBrightness must be >= 0 and < 1"); - } - if (lowBrightness >= highBrightness) - { - throw new Exception("offBrightness must be less than onBrightness"); - } - - Stop(); - - animationTask = new Task(async () => - { - cancellationTokenSource = new CancellationTokenSource(); - await StartBlinkAsync((TimeSpan)onDuration, (TimeSpan)offDuration, highBrightness, lowBrightness, cancellationTokenSource.Token); - }); - animationTask.Start(); - } - - /// - /// Start blinking the LED - /// - /// on duration in ms - /// off duration in ms - /// maximum brightness - /// minimum brightness - /// token for cancellation - protected async Task StartBlinkAsync(TimeSpan onDuration, TimeSpan offDuration, float highBrightness, float lowBrightness, CancellationToken cancellationToken) - { - while (true) - { - if (cancellationToken.IsCancellationRequested) - { - break; - } - - Brightness = highBrightness; - await Task.Delay(onDuration); - Brightness = lowBrightness; - await Task.Delay(offDuration); - } - - Port.DutyCycle = IsOn ? maximumPwmDuty : 0; - } - - /// - /// Start the Pulse animation which gradually alternates the brightness of the LED between a low and high brightness setting. - /// - /// - /// - public void StartPulse(float highBrightness = 1, float lowBrightness = 0.15F) - { - var pulseDuration = TimeSpan.FromMilliseconds(600); - - if (highBrightness > 1 || highBrightness <= 0) - { - throw new ArgumentOutOfRangeException(nameof(highBrightness), "highBrightness must be > 0 and <= 1"); - } - if (lowBrightness >= 1 || lowBrightness < 0) - { - throw new ArgumentOutOfRangeException(nameof(lowBrightness), "lowBrightness must be >= 0 and < 1"); - } - if (lowBrightness >= highBrightness) - { - throw new Exception("lowBrightness must be less than highbrightness"); - } - - Stop(); - - animationTask = new Task(async () => - { - cancellationTokenSource = new CancellationTokenSource(); - await StartPulseAsync(pulseDuration, highBrightness, lowBrightness, cancellationTokenSource.Token); - }); - animationTask.Start(); - } - - /// - /// Start the Pulse animation which gradually alternates the brightness of the LED between a low and high brightness setting, using the durations provided. + /// Dispose of the object /// - /// - /// - /// - public void StartPulse(TimeSpan pulseDuration, float highBrightness = 1, float lowBrightness = 0.15F) + public void Dispose() { - if (highBrightness > 1 || highBrightness <= 0) - { - throw new ArgumentOutOfRangeException(nameof(highBrightness), "highBrightness must be > 0 and <= 1"); - } - if (lowBrightness >= 1 || lowBrightness < 0) - { - throw new ArgumentOutOfRangeException(nameof(lowBrightness), "lowBrightness must be >= 0 and < 1"); - } - if (lowBrightness >= highBrightness) - { - throw new Exception("lowBrightness must be less than highbrightness"); - } - - Stop(); - - animationTask = new Task(async () => - { - cancellationTokenSource = new CancellationTokenSource(); - await StartPulseAsync(pulseDuration, highBrightness, lowBrightness, cancellationTokenSource.Token); - }); - animationTask.Start(); + Dispose(disposing: true); + GC.SuppressFinalize(this); } /// - /// Start pulsing the led + /// Dispose of the object /// - /// duration in ms - /// maximum brightness - /// minimum brightness - /// token used to cancel pulse - protected async Task StartPulseAsync(TimeSpan pulseDuration, float highBrightness, float lowBrightness, CancellationToken cancellationToken) + /// Is disposing + protected virtual void Dispose(bool disposing) { - float brightness = lowBrightness; - bool ascending = true; - TimeSpan intervalTime = TimeSpan.FromMilliseconds(60); // 60 miliseconds is probably the fastest update we want to do, given that threads are given 20 miliseconds by default. - float steps = (float)(pulseDuration.TotalMilliseconds / intervalTime.TotalMilliseconds); - float delta = (highBrightness - lowBrightness) / steps; - - while (true) + if (!IsDisposed) { - if (cancellationToken.IsCancellationRequested) - { - break; - } - - if (brightness <= lowBrightness) - { - ascending = true; - } - else if (brightness >= highBrightness) - { - ascending = false; - } - - brightness += delta * (ascending ? 1 : -1); - - if (brightness < 0) - { - brightness = 0; - } - else if (brightness > 1) + if (disposing && createdPwm) { - brightness = 1; + Port.Dispose(); } - Brightness = brightness; - - await Task.Delay(intervalTime); + IsDisposed = true; } } - - /// - /// Stops any running animations. - /// - public void Stop() - { - cancellationTokenSource?.Cancel(); - IsOn = false; - } } } \ No newline at end of file diff --git a/Source/Meadow.Foundation.Core/Leds/PwmLedBarGraph.Animations.cs b/Source/Meadow.Foundation.Core/Leds/PwmLedBarGraph.Animations.cs new file mode 100644 index 0000000000..1fbd86cc9f --- /dev/null +++ b/Source/Meadow.Foundation.Core/Leds/PwmLedBarGraph.Animations.cs @@ -0,0 +1,266 @@ +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace Meadow.Foundation.Leds +{ + public partial class PwmLedBarGraph + { + private object syncRoot = new object(); + + private Task? animationTask; + private CancellationTokenSource? cancellationTokenSource; + + /// + /// Stops the LED bar graph when its blinking + /// + public async Task StopAnimation() + { + if (animationTask != null) + { + cancellationTokenSource?.Cancel(); + await animationTask; + animationTask = null; + cancellationTokenSource = null; + } + } + + /// + /// Stops the blinking animation on an individual LED + /// + /// Index of the LED + public Task StopAnimation(int index) + { + if (index < 0 || index >= Count) + { + throw new ArgumentOutOfRangeException(); + } + + return pwmLeds[index].StopAnimation(); + } + + /// + /// Starts a blink animation on an individual LED + /// + /// Index of the LED + /// The maximum brightness of the animation + /// The minimum brightness of the animation + public Task StartBlink( + int index, + float highBrightness = 1, + float lowBrightness = 0) + { + if (index < 0 || index >= Count) + { + throw new ArgumentOutOfRangeException(); + } + + return pwmLeds[index].StartBlink(highBrightness, lowBrightness); + } + + /// + /// Starts a blink animation on an individual LED + /// + /// Index of the LED + /// The duration the LED stays in high brightness + /// The duration the LED stays in low brightness + /// The maximum brightness of the animation + /// The minimum brightness of the animation + public Task StartBlink( + int index, + TimeSpan highBrightnessDuration, + TimeSpan lowBrightnessDuration, + float highBrightness = 1, + float lowBrightness = 0) + { + if (index < 0 || index >= Count) + { + throw new ArgumentOutOfRangeException(); + } + + return pwmLeds[index].StartBlink(highBrightnessDuration, lowBrightnessDuration, highBrightness, lowBrightness); + } + + /// + /// Start the Blink animation which sets the brightness of the LED alternating between a low and high brightness setting. + /// + /// The maximum brightness of the animation + /// The minimum brightness of the animation + public Task StartBlink(float highBrightness = 1, float lowBrightness = 0) + { + return StartBlink(TimeSpan.FromMilliseconds(500), TimeSpan.FromMilliseconds(500), highBrightness, lowBrightness); + } + + /// + /// Start the Blink animation which sets the brightness of the LED alternating between a low and high brightness setting, using the durations provided. + /// + /// On duration. + /// Off duration. + /// High brigtness. + /// Low brightness. + public async Task StartBlink( + TimeSpan highBrightnessDuration, + TimeSpan lowBrightnessDuration, + float highBrightness = 1, + float lowBrightness = 0) + { + await StopAnimation(); + + lock (syncRoot) + { + cancellationTokenSource = new CancellationTokenSource(); + + animationTask = new Task(() => + { + while (cancellationTokenSource.Token.IsCancellationRequested == false) + { + foreach (var led in pwmLeds) + { + led.SetBrightness(highBrightness); + } + Thread.Sleep(highBrightnessDuration); + + foreach (var led in pwmLeds) + { + led.SetBrightness(lowBrightness); + } + Thread.Sleep(lowBrightnessDuration); + } + }, cancellationTokenSource.Token, TaskCreationOptions.LongRunning); + + animationTask.Start(); + } + } + + /// + /// Starts a pulse animation on an individual LED + /// + /// Index of the LED + /// The maximum brightness of the animation + /// The minimum brightness of the animation + public Task StartPulse(int index, float highBrightness = 1, float lowBrightness = 0.15F) + { + if (index < 0 || index >= Count) + { + throw new ArgumentOutOfRangeException(); + } + + return pwmLeds[index].StartPulse(highBrightness, lowBrightness); + } + + /// + /// Starts a pulse animation on an individual LED with the specified pulse cycle + /// + /// Index of the LED + /// The pulse animation duration + /// The maximum brightness of the animation + /// The minimum brightness of the animation + public Task StartPulse(int index, TimeSpan pulseDuration, float highBrightness = 1, float lowBrightness = 0.15F) + { + if (index < 0 || index >= Count) + { + throw new ArgumentOutOfRangeException(); + } + + return pwmLeds[index].StartPulse(pulseDuration, highBrightness, lowBrightness); + } + + /// + /// Start the Pulse animation which gradually alternates the brightness of the LED between a low and high brightness setting. + /// + /// The maximum brightness of the animation + /// The minimum brightness of the animation + public Task StartPulse(float highBrightness = 1, float lowBrightness = 0.15F) + { + return StartPulse(TimeSpan.FromMilliseconds(600), highBrightness, lowBrightness); + } + + /// + /// Start the Pulse animation which gradually alternates the brightness of the LED between a low and high brightness setting, using the durations provided. + /// + /// The pulse animation duration + /// The maximum brightness of the animation + /// The minimum brightness of the animation + public async Task StartPulse( + TimeSpan pulseDuration, + float highBrightness = 1, + float lowBrightness = 0.15F) + { + ValidateBrightness(highBrightness, lowBrightness); + + await StopAnimation(); + + lock (syncRoot) + { + cancellationTokenSource = new CancellationTokenSource(); + + animationTask = new Task(() => + { + float brightness = lowBrightness; + bool ascending = true; + var intervalTime = TimeSpan.FromMilliseconds(60); // 60 miliseconds is probably the fastest update we want to do, given that threads are given 20 miliseconds by default. + float steps = (float)(pulseDuration.TotalMilliseconds / intervalTime.TotalMilliseconds); + float delta = (highBrightness - lowBrightness) / steps; + + while (cancellationTokenSource.Token.IsCancellationRequested == false) + { + if (brightness <= lowBrightness) + { + ascending = true; + } + else if (brightness >= highBrightness) + { + ascending = false; + } + + brightness += delta * (ascending ? 1 : -1); + + if (brightness < lowBrightness) + { + brightness = lowBrightness; + } + else if (brightness > highBrightness) + { + brightness = highBrightness; + } + + SetBrightness(brightness); + + Thread.Sleep(intervalTime); + } + }, cancellationTokenSource.Token, TaskCreationOptions.LongRunning); + + animationTask.Start(); + } + } + + /// + /// Validates LED brightness to ensure they're within the range 0 (off) - 1 (full brighness) + /// + /// The maximum brightness of the animation + /// The minimum brightness of the animation + protected void ValidateBrightness(float highBrightness, float lowBrightness) + { + if (highBrightness > 1 || highBrightness <= 0) + { + throw new ArgumentOutOfRangeException(nameof(highBrightness), "onBrightness must be > 0 and <= 1"); + } + if (lowBrightness >= 1 || lowBrightness < 0) + { + throw new ArgumentOutOfRangeException(nameof(lowBrightness), "lowBrightness must be >= 0 and < 1"); + } + if (lowBrightness >= highBrightness) + { + throw new Exception("offBrightness must be less than onBrightness"); + } + } + + /// + /// Returns the index of the last LED turned on + /// + public int GetTopLedForPercentage() + { + return (int)Math.Max(0, Percentage * Count - 1); + } + } +} diff --git a/Source/Meadow.Foundation.Core/Leds/PwmLedBarGraph.cs b/Source/Meadow.Foundation.Core/Leds/PwmLedBarGraph.cs index b2c1176792..bb2bcd9f77 100644 --- a/Source/Meadow.Foundation.Core/Leds/PwmLedBarGraph.cs +++ b/Source/Meadow.Foundation.Core/Leds/PwmLedBarGraph.cs @@ -1,7 +1,6 @@ using Meadow.Hardware; using Meadow.Units; using System; -using System.Threading; using System.Threading.Tasks; namespace Meadow.Foundation.Leds @@ -9,11 +8,8 @@ namespace Meadow.Foundation.Leds /// /// Represents an LED bar graph composed on multiple PWM LEDs /// - public class PwmLedBarGraph + public partial class PwmLedBarGraph { - private Task? animationTask; - private CancellationTokenSource? cancellationTokenSource; - /// /// Array to hold pwm leds for bar graph /// @@ -27,12 +23,7 @@ public class PwmLedBarGraph /// /// A value between 0 and 1 that controls the number of LEDs that are activated /// - public float Percentage - { - get => percentage; - set => SetPercentage(percentage = value); - } - float percentage; + public float Percentage { get; protected set; } /// /// Create an LedBarGraph instance for single color LED bar graphs @@ -94,363 +85,79 @@ public PwmLedBarGraph(IPwmPort[] ports, Voltage[] forwardVoltage) } } - /// - /// Set the percentage of LEDs that are on starting from index 0 - /// - /// Percentage (Range from 0 - 1) - protected void SetPercentage(float percentage) - { - if (percentage < 0 || percentage > 1) - { - throw new ArgumentOutOfRangeException(); - } - - var value = percentage * Count; - - for (int i = 1; i <= Count; i++) - { - if (i <= value) - { - SetLed(i - 1, true); - } - else if (i <= value + 1) - { - SetLedBrightness(i - 1, value + 1 - i); - } - else - { - SetLed(i - 1, false); - } - } - } - - /// - /// Returns the index of the last LED turned on - /// - /// - public int GetTopLedForPercentage() - { - return (int)Math.Max(0, percentage * Count - 1); - } - /// /// Set the LED state /// - /// index of the LED - /// - public void SetLed(int index, bool isOn) + /// Index of the LED + /// True for on, False for off + public async Task SetLed(int index, bool isOn) { if (index < 0 || index >= Count) { throw new ArgumentOutOfRangeException(); } - pwmLeds[index].Stop(); + await pwmLeds[index].StopAnimation(); pwmLeds[index].IsOn = isOn; } - /// - /// Set the brightness to the LED bar graph using PWM - /// - /// - public void SetLedBrightness(double brightness) - { - foreach (var led in pwmLeds) - { - led.Stop(); - led.IsOn = false; - led.Brightness = (float)brightness; - } - } - /// /// Set the brightness of an individual LED when using PWM /// - /// - /// - public void SetLedBrightness(int index, float brightness) - { - if (index < 0 || index >= Count) - { - throw new ArgumentOutOfRangeException(); - } - - pwmLeds[index].Stop(); - pwmLeds[index].IsOn = false; - pwmLeds[index].Brightness = brightness; - } - - /// - /// Starts a blink animation on an individual LED - /// - /// - /// - /// - public void StartBlink(int index, float highBrightness = 1, float lowBrightness = 0) - { - if (index < 0 || index >= Count) - { - throw new ArgumentOutOfRangeException(); - } - - pwmLeds[index].StartBlink(highBrightness, lowBrightness); - } - - /// - /// Starts a blink animation on an individual LED - /// - /// - /// - /// - /// - /// - public void StartBlink(int index, TimeSpan highBrightnessDuration, TimeSpan lowBrightnessDuration, float highBrightness = 1, float lowBrightness = 0) - { - if (index < 0 || index >= Count) - { - throw new ArgumentOutOfRangeException(); - } - - pwmLeds[index].StartBlink(highBrightnessDuration, lowBrightnessDuration, highBrightness, lowBrightness); - } - - /// - /// Start the Blink animation which sets the brightness of the LED alternating between a low and high brightness setting. - /// - /// High brigtness. - /// Low brightness. - public void StartBlink(float highBrightness = 1, float lowBrightness = 0) - { - var highBrightnessDuration = TimeSpan.FromMilliseconds(500); - var lowBrightnessDuration = TimeSpan.FromMilliseconds(500); - - Stop(); - - animationTask = new Task(async () => - { - cancellationTokenSource = new CancellationTokenSource(); - await StartBlinkAsync(highBrightnessDuration, lowBrightnessDuration, highBrightness, lowBrightness, cancellationTokenSource.Token); - }); - animationTask.Start(); - } - - /// - /// Start the Blink animation which sets the brightness of the LED alternating between a low and high brightness setting, using the durations provided. - /// - /// On duration. - /// Off duration. - /// High brigtness. - /// Low brightness. - public void StartBlink(TimeSpan highBrightnessDuration, TimeSpan lowBrightnessDuration, float highBrightness = 1, float lowBrightness = 0) - { - Stop(); - - animationTask = new Task(async () => - { - cancellationTokenSource = new CancellationTokenSource(); - await StartBlinkAsync(highBrightnessDuration, lowBrightnessDuration, highBrightness, lowBrightness, cancellationTokenSource.Token); - }); - animationTask.Start(); - } - - /// - /// Set LED to blink - /// - /// - /// - /// - /// - /// - /// - protected async Task StartBlinkAsync(TimeSpan onDuration, TimeSpan offDuration, float highBrightness, float lowBrightness, CancellationToken cancellationToken) - { - while (true) - { - if (cancellationToken.IsCancellationRequested) - { - break; - } - - foreach (var led in pwmLeds) - { - led.Brightness = highBrightness; - } - await Task.Delay(onDuration); - - if (cancellationToken.IsCancellationRequested) - { - break; - } - - foreach (var led in pwmLeds) - { - led.Brightness = lowBrightness; - } - await Task.Delay(offDuration); - } - } - - /// - /// Starts a pulse animation on an individual LED - /// - /// - /// - /// - public void StartPulse(int index, float highBrightness = 1, float lowBrightness = 0.15F) + /// Index of the LED + /// Valid values are from 0 to 1, inclusive + public async Task SetLedBrightness(int index, float brightness) { if (index < 0 || index >= Count) { throw new ArgumentOutOfRangeException(); } - pwmLeds[index].StartPulse(highBrightness, lowBrightness); + await pwmLeds[index].StopAnimation(); + pwmLeds[index].SetBrightness(brightness); } /// - /// Starts a pulse animation on an individual LED with the specified pulse cycle + /// Set the percentage of LEDs that are on starting from index 0 /// - /// - /// - /// - /// - public void StartPulse(int index, TimeSpan pulseDuration, float highBrightness = 1, float lowBrightness = 0.15F) + /// Percentage (Range from 0 - 1) + public async Task SetPercentage(float percentage) { - if (index < 0 || index >= Count) + if (percentage < 0 || percentage > 1) { throw new ArgumentOutOfRangeException(); } - pwmLeds[index].StartPulse(pulseDuration, highBrightness, lowBrightness); - } - - /// - /// Start the Pulse animation which gradually alternates the brightness of the LED between a low and high brightness setting. - /// - /// - /// - public void StartPulse(float highBrightness = 1, float lowBrightness = 0.15F) - { - if (highBrightness > 1 || highBrightness <= 0) - { - throw new ArgumentOutOfRangeException(nameof(highBrightness), "highBrightness must be > 0 and <= 1"); - } - if (lowBrightness >= 1 || lowBrightness < 0) - { - throw new ArgumentOutOfRangeException(nameof(lowBrightness), "lowBrightness must be >= 0 and < 1"); - } - if (lowBrightness >= highBrightness) - { - throw new Exception("lowBrightness must be less than highbrightness"); - } - - Stop(); - - animationTask = new Task(async () => - { - cancellationTokenSource = new CancellationTokenSource(); - await StartPulseAsync(TimeSpan.FromSeconds(1), highBrightness, lowBrightness, cancellationTokenSource.Token); - }); - animationTask.Start(); - } - - /// - /// Start the Pulse animation which gradually alternates the brightness of the LED between a low and high brightness setting, using the durations provided. - /// - /// - /// - /// - public void StartPulse(TimeSpan pulseDuration, float highBrightness = 1, float lowBrightness = 0.15F) - { - if (highBrightness > 1 || highBrightness <= 0) - { - throw new ArgumentOutOfRangeException(nameof(highBrightness), "highBrightness must be > 0 and <= 1"); - } - if (lowBrightness >= 1 || lowBrightness < 0) - { - throw new ArgumentOutOfRangeException(nameof(lowBrightness), "lowBrightness must be >= 0 and < 1"); - } - if (lowBrightness >= highBrightness) - { - throw new Exception("lowBrightness must be less than highbrightness"); - } - - Stop(); - - animationTask = new Task(async () => - { - cancellationTokenSource = new CancellationTokenSource(); - await StartPulseAsync(pulseDuration, highBrightness, lowBrightness, cancellationTokenSource.Token); - }); - animationTask.Start(); - } - - /// - /// Start the Pulse animation which gradually alternates the brightness of the LED between a low and high brightness setting, using the durations provided. - /// - /// - /// - /// - /// - /// - protected async Task StartPulseAsync(TimeSpan pulseDuration, float highBrightness, float lowBrightness, CancellationToken cancellationToken) - { - float brightness = lowBrightness; - bool ascending = true; - TimeSpan intervalTime = TimeSpan.FromMilliseconds(60); // 60 miliseconds is probably the fastest update we want to do, given that threads are given 20 miliseconds by default. - float steps = (float)(pulseDuration.TotalMilliseconds / intervalTime.TotalMilliseconds); - float delta = (highBrightness - lowBrightness) / steps; + var value = percentage * Count; - while (true) + for (int i = 1; i <= Count; i++) { - if (cancellationToken.IsCancellationRequested) - { - break; - } - - if (brightness <= lowBrightness) + if (i <= value) { - ascending = true; + await SetLed(i - 1, true); } - else if (brightness >= highBrightness) + else if (i <= value + 1) { - ascending = false; + await SetLedBrightness(i - 1, value + 1 - i); } - - brightness += delta * (ascending ? 1 : -1); - - foreach (var led in pwmLeds) + else { - led.Brightness = Math.Clamp(brightness, 0, 1); + await SetLed(i - 1, false); } - - await Task.Delay(intervalTime); } } /// - /// Stops any running animations. + /// Set the brightness to the LED bar graph using PWM /// - public void Stop() + /// Valid values are from 0 to 1, inclusive + public async Task SetBrightness(float brightness) { - cancellationTokenSource?.Cancel(); - foreach (var led in pwmLeds) { - led.Stop(); + await led.StopAnimation(); + led.SetBrightness(brightness); } } - - /// - /// Stops any animation on an individual LED and/or turns it off - /// - public void Stop(int index) - { - if (index < 0 || index >= Count) - { - throw new ArgumentOutOfRangeException(); - } - - pwmLeds[index].Stop(); - } } } \ No newline at end of file diff --git a/Source/Meadow.Foundation.Core/Leds/RgbLed.Animations.cs b/Source/Meadow.Foundation.Core/Leds/RgbLed.Animations.cs new file mode 100644 index 0000000000..14bc482610 --- /dev/null +++ b/Source/Meadow.Foundation.Core/Leds/RgbLed.Animations.cs @@ -0,0 +1,95 @@ +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace Meadow.Foundation.Leds +{ + /// + /// Utility functions to provide blinking and pulsing for RgbLed + /// + public partial class RgbLed + { + private object syncRoot = new object(); + + private Task? animationTask = null; + private CancellationTokenSource? cancellationTokenSource = null; + + /// + /// Stops the current LED animation + /// + public async Task StopAnimation() + { + if (animationTask != null) + { + cancellationTokenSource?.Cancel(); + await animationTask; + animationTask = null; + cancellationTokenSource = null; + } + } + + /// + /// Start the Blink animation which sets turns the LED on and off on an interval of 1 second (500ms on, 500ms off) + /// + public Task StartBlink() + { + return StartBlink(TimeSpan.FromMilliseconds(500), TimeSpan.FromMilliseconds(500)); + } + + /// + /// Start the Blink animation which sets turns the LED on and off on an interval of 1 second (500ms on, 500ms off) + /// + /// The LED color + public Task StartBlink(RgbLedColors color) + { + return StartBlink(color, TimeSpan.FromMilliseconds(500), TimeSpan.FromMilliseconds(500)); + } + + /// + /// Start the Blink animation which sets turns the LED on and off with the especified durations and color + /// + /// The LED color + /// The duration the LED stays on + /// The duration the LED stays off + public async Task StartBlink( + RgbLedColors color, + TimeSpan onDuration, + TimeSpan offDuration) + { + await StopAnimation(); + + SetColor(color); + + await StartBlink(onDuration, offDuration); + } + + /// + /// Start the Blink animation which sets turns the LED on and off with the especified durations and current color + /// + /// The duration the LED stays on + /// The duration the LED stays off + public async Task StartBlink(TimeSpan onDuration, TimeSpan offDuration) + { + await StopAnimation(); + + lock (syncRoot) + { + cancellationTokenSource = new CancellationTokenSource(); + + animationTask = new Task(() => + { + while (cancellationTokenSource.Token.IsCancellationRequested == false) + { + IsOn = true; + Thread.Sleep(onDuration); + + IsOn = false; + Thread.Sleep(offDuration); + } + }, cancellationTokenSource.Token, TaskCreationOptions.LongRunning); + + animationTask.Start(); + } + } + } +} diff --git a/Source/Meadow.Foundation.Core/Leds/RgbLed.cs b/Source/Meadow.Foundation.Core/Leds/RgbLed.cs index a173b2e6d1..16aaf32ab3 100644 --- a/Source/Meadow.Foundation.Core/Leds/RgbLed.cs +++ b/Source/Meadow.Foundation.Core/Leds/RgbLed.cs @@ -1,8 +1,5 @@ using Meadow.Hardware; using Meadow.Peripherals.Leds; -using System; -using System.Threading; -using System.Threading.Tasks; namespace Meadow.Foundation.Leds { @@ -11,31 +8,28 @@ namespace Meadow.Foundation.Leds /// public partial class RgbLed : IRgbLed { - private Task? animationTask; - private CancellationTokenSource? cancellationTokenSource; - /// - /// Get the color the LED has been set to. + /// The current LED color /// public RgbLedColors Color { get; protected set; } = RgbLedColors.White; /// - /// Get the red LED port + /// The red LED port /// protected IDigitalOutputPort RedPort { get; set; } /// - /// Get the green LED port + /// The green LED port /// protected IDigitalOutputPort GreenPort { get; set; } /// - /// Get the blue LED port + ///The blue LED port /// protected IDigitalOutputPort BluePort { get; set; } /// - /// Is the LED using a common cathode + /// The common type (common annode or common cathode) /// public CommonType Common { get; protected set; } @@ -45,16 +39,12 @@ public partial class RgbLed : IRgbLed public bool IsOn { get => isOn; - set - { - SetColor(value ? Color : RgbLedColors.Black); - isOn = value; - } + set => UpdateLed(isOn = value); } bool isOn; /// - /// Initializes a new instance of the class. + /// Create instance of RgbLed /// /// Red Pin /// Green Pin @@ -73,7 +63,7 @@ public RgbLed( { } /// - /// Initializes a new instance of the class. + /// Create instance of RgbLed /// /// Red Port /// Green Port @@ -91,127 +81,71 @@ public RgbLed( Common = commonType; } - /// - /// Stops any running animations. - /// - public void Stop() - { - cancellationTokenSource?.Cancel(); - IsOn = false; - } - /// /// Sets the current color of the LED. /// - /// + /// The color value public void SetColor(RgbLedColors color) { Color = color; - bool onState = (Common == CommonType.CommonCathode); - - switch (color) - { - case RgbLedColors.Red: - RedPort.State = onState; - GreenPort.State = !onState; - BluePort.State = !onState; - break; - case RgbLedColors.Green: - RedPort.State = !onState; - GreenPort.State = onState; - BluePort.State = !onState; - break; - case RgbLedColors.Blue: - RedPort.State = !onState; - GreenPort.State = !onState; - BluePort.State = onState; - break; - case RgbLedColors.Yellow: - RedPort.State = onState; - GreenPort.State = onState; - BluePort.State = !onState; - break; - case RgbLedColors.Magenta: - RedPort.State = onState; - GreenPort.State = !onState; - BluePort.State = onState; - break; - case RgbLedColors.Cyan: - RedPort.State = !onState; - GreenPort.State = onState; - BluePort.State = onState; - break; - case RgbLedColors.White: - RedPort.State = onState; - GreenPort.State = onState; - BluePort.State = onState; - break; - case RgbLedColors.Black: - RedPort.State = !onState; - GreenPort.State = !onState; - BluePort.State = !onState; - break; - } - } - - /// - /// Starts the blink animation LED turning it on (500) and off (500) - /// - /// - public void StartBlink(RgbLedColors color) - { - var onDuration = TimeSpan.FromMilliseconds(500); - var offDuration = TimeSpan.FromMilliseconds(500); - - Stop(); - - animationTask = new Task(async () => - { - cancellationTokenSource = new CancellationTokenSource(); - await StartBlinkAsync(color, onDuration, offDuration, cancellationTokenSource.Token); - }); - animationTask.Start(); + IsOn = true; } /// - /// Starts the blink animation with the specified on and off duration. + /// Turns on LED with current color or LED off /// - /// - /// - /// - public void StartBlink(RgbLedColors color, TimeSpan onDuration, TimeSpan offDuration) + /// True for on, False for off + protected void UpdateLed(bool isOn) { - Stop(); - - animationTask = new Task(async () => - { - cancellationTokenSource = new CancellationTokenSource(); - await StartBlinkAsync(color, onDuration, offDuration, cancellationTokenSource.Token); - }); - animationTask.Start(); - } + bool onState = (Common == CommonType.CommonCathode); - /// - /// Turn the LED on and off (blink) - /// - /// - /// - /// - /// - protected async Task StartBlinkAsync(RgbLedColors color, TimeSpan onDuration, TimeSpan offDuration, CancellationToken cancellationToken) - { - while (true) + if (isOn) { - if (cancellationToken.IsCancellationRequested) + switch (Color) { - break; + case RgbLedColors.Red: + RedPort.State = onState; + GreenPort.State = !onState; + BluePort.State = !onState; + break; + case RgbLedColors.Green: + RedPort.State = !onState; + GreenPort.State = onState; + BluePort.State = !onState; + break; + case RgbLedColors.Blue: + RedPort.State = !onState; + GreenPort.State = !onState; + BluePort.State = onState; + break; + case RgbLedColors.Yellow: + RedPort.State = onState; + GreenPort.State = onState; + BluePort.State = !onState; + break; + case RgbLedColors.Magenta: + RedPort.State = onState; + GreenPort.State = !onState; + BluePort.State = onState; + break; + case RgbLedColors.Cyan: + RedPort.State = !onState; + GreenPort.State = onState; + BluePort.State = onState; + break; + case RgbLedColors.White: + RedPort.State = onState; + GreenPort.State = onState; + BluePort.State = onState; + break; } - - SetColor(color); - await Task.Delay(onDuration); - SetColor(RgbLedColors.Black); - await Task.Delay(offDuration); + } + else + { + RedPort.State = !onState; + GreenPort.State = !onState; + BluePort.State = !onState; } } } diff --git a/Source/Meadow.Foundation.Core/Leds/RgbLedColors.cs b/Source/Meadow.Foundation.Core/Leds/RgbLedColors.cs new file mode 100644 index 0000000000..fa731d899f --- /dev/null +++ b/Source/Meadow.Foundation.Core/Leds/RgbLedColors.cs @@ -0,0 +1,41 @@ +namespace Meadow.Foundation.Leds +{ + /// + /// Colors for RGB Led + /// + public enum RgbLedColors + { + /// + /// Red (red LED only) + /// + Red, + /// + /// Green (green LED only) + /// + Green, + /// + /// Blue (blue LED only) + /// + Blue, + /// + /// Yellow (red and green LEDs) + /// + Yellow, + /// + /// Magenta (blue and red LEDs) + /// + Magenta, + /// + /// Cyan (blue and green LEDs) + /// + Cyan, + /// + /// White (red, green and blue LEDs) + /// + White, + /// + /// Count of colors + /// + count, + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Core/Leds/RgbPwmLed.Animations.cs b/Source/Meadow.Foundation.Core/Leds/RgbPwmLed.Animations.cs new file mode 100644 index 0000000000..f45cc7cd22 --- /dev/null +++ b/Source/Meadow.Foundation.Core/Leds/RgbPwmLed.Animations.cs @@ -0,0 +1,248 @@ +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace Meadow.Foundation.Leds +{ + /// + /// Utility functions to provide blinking and pulsing for RgbPwmLed + /// + public partial class RgbPwmLed + { + private object syncRoot = new object(); + + private Task? animationTask = null; + private CancellationTokenSource? cancellationTokenSource = null; + + /// + /// Stops the current LED animation + /// + public async Task StopAnimation() + { + if (animationTask != null) + { + cancellationTokenSource?.Cancel(); + await animationTask; + animationTask = null; + cancellationTokenSource = null; + } + } + + /// + /// Start the Blink animation which sets the brightness of the LED alternating between a low and high brightness + /// On an interval of 1 second (500ms on, 500ms off) + /// + /// The maximum brightness of the animation + /// The minimum brightness of the animation + public Task StartBlink(float highBrightness = 1f, float lowBrightness = 0f) + { + return StartBlink(TimeSpan.FromMilliseconds(500), TimeSpan.FromMilliseconds(500), highBrightness, lowBrightness); + } + + /// + /// Start the Blink animation which sets the brightness of the LED alternating between a low and high brightness + /// On an interval of 1 second (500ms on, 500ms off) + /// + /// The LED color + /// The maximum brightness of the animation + /// The minimum brightness of the animation + public Task StartBlink( + Color color, + float highBrightness = 1f, + float lowBrightness = 0f) + { + return StartBlink(color, TimeSpan.FromMilliseconds(500), TimeSpan.FromMilliseconds(500), highBrightness, lowBrightness); + } + + /// + /// Start the Blink animation which sets the brightness of the LED alternating between a low and high brightness setting, using the durations provided. + /// + /// The LED color + /// The duration the LED stays on + /// The duration the LED stays off + /// The maximum brightness of the animation + /// The minimum brightness of the animation + + public async Task StartBlink( + Color color, + TimeSpan onDuration, + TimeSpan offDuration, + float highBrightness = 1f, + float lowBrightness = 0f) + { + ValidateBrightness(highBrightness, lowBrightness); + + await StopAnimation(); + + SetColor(color); + + await StartBlink(onDuration, offDuration, highBrightness, lowBrightness); + } + + /// + /// Start the Blink animation which sets the brightness of the LED alternating between a low and high brightness setting, using the durations provided. + /// + /// The duration the LED stays on + /// The duration the LED stays off + /// The maximum brightness of the animation + /// The minimum brightness of the animation + + public async Task StartBlink( + TimeSpan onDuration, + TimeSpan offDuration, + float highBrightness = 1f, + float lowBrightness = 0f) + { + ValidateBrightness(highBrightness, lowBrightness); + + await StopAnimation(); + + lock (syncRoot) + { + cancellationTokenSource = new CancellationTokenSource(); + + animationTask = new Task(() => + { + while (cancellationTokenSource.Token.IsCancellationRequested == false) + { + SetBrightness(highBrightness); + Thread.Sleep(onDuration); + + SetBrightness(lowBrightness); + Thread.Sleep(offDuration); + } + }, cancellationTokenSource.Token, TaskCreationOptions.LongRunning); + + animationTask.Start(); + } + } + + /// + /// Start the Pulse animation which gradually alternates the brightness of the LED between a low and high brightness setting + /// with a cycle time of 600ms + /// + /// The maximum brightness of the animation + /// The minimum brightness of the animation + public Task StartPulse(float highBrightness = 1, float lowBrightness = 0.15F) + { + return StartPulse(TimeSpan.FromMilliseconds(600), highBrightness, lowBrightness); + } + + /// + /// Start the Pulse animation which gradually alternates the brightness of the LED between a low and high brightness setting + /// with a cycle time of 600ms + /// + /// The LED color + /// The maximum brightness of the animation + /// The minimum brightness of the animation + public Task StartPulse( + Color color, + float highBrightness = 1, + float lowBrightness = 0.15F) + { + return StartPulse(color, TimeSpan.FromMilliseconds(600), highBrightness, lowBrightness); + } + + /// + /// Start the Pulse animation which gradually alternates the brightness of the LED between a low and high brightness setting, using the durations provided. + /// + /// The LED color + /// The pulse animation duration + /// The maximum brightness of the animation + /// The minimum brightness of the animation + public async Task StartPulse( + Color color, + TimeSpan pulseDuration, + float highBrightness = 1, + float lowBrightness = 0.15F) + { + ValidateBrightness(highBrightness, lowBrightness); + + await StopAnimation(); + + SetColor(color); + + await StartPulse(pulseDuration, highBrightness, lowBrightness); + } + + /// + /// Start the Pulse animation which gradually alternates the brightness of the LED between a low and high brightness setting, using the durations provided. + /// + /// The pulse animation duration + /// The maximum brightness of the animation + /// The minimum brightness of the animation + public async Task StartPulse( + TimeSpan pulseDuration, + float highBrightness = 1, + float lowBrightness = 0.15F) + { + ValidateBrightness(highBrightness, lowBrightness); + + await StopAnimation(); + + lock (syncRoot) + { + cancellationTokenSource = new CancellationTokenSource(); + + animationTask = new Task(() => + { + float brightness = lowBrightness; + bool ascending = true; + var intervalTime = TimeSpan.FromMilliseconds(60); // 60 miliseconds is probably the fastest update we want to do, given that threads are given 20 miliseconds by default. + float steps = (float)(pulseDuration.TotalMilliseconds / intervalTime.TotalMilliseconds); + float delta = (highBrightness - lowBrightness) / steps; + + while (cancellationTokenSource.Token.IsCancellationRequested == false) + { + if (brightness <= lowBrightness) + { + ascending = true; + } + else if (brightness >= highBrightness) + { + ascending = false; + } + + brightness += delta * (ascending ? 1 : -1); + + if (brightness < lowBrightness) + { + brightness = lowBrightness; + } + else if (brightness > highBrightness) + { + brightness = highBrightness; + } + + SetBrightness(brightness); + + Thread.Sleep(intervalTime); + } + }, cancellationTokenSource.Token, TaskCreationOptions.LongRunning); + + animationTask.Start(); + } + } + + /// + /// Validates LED brightness to ensure they're within the range 0 (off) - 1 (full brighness) + /// + /// The maximum brightness of the animation + /// The minimum brightness of the animation + protected void ValidateBrightness(float highBrightness, float lowBrightness) + { + if (highBrightness > 1 || highBrightness <= 0) + { + throw new ArgumentOutOfRangeException(nameof(highBrightness), "onBrightness must be > 0 and <= 1"); + } + if (lowBrightness >= 1 || lowBrightness < 0) + { + throw new ArgumentOutOfRangeException(nameof(lowBrightness), "lowBrightness must be >= 0 and < 1"); + } + if (lowBrightness >= highBrightness) + { + throw new Exception("offBrightness must be less than onBrightness"); + } + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Core/Leds/RgbPwmLed.cs b/Source/Meadow.Foundation.Core/Leds/RgbPwmLed.cs index 122ddd87a4..31dbf78b77 100644 --- a/Source/Meadow.Foundation.Core/Leds/RgbPwmLed.cs +++ b/Source/Meadow.Foundation.Core/Leds/RgbPwmLed.cs @@ -2,25 +2,18 @@ using Meadow.Peripherals.Leds; using Meadow.Units; using System; -using System.Threading; -using System.Threading.Tasks; namespace Meadow.Foundation.Leds { /// - /// Represents a Pulse-Width-Modulation (PWM) controlled RGB LED. Controlling an RGB LED with - /// PWM allows for more colors to be expressed than if it were simply controlled with normal - /// digital outputs which provide only binary control at each pin. As such, a PWM controlled - /// RGB LED can express millions of colors, as opposed to the 8 colors that can be expressed - /// via binary digital output. + /// Represents a Pulse-Width-Modulation (PWM) controlled RGB LED /// - public class RgbPwmLed + public partial class RgbPwmLed { - private Task? animationTask = null; - private CancellationTokenSource? cancellationTokenSource = null; - static readonly Frequency DefaultFrequency = new Frequency(200, Frequency.UnitType.Hertz); + readonly float DEFAULT_DUTY_CYCLE = 0f; + readonly double maxRedDutyCycle = 1; readonly double maxGreenDutyCycle = 1; readonly double maxBlueDutyCycle = 1; @@ -50,66 +43,66 @@ public bool IsOn bool isOn; /// - /// The color the LED has been set to. + /// The current LED color /// public Color Color { get; protected set; } = Color.White; /// - /// The brightness value assigned to the LED relative to Color + /// The brightness value assigned to the LED /// public float Brightness { get; protected set; } = 1f; /// - /// Get the red LED port + /// The red LED port /// protected IPwmPort RedPwm { get; set; } /// - /// Get the blue LED port + /// The blue LED port /// protected IPwmPort BluePwm { get; set; } /// - /// Get the green LED port + /// The green LED port /// protected IPwmPort GreenPwm { get; set; } /// - /// Gets the common type + /// The common type (common annode or common cathode) /// public CommonType Common { get; protected set; } /// - /// Get the red LED forward voltage + /// The red LED forward voltage /// public Voltage RedForwardVoltage { get; protected set; } /// - /// Get the green LED forward voltage + /// The green LED forward voltage /// public Voltage GreenForwardVoltage { get; protected set; } /// - /// Get the blue LED forward voltage + /// The blue LED forward voltage /// public Voltage BlueForwardVoltage { get; protected set; } /// - /// Create instance of RgbPwmLed + /// Create instance of RgbPwmLed /// - /// - /// - /// - /// + /// The PWM port for the red LED + /// The PWM port for the green LED + /// The PWM port for the blue LED + /// Common annode or common cathode public RgbPwmLed( - IPwmPort redPwm, - IPwmPort greenPwm, - IPwmPort bluePwm, + IPwmPort redPwmPort, + IPwmPort greenPwmPort, + IPwmPort bluePwmPort, CommonType commonType = CommonType.CommonCathode) { - RedPwm = redPwm; - GreenPwm = greenPwm; - BluePwm = bluePwm; + RedPwm = redPwmPort; + GreenPwm = greenPwmPort; + BluePwm = bluePwmPort; RedForwardVoltage = TypicalForwardVoltage.Red; GreenForwardVoltage = TypicalForwardVoltage.Green; @@ -117,21 +110,20 @@ public RgbPwmLed( Common = commonType; - // calculate and set maximum PWM duty cycles maxRedDutyCycle = Helpers.CalculateMaximumDutyCycle(RedForwardVoltage); maxGreenDutyCycle = Helpers.CalculateMaximumDutyCycle(GreenForwardVoltage); maxBlueDutyCycle = Helpers.CalculateMaximumDutyCycle(BlueForwardVoltage); - ResetPwms(); + ResetPwmPorts(); } /// - /// Create instance of RgbPwmLed + /// Create instance of RgbPwmLed /// - /// - /// - /// - /// + /// The PWM pin for the red LED + /// The PWM pin for the green LED + /// The PWM pin for the blue LED + /// Common annode or common cathode public RgbPwmLed( IPin redPwmPin, IPin greenPwmPin, @@ -145,16 +137,15 @@ public RgbPwmLed( { } /// - /// Instantiates a RgbPwmLed object with the especified IO device, connected - /// to three digital pins for red, green and blue channels, respectively + /// Create instance of RgbPwmLed /// - /// - /// - /// - /// - /// - /// - /// + /// The PWM pin for the red LED + /// The PWM pin for the green LED + /// The PWM pin for the blue LED + /// The forward voltage for the red LED + /// The forward voltage for the green LED + /// The forward voltage for the blue LED + /// Common annode or common cathode public RgbPwmLed( IPin redPwmPin, IPin greenPwmPin, @@ -174,317 +165,117 @@ public RgbPwmLed( { } /// - /// - /// Implementation notes: Architecturally, it would be much cleaner to construct this class - /// as three PwmLeds. Then each one's implementation would be self-contained. However, that - /// would require three additional threads during ON; one contained by each PwmLed. For this - /// reason, I'm basically duplicating the functionality for all three in here. + /// Create instance of RgbPwmLed /// - /// - /// - /// - /// - /// - /// - /// + /// The PWM port for the red LED + /// The PWM port for the green LED + /// The PWM port for the blue LED + /// The forward voltage for the red LED + /// The forward voltage for the green LED + /// The forward voltage for the blue LED + /// Common annode or common cathode public RgbPwmLed( - IPwmPort redPwm, - IPwmPort greenPwm, - IPwmPort bluePwm, + IPwmPort redPwmPort, + IPwmPort greenPwmPort, + IPwmPort bluePwmPort, Voltage redLedForwardVoltage, Voltage greenLedForwardVoltage, Voltage blueLedForwardVoltage, CommonType commonType = CommonType.CommonCathode) { - // validate and persist forward voltages - if (redLedForwardVoltage < MIN_FORWARD_VOLTAGE || redLedForwardVoltage > MAX_FORWARD_VOLTAGE) - { - throw new ArgumentOutOfRangeException(nameof(redLedForwardVoltage), "error, forward voltage must be between 0, and 3.3"); - } - RedForwardVoltage = redLedForwardVoltage; + ValidateForwardVoltages(redLedForwardVoltage, greenLedForwardVoltage, blueLedForwardVoltage); - if (greenLedForwardVoltage < MIN_FORWARD_VOLTAGE || greenLedForwardVoltage > MAX_FORWARD_VOLTAGE) - { - throw new ArgumentOutOfRangeException(nameof(greenLedForwardVoltage), "error, forward voltage must be between 0, and 3.3"); - } + RedForwardVoltage = redLedForwardVoltage; GreenForwardVoltage = greenLedForwardVoltage; - - if (blueLedForwardVoltage < MIN_FORWARD_VOLTAGE || blueLedForwardVoltage > MAX_FORWARD_VOLTAGE) - { - throw new ArgumentOutOfRangeException(nameof(blueLedForwardVoltage), "error, forward voltage must be between 0, and 3.3"); - } BlueForwardVoltage = blueLedForwardVoltage; Common = commonType; - RedPwm = redPwm; - GreenPwm = greenPwm; - BluePwm = bluePwm; + RedPwm = redPwmPort; + GreenPwm = greenPwmPort; + BluePwm = bluePwmPort; - // calculate and set maximum PWM duty cycles maxRedDutyCycle = Helpers.CalculateMaximumDutyCycle(RedForwardVoltage); maxGreenDutyCycle = Helpers.CalculateMaximumDutyCycle(GreenForwardVoltage); maxBlueDutyCycle = Helpers.CalculateMaximumDutyCycle(BlueForwardVoltage); - ResetPwms(); - } - - /// - /// Resets all PWM ports - /// - protected void ResetPwms() - { - RedPwm.Frequency = GreenPwm.Frequency = BluePwm.Frequency = DefaultFrequency; - RedPwm.DutyCycle = GreenPwm.DutyCycle = BluePwm.DutyCycle = DEFAULT_DUTY_CYCLE; - // invert the PWM signal if it common anode - RedPwm.Inverted = GreenPwm.Inverted = BluePwm.Inverted - = (Common == CommonType.CommonAnode); - - RedPwm.Start(); GreenPwm.Start(); BluePwm.Start(); + ResetPwmPorts(); } /// - /// Sets the current color of the LED. + /// Validates forward voltages to ensure they're within the range MIN_FORWARD_VOLTAGE to MAX_FORWARD_VOLTAGE /// - /// - /// - public void SetColor(Color color, float brightness = 1) + /// The forward voltage for the red LED + /// The forward voltage for the green LED + /// The forward voltage for the blue LED + protected void ValidateForwardVoltages(Voltage redLedForwardVoltage, + Voltage greenLedForwardVoltage, + Voltage blueLedForwardVoltage) { - if (color == Color && brightness == Brightness) + if (redLedForwardVoltage < MIN_FORWARD_VOLTAGE || redLedForwardVoltage > MAX_FORWARD_VOLTAGE) { - return; + throw new ArgumentOutOfRangeException(nameof(redLedForwardVoltage), "error, forward voltage must be between 0, and 3.3"); } - Color = color; - Brightness = brightness; - - RedPwm.DutyCycle = (float)(Color.R / 255.0 * maxRedDutyCycle * brightness); - GreenPwm.DutyCycle = (float)(Color.G / 255.0 * maxGreenDutyCycle * brightness); - BluePwm.DutyCycle = (float)(Color.B / 255.0 * maxBlueDutyCycle * brightness); - } - - /// - /// Stops any running animations. - /// - public void Stop() - { - cancellationTokenSource?.Cancel(); - IsOn = false; - } - - /// - /// Start the Blink animation which sets the brightness of the LED alternating between a low and high brightness setting. - /// - /// - /// - /// - public void StartBlink(Color color, float highBrightness = 1f, float lowBrightness = 0f) - { - var onDuration = TimeSpan.FromMilliseconds(500); - var offDuration = TimeSpan.FromMilliseconds(500); - - if (highBrightness > 1 || highBrightness <= 0) - { - throw new ArgumentOutOfRangeException(nameof(highBrightness), "onBrightness must be > 0 and <= 1"); - } - if (lowBrightness >= 1 || lowBrightness < 0) - { - throw new ArgumentOutOfRangeException(nameof(lowBrightness), "lowBrightness must be >= 0 and < 1"); - } - if (lowBrightness >= highBrightness) + if (greenLedForwardVoltage < MIN_FORWARD_VOLTAGE || greenLedForwardVoltage > MAX_FORWARD_VOLTAGE) { - throw new Exception("offBrightness must be less than onBrightness"); + throw new ArgumentOutOfRangeException(nameof(greenLedForwardVoltage), "error, forward voltage must be between 0, and 3.3"); } - Color = color; - - Stop(); - - animationTask = new Task(async () => + if (blueLedForwardVoltage < MIN_FORWARD_VOLTAGE || blueLedForwardVoltage > MAX_FORWARD_VOLTAGE) { - cancellationTokenSource = new CancellationTokenSource(); - await StartBlinkAsync(color, (TimeSpan)onDuration, (TimeSpan)offDuration, highBrightness, lowBrightness, cancellationTokenSource.Token); - }); - animationTask.Start(); + throw new ArgumentOutOfRangeException(nameof(blueLedForwardVoltage), "error, forward voltage must be between 0, and 3.3"); + } } /// - /// Start the Blink animation which sets the brightness of the LED alternating between a low and high brightness setting, using the durations provided. + /// Resets all PWM ports /// - /// - /// - /// - /// - /// - public void StartBlink(Color color, TimeSpan onDuration, TimeSpan offDuration, float highBrightness = 1f, float lowBrightness = 0f) + protected void ResetPwmPorts() { - if (highBrightness > 1 || highBrightness <= 0) - { - throw new ArgumentOutOfRangeException(nameof(highBrightness), "onBrightness must be > 0 and <= 1"); - } - if (lowBrightness >= 1 || lowBrightness < 0) - { - throw new ArgumentOutOfRangeException(nameof(lowBrightness), "lowBrightness must be >= 0 and < 1"); - } - if (lowBrightness >= highBrightness) - { - throw new Exception("offBrightness must be less than onBrightness"); - } - - Color = color; - - Stop(); + RedPwm.Frequency = GreenPwm.Frequency = BluePwm.Frequency = DefaultFrequency; + RedPwm.DutyCycle = GreenPwm.DutyCycle = BluePwm.DutyCycle = DEFAULT_DUTY_CYCLE; - animationTask = new Task(async () => - { - cancellationTokenSource = new CancellationTokenSource(); - await StartBlinkAsync(color, onDuration, offDuration, highBrightness, lowBrightness, cancellationTokenSource.Token); - }); - animationTask.Start(); - } + // invert the PWM signal if it common anode + RedPwm.Inverted = GreenPwm.Inverted = BluePwm.Inverted = Common == CommonType.CommonAnode; - /// - /// Start blinking led - /// - /// color to blink - /// on duration in ms - /// off duration in ms - /// maximum brightness - /// minimum brightness - /// token to cancel blink - protected async Task StartBlinkAsync(Color color, TimeSpan onDuration, TimeSpan offDuration, float highBrightness, float lowBrightness, CancellationToken cancellationToken) - { - while (true) - { - if (cancellationToken.IsCancellationRequested) - { - break; - } - - SetColor(color, highBrightness); - await Task.Delay(onDuration); - SetColor(color, lowBrightness); - await Task.Delay(offDuration); - } + RedPwm.Start(); + GreenPwm.Start(); + BluePwm.Start(); } /// - /// Start the Pulse animation which gradually alternates the brightness of the LED between a low and high brightness setting. + /// Set the led brightness /// - /// - /// - /// - public void StartPulse(Color color, float highBrightness = 1, float lowBrightness = 0.15F) + /// Valid values are from 0 to 1, inclusive + public void SetBrightness(float brightness) { - var pulseDuration = TimeSpan.FromMilliseconds(600); - - if (highBrightness > 1 || highBrightness <= 0) + if (brightness < 0 || brightness > 1) { - throw new ArgumentOutOfRangeException(nameof(highBrightness), "onBrightness must be > 0 and <= 1"); - } - if (lowBrightness >= 1 || lowBrightness < 0) - { - throw new ArgumentOutOfRangeException(nameof(lowBrightness), "lowBrightness must be >= 0 and < 1"); - } - if (lowBrightness >= highBrightness) - { - throw new Exception("offBrightness must be less than onBrightness"); + throw new ArgumentOutOfRangeException(nameof(brightness), "error, brightness must be between 0, and 1"); } - Color = color; - - Stop(); - - animationTask = new Task(async () => - { - cancellationTokenSource = new CancellationTokenSource(); - await StartPulseAsync(color, pulseDuration, highBrightness, lowBrightness, cancellationTokenSource.Token); - }); - animationTask.Start(); + SetColor(Color, brightness); } /// - /// Start the Pulse animation which gradually alternates the brightness of the LED between a low and high brightness setting, using the durations provided. + /// Sets the current color of the LED /// - /// - /// - /// - /// - public void StartPulse(Color color, TimeSpan pulseDuration, float highBrightness = 1, float lowBrightness = 0.15F) + /// The LED color + /// Valid values are from 0 to 1, inclusive + public void SetColor(Color color, float brightness = 1) { - if (highBrightness > 1 || highBrightness <= 0) - { - throw new ArgumentOutOfRangeException(nameof(highBrightness), "onBrightness must be > 0 and <= 1"); - } - if (lowBrightness >= 1 || lowBrightness < 0) - { - throw new ArgumentOutOfRangeException(nameof(lowBrightness), "lowBrightness must be >= 0 and < 1"); - } - if (lowBrightness >= highBrightness) + if (color == Color && brightness == Brightness) { - throw new Exception("offBrightness must be less than onBrightness"); + return; } Color = color; + Brightness = brightness; - Stop(); - - animationTask = new Task(async () => - { - cancellationTokenSource = new CancellationTokenSource(); - await StartPulseAsync(color, pulseDuration, highBrightness, lowBrightness, cancellationTokenSource.Token); - }); - animationTask.Start(); - } - - /// - /// Start led pulsing - /// - /// color to pulse - /// pulse duration in ms - /// maximum brightness - /// minimum brightness - /// token to cancel pulse - protected async Task StartPulseAsync(Color color, TimeSpan pulseDuration, float highBrightness, float lowBrightness, CancellationToken cancellationToken) - { - float brightness = lowBrightness; - bool ascending = true; - TimeSpan intervalTime = TimeSpan.FromMilliseconds(60); // 60 miliseconds is probably the fastest update we want to do, given that threads are given 20 miliseconds by default. - float steps = (float)(pulseDuration.TotalMilliseconds / intervalTime.TotalMilliseconds); - float delta = (highBrightness - lowBrightness) / steps; - - while (true) - { - if (cancellationToken.IsCancellationRequested) - { - break; - } - - if (brightness <= lowBrightness) - { - ascending = true; - } - else if (brightness >= highBrightness) - { - ascending = false; - } - - brightness += delta * (ascending ? 1 : -1); - - if (brightness < 0) - { - brightness = 0; - } - else - if (brightness > 1) - { - brightness = 1; - } - - SetColor(color, brightness); - - await Task.Delay(intervalTime); - } + RedPwm.DutyCycle = (float)(Color.R / 255.0 * maxRedDutyCycle * brightness); + GreenPwm.DutyCycle = (float)(Color.G / 255.0 * maxGreenDutyCycle * brightness); + BluePwm.DutyCycle = (float)(Color.B / 255.0 * maxBlueDutyCycle * brightness); } } } \ No newline at end of file diff --git a/Source/Meadow.Foundation.Core/PollingSensorBase.cs b/Source/Meadow.Foundation.Core/PollingSensorBase.cs index 318e4331ef..9847dc131a 100644 --- a/Source/Meadow.Foundation.Core/PollingSensorBase.cs +++ b/Source/Meadow.Foundation.Core/PollingSensorBase.cs @@ -26,14 +26,14 @@ public abstract class PollingSensorBase /// The default is 5 seconds. public override void StartUpdating(TimeSpan? updateInterval = null) { - lock (samplingLock) + lock (samplingLock) { if (IsSampling) { return; } IsSampling = true; // if an update interval has been passed in, override the default - if(updateInterval is { } ui) { base.UpdateInterval = ui; } + if (updateInterval is { } ui) { base.UpdateInterval = ui; } base.SamplingTokenSource = new CancellationTokenSource(); CancellationToken ct = SamplingTokenSource.Token; @@ -41,11 +41,11 @@ public override void StartUpdating(TimeSpan? updateInterval = null) UNIT oldConditions; ChangeResult result; - Task.Run(async () => + var t = new Task(async () => { - while (true) + while (true) { - if (ct.IsCancellationRequested) + if (ct.IsCancellationRequested) { observers.ForEach(x => x.OnCompleted()); IsSampling = false; @@ -61,7 +61,8 @@ public override void StartUpdating(TimeSpan? updateInterval = null) await Task.Delay(UpdateInterval); } - }, SamplingTokenSource.Token); + }, SamplingTokenSource.Token, TaskCreationOptions.LongRunning); + t.Start(); } } @@ -70,7 +71,7 @@ public override void StartUpdating(TimeSpan? updateInterval = null) /// public override void StopUpdating() { - lock (samplingLock) + lock (samplingLock) { if (!IsSampling) { return; } diff --git a/Source/Meadow.Foundation.Core/SamplingSensorBase.cs b/Source/Meadow.Foundation.Core/SamplingSensorBase.cs index 747216a2c1..2d083e2f09 100644 --- a/Source/Meadow.Foundation.Core/SamplingSensorBase.cs +++ b/Source/Meadow.Foundation.Core/SamplingSensorBase.cs @@ -67,10 +67,9 @@ protected virtual void RaiseEventsAndNotify(IChangeResult changeResult) /// Convenience method to get the current sensor readings. For frequent reads, use /// StartSampling() and StopSampling() in conjunction with the SampleBuffer. /// - public virtual async Task Read() + public virtual Task Read() { - Conditions = await ReadSensor(); - return Conditions; + return ReadSensor(); } /// diff --git a/Source/Meadow.Foundation.Core/Sensors/Buttons/PushButton.cs b/Source/Meadow.Foundation.Core/Sensors/Buttons/PushButton.cs index 8495ba060f..9d4177cc0f 100644 --- a/Source/Meadow.Foundation.Core/Sensors/Buttons/PushButton.cs +++ b/Source/Meadow.Foundation.Core/Sensors/Buttons/PushButton.cs @@ -39,7 +39,7 @@ public TimeSpan DebounceDuration /// /// The button state polling interval for PushButton instances that are created - /// from a port that doesn't have an tnterrupt mode of EdgeBoth - otherwise ignored + /// from a port that doesn't have an interrupt mode of EdgeBoth - otherwise ignored /// public TimeSpan ButtonPollingInterval { get; set; } = TimeSpan.FromMilliseconds(100); @@ -141,7 +141,7 @@ public PushButton(IDigitalInputPort inputPort) bool currentState = DigitalIn.State; - _ = Task.Run(async () => + var t = new Task(async () => { while (!ctsPolling.Token.IsCancellationRequested) { @@ -152,7 +152,8 @@ public PushButton(IDigitalInputPort inputPort) await Task.Delay(ButtonPollingInterval); } - }); + }, ctsPolling.Token, TaskCreationOptions.LongRunning); + t.Start(); } } diff --git a/Source/Meadow.Foundation.Core/Sensors/Hid/DigitalJoystick.cs b/Source/Meadow.Foundation.Core/Sensors/Hid/DigitalJoystick.cs new file mode 100644 index 0000000000..b0e49a2250 --- /dev/null +++ b/Source/Meadow.Foundation.Core/Sensors/Hid/DigitalJoystick.cs @@ -0,0 +1,145 @@ +using Meadow.Foundation.Sensors.Buttons; +using Meadow.Hardware; +using Meadow.Peripherals.Sensors.Hid; +using System; + +namespace Meadow.Foundation.Sensors.Hid +{ + /// + /// Represents a 4 switch digital joystick / directional pad (D-pad) + /// + public class DigitalJoystick : IDigitalJoystick + { + /// + /// Get the current digital joystick position + /// + public DigitalJoystickPosition? Position { get; protected set; } = DigitalJoystickPosition.Center; + + /// + /// Raised when the digital joystick position changes + /// + public event EventHandler> Updated = delegate { }; + + /// + /// The PushButton class for the up digital joystick switch + /// + public PushButton ButtonUp { get; protected set; } + /// + /// The PushButton class for the down digital joystick switch + /// + public PushButton ButtonDown { get; protected set; } + /// + /// The PushButton class for the left digital joystick switch + /// + public PushButton ButtonLeft { get; protected set; } + /// + /// The PushButton class for the right digital joystick switch + /// + public PushButton ButtonRight { get; protected set; } + + /// + /// Create a new DigitalJoystick object + /// + /// The pin connected to the up switch + /// The pin connected to the down switch + /// The pin connected to the left switch + /// The pin connected to the right switch + /// The resistor mode for all pins + public DigitalJoystick(IPin pinUp, IPin pinDown, IPin pinLeft, IPin pinRight, ResistorMode resistorMode) + : this(pinUp.CreateDigitalInputPort(InterruptMode.EdgeBoth, resistorMode), + pinDown.CreateDigitalInputPort(InterruptMode.EdgeBoth, resistorMode), + pinLeft.CreateDigitalInputPort(InterruptMode.EdgeBoth, resistorMode), + pinRight.CreateDigitalInputPort(InterruptMode.EdgeBoth, resistorMode)) + { } + + /// + /// Create a new DigitalJoystick object + /// + /// The digital port for the up switch + /// The digital port for the down switch + /// The digital port for the left switch + /// The digital port for the right switch + public DigitalJoystick(IDigitalInputPort portUp, + IDigitalInputPort portDown, + IDigitalInputPort portLeft, + IDigitalInputPort portRight) + { + ButtonUp = new PushButton(portUp); + ButtonDown = new PushButton(portDown); + ButtonLeft = new PushButton(portLeft); + ButtonRight = new PushButton(portRight); + + ButtonUp.PressStarted += PressStarted; + ButtonDown.PressStarted += PressStarted; + ButtonLeft.PressStarted += PressStarted; + ButtonRight.PressStarted += PressStarted; + + ButtonUp.PressEnded += PressEnded; + ButtonDown.PressEnded += PressEnded; + ButtonLeft.PressEnded += PressEnded; + ButtonUp.PressEnded += PressEnded; + } + + private void PressEnded(object sender, EventArgs e) + => Update(); + + private void PressStarted(object sender, EventArgs e) + => Update(); + + void Update() + { + var isLeftPressed = ButtonLeft.State; + var isRightPressed = ButtonRight.State; + var isUpPressed = ButtonUp.State; + var isDownPressed = ButtonDown.State; + + var newPosition = GetDigitalPosition(isLeftPressed, isRightPressed, isUpPressed, isDownPressed); + + if (newPosition != Position) + { + Updated?.Invoke(this, new ChangeResult(newPosition, Position)); + Position = newPosition; + } + } + + DigitalJoystickPosition GetDigitalPosition(bool isLeftPressed, bool isRightPressed, bool isUpPressed, bool isDownPressed) + { + if (isRightPressed) + { //Right + if (isUpPressed) + { + return DigitalJoystickPosition.UpRight; + } + if (isDownPressed) + { + return DigitalJoystickPosition.DownRight; + } + return DigitalJoystickPosition.Right; + } + else if (isLeftPressed) + { //Left + if (isUpPressed) + { + return DigitalJoystickPosition.UpLeft; + } + if (isDownPressed) + { + return DigitalJoystickPosition.DownLeft; + } + return DigitalJoystickPosition.Left; + } + else if (isUpPressed) + { //Up + return DigitalJoystickPosition.Up; + } + else if (isDownPressed) + { //Down + return DigitalJoystickPosition.Down; + } + else + { //Center + return DigitalJoystickPosition.Center; + } + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Core/Sensors/Rotary/RotaryEncoder.cs b/Source/Meadow.Foundation.Core/Sensors/Rotary/RotaryEncoder.cs index 3382e35a90..160e0fa15b 100644 --- a/Source/Meadow.Foundation.Core/Sensors/Rotary/RotaryEncoder.cs +++ b/Source/Meadow.Foundation.Core/Sensors/Rotary/RotaryEncoder.cs @@ -58,13 +58,14 @@ public class RotaryEncoder : IRotaryEncoder 0, 1, -1, 0 }; /// - /// Instantiate a new RotaryEncoder on the specified pins. + /// Instantiate a new RotaryEncoder on the specified pins /// - /// - /// - public RotaryEncoder(IPin aPhasePin, IPin bPhasePin) : - this(aPhasePin.CreateDigitalInputPort(InterruptMode.EdgeBoth, ResistorMode.InternalPullDown, TimeSpan.Zero, TimeSpan.FromMilliseconds(0.1)), - bPhasePin.CreateDigitalInputPort(InterruptMode.EdgeBoth, ResistorMode.InternalPullDown, TimeSpan.Zero, TimeSpan.FromMilliseconds(0.1))) + /// Pin A + /// Pin B + /// Do the encode pins use a common ground (true) or common positive (false) + public RotaryEncoder(IPin aPhasePin, IPin bPhasePin, bool isCommonGround = false) : + this(aPhasePin.CreateDigitalInputPort(InterruptMode.EdgeBoth, isCommonGround ? ResistorMode.InternalPullUp : ResistorMode.InternalPullDown, TimeSpan.Zero, TimeSpan.FromMilliseconds(0.1)), + bPhasePin.CreateDigitalInputPort(InterruptMode.EdgeBoth, isCommonGround ? ResistorMode.InternalPullUp : ResistorMode.InternalPullDown, TimeSpan.Zero, TimeSpan.FromMilliseconds(0.1))) { } /// diff --git a/Source/Meadow.Foundation.Core/Sensors/Temperature/AnalogTemperature.cs b/Source/Meadow.Foundation.Core/Sensors/Temperature/AnalogTemperature.cs index 78b64af733..1a257b27bb 100644 --- a/Source/Meadow.Foundation.Core/Sensors/Temperature/AnalogTemperature.cs +++ b/Source/Meadow.Foundation.Core/Sensors/Temperature/AnalogTemperature.cs @@ -203,7 +203,7 @@ public AnalogTemperature(IAnalogInputPort analogInputPort, /// Convenience method to get the current temperature. For frequent reads, use /// StartSampling() and StopSampling() in conjunction with the SampleBuffer. /// - /// A float value that's ann average value of all the samples taken. + /// The temperature averages of the given sample count protected override async Task ReadSensor() { var voltage = await AnalogInputPort.Read(); @@ -260,7 +260,7 @@ protected override void RaiseEventsAndNotify(IChangeResult ch /// Converts voltage to Temperature /// /// - /// temperature at a Temperature struct + /// Temperature protected Units.Temperature VoltageToTemperature(Voltage voltage) { return new Units.Temperature(SensorCalibration.SampleReading + diff --git a/Source/Meadow.Foundation.Core/Speakers/PiezoSpeaker.cs b/Source/Meadow.Foundation.Core/Speakers/PiezoSpeaker.cs index 62ce37ea3f..68447f2146 100644 --- a/Source/Meadow.Foundation.Core/Speakers/PiezoSpeaker.cs +++ b/Source/Meadow.Foundation.Core/Speakers/PiezoSpeaker.cs @@ -11,6 +11,12 @@ namespace Meadow.Foundation.Audio /// public class PiezoSpeaker : IToneGenerator { + /// + /// The volume from 0-1 + /// Defined by the PWM port duty cycle from 0 to 0.5 + /// + public float Volume { get; protected set; } = 1.0f; + /// /// Gets the port that is driving the Piezo Speaker /// @@ -72,7 +78,7 @@ public async Task PlayTone(Frequency frequency, TimeSpan duration) isPlaying = true; Port.Frequency = frequency; - Port.DutyCycle = 0.5f; + Port.DutyCycle = Volume / 2f; if (duration.TotalMilliseconds > 0) { @@ -91,5 +97,19 @@ public void StopTone() { Port.DutyCycle = 0f; } + + /// + /// Set the playback volume + /// + /// The volume from 0 (off) to 1 (max volume) + public void SetVolume(float volume) + { + Volume = Math.Clamp(volume, 0, 1); + + if(isPlaying) + { + Port.DutyCycle = Volume / 2f; + } + } } } \ No newline at end of file diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Audio.MicroAudio/Driver/Audio.MicroAudio.csproj b/Source/Meadow.Foundation.Libraries_and_Frameworks/Audio.MicroAudio/Driver/Audio.MicroAudio.csproj new file mode 100644 index 0000000000..148d246885 --- /dev/null +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Audio.MicroAudio/Driver/Audio.MicroAudio.csproj @@ -0,0 +1,22 @@ + + + true + Wilderness Labs, Inc + netstandard2.1 + Library + MicroAudio + Wilderness Labs, Inc + http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ + Meadow.Foundation.Audio.MicroAudio + icon.png + https://github.com/WildernessLabs/Meadow.Foundation + Meadow,Meadow.Foundation,Audio,Songs,Tone,Tones,Music,Sound,Effects + 0.1.0 + true + Lightweight single-voice sound effect and music player designed for embedded applications + + + + + + diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Audio.MicroAudio/Driver/GameSounds.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Audio.MicroAudio/Driver/GameSounds.cs new file mode 100644 index 0000000000..4d1ed96946 --- /dev/null +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Audio.MicroAudio/Driver/GameSounds.cs @@ -0,0 +1,325 @@ +using Meadow.Peripherals.Speakers; +using Meadow.Units; +using System; +using System.Threading.Tasks; + +namespace Meadow.Foundation.Audio +{ + /// + /// A class for playing game sounds using an IToneGenerator + /// + public class GameSounds + { + private readonly IToneGenerator toneGenerator; + private readonly int defaultDuration = 100; + private readonly int defaultPause = 50; + + /// + /// Initializes a new instance of the class + /// + /// The object to use for audio playback + public GameSounds(IToneGenerator toneGenerator) + { + this.toneGenerator = toneGenerator; + } + + /// + /// Plays the specified sound effect + /// + /// The sound effect to play + public Task PlayEffect(GameSoundEffect effect) + { + return effect switch + { + GameSoundEffect.Activation => PlayActivation(), + GameSoundEffect.Blip => PlayBlip(), + GameSoundEffect.BossBattle => PlayBossBattle(), + GameSoundEffect.ButtonPress => PlayButtonPress(), + GameSoundEffect.Coin => PlayCoin(), + GameSoundEffect.Collectible => PlayCollectible(), + GameSoundEffect.Countdown => PlayCountdown(), + GameSoundEffect.EnemyDeath => PlayEnemyDeath(), + GameSoundEffect.Explosion => PlayExplosion(), + GameSoundEffect.Footstep => PlayFootstep(), + GameSoundEffect.GameOver => PlayGameOver(), + GameSoundEffect.Health => PlayHealth(), + GameSoundEffect.Hit => PlayHit(), + GameSoundEffect.Jump => PlayJump(), + GameSoundEffect.Laser => PlayLaser(), + GameSoundEffect.LevelComplete => PlayLevelComplete(), + GameSoundEffect.MenuNavigate => PlayMenuNavigate(), + GameSoundEffect.PowerDown => PlayPowerDown(), + GameSoundEffect.PowerUp => PlayPowerUp(), + GameSoundEffect.SecretFound => PlaySecretFound(), + GameSoundEffect.Teleport => PlayTeleport(), + GameSoundEffect.Victory => PlayVictory(), + GameSoundEffect.Warning => PlayWarning(), + GameSoundEffect.WeaponSwitch => PlayWeaponSwitch(), + _ => throw new ArgumentException("Invalid game sound effect specified.", nameof(effect)), + }; + } + + + /// + /// Plays a simple blip sound effect + /// + private async Task PlayBlip() + { + await toneGenerator.PlayTone(new Frequency(440), TimeSpan.FromMilliseconds(defaultDuration)); + } + + /// + /// Plays a power-up or item pick-up sound effect + /// + private async Task PlayPowerUp() + { + await toneGenerator.PlayTone(new Frequency(880), TimeSpan.FromMilliseconds(defaultDuration)); + await Task.Delay(TimeSpan.FromMilliseconds(defaultPause)); + await toneGenerator.PlayTone(new Frequency(1760), TimeSpan.FromMilliseconds(defaultDuration)); + } + + /// + /// Plays a coin or currency collection sound effect + /// + private async Task PlayCoin() + { + await toneGenerator.PlayTone(new Frequency(1047), TimeSpan.FromMilliseconds(defaultDuration)); + } + + /// + /// Plays a jump or hop sound effect + /// + private async Task PlayJump() + { + await toneGenerator.PlayTone(new Frequency(440), TimeSpan.FromMilliseconds(defaultDuration)); + await Task.Delay(TimeSpan.FromMilliseconds(defaultPause)); + await toneGenerator.PlayTone(new Frequency(880), TimeSpan.FromMilliseconds(defaultDuration)); + } + + /// + /// Plays a hit or damage sound effect + /// + private async Task PlayHit() + { + await toneGenerator.PlayTone(new Frequency(440), TimeSpan.FromMilliseconds(defaultDuration >> 1)); + await toneGenerator.PlayTone(new Frequency(220), TimeSpan.FromMilliseconds(defaultDuration >> 1)); + } + + /// + /// Plays a laser or projectile firing sound effect + /// + private async Task PlayLaser() + { + await toneGenerator.PlayTone(new Frequency(440), TimeSpan.FromMilliseconds(defaultDuration >> 1)); + await toneGenerator.PlayTone(new Frequency(1760), TimeSpan.FromMilliseconds(defaultDuration >> 1)); + } + + /// + /// Plays an explosion or destruction sound effect + /// + private async Task PlayExplosion() + { + await toneGenerator.PlayTone(new Frequency(440), TimeSpan.FromMilliseconds(defaultDuration >> 1)); + await toneGenerator.PlayTone(new Frequency(220), TimeSpan.FromMilliseconds(defaultDuration >> 1)); + await toneGenerator.PlayTone(new Frequency(110), TimeSpan.FromMilliseconds(defaultDuration >> 1)); + await toneGenerator.PlayTone(new Frequency(55), TimeSpan.FromMilliseconds(defaultDuration >> 1)); + } + + /// + /// Plays a game over or failure sound effect + /// + private async Task PlayGameOver() + { + await toneGenerator.PlayTone(new Frequency(440), TimeSpan.FromMilliseconds(defaultDuration)); + await Task.Delay(TimeSpan.FromMilliseconds(defaultPause)); + await toneGenerator.PlayTone(new Frequency(220), TimeSpan.FromMilliseconds(defaultDuration)); + await Task.Delay(TimeSpan.FromMilliseconds(defaultPause)); + await toneGenerator.PlayTone(new Frequency(110), TimeSpan.FromMilliseconds(defaultDuration)); + await Task.Delay(TimeSpan.FromMilliseconds(defaultPause)); + await toneGenerator.PlayTone(new Frequency(55), TimeSpan.FromMilliseconds(defaultDuration)); + } + + /// + /// Plays a victory or success sound effect + /// + private async Task PlayVictory() + { + await toneGenerator.PlayTone(new Frequency(440), TimeSpan.FromMilliseconds(defaultDuration >> 2)); + await toneGenerator.PlayTone(new Frequency(659), TimeSpan.FromMilliseconds(defaultDuration >> 2)); + await toneGenerator.PlayTone(new Frequency(880), TimeSpan.FromMilliseconds(defaultDuration >> 2)); + await toneGenerator.PlayTone(new Frequency(1175), TimeSpan.FromMilliseconds(defaultDuration >> 2)); + } + + /// + /// Plays a countdown or timer sound effect + /// + private async Task PlayCountdown() + { + await toneGenerator.PlayTone(new Frequency(880), TimeSpan.FromMilliseconds(defaultDuration >> 1)); + await Task.Delay(TimeSpan.FromMilliseconds(defaultPause)); + await toneGenerator.PlayTone(new Frequency(783.99), TimeSpan.FromMilliseconds(defaultDuration >> 1)); + await Task.Delay(TimeSpan.FromMilliseconds(defaultPause)); + await toneGenerator.PlayTone(new Frequency(698.46), TimeSpan.FromMilliseconds(defaultDuration >> 1)); + await Task.Delay(TimeSpan.FromMilliseconds(defaultPause)); + await toneGenerator.PlayTone(new Frequency(587.33), TimeSpan.FromMilliseconds(defaultDuration >> 1)); + await Task.Delay(TimeSpan.FromMilliseconds(defaultPause)); + await toneGenerator.PlayTone(new Frequency(523.25), TimeSpan.FromMilliseconds(defaultDuration >> 1)); + } + + /// + /// Plays a power-down sound effect + /// + private async Task PlayPowerDown() + { + await toneGenerator.PlayTone(new Frequency(523.25), TimeSpan.FromMilliseconds(defaultDuration >> 1)); + await toneGenerator.PlayTone(new Frequency(440), TimeSpan.FromMilliseconds(defaultDuration >> 1)); + await toneGenerator.PlayTone(new Frequency(349.23), TimeSpan.FromMilliseconds(defaultDuration >> 1)); + } + + /// + /// Plays a button press sound effect + /// + private async Task PlayButtonPress() + { + await toneGenerator.PlayTone(new Frequency(440), TimeSpan.FromMilliseconds(defaultDuration)); + } + + /// + /// Plays a menu navigation sound effect + /// + private async Task PlayMenuNavigate() + { + await toneGenerator.PlayTone(new Frequency(440), TimeSpan.FromMilliseconds(defaultDuration >> 2)); + await toneGenerator.PlayTone(new Frequency(880), TimeSpan.FromMilliseconds(defaultDuration >> 2)); + } + + /// + /// Plays a collectible item sound effect + /// + private async Task PlayCollectible() + { + await toneGenerator.PlayTone(new Frequency(1047), TimeSpan.FromMilliseconds(defaultDuration)); + } + + /// + /// Plays a boss battle theme. + /// + private async Task PlayBossBattle() + { + await toneGenerator.PlayTone(new Frequency(440), TimeSpan.FromMilliseconds(defaultDuration >> 2)); + await toneGenerator.PlayTone(new Frequency(554.37), TimeSpan.FromMilliseconds(defaultDuration >> 2)); + await toneGenerator.PlayTone(new Frequency(659.25), TimeSpan.FromMilliseconds(defaultDuration >> 2)); + await toneGenerator.PlayTone(new Frequency(783.99), TimeSpan.FromMilliseconds(defaultDuration >> 2)); + } + + /// + /// Plays a secret found sound effect + /// + private async Task PlaySecretFound() + { + await toneGenerator.PlayTone(new Frequency(880), TimeSpan.FromMilliseconds(defaultDuration >> 1)); + await toneGenerator.PlayTone(new Frequency(1174.66), TimeSpan.FromMilliseconds(defaultDuration >> 1)); + await toneGenerator.PlayTone(new Frequency(1396.91), TimeSpan.FromMilliseconds(defaultDuration >> 1)); + } + + /// + /// Plays a level complete sound effect + /// + private async Task PlayLevelComplete() + { + await toneGenerator.PlayTone(new Frequency(1047), TimeSpan.FromMilliseconds(defaultDuration >> 2)); + await toneGenerator.PlayTone(new Frequency(1396.91), TimeSpan.FromMilliseconds(defaultDuration >> 2)); + await toneGenerator.PlayTone(new Frequency(1760), TimeSpan.FromMilliseconds(defaultDuration >> 2)); + await toneGenerator.PlayTone(new Frequency(2217.46), TimeSpan.FromMilliseconds(defaultDuration >> 2)); + } + + /// + /// Plays a weapon switch sound effect + /// + private async Task PlayWeaponSwitch() + { + await toneGenerator.PlayTone(new Frequency(523.25), TimeSpan.FromMilliseconds(defaultDuration >> 2)); + await Task.Delay(TimeSpan.FromMilliseconds(defaultPause)); + await toneGenerator.PlayTone(new Frequency(440), TimeSpan.FromMilliseconds(defaultDuration >> 2)); + await Task.Delay(TimeSpan.FromMilliseconds(defaultPause)); + await toneGenerator.PlayTone(new Frequency(349.23), TimeSpan.FromMilliseconds(defaultDuration >> 2)); + } + + /// + /// Plays a warning or alarm sound effect + /// + private async Task PlayWarning() + { + await toneGenerator.PlayTone(new Frequency(1047), TimeSpan.FromMilliseconds(defaultDuration >> 1)); + await toneGenerator.PlayTone(new Frequency(880), TimeSpan.FromMilliseconds(defaultDuration >> 1)); + await toneGenerator.PlayTone(new Frequency(783.99), TimeSpan.FromMilliseconds(defaultDuration >> 1)); + } + + /// + /// Plays a teleport or warp sound effect + /// + private async Task PlayTeleport() + { + await toneGenerator.PlayTone(new Frequency(880), TimeSpan.FromMilliseconds(defaultDuration >> 1)); + await toneGenerator.PlayTone(new Frequency(783.99), TimeSpan.FromMilliseconds(defaultDuration >> 1)); + await toneGenerator.PlayTone(new Frequency(659.25), TimeSpan.FromMilliseconds(defaultDuration >> 1)); + await toneGenerator.PlayTone(new Frequency(523.25), TimeSpan.FromMilliseconds(defaultDuration >> 1)); + } + + /// + /// Plays a health pickup or healing sound effect + /// + private async Task PlayHealth() + { + await toneGenerator.PlayTone(new Frequency(622.25), TimeSpan.FromMilliseconds(defaultDuration >> 2)); + await toneGenerator.PlayTone(new Frequency(659.25), TimeSpan.FromMilliseconds(defaultDuration >> 2)); + await toneGenerator.PlayTone(new Frequency(698.46), TimeSpan.FromMilliseconds(defaultDuration >> 2)); + await toneGenerator.PlayTone(new Frequency(783.99), TimeSpan.FromMilliseconds(defaultDuration >> 2)); + } + + /// + /// Plays a footstep or movement sound effect + /// + private async Task PlayFootstep() + { + await toneGenerator.PlayTone(new Frequency(196), TimeSpan.FromMilliseconds(defaultDuration >> 3)); + } + + /// + /// Plays an item activation or use sound effect + /// + private async Task PlayActivation() + { + await toneGenerator.PlayTone(new Frequency(440), TimeSpan.FromMilliseconds(defaultDuration >> 2)); + await toneGenerator.PlayTone(new Frequency(880), TimeSpan.FromMilliseconds(defaultDuration >> 2)); + await toneGenerator.PlayTone(new Frequency(440), TimeSpan.FromMilliseconds(defaultDuration >> 2)); + } + + /// + /// Plays an enemy death or defeat sound effect + /// + private async Task PlayEnemyDeath() + { + await toneGenerator.PlayTone(new Frequency(1568), TimeSpan.FromMilliseconds(defaultDuration >> 1)); + await toneGenerator.PlayTone(new Frequency(1244.51), TimeSpan.FromMilliseconds(defaultDuration >> 1)); + await toneGenerator.PlayTone(new Frequency(1046.5), TimeSpan.FromMilliseconds(defaultDuration >> 1)); + await toneGenerator.PlayTone(new Frequency(783.99), TimeSpan.FromMilliseconds(defaultDuration >> 1)); + } + + /// + /// Plays a splash sound effect + /// + public async Task PlaySplash() + { + await toneGenerator.PlayTone(new Frequency(220), TimeSpan.FromMilliseconds(defaultDuration >> 2)); + await Task.Delay(TimeSpan.FromMilliseconds(defaultPause)); + await toneGenerator.PlayTone(new Frequency(440), TimeSpan.FromMilliseconds(defaultDuration >> 2)); + await Task.Delay(TimeSpan.FromMilliseconds(defaultPause)); + await toneGenerator.PlayTone(new Frequency(880), TimeSpan.FromMilliseconds(defaultDuration >> 2)); + await Task.Delay(TimeSpan.FromMilliseconds(defaultPause)); + await toneGenerator.PlayTone(new Frequency(440), TimeSpan.FromMilliseconds(defaultDuration >> 2)); + await Task.Delay(TimeSpan.FromMilliseconds(defaultPause)); + await toneGenerator.PlayTone(new Frequency(220), TimeSpan.FromMilliseconds(defaultDuration >> 2)); + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Audio.MicroAudio/Driver/MicroAudio.Enums.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Audio.MicroAudio/Driver/MicroAudio.Enums.cs new file mode 100644 index 0000000000..822cc76334 --- /dev/null +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Audio.MicroAudio/Driver/MicroAudio.Enums.cs @@ -0,0 +1,294 @@ +namespace Meadow.Foundation.Audio +{ + /// + /// Represents a musical note + /// + public enum Pitch : int + { + /// + /// The C note + /// + C = 0, + /// + /// The C sharp note + /// + CSharp = 1, + /// + /// The enharmonic equivalent of C sharp + /// + DFlat = 1, + /// + /// The D note + /// + D = 2, + /// + /// The D sharp note + /// + DSharp = 3, + /// + /// The enharmonic equivalent of D sharp + /// + EFlat = 3, + /// + /// The E note + /// + E = 4, + /// + /// The F note + /// + F = 5, + /// + /// The F sharp note + /// + FSharp = 6, + /// + /// The enharmonic equivalent of F sharp + /// + GFlat = 6, + /// + /// The G note + /// + G = 7, + /// + /// The G sharp note + /// + GSharp = 8, + /// + /// The enharmonic equivalent of G sharp + /// + AFlat = 8, + /// + /// The A note + /// + A = 9, + /// + /// The A sharp note + /// + ASharp = 10, + /// + /// The enharmonic equivalent of A sharp + /// + BFlat = 10, + /// + /// The B note + /// + B = 11, + /// + /// Represents a rest note + /// + Rest + } + + /// + /// Represents the duration of a musical note + /// + public enum NoteDuration + { + /// + /// A whole note + /// + Whole = 4000, + /// + /// A half note + /// + Half = 2000, + /// + /// A quarter note + /// + Quarter = 1000, + /// + /// An eighth note + /// + Eighth = 500, + /// + /// A sixteenth note + /// + Sixteenth = 250, + /// + /// A thirty-second note + /// + ThirtySecond = 125, + /// + /// A whole note triplet + /// + WholeTriplet = 6000, + /// + /// A dotted half note + /// + DottedHalf = 3000 + } + + /// + /// Represents the different sound effects that can be played by the class + /// + public enum SystemSoundEffect + { + /// + /// An alarm or emergency sound effect + /// + Alarm, + /// + /// An alert or notification sound effect + /// + Alert, + /// + /// A simple beep sound effect + /// + Beep, + /// + /// A buzzing or vibrating sound effect + /// + Buzz, + /// + /// A chime or bell sound effect + /// + Chime, + /// + /// A short click sound effect + /// + Click, + /// + /// A failure or error sound effect + /// + Failure, + /// + /// A fanfare or celebratory sound effect + /// + Fanfare, + /// + /// A notification sound effect + /// + Notification, + /// + /// A popping sound effect + /// + Pop, + /// + /// A power-up sound effect + /// + PowerUp, + /// + /// A power-down sound effect + /// + PowerDown, + /// + /// A success or positive feedback sound effect + /// + Success, + /// + /// A short tick or click sound effect + /// + Tick, + /// + /// A warning or caution sound effect + /// + Warning, + } + + /// + /// Represents the different sound effects that can be played by the class + /// + public enum GameSoundEffect + { + /// + /// A sound effect indicating the activation or use of an item or power-up + /// + Activation, + /// + /// A simple blip sound effect + /// + Blip, + /// + /// A sound effect indicating a boss battle or end challenge + /// + BossBattle, + /// + /// A button press or selection sound effect + /// + ButtonPress, + /// + /// A coin or currency collection sound effect + /// + Coin, + /// + /// A sound effect indicating the collection of an item or bonus + /// + Collectible, + /// + /// A countdown or timer sound effect + /// + Countdown, + /// + /// A sound effect indicating the death or defeat of an enemy + /// + EnemyDeath, + /// + /// An explosion or destruction sound effect + /// + Explosion, + /// + /// A sound effect indicating a footstep or movement + /// + Footstep, + /// + /// A game over or failure sound effect + /// + GameOver, + /// + /// A sound effect indicating a health pickup or healing + /// + Health, + /// + /// A hit or damage sound effect + /// + Hit, + /// + /// A jump or hop sound effect + /// + Jump, + /// + /// A laser or projectile firing sound effect + /// + Laser, + /// + /// A sound effect indicating the completion of a level or challenge + /// + LevelComplete, + /// + /// A menu navigation or selection sound effect + /// + MenuNavigate, + /// + /// A power-up or item pick-up sound effect + /// + PowerUp, + /// + /// A power-down or failure sound effect + /// + PowerDown, + /// + /// A sound effect indicating the discovery of a secret or hidden item + /// + SecretFound, + /// + /// A sound effect indicating a spash in water + /// + Splash, + /// + /// A sound effect indicating a teleport or warp + /// + Teleport, + /// + /// A victory or success sound effect + /// + Victory, + /// + /// A warning or alarm sound effect + /// + Warning, + /// + /// A sound effect indicating a weapon or tool switch + /// + WeaponSwitch, + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Audio.MicroAudio/Driver/MicroAudio.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Audio.MicroAudio/Driver/MicroAudio.cs new file mode 100644 index 0000000000..8cf83490b5 --- /dev/null +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Audio.MicroAudio/Driver/MicroAudio.cs @@ -0,0 +1,74 @@ +using Meadow.Peripherals.Speakers; +using System; +using System.Threading.Tasks; + +namespace Meadow.Foundation.Audio +{ + /// + /// Provide high level audio functions + /// + public partial class MicroAudio + { + readonly IToneGenerator speaker; + + SystemSounds systemSounds; + GameSounds gameSounds; + + /// + /// Create a new MicroAudio instance from a IToneGenerator driver instance + /// + /// An IToneGenerator object + public MicroAudio(IToneGenerator speaker) + { + this.speaker = speaker; + } + + /// + /// Set the playback volume + /// + /// The volume from 0-1 + public void SetVolume(float volume) + { + speaker?.SetVolume(volume); + } + + /// + /// Plays the specified system sound effect + /// + /// The sound effect to play + /// The number of times to play the sound effect + public async Task PlaySystemSound(SystemSoundEffect effect, int numberOfLoops = 1) + { + systemSounds ??= new SystemSounds(speaker); + + for(int i = 0; i < numberOfLoops; i++) + { + await systemSounds.PlayEffect(effect); + } + } + + /// + /// Plays the specified game sound effect + /// + /// The sound effect to play + /// /// The number of times to play the sound effect + public async Task PlayGameSound(GameSoundEffect effect, int numberOfLoops = 1) + { + gameSounds ??= new GameSounds(speaker); + + for (int i = 0; i < numberOfLoops; i++) + { + await gameSounds.PlayEffect(effect); + } + } + + /// + /// Play the specified song + /// + /// The song object + public Task PlaySong(Song song) + { + return song.Play(speaker); + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Audio.MicroAudio/Driver/Note.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Audio.MicroAudio/Driver/Note.cs new file mode 100644 index 0000000000..93b3ca8436 --- /dev/null +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Audio.MicroAudio/Driver/Note.cs @@ -0,0 +1,34 @@ +namespace Meadow.Foundation.Audio +{ + /// + /// Represents a musical note, with a specific pitch, octave, and duration + /// + public class Note + { + /// + /// The pitch of the note + /// + public Pitch Pitch { get; } + /// + /// The octave of the note + /// + public int Octave { get; } + /// + /// The duration of the note + /// + public NoteDuration Duration { get; } + + /// + /// Creates a new instance of the Note class, with the specified pitch, octave, and duration + /// + /// The pitch of the note + /// The octave of the note + /// The duration of the note + public Note(Pitch pitch, int octave, NoteDuration duration) + { + Pitch = pitch; + Octave = octave; + Duration = duration; + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Audio.MicroAudio/Driver/NotesToFrequency.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Audio.MicroAudio/Driver/NotesToFrequency.cs new file mode 100644 index 0000000000..24a2a7040e --- /dev/null +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Audio.MicroAudio/Driver/NotesToFrequency.cs @@ -0,0 +1,35 @@ +using Meadow.Units; +using System; + +namespace Meadow.Foundation.Audio +{ + /// + /// A utility class for converting musical notes to their corresponding frequencies in hertz + /// + public class NotesToFrequency + { + /// + /// The frequency of the A4 note, in hertz + /// + public static Frequency A4Frequency { get; set; } = new Frequency(440.0, Frequency.UnitType.Hertz); + + private static double SemitoneRatio { get; } = 1.059463094359; + + /// + /// Converts the specified musical note to its frequency in hertz + /// + /// The musical note to convert + /// The frequency of the note in hertz + public static Frequency ConvertToFrequency(Note note) + { + int semitonesFromA4 = CalculateSemitonesFromA4(note.Pitch, note.Octave); + return A4Frequency * Math.Pow(SemitoneRatio, semitonesFromA4); + } + + private static int CalculateSemitonesFromA4(Pitch pitch, int octave) + { + int semitonesFromC0 = (int)pitch + (octave - 1) * 12; + return semitonesFromC0 - 9; + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Audio.MicroAudio/Driver/Song.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Audio.MicroAudio/Driver/Song.cs new file mode 100644 index 0000000000..d1e5abdcb1 --- /dev/null +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Audio.MicroAudio/Driver/Song.cs @@ -0,0 +1,58 @@ +using Meadow.Peripherals.Speakers; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Meadow.Foundation.Audio +{ + /// + /// A class for playing a sequence of musical notes + /// + public class Song + { + /// + /// The collection of notes in order for the song + /// + public readonly List Notes = new List(); + + /// + /// Creates a new instance of the Song class + /// + public Song() + { + } + + /// + /// Adds a musical note to the sequence of notes to be played + /// + /// The musical note to add + public void AddNote(Note note) + { + Notes.Add(note); + } + + /// + /// Plays the sequence of musical notes, with the specified tempo + /// + /// The IToneGenerator object to play the song + /// The tempo of the music, in beats per minute + /// A Task representing the asynchronous playback operation + public async Task Play(IToneGenerator speaker, int tempo = 120) + { + foreach (var note in Notes) + { + int duration = (int)(60.0 / tempo * (int)note.Duration); + + if (note.Pitch == Pitch.Rest) + { + await Task.Delay(TimeSpan.FromMilliseconds(duration)); + } + else + { + var frequency = NotesToFrequency.ConvertToFrequency(note); + await speaker.PlayTone(frequency, TimeSpan.FromMilliseconds(duration)); + } + } + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Audio.MicroAudio/Driver/SystemSounds.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Audio.MicroAudio/Driver/SystemSounds.cs new file mode 100644 index 0000000000..cc4736b9a9 --- /dev/null +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Audio.MicroAudio/Driver/SystemSounds.cs @@ -0,0 +1,198 @@ +using Meadow.Peripherals.Speakers; +using Meadow.Units; +using System; +using System.Threading.Tasks; + +namespace Meadow.Foundation.Audio +{ + /// + /// A class for playing system sounds using an IToneGenerator + /// + public class SystemSounds + { + private readonly int defaultDuration; + private readonly int defaultPause; + private readonly IToneGenerator toneGenerator; + + /// + /// Creates a new instance of the SystemSounds class, using the specified IToneGenerator for audio output + /// + /// The IToneGenerator to use for audio output + /// The default duration of system sounds, in milliseconds (optional; defaults to 100) + /// The default pause between system sounds, in milliseconds (optional; defaults to 50) + + public SystemSounds(IToneGenerator toneGenerator, int defaultDuration = 100, int defaultPause = 50) + { + this.toneGenerator = toneGenerator; + this.defaultDuration = defaultDuration; + this.defaultPause = defaultPause; + } + + /// + /// Plays the specified sound effect + /// + /// The sound effect to play + public Task PlayEffect(SystemSoundEffect effect) + { + return effect switch + { + SystemSoundEffect.Alert => PlayAlert(), + SystemSoundEffect.Alarm => PlayAlarm(), + SystemSoundEffect.Beep => PlayBeep(), + SystemSoundEffect.Buzz => PlayBuzz(), + SystemSoundEffect.Chime => PlayChime(), + SystemSoundEffect.Click => PlayClick(), + SystemSoundEffect.Failure => PlayFailure(), + SystemSoundEffect.Fanfare => PlayFanfare(), + SystemSoundEffect.Notification => PlayNotification(), + SystemSoundEffect.Pop => PlayPop(), + SystemSoundEffect.PowerDown => PlayPowerDown(), + SystemSoundEffect.PowerUp => PlayPowerUp(), + SystemSoundEffect.Success => PlaySuccess(), + SystemSoundEffect.Tick => PlayTick(), + SystemSoundEffect.Warning => PlayWarning(), + _ => throw new ArgumentException($"Unknown effect: {effect}"), + }; + } + + + private async Task PlayBeep() + { + await toneGenerator.PlayTone(new Frequency(1000), TimeSpan.FromMilliseconds(defaultDuration)); + } + + private async Task PlaySuccess() + { + await toneGenerator.PlayTone(new Frequency(1000), TimeSpan.FromMilliseconds(defaultDuration)); + await Task.Delay(TimeSpan.FromMilliseconds(defaultPause)); + await toneGenerator.PlayTone(new Frequency(1500), TimeSpan.FromMilliseconds(defaultDuration)); + } + + private async Task PlayFailure() + { + await toneGenerator.PlayTone(new Frequency(1500), TimeSpan.FromMilliseconds(defaultDuration)); + await Task.Delay(TimeSpan.FromMilliseconds(defaultPause)); + await toneGenerator.PlayTone(new Frequency(1000), TimeSpan.FromMilliseconds(defaultDuration)); + } + + private async Task PlayWarning() + { + await toneGenerator.PlayTone(new Frequency(500), TimeSpan.FromMilliseconds(defaultDuration)); + await Task.Delay(TimeSpan.FromMilliseconds(defaultPause)); + await toneGenerator.PlayTone(new Frequency(500), TimeSpan.FromMilliseconds(defaultDuration)); + await Task.Delay(TimeSpan.FromMilliseconds(defaultPause)); + await toneGenerator.PlayTone(new Frequency(500), TimeSpan.FromMilliseconds(defaultDuration)); + } + + private async Task PlayAlarm() + { + for (int i = 0; i < 5; i++) + { + await toneGenerator.PlayTone(new Frequency(1000), TimeSpan.FromMilliseconds(defaultDuration)); + await Task.Delay(TimeSpan.FromMilliseconds(defaultPause)); + } + } + + private async Task PlayTick() + { + await toneGenerator.PlayTone(new Frequency(1000), TimeSpan.FromMilliseconds(defaultDuration / 4)); + } + + private async Task PlayChime() + { + await toneGenerator.PlayTone(new Frequency(262), TimeSpan.FromMilliseconds(defaultDuration / 4)); + await Task.Delay(TimeSpan.FromMilliseconds(defaultPause)); + await toneGenerator.PlayTone(new Frequency(330), TimeSpan.FromMilliseconds(defaultDuration / 4)); + await Task.Delay(TimeSpan.FromMilliseconds(defaultPause)); + await toneGenerator.PlayTone(new Frequency(392), TimeSpan.FromMilliseconds(defaultDuration / 4)); + await Task.Delay(TimeSpan.FromMilliseconds(defaultPause)); + await toneGenerator.PlayTone(new Frequency(523), TimeSpan.FromMilliseconds(defaultDuration / 4)); + } + + /// + /// Plays a buzzing or vibrating sound effect + /// + private async Task PlayBuzz() + { + await toneGenerator.PlayTone(new Frequency(500), TimeSpan.FromMilliseconds(defaultDuration / 2)); + await Task.Delay(TimeSpan.FromMilliseconds(defaultPause)); + await toneGenerator.PlayTone(new Frequency(500), TimeSpan.FromMilliseconds(defaultDuration / 2)); + } + + /// + /// Plays a fanfare or celebratory sound effect + /// + private async Task PlayFanfare() + { + await toneGenerator.PlayTone(new Frequency(784), TimeSpan.FromMilliseconds(defaultDuration / 2)); + await toneGenerator.PlayTone(new Frequency(659), TimeSpan.FromMilliseconds(defaultDuration / 2)); + await toneGenerator.PlayTone(new Frequency(523), TimeSpan.FromMilliseconds(defaultDuration / 2)); + await Task.Delay(TimeSpan.FromMilliseconds(defaultPause)); + await toneGenerator.PlayTone(new Frequency(784), TimeSpan.FromMilliseconds(defaultDuration / 2)); + await toneGenerator.PlayTone(new Frequency(659), TimeSpan.FromMilliseconds(defaultDuration / 2)); + await toneGenerator.PlayTone(new Frequency(523), TimeSpan.FromMilliseconds(defaultDuration / 2)); + } + + /// + /// Plays an alert or notification sound effect + /// + private async Task PlayAlert() + { + await toneGenerator.PlayTone(new Frequency(1047), TimeSpan.FromMilliseconds(defaultDuration / 8)); + await Task.Delay(TimeSpan.FromMilliseconds(defaultPause)); + await toneGenerator.PlayTone(new Frequency(1175), TimeSpan.FromMilliseconds(defaultDuration / 8)); + await Task.Delay(TimeSpan.FromMilliseconds(defaultPause)); + await toneGenerator.PlayTone(new Frequency(1319), TimeSpan.FromMilliseconds(defaultDuration / 8)); + await Task.Delay(TimeSpan.FromMilliseconds(defaultPause)); + await toneGenerator.PlayTone(new Frequency(1397), TimeSpan.FromMilliseconds(defaultDuration / 8)); + } + + /// + /// Plays a short click sound effect + /// + private async Task PlayClick() + { + await toneGenerator.PlayTone(new Frequency(1000), TimeSpan.FromMilliseconds(defaultDuration / 8)); + } + + /// + /// Plays a popping sound effect + /// + private async Task PlayPop() + { + await toneGenerator.PlayTone(new Frequency(500), TimeSpan.FromMilliseconds(defaultDuration / 4)); + } + + /// + /// Plays a power-up sound effect + /// + private async Task PlayPowerUp() + { + await toneGenerator.PlayTone(new Frequency(200), TimeSpan.FromMilliseconds(defaultDuration / 2)); + await toneGenerator.PlayTone(new Frequency(1000), TimeSpan.FromMilliseconds(defaultDuration / 2)); + } + + /// + /// Plays a power-down sound effect + /// + private async Task PlayPowerDown() + { + await toneGenerator.PlayTone(new Frequency(1000), TimeSpan.FromMilliseconds(defaultDuration / 2)); + await toneGenerator.PlayTone(new Frequency(200), TimeSpan.FromMilliseconds(defaultDuration / 2)); + } + + /// + /// Plays a notification sound effect + /// + private async Task PlayNotification() + { + await toneGenerator.PlayTone(new Frequency(880), TimeSpan.FromMilliseconds(defaultDuration / 8)); + await toneGenerator.PlayTone(new Frequency(784), TimeSpan.FromMilliseconds(defaultDuration / 8)); + await toneGenerator.PlayTone(new Frequency(698), TimeSpan.FromMilliseconds(defaultDuration / 8)); + await Task.Delay(TimeSpan.FromMilliseconds(defaultPause)); + await toneGenerator.PlayTone(new Frequency(880), TimeSpan.FromMilliseconds(defaultDuration / 8)); + await toneGenerator.PlayTone(new Frequency(784), TimeSpan.FromMilliseconds(defaultDuration / 8)); + await toneGenerator.PlayTone(new Frequency(698), TimeSpan.FromMilliseconds(defaultDuration / 8)); + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Audio.MicroAudio/Samples/Audio.MicroAudio_Sample/Audio.MicroAudio_Sample.csproj b/Source/Meadow.Foundation.Libraries_and_Frameworks/Audio.MicroAudio/Samples/Audio.MicroAudio_Sample/Audio.MicroAudio_Sample.csproj new file mode 100644 index 0000000000..0f5262f559 --- /dev/null +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Audio.MicroAudio/Samples/Audio.MicroAudio_Sample/Audio.MicroAudio_Sample.csproj @@ -0,0 +1,20 @@ + + + https://github.com/WildernessLabs/Meadow.Foundation + Wilderness Labs, Inc + Wilderness Labs, Inc + true + netstandard2.1 + Library + App + + + + + + + + Always + + + diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Audio.MicroAudio/Samples/Audio.MicroAudio_Sample/CScale.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Audio.MicroAudio/Samples/Audio.MicroAudio_Sample/CScale.cs new file mode 100644 index 0000000000..98acd8337f --- /dev/null +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Audio.MicroAudio/Samples/Audio.MicroAudio_Sample/CScale.cs @@ -0,0 +1,24 @@ +using Meadow.Foundation.Audio; + +namespace Audio.MicroAudio_Sample +{ + namespace SongPlayer + { + internal class CScale : Song + { + public CScale() + { + AddNotes(); + } + + void AddNotes() + { + for (int i = 0; i < 12; i++) + { + AddNote(new Note((Pitch)(i), 3, NoteDuration.Quarter)); + } + AddNote(new Note(Pitch.C, 4, NoteDuration.Quarter)); + } + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Audio.MicroAudio/Samples/Audio.MicroAudio_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Audio.MicroAudio/Samples/Audio.MicroAudio_Sample/MeadowApp.cs new file mode 100644 index 0000000000..edd889e0a0 --- /dev/null +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Audio.MicroAudio/Samples/Audio.MicroAudio_Sample/MeadowApp.cs @@ -0,0 +1,86 @@ +using Audio.MicroAudio_Sample.SongPlayer; +using Meadow; +using Meadow.Devices; +using Meadow.Foundation.Audio; +using Meadow.Gateways.Bluetooth; +using Meadow.Peripherals.Speakers; +using System; +using System.Threading.Tasks; + +namespace MicroAudio_Sample +{ + public class MeadowApp : App + { + private MicroAudio audio; + + IToneGenerator speaker; + + public override Task Initialize() + { + Resolver.Log.Info("Initialize..."); + + speaker = new PiezoSpeaker(Device.Pins.D11); + + audio = new MicroAudio(speaker); + + return Task.CompletedTask; + } + + public override async Task Run() + { + Resolver.Log.Info("Play happy birthday"); + await HappyBirthDay(speaker); + + await Task.Delay(1000); + + Resolver.Log.Info("Play C scale"); + var scale = new CScale(); + await audio.PlaySong(scale); + + await Task.Delay(1000); + + Resolver.Log.Info("Sound effects test"); + await SoundEffectsTest(); + + Resolver.Log.Info("Game effects test"); + await GameEffectsTest(); + } + + Task HappyBirthDay(IToneGenerator speaker) + { + var happyBirthday = new Song(); + happyBirthday.AddNote(new Note(Pitch.C, 3, NoteDuration.Quarter)); + happyBirthday.AddNote(new Note(Pitch.C, 3, NoteDuration.Quarter)); + happyBirthday.AddNote(new Note(Pitch.D, 3, NoteDuration.Half)); + happyBirthday.AddNote(new Note(Pitch.C, 3, NoteDuration.Half)); + happyBirthday.AddNote(new Note(Pitch.F, 3, NoteDuration.Half)); + happyBirthday.AddNote(new Note(Pitch.E, 3, NoteDuration.Whole)); + + return happyBirthday.Play(speaker, 160); + } + + async Task GameEffectsTest() + { + foreach (GameSoundEffect effect in Enum.GetValues(typeof(GameSoundEffect))) + { + Resolver.Log.Info($"Playing {effect} game effect..."); + await audio.PlayGameSound(effect); + await Task.Delay(1000); + } + + Resolver.Log.Info("Sound effects demo complete."); + } + + async Task SoundEffectsTest() + { + foreach (SystemSoundEffect effect in Enum.GetValues(typeof(SystemSoundEffect))) + { + Resolver.Log.Info($"Playing {effect} sound effect..."); + await audio.PlaySystemSound(effect); + await Task.Delay(1000); + } + + Resolver.Log.Info("Sound effects demo complete."); + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Sh1106/Samples/Sh1106_Sample/meadow.config.yaml b/Source/Meadow.Foundation.Libraries_and_Frameworks/Audio.MicroAudio/Samples/Audio.MicroAudio_Sample/meadow.config.yaml similarity index 100% rename from Source/Meadow.Foundation.Peripherals/Displays.Sh1106/Samples/Sh1106_Sample/meadow.config.yaml rename to Source/Meadow.Foundation.Libraries_and_Frameworks/Audio.MicroAudio/Samples/Audio.MicroAudio_Sample/meadow.config.yaml diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/DataLoggers.AdafruitIO/Driver/DataLoggers.AdafruitIO.csproj b/Source/Meadow.Foundation.Libraries_and_Frameworks/DataLoggers.AdafruitIO/Driver/DataLoggers.AdafruitIO.csproj index bc01078230..5ffef7852f 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/DataLoggers.AdafruitIO/Driver/DataLoggers.AdafruitIO.csproj +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/DataLoggers.AdafruitIO/Driver/DataLoggers.AdafruitIO.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/DataLoggers.SensorReading/Driver/DataLoggers.SensorReading.csproj b/Source/Meadow.Foundation.Libraries_and_Frameworks/DataLoggers.SensorReading/Driver/DataLoggers.SensorReading.csproj index 9a3ee85e03..da1bd10972 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/DataLoggers.SensorReading/Driver/DataLoggers.SensorReading.csproj +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/DataLoggers.SensorReading/Driver/DataLoggers.SensorReading.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/DataLoggers.ThingSpeak/Driver/DataLoggers.ThingSpeak.csproj b/Source/Meadow.Foundation.Libraries_and_Frameworks/DataLoggers.ThingSpeak/Driver/DataLoggers.ThingSpeak.csproj index 133a4482a1..8889a0373a 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/DataLoggers.ThingSpeak/Driver/DataLoggers.ThingSpeak.csproj +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/DataLoggers.ThingSpeak/Driver/DataLoggers.ThingSpeak.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/BaseClasses/InputBase.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/BaseClasses/InputBase.cs index 4cb2e94954..5a4ada89fe 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/BaseClasses/InputBase.cs +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/BaseClasses/InputBase.cs @@ -1,6 +1,6 @@ using Meadow.Peripherals.Displays; -namespace Meadow.Foundation.Displays.TextDisplayMenu.InputTypes +namespace Meadow.Foundation.Displays.UI.InputTypes { /// /// Represents a base input menu item diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/BaseClasses/MenuItemBase.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/BaseClasses/MenuItemBase.cs index 05cde8d488..c17014afc9 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/BaseClasses/MenuItemBase.cs +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/BaseClasses/MenuItemBase.cs @@ -1,47 +1,47 @@ -using Newtonsoft.Json; -namespace Meadow.Foundation.Displays.TextDisplayMenu +using System.Text.Json.Serialization; + +namespace Meadow.Foundation.Displays.UI { /// /// Represents a text display menu item /// - [JsonObject(MemberSerialization.OptIn)] public class MenuItem { /// /// Sub items in the menu /// - [JsonProperty("sub")] + [JsonPropertyName("sub")] public MenuItem[] SubItems { get; set; } /// /// The text on the menu item /// - [JsonProperty("text")] + [JsonPropertyName("text")] public string Text { get; set; } /// /// The optional command when the item is selected /// - [JsonProperty("command")] + [JsonPropertyName("command")] public string Command { get; set; } /// /// The menu item type /// - [JsonProperty("type")] + [JsonPropertyName("type")] public string Type { get; set; } /// /// The menu item id /// - [JsonProperty("id")] + [JsonPropertyName("id")] public string Id { get; set; } /// /// The menu item value /// - [JsonProperty("value")] + [JsonPropertyName("value")] public object Value { get; set; } /// diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/BaseClasses/NumericBase.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/BaseClasses/NumericBase.cs index eb4f7d9e4c..89783e4f56 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/BaseClasses/NumericBase.cs +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/BaseClasses/NumericBase.cs @@ -1,6 +1,6 @@ using System; -namespace Meadow.Foundation.Displays.TextDisplayMenu.InputTypes +namespace Meadow.Foundation.Displays.UI.InputTypes { /// /// Represents a base Numeric input type diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/BaseClasses/TimeBase.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/BaseClasses/TimeBase.cs index 01821d2adc..e4bef47bcd 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/BaseClasses/TimeBase.cs +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/BaseClasses/TimeBase.cs @@ -1,6 +1,6 @@ using System; -namespace Meadow.Foundation.Displays.TextDisplayMenu.InputTypes +namespace Meadow.Foundation.Displays.UI.InputTypes { /// /// A base time input type diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/Displays.TextDisplayMenu.csproj b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/Displays.TextDisplayMenu.csproj index 29f59b96a2..81a0d23d1d 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/Displays.TextDisplayMenu.csproj +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/Displays.TextDisplayMenu.csproj @@ -17,7 +17,7 @@ - - + + diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/EventHandlers.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/EventHandlers.cs index 20771b0253..fa18d81b7c 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/EventHandlers.cs +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/EventHandlers.cs @@ -1,6 +1,6 @@ using System; -namespace Meadow.Foundation.Displays.TextDisplayMenu +namespace Meadow.Foundation.Displays.UI { /// /// Text display MenuSelectedEventArgs diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/Age.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/Age.cs index 525f4bc881..001012b279 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/Age.cs +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/Age.cs @@ -1,4 +1,4 @@ -namespace Meadow.Foundation.Displays.TextDisplayMenu.InputTypes +namespace Meadow.Foundation.Displays.UI.InputTypes { /// /// Age input type diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/Boolean.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/Boolean.cs index 826525bb94..730bab234c 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/Boolean.cs +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/Boolean.cs @@ -1,4 +1,4 @@ -namespace Meadow.Foundation.Displays.TextDisplayMenu.InputTypes +namespace Meadow.Foundation.Displays.UI.InputTypes { /// /// Text display menu bool input type diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/Date.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/Date.cs index 1981b6cc4a..32d98e106e 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/Date.cs +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/Date.cs @@ -1,6 +1,6 @@ using System; -namespace Meadow.Foundation.Displays.TextDisplayMenu.InputTypes +namespace Meadow.Foundation.Displays.UI.InputTypes { /// /// Text display menu Date input type diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/InputHelpers.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/InputHelpers.cs index ab86bff46c..7bd5af04f3 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/InputHelpers.cs +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/InputHelpers.cs @@ -1,6 +1,6 @@ using System.Text; -namespace Meadow.Foundation.Displays.TextDisplayMenu.InputTypes +namespace Meadow.Foundation.Displays.UI.InputTypes { internal static class InputHelpers { diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/InputType.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/InputType.cs new file mode 100644 index 0000000000..4636b20e33 --- /dev/null +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/InputType.cs @@ -0,0 +1,12 @@ +internal enum InputType +{ + Age, + Boolean, + Date, + Numerical, + Onff, + Temperature, + Time, + TimeDetailed, + TimeShort, +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/ListBase.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/ListBase.cs index 6450129b2e..37815f37c2 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/ListBase.cs +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/ListBase.cs @@ -1,6 +1,6 @@ using System; -namespace Meadow.Foundation.Displays.TextDisplayMenu.InputTypes +namespace Meadow.Foundation.Displays.UI.InputTypes { /// /// Text display menu base List input type diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/Numerical.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/Numerical.cs index e9e0d9efa8..39705b30d0 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/Numerical.cs +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/Numerical.cs @@ -1,4 +1,4 @@ -namespace Meadow.Foundation.Displays.TextDisplayMenu.InputTypes +namespace Meadow.Foundation.Displays.UI.InputTypes { /// /// Text display menu Numerical input item diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/OnOff.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/OnOff.cs index 1a452ae297..70497f3b0a 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/OnOff.cs +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/OnOff.cs @@ -1,4 +1,4 @@ -namespace Meadow.Foundation.Displays.TextDisplayMenu.InputTypes +namespace Meadow.Foundation.Displays.UI.InputTypes { /// /// Text display menu on/off input item diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/Temperature.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/Temperature.cs index 8f7ebf391e..a502d390bc 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/Temperature.cs +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/Temperature.cs @@ -1,4 +1,4 @@ -namespace Meadow.Foundation.Displays.TextDisplayMenu.InputTypes +namespace Meadow.Foundation.Displays.UI.InputTypes { /// /// Text display menu Temperature input item diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/Time.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/Time.cs index a14d28c84b..a4cf9df1a6 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/Time.cs +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/Time.cs @@ -1,4 +1,4 @@ -namespace Meadow.Foundation.Displays.TextDisplayMenu.InputTypes +namespace Meadow.Foundation.Displays.UI.InputTypes { /// /// Text display menu Time input item diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/TimeDetailed.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/TimeDetailed.cs index 8095a8efa5..b60ffbc2f9 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/TimeDetailed.cs +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/TimeDetailed.cs @@ -1,4 +1,4 @@ -namespace Meadow.Foundation.Displays.TextDisplayMenu.InputTypes +namespace Meadow.Foundation.Displays.UI.InputTypes { /// /// Text display menu TimeDetailed input item diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/TimeShort.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/TimeShort.cs index 59e8542e94..072659b182 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/TimeShort.cs +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/InputTypes/TimeShort.cs @@ -1,4 +1,4 @@ -namespace Meadow.Foundation.Displays.TextDisplayMenu.InputTypes +namespace Meadow.Foundation.Displays.UI.InputTypes { /// /// Text display menu TimeShort input item diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/Interfaces/IMenuInputItem.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/Interfaces/IMenuInputItem.cs index 4ee6e7011c..b51aad175a 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/Interfaces/IMenuInputItem.cs +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/Interfaces/IMenuInputItem.cs @@ -1,9 +1,9 @@ using Meadow.Peripherals.Displays; -namespace Meadow.Foundation.Displays.TextDisplayMenu +namespace Meadow.Foundation.Displays.UI { /// - /// Text display Menu Input abstraction + /// Text display TextDisplayMenu Input abstraction /// public interface IMenuInputItem : IPage { diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/Interfaces/IPage.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/Interfaces/IPage.cs index 309fc88684..79e35a9ac2 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/Interfaces/IPage.cs +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/Interfaces/IPage.cs @@ -1,4 +1,4 @@ -namespace Meadow.Foundation.Displays.TextDisplayMenu +namespace Meadow.Foundation.Displays.UI { /// /// Text display menu page abstraction diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/MenuPage.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/MenuPage.cs index 3ed3cc339f..42511a5271 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/MenuPage.cs +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/MenuPage.cs @@ -1,7 +1,6 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; -namespace Meadow.Foundation.Displays.TextDisplayMenu +namespace Meadow.Foundation.Displays.UI { /// /// Text display MenuPage class @@ -13,8 +12,9 @@ public class MenuPage : IPage /// public int ScrollPosition { - get => scrollPosition; - set { + get => scrollPosition; + set + { if (value > MenuItems.Count - 1 || value < 0) { Resolver.Log.Warn("Attempting to set a scroll position outside of item range: " + value.ToString()); diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/TextCharacters.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/TextCharacters.cs index d6bfbb2461..99753c6bfe 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/TextCharacters.cs +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/TextCharacters.cs @@ -1,4 +1,4 @@ -namespace Meadow.Foundation.Displays.TextDisplayMenu +namespace Meadow.Foundation.Displays.UI { /// /// TextCharacters class for custom characters on LCD character displays diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/TextDisplayMenu.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/TextDisplayMenu.cs index f0157ee8fd..69ec074875 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/TextDisplayMenu.cs +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Driver/TextDisplayMenu.cs @@ -1,17 +1,16 @@ -using System; +using Meadow.Foundation.Displays.UI.InputTypes; +using Meadow.Peripherals.Displays; +using System; using System.Collections; using System.Collections.Generic; -using System.IO; -using Meadow.Foundation.Displays.TextDisplayMenu.InputTypes; -using Meadow.Peripherals.Displays; -using Newtonsoft.Json; +using System.Text.Json; -namespace Meadow.Foundation.Displays.TextDisplayMenu +namespace Meadow.Foundation.Displays.UI { /// - /// TextDisplayMenu Menu class + /// TextDisplayMenu TextDisplayMenu class /// - public class Menu + public class TextDisplayMenu { const string INPUT_TYPES_NAMESPACE = "Meadow.Foundation.Displays.TextDisplayMenu.InputTypes."; ITextDisplay display; @@ -46,12 +45,12 @@ public class Menu public bool IsEnabled { get; protected set; } = false; /// - /// Create a new Menu object + /// Create a new TextDisplayMenu object /// /// The display to render the menu /// Json to define the menu structure /// True to show Back item on root menu - public Menu(ITextDisplay display, byte[] menuJson, bool showBackOnRoot = false) + public TextDisplayMenu(ITextDisplay display, byte[] menuJson, bool showBackOnRoot = false) { this.showBackOnRoot = showBackOnRoot; var items = ParseMenuData(menuJson); @@ -59,12 +58,12 @@ public Menu(ITextDisplay display, byte[] menuJson, bool showBackOnRoot = false) } /// - /// Create a new Menu object + /// Create a new TextDisplayMenu object /// /// The display to render the menu - /// Menu items array + /// TextDisplayMenu items array /// True to show Back item on root menu - public Menu(ITextDisplay display, MenuItem[] menuItems, bool showBackOnRoot = false) + public TextDisplayMenu(ITextDisplay display, MenuItem[] menuItems, bool showBackOnRoot = false) { Init(display, CreateMenuPage(menuItems, showBackOnRoot)); } @@ -73,7 +72,7 @@ MenuItem[] ParseMenuData(byte[] menuJson) { var menuString = System.Text.Encoding.Default.GetString(menuJson); - return JsonConvert.DeserializeObject(menuString); + return JsonSerializer.Deserialize(menuString); } void Init(ITextDisplay display, MenuPage menuPage) @@ -109,7 +108,7 @@ public void Disable() } /// - /// Create a Menu page + /// Create a TextDisplayMenu page /// /// Items to populate page /// True to add a back item @@ -126,7 +125,7 @@ protected MenuPage CreateMenuPage(MenuItem[] items, bool addBack) foreach (var item in items) { menuPage.MenuItems.Add(item); - } + } return menuPage; } @@ -136,7 +135,8 @@ protected MenuPage CreateMenuPage(MenuItem[] items, bool addBack) /// protected void ShowCurrentPage() { - if (!IsEnabled) { + if (!IsEnabled) + { Resolver.Log.Warn("Render not enabled"); return; } @@ -186,7 +186,7 @@ protected void ShowCurrentPage() /// The item text protected string GetItemText(MenuItem item, bool isSelected) { - if(item == null) + if (item == null) { Resolver.Log.Warn("GetItemText: item is null"); return "no item"; @@ -216,7 +216,7 @@ protected string GetItemText(MenuItem item, bool isSelected) string padding = string.Empty; if (paddingLength > 0) { padding = new string(' ', paddingLength); } - itemText += padding + (isSelected?"*":">"); + itemText += padding + (isSelected ? "*" : ">"); } return itemText; @@ -228,7 +228,7 @@ protected string GetItemText(MenuItem item, bool isSelected) protected void UpdateCurrentMenuPage() { currentMenuPage = rootMenuPage; - } + } /// /// Next input - navigates down/forward in the list of items @@ -236,9 +236,9 @@ protected void UpdateCurrentMenuPage() /// True if successful, false in menu is disabled public bool Next() { - if(IsEnabled == false) { return false; } + if (IsEnabled == false) { return false; } - if(currentInputItem != null) + if (currentInputItem != null) { currentInputItem.Next(); } @@ -327,7 +327,7 @@ public bool Select() Exited(this, new EventArgs()); return true; } - + // if currently on a subpage and user selects back, pop back to parent page. if (currentMenuPage.ScrollPosition == 0 && pageStack.Count > 0) { @@ -359,19 +359,10 @@ public bool Select() else if (menuItem.Type != string.Empty) { pageStack.Push(currentMenuPage); - - isEditMode = true; - // create the new input type - var type = Type.GetType(INPUT_TYPES_NAMESPACE + menuItem.Type); - - if (type == null) - { - throw new ArgumentException(menuItem.Type + " was not found"); - } + isEditMode = true; - var constructor = type.GetConstructor(new Type[] { }); - currentInputItem = constructor.Invoke(new object[] { }) as IMenuInputItem; + currentInputItem = GetMenuInputItemFromName(menuItem.Type); // setup callback currentInputItem.ValueChanged += delegate (object sender, ValueChangedEventArgs e) @@ -400,6 +391,30 @@ public bool Select() } } + enum DaysOfWeek { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday }; + + IMenuInputItem GetMenuInputItemFromName(string name) + { + if (Enum.TryParse(name, out InputType inputType) == false) + { + throw new ArgumentException(name + " was not found"); + } + + return inputType switch + { + InputType.Age => new Age(), + InputType.Boolean => new InputTypes.Boolean(), + InputType.Date => new Date(), + InputType.Numerical => new Numerical(), + InputType.Onff => new OnOff(), + InputType.Temperature => new Temperature(), + InputType.Time => new Time(), + InputType.TimeDetailed => new TimeDetailed(), + InputType.TimeShort => new TimeShort(), + _ => null, + }; + } + /// /// Refresh / redraw the menu /// @@ -441,7 +456,7 @@ private void UpdateMenuItemValue(string id, object value) MenuItem node = null; foreach (var menuItem in rootMenuPage.MenuItems) { - node = FindNodeById(menuItem as MenuItem, id); + node = FindNodeById(menuItem, id); if (node != null) { break; } } @@ -465,7 +480,7 @@ private MenuItem FindNodeById(MenuItem menuItem, string id) { foreach (var subMenuItem in menuItem.SubItems) { - var node = FindNodeById(subMenuItem as MenuItem, id); + var node = FindNodeById(subMenuItem, id); if (node != null) return node; } } diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Samples/TextDisplayMenu_GameMenu_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Samples/TextDisplayMenu_GameMenu_Sample/MeadowApp.cs index 20eaf9e04c..1d5316d543 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Samples/TextDisplayMenu_GameMenu_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Samples/TextDisplayMenu_GameMenu_Sample/MeadowApp.cs @@ -1,42 +1,38 @@ using Meadow; using Meadow.Devices; using Meadow.Foundation.Displays; -using Meadow.Foundation.Displays.TextDisplayMenu; +using Meadow.Foundation.Displays.UI; using Meadow.Foundation.Graphics; using Meadow.Foundation.Sensors.Buttons; -using Meadow.Hardware; -using Meadow.Peripherals.Displays; using Meadow.Peripherals.Sensors.Buttons; using System; using System.IO; using System.Reflection; using System.Threading.Tasks; -namespace MeadowApp +namespace TextDisplayMenu_GameMenu_Sample { public class MeadowApp : App { - Menu menu; + TextDisplayMenu menu; - MicroGraphics graphics; - Ssd1309 ssd1309; + MicroGraphics microGraphics; IButton up = null; IButton down = null; IButton left = null; IButton right = null; + bool playGame = false; + public override Task Initialize() { Resolver.Log.Info("Initialize..."); - Resolver.Log.Info("Create Display with SPI..."); - - var config = new SpiClockConfiguration(Ssd1309.DefaultSpiBusSpeed, Ssd1309.DefaultSpiClockMode); - - var bus = Device.CreateSpiBus(Device.Pins.SCK, Device.Pins.MOSI, Device.Pins.MISO, config); + var bus = Device.CreateSpiBus(); - ssd1309 = new Ssd1309 + // SSD1309 with SPI + var ssd1309 = new Ssd1309 ( spiBus: bus, chipSelectPin: Device.Pins.D02, @@ -44,49 +40,67 @@ public override Task Initialize() resetPin: Device.Pins.D00 ); - Resolver.Log.Info("Create MicroGraphics..."); + // SSD1309 with I2C + //var ssd1309 = new Ssd1309 + //( + // Device.CreateI2cBus() + //); - graphics = new MicroGraphics(ssd1309) + microGraphics = new MicroGraphics(ssd1309) { CurrentFont = new Font8x12(), }; - graphics.Clear(); - graphics.DrawText(0, 0, "Loading Menu"); - graphics.Show(); + microGraphics.Clear(); + microGraphics.DrawText(0, 0, "Loading Menu"); + microGraphics.Show(); - CreateMenu(graphics); + Resolver.Log.Info("Load menu data..."); + + var menuData = LoadResource("menu.json"); + + Resolver.Log.Info("Create menu..."); + + menu = new TextDisplayMenu(microGraphics, menuData, false); + + menu.Selected += Menu_Selected; Resolver.Log.Info("Create buttons..."); - up = new PushButton(Device.Pins.D09, ResistorMode.InternalPullDown); + up = new PushButton(Device.Pins.D09); up.Clicked += Up_Clicked; - left = new PushButton(Device.Pins.D11, ResistorMode.InternalPullDown); + left = new PushButton(Device.Pins.D11); left.Clicked += Left_Clicked; - right = new PushButton(Device.Pins.D10, ResistorMode.InternalPullDown); + right = new PushButton(Device.Pins.D10); right.Clicked += Right_Clicked; - down = new PushButton(Device.Pins.D12, ResistorMode.InternalPullDown); + down = new PushButton(Device.Pins.D12); down.Clicked += Down_Clicked; + Resolver.Log.Info("Enable menu..."); + menu.Enable(); return Task.CompletedTask; } - private void Down_Clicked(object sender, EventArgs e) + private void Up_Clicked(object sender, EventArgs e) { - if (menu.IsEnabled) { menu.Next(); } + Resolver.Log.Info("Up_Clicked"); + if (menu.IsEnabled) + { + menu.Previous(); + } } - private void Right_Clicked(object sender, EventArgs e) + private void Down_Clicked(object sender, EventArgs e) { - Resolver.Log.Info("Right_Clicked"); + Resolver.Log.Info("Down_Clicked"); if (menu.IsEnabled) { - menu.Select(); + menu.Next(); } } @@ -99,15 +113,24 @@ private void Left_Clicked(object sender, EventArgs e) } } - private void Up_Clicked(object sender, EventArgs e) + private void Right_Clicked(object sender, EventArgs e) { + Resolver.Log.Info("Right_Clicked"); if (menu.IsEnabled) { - menu.Previous(); + menu.Select(); } } - bool playGame = false; + private void Menu_Selected(object sender, MenuSelectedEventArgs e) + { + Resolver.Log.Info($"******** Selected: {e.Command}"); + + DisableMenu(); + + _ = StartGame(e.Command); + } + async Task StartGame(string command) { Resolver.Log.Info($"******** {command}"); @@ -121,13 +144,13 @@ await Task.Run(() => { while (count < 150 && playGame == true) { - graphics.Clear(); - graphics.DrawText(0, 0, $"{command}:"); - graphics.DrawText(0, 20, $"{count++}"); - graphics.DrawPixel(x += xD, y += yD); - if (x == graphics.Width || x == 0) { xD *= -1; }; - if (y == graphics.Height || y == 0) { yD *= -1; }; - graphics.Show(); + microGraphics.Clear(); + microGraphics.DrawText(0, 0, $"{command}:"); + microGraphics.DrawText(0, 20, $"{count++}"); + microGraphics.DrawPixel(x += xD, y += yD); + if (x == microGraphics.Width || x == 0) { xD *= -1; }; + if (y == microGraphics.Height || y == 0) { yD *= -1; }; + microGraphics.Show(); } }).ConfigureAwait(false); @@ -146,34 +169,10 @@ void DisableMenu() menu?.Disable(); } - void CreateMenu(ITextDisplay display) - { - Resolver.Log.Info("Load menu data..."); - - var menuData = LoadResource("menu.json"); - - Resolver.Log.Info($"Data length: {menuData.Length}..."); - - Resolver.Log.Info("Create menu..."); - - menu = new Menu(display, menuData, false); - - menu.Selected += Menu_Selected; - } - - private void Menu_Selected(object sender, MenuSelectedEventArgs e) - { - Resolver.Log.Info($"******** Selected: {e.Command}"); - - DisableMenu(); - - _ = StartGame(e.Command); - } - byte[] LoadResource(string filename) { var assembly = Assembly.GetExecutingAssembly(); - var resourceName = $"Graphics.TextDisplayMenu_GameMenu_Sample.{filename}"; + var resourceName = $"TextDisplayMenu_GameMenu_Sample.{filename}"; using Stream stream = assembly.GetManifestResourceStream(resourceName); using var ms = new MemoryStream(); diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Samples/TextDisplayMenu_GameMenu_Sample/TextDisplayMenu_GameMenu_Sample.csproj b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Samples/TextDisplayMenu_GameMenu_Sample/TextDisplayMenu_GameMenu_Sample.csproj index b53abd752b..be9dfbc67b 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Samples/TextDisplayMenu_GameMenu_Sample/TextDisplayMenu_GameMenu_Sample.csproj +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Samples/TextDisplayMenu_GameMenu_Sample/TextDisplayMenu_GameMenu_Sample.csproj @@ -16,7 +16,7 @@ - + diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Samples/TextDisplayMenu_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Samples/TextDisplayMenu_Sample/MeadowApp.cs index a2c6a5ac53..94538faf45 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Samples/TextDisplayMenu_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Samples/TextDisplayMenu_Sample/MeadowApp.cs @@ -1,23 +1,19 @@ using Meadow; using Meadow.Devices; using Meadow.Foundation.Displays; -using Meadow.Foundation.Displays.TextDisplayMenu; +using Meadow.Foundation.Displays.UI; using Meadow.Foundation.Graphics; using Meadow.Foundation.Sensors.Buttons; -using Meadow.Hardware; -using Meadow.Peripherals.Displays; using Meadow.Peripherals.Sensors.Buttons; using System.IO; using System.Reflection; using System.Threading.Tasks; -namespace MeadowApp +namespace TextDisplayMenu_Sample { public class MeadowApp : App { - Menu menu; - - Ssd1309 ssd1309; + TextDisplayMenu menu; IButton next = null; IButton previous = null; @@ -27,28 +23,29 @@ public override Task Initialize() { Resolver.Log.Info("Initialize..."); - var config = new SpiClockConfiguration(Ssd1309.DefaultSpiBusSpeed, Ssd1309.DefaultSpiClockMode); - - var bus = Device.CreateSpiBus(Device.Pins.SCK, Device.Pins.MOSI, Device.Pins.MISO, config); - - ssd1309 = new Ssd1309 + // SSD1309 with SPI + var ssd1309 = new Ssd1309 ( - spiBus: bus, + spiBus: Device.CreateSpiBus(), chipSelectPin: Device.Pins.D02, dcPin: Device.Pins.D01, resetPin: Device.Pins.D00 ); - Resolver.Log.Info("Create MicroGraphics..."); + // SSD1309 with I2C + //var ssd1309 = new Ssd1309 + //( + // Device.CreateI2cBus() + //); - var gl = new MicroGraphics(ssd1309) + var microGraphics = new MicroGraphics(ssd1309) { CurrentFont = new Font8x12(), }; - gl.Clear(); - gl.DrawText(0, 0, "Loading Menu"); - gl.Show(); + microGraphics.Clear(); + microGraphics.DrawText(0, 0, "Loading Menu"); + microGraphics.Show(); Resolver.Log.Info("Load menu data..."); @@ -60,7 +57,7 @@ public override Task Initialize() Resolver.Log.Info("Create menu..."); - menu = new Menu(ssd1309 as ITextDisplay, menuData, false); + menu = new TextDisplayMenu(microGraphics, menuData, false); next = new PushButton(Device.Pins.D10); next.Clicked += (s, e) => { menu.Next(); }; @@ -81,16 +78,12 @@ public override Task Initialize() byte[] LoadResource(string filename) { var assembly = Assembly.GetExecutingAssembly(); - var resourceName = $"Graphics.TextDisplayMenu_Sample.{filename}"; + var resourceName = $"TextDisplayMenu_Sample.{filename}"; - using (Stream stream = assembly.GetManifestResourceStream(resourceName)) - { - using (var ms = new MemoryStream()) - { - stream.CopyTo(ms); - return ms.ToArray(); - } - } + using Stream stream = assembly.GetManifestResourceStream(resourceName); + using var ms = new MemoryStream(); + stream.CopyTo(ms); + return ms.ToArray(); } } } \ No newline at end of file diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Samples/TextDisplayMenu_Sample/TextDisplayMenu_Sample.csproj b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Samples/TextDisplayMenu_Sample/TextDisplayMenu_Sample.csproj index b53abd752b..be9dfbc67b 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Samples/TextDisplayMenu_Sample/TextDisplayMenu_Sample.csproj +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Displays.TextDisplayMenu/Samples/TextDisplayMenu_Sample/TextDisplayMenu_Sample.csproj @@ -16,7 +16,7 @@ - + diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroGraphics/Driver/Buffers/Buffer1bpp.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroGraphics/Driver/Buffers/Buffer1bpp.cs index 03b77721da..f33fd11f87 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroGraphics/Driver/Buffers/Buffer1bpp.cs +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroGraphics/Driver/Buffers/Buffer1bpp.cs @@ -19,8 +19,8 @@ public class Buffer1bpp : PixelBufferBase /// width of buffer in pixels /// height of buffer in pixels /// data to copy into buffer - public Buffer1bpp(int width, int height, byte[] buffer) : - base(width, height, buffer) + public Buffer1bpp(int width, int height, byte[] buffer) : + base(width, height, buffer) { } /// @@ -28,8 +28,8 @@ public Buffer1bpp(int width, int height, byte[] buffer) : /// /// width of buffer in pixels /// height of buffer in pixels - public Buffer1bpp(int width, int height) : - base(width, height) + public Buffer1bpp(int width, int height) : + base(width, height) { } /// @@ -49,7 +49,8 @@ public Buffer1bpp(int width, int height, int pageSize) Width = width; Height = height; - int bufferSize = width * height / 8; + int bufferSize = (height * width >> 3); + bufferSize += bufferSize % pageSize; Buffer = new byte[bufferSize]; @@ -63,7 +64,7 @@ public Buffer1bpp(int width, int height, int pageSize) /// true if pixel is set / enabled public virtual bool GetPixelIsEnabled(int x, int y) { - var index = (y >> 8) * Width + x; + var index = (y >> 3) * Width + x; return (Buffer[index] & (1 << y % 8)) != 0; } @@ -87,16 +88,11 @@ public override Color GetPixel(int x, int y) /// is pixel enabled (on) public virtual void SetPixel(int x, int y, bool enabled) { - var index = (y >> 3) * Width + x; //divide by 8 + var index = (y >> 3) * Width + x; - if (enabled) - { - Buffer[index] = (byte)(Buffer[index] | (byte)(1 << (y % 8))); - } - else - { - Buffer[index] = (byte)(Buffer[index] & ~(byte)(1 << (y % 8))); - } + var bitMask = (byte)(1 << (y % 8)); + + Buffer[index] = enabled ? (byte)(Buffer[index] | bitMask) : (byte)(Buffer[index] & ~bitMask); } /// @@ -137,12 +133,12 @@ public override void Fill(int x, int y, int width, int height, Color color) } var isColored = color.Color1bpp; - + for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { //byte aligned and at least 8 rows to go - if((j + y) % 8 == 0 && j + y + 8 <= height) + if ((j + y) % 8 == 0 && j + y + 8 <= height) { //set an entire byte - fast Buffer[((j + y) >> 3) * Width + x + i] = (byte)((isColored) ? 0xFF : 0); @@ -183,7 +179,7 @@ public void Clear(bool enabled) /// y position of pixel public override void InvertPixel(int x, int y) { - var index = (y / 8 * Width) + x; + var index = (y >> 3) * Width + x; Buffer[index] = Buffer[index] ^= (byte)(1 << y % 8); } diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroGraphics/Driver/Buffers/Buffer1bppV.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroGraphics/Driver/Buffers/Buffer1bppV.cs index 38f5e94cb4..9a3928d51b 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroGraphics/Driver/Buffers/Buffer1bppV.cs +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroGraphics/Driver/Buffers/Buffer1bppV.cs @@ -44,9 +44,9 @@ public Buffer1bppV(int width, int height, int pageSize) Width = width; Height = height; - width = width % 8 > 0 ? width + 8 - (width % 8) : width; + width = (width + 7) & ~7; - int bufferSize = width * height / 8; + int bufferSize = (width * height) >> 3; bufferSize += bufferSize % pageSize; Buffer = new byte[bufferSize]; @@ -60,7 +60,7 @@ public Buffer1bppV(int width, int height, int pageSize) /// true if pixel is set / enabled public override bool GetPixelIsEnabled(int x, int y) { - return (Buffer[(x + y * Width) / 8] & (0x80 >> (x % 8))) != 0; + return (Buffer[(x + y * Width) >> 3] & (0x80 >> (x % 8))) != 0; } /// @@ -71,14 +71,10 @@ public override bool GetPixelIsEnabled(int x, int y) /// is pixel enabled (on) public override void SetPixel(int x, int y, bool enabled) { - if (enabled) - { //0x80 = 128 = 0b_10000000 - Buffer[(x + y * Width) / 8] |= (byte)(0x80 >> (x % 8)); - } - else - { - Buffer[(x + y * Width) / 8] &= (byte)~(0x80 >> (x % 8)); - } + int index = (x + y * Width) >> 3; + byte bitMask = (byte)(0x80 >> (x % 8)); + + Buffer[index] = enabled ? (byte)(Buffer[index] | bitMask) : (byte)(Buffer[index] & ~bitMask); } /// @@ -103,7 +99,7 @@ public override void Fill(int x, int y, int width, int height, Color color) for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) - { + { //ToDo - optimize for full byte copies SetPixel(x + i, y + j, isColored); } @@ -117,7 +113,7 @@ public override void Fill(int x, int y, int width, int height, Color color) /// y position of pixel public override void InvertPixel(int x, int y) { - Buffer[(x + y * Width) / 8] ^= (byte)~(0x80 >> (x % 8)); + Buffer[(x + y * Width) >> 3] ^= (byte)~(0x80 >> (x % 8)); } /// diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroGraphics/Driver/Buffers/PixelBufferBase.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroGraphics/Driver/Buffers/PixelBufferBase.cs index dda36c13f3..ee22d868d3 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroGraphics/Driver/Buffers/PixelBufferBase.cs +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroGraphics/Driver/Buffers/PixelBufferBase.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; namespace Meadow.Foundation.Graphics.Buffers { @@ -51,7 +52,7 @@ public int BitDepth /// /// Number of bytes in buffer /// - public int ByteCount => (Width * Height * BitDepth) / 8; + public int ByteCount => (Width * Height * BitDepth) >> 3; /// /// The buffer that holds the pixel data @@ -87,7 +88,7 @@ public PixelBufferBase(int width, int height, byte[] buffer) { Width = width; Height = height; - if(buffer.Length != ByteCount) + if (buffer.Length != ByteCount) { throw new ArgumentException($"Provided buffer length ({buffer.Length}) does not match this buffer's ByteCount ({ByteCount})."); } @@ -101,7 +102,7 @@ public PixelBufferBase(int width, int height, byte[] buffer) /// If true, will recreates the buffer if it already exists public void InitializeBuffer(bool replaceIfExists = false) { - if(Buffer == null || replaceIfExists) + if (Buffer == null || replaceIfExists) { Buffer = new byte[ByteCount]; } @@ -120,7 +121,7 @@ public virtual void Clear() /// /// Fill color public abstract void Fill(Color color); - + /// /// Fill a region of the pixel buffer with a color /// @@ -182,7 +183,7 @@ protected void WriteBufferSlow(int originX, int originY, IPixelBuffer buffer) { for (var x = 0; x < buffer.Width; x++) { - for(var y = 0; y < buffer.Height; y++) + for (var y = 0; y < buffer.Height; y++) { SetPixel(originX + x, originY + y, buffer.GetPixel(x, y)); } @@ -195,94 +196,87 @@ protected void WriteBufferSlow(int originX, int originY, IPixelBuffer buffer) /// Buffer type /// Rotation /// The new buffer - public T RotateAndConvert(RotationType rotation) + public T RotateAndConvert(RotationType rotation) where T : PixelBufferBase, new() { T newBuffer; + int[] rowLookup; + int[] colLookup; switch (rotation) { case RotationType._90Degrees: - newBuffer = new T - { - Width = Height, - Height = Width - }; - newBuffer.InitializeBuffer(); - - for (int i = 0; i < Width; i++) - { - for (int j = 0; j < Height; j++) - { - newBuffer.SetPixel(Height - j - 1, i, GetPixel(i, j)); - } - } + newBuffer = new T { Width = Height, Height = Width }; + rowLookup = Enumerable.Range(0, Height).Reverse().ToArray(); + colLookup = Enumerable.Range(0, Width).ToArray(); break; case RotationType._270Degrees: - newBuffer = new T - { - Width = Height, - Height = Width - }; - newBuffer.InitializeBuffer(); - - for (int i = 0; i < Width; i++) - { - for (int j = 0; j < Height; j++) - { - newBuffer.SetPixel(j, Width - i - 1, GetPixel(i, j)); - } - } + newBuffer = new T { Width = Height, Height = Width }; + rowLookup = Enumerable.Range(0, Height).ToArray(); + colLookup = Enumerable.Range(0, Width).Reverse().ToArray(); break; case RotationType._180Degrees: - newBuffer = new T - { - Width = Width, - Height = Height - }; - newBuffer.InitializeBuffer(); - - for (int i = 0; i < Width; i++) - { - for (int j = 0; j < Height; j++) - { - newBuffer.SetPixel(Width - i - 1, Height - j - 1, GetPixel(i, j)); - } - } + newBuffer = new T { Width = Width, Height = Height }; + rowLookup = Enumerable.Range(0, Width).Reverse().ToArray(); + colLookup = Enumerable.Range(0, Height).Reverse().ToArray(); break; case RotationType.Default: default: - newBuffer = new T - { - Width = Height, - Height = Width - }; - newBuffer.InitializeBuffer(); - - for (int i = 0; i < Width; i++) - { - for (int j = 0; j < Height; j++) - { - newBuffer.SetPixel(i, j, GetPixel(i, j)); - } - } - break; + return Clone(); + } + + newBuffer.InitializeBuffer(); + + for (int i = 0; i < Width; i++) + { + for (int j = 0; j < Height; j++) + { + newBuffer.SetPixel(rowLookup[j], colLookup[i], GetPixel(i, j)); + } } return newBuffer; } + /// + /// Create a new buffer scaled up from the existing buffer + /// + /// Buffer type + /// Integer scale ratio + /// The new buffer + + public T ScaleUp(int scaleFactor) + where T : PixelBufferBase, new() + { + T newBuffer = new T + { + Width = Width * scaleFactor, + Height = Height * scaleFactor, + }; + newBuffer.InitializeBuffer(true); + newBuffer.Clear(); + + for (int i = 0; i < Width; i++) + { + for (int j = 0; j < Height; j++) + { + newBuffer.Fill(i * scaleFactor, j * scaleFactor, scaleFactor, scaleFactor, GetPixel(i, j)); + } + } + return newBuffer; + } + /// /// Create a new pixel buffer and /// copy/convert pixel data from existing buffer /// /// The buffer type to convert to /// A pixel buffer derrived from PixelBufferBase - public T ConvertPixelBuffer() + public T ConvertPixelBuffer() where T : PixelBufferBase, new() { - if(GetType() == typeof(T)) - { + if (GetType() == typeof(T)) + { return Clone(); } @@ -303,7 +297,7 @@ public T ConvertPixelBuffer() return newBuffer; } - + /// /// Make a copy of the buffer object /// Intentionally private diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroGraphics/Driver/Graphics.MicroGraphics.csproj b/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroGraphics/Driver/Graphics.MicroGraphics.csproj index 6bf01b4d0d..f82424dd8a 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroGraphics/Driver/Graphics.MicroGraphics.csproj +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroGraphics/Driver/Graphics.MicroGraphics.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroGraphics/Driver/Image.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroGraphics/Driver/Image.cs index d8364a3877..1e98d9ae88 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroGraphics/Driver/Image.cs +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroGraphics/Driver/Image.cs @@ -118,7 +118,7 @@ private void LoadBitmap(Stream source) source.Seek(-4, SeekOrigin.Current); source.Read(dib, 0, dib.Length); - var width = BitConverter.ToInt32(dib, 18 - 14 ); + var width = BitConverter.ToInt32(dib, 18 - 14); var height = BitConverter.ToInt32(dib, 22 - 14); var invertedRows = false; if (height < 0) @@ -150,9 +150,9 @@ private void LoadBitmap(Stream source) throw new NotSupportedException("Unsupported bitmap compression"); } - var bytesPerRow = (int)(width * (BitsPerPixel / 8f)); + var bytesPerRow = width * (BitsPerPixel >> 3); // BMP row length is evenly divisible by 4 - var mod = (bytesPerRow % 4); + var mod = bytesPerRow % 4; var rowPad = mod == 0 ? 0 : 4 - mod; var pixelBufferSize = height * bytesPerRow; var pixelData = new byte[pixelBufferSize]; @@ -222,7 +222,7 @@ private void ConvertRGBBufferToBGRBuffer(byte[] buffer) { byte temp; - for (int i = 0; i < buffer.Length; i+=3) + for (int i = 0; i < buffer.Length; i += 3) { // pull red temp = buffer[i]; diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroGraphics/Driver/MicroGraphics.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroGraphics/Driver/MicroGraphics.cs index 03aa4388be..3e96bd173f 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroGraphics/Driver/MicroGraphics.cs +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroGraphics/Driver/MicroGraphics.cs @@ -19,10 +19,11 @@ public partial class MicroGraphics /// /// PixelBuffer draw target /// - protected IPixelBuffer pixelBuffer; + protected IPixelBuffer PixelBuffer => (display != null) ? display.PixelBuffer : _memoryBuffer; + private readonly IPixelBuffer _memoryBuffer; /// - /// Ingore pixels that are outside of the pixel buffer coordinate space + /// ignore pixels that are outside of the pixel buffer coordinate space /// public bool IgnoreOutOfBoundsPixels = true; @@ -33,12 +34,7 @@ public IFont CurrentFont { get { - // lazy load - if (currentFont == null) - { - currentFont = new Font6x8(); - } - + currentFont ??= new Font6x8(); return currentFont; } set @@ -55,7 +51,7 @@ public IFont CurrentFont /// /// Current color mode /// - public ColorMode ColorMode => pixelBuffer.ColorMode; + public ColorMode ColorMode => PixelBuffer.ColorMode; /// /// Current rotation used for drawing pixels to the display @@ -87,14 +83,34 @@ public RotationType Rotation public Color PenColor { get; set; } = Color.White; /// - /// Return the height of the display after accounting for the rotation. + /// Return the height of the display after accounting for the rotation /// - public int Height => Rotation == RotationType.Default || Rotation == RotationType._180Degrees ? pixelBuffer.Height : pixelBuffer.Width; + public int Height + { + get + { + if (display is IRotatableDisplay) + { + return display.Height; + } + return Rotation == RotationType.Default || Rotation == RotationType._180Degrees ? PixelBuffer.Height : PixelBuffer.Width; + } + } /// - /// Return the width of the display after accounting for the rotation. + /// Return the width of the display after accounting for the rotation /// - public int Width => Rotation == RotationType.Default || Rotation == RotationType._180Degrees ? pixelBuffer.Width : pixelBuffer.Height; + public int Width + { + get + { + if (display is IRotatableDisplay) + { + return display.Width; + } + return Rotation == RotationType.Default || Rotation == RotationType._180Degrees ? PixelBuffer.Width : PixelBuffer.Height; + } + } /// /// Text display configuration for use with text display menu @@ -123,8 +139,6 @@ public RotationType Rotation public MicroGraphics(IGraphicsDisplay display) { this.display = display; - - this.pixelBuffer = display.PixelBuffer; } /// @@ -134,7 +148,7 @@ public MicroGraphics(IGraphicsDisplay display) /// Initialize the offscreen buffer if true public MicroGraphics(PixelBufferBase pixelBuffer, bool initializeBuffer) { - this.pixelBuffer = pixelBuffer; + _memoryBuffer = pixelBuffer; if (initializeBuffer) { @@ -155,7 +169,14 @@ public virtual void DrawPixel(int x, int y, Color color) return; } - pixelBuffer.SetPixel(GetXForRotation(x, y), GetYForRotation(x, y), color); + if (display is IRotatableDisplay) + { + PixelBuffer.SetPixel(x, y, color); + } + else + { + PixelBuffer.SetPixel(GetXForRotation(x, y), GetYForRotation(x, y), color); + } } /// @@ -190,7 +211,7 @@ public virtual void DrawPixel(int index) return; } - pixelBuffer.SetPixel(index % pixelBuffer.Width, index / pixelBuffer.Width, PenColor); + PixelBuffer.SetPixel(index % PixelBuffer.Width, index / PixelBuffer.Width, PenColor); } /// @@ -205,7 +226,7 @@ public void InvertPixel(int x, int y) return; } - pixelBuffer.InvertPixel(GetXForRotation(x, y), GetYForRotation(x, y)); + PixelBuffer.InvertPixel(GetXForRotation(x, y), GetYForRotation(x, y)); } /// @@ -516,29 +537,12 @@ public void DrawArc(int centerX, int centerY, int radius, Angle startAngle, Angl int offset = centerBetweenPixels ? 1 : 0; - if (startAngle > endAngle) - { - endAngle += new Angle(360); - } + double startAngleRadians = startAngle.Radians; + double endAngleRadians = endAngle.Radians; - bool IsCoordinateOnArc(int x, int y) + if (startAngleRadians > endAngleRadians) { - var angle = Math.Atan2(y, x); - if (angle < 0) { angle += 2 * Math.PI; } - - if (angle >= startAngle.Radians && - angle <= endAngle.Radians) - { - return true; - } - - if (angle >= (startAngle.Radians - 2 * Math.PI) && - angle <= (endAngle.Radians - 2 * Math.PI)) - { - return true; - } - - return false; + (endAngleRadians, startAngleRadians) = (startAngleRadians, endAngleRadians); } void DrawArcPoint(int x, int y, Color color) @@ -555,17 +559,23 @@ void DrawArcPoint(int x, int y, Color color) while (x <= y) { - if (IsCoordinateOnArc(y, -x)) DrawArcPoint(centerX + y - offset, centerY - x, color); //1 - if (IsCoordinateOnArc(x, -y)) DrawArcPoint(centerX + x - offset, centerY - y, color); //2 - - if (IsCoordinateOnArc(-x, -y)) DrawArcPoint(centerX - x, centerY - y, color); //3 - if (IsCoordinateOnArc(-y, -x)) DrawArcPoint(centerX - y, centerY - x, color); //4 - - if (IsCoordinateOnArc(-y, x)) DrawArcPoint(centerX - y, centerY + x - offset, color); //5 - if (IsCoordinateOnArc(-x, y)) DrawArcPoint(centerX - x, centerY + y - offset, color); //6 - - if (IsCoordinateOnArc(x, y)) DrawArcPoint(centerX + x - offset, centerY + y - offset, color); //7 - if (IsCoordinateOnArc(y, x)) DrawArcPoint(centerX + y - offset, centerY + x - offset, color); //8 + double angle1 = Math.Atan2(y, -x); + double angle2 = Math.Atan2(x, -y); + double angle3 = Math.Atan2(-x, -y); + double angle4 = Math.Atan2(-y, -x); + double angle5 = Math.Atan2(-y, x); + double angle6 = Math.Atan2(-x, y); + double angle7 = Math.Atan2(x, y); + double angle8 = Math.Atan2(y, x); + + if (angle1 >= startAngleRadians && angle1 <= endAngleRadians) { DrawArcPoint(centerX + y - offset, centerY - x, color); } + if (angle2 >= startAngleRadians && angle2 <= endAngleRadians) { DrawArcPoint(centerX + x - offset, centerY - y, color); } + if (angle3 >= startAngleRadians && angle3 <= endAngleRadians) { DrawArcPoint(centerX - x, centerY - y, color); } + if (angle4 >= startAngleRadians && angle4 <= endAngleRadians) { DrawArcPoint(centerX - y, centerY - x, color); } + if (angle5 >= startAngleRadians && angle5 <= endAngleRadians) { DrawArcPoint(centerX - y, centerY + x - offset, color); } + if (angle6 >= startAngleRadians && angle6 <= endAngleRadians) { DrawArcPoint(centerX - x, centerY + y - offset, color); } + if (angle7 >= startAngleRadians && angle7 <= endAngleRadians) { DrawArcPoint(centerX + x - offset, centerY + y - offset, color); } + if (angle8 >= startAngleRadians && angle8 <= endAngleRadians) { DrawArcPoint(centerX + y - offset, centerY + x - offset, color); } if (d < 0) { @@ -1241,12 +1251,7 @@ public void DrawText(int x, int y, string text, Color color, VerticalAlignment alignmentV = VerticalAlignment.Top, IFont? font = null) { - var fontToDraw = font != null ? font : CurrentFont; - - if (fontToDraw == null) - { - throw new Exception("CurrentFont must be set before calling DrawText."); - } + var fontToDraw = (font ?? CurrentFont) ?? throw new Exception("CurrentFont must be set before calling DrawText."); byte[] bitMap = GetBytesForTextBitmap(text, fontToDraw); @@ -1323,9 +1328,9 @@ public void DrawBuffer(int x, int y, IPixelBuffer buffer) } //fast and happy path - if (Rotation == RotationType.Default && isInBounds) + if (display is IRotatableDisplay || Rotation == RotationType.Default && isInBounds) { - pixelBuffer.WriteBuffer(x, y, buffer); + PixelBuffer.WriteBuffer(x, y, buffer); } else //loop over every pixel { @@ -1333,7 +1338,7 @@ public void DrawBuffer(int x, int y, IPixelBuffer buffer) { for (int j = yStartIndex; j < heightToDraw; j++) { - pixelBuffer.SetPixel(GetXForRotation(x + i, y + j), + PixelBuffer.SetPixel(GetXForRotation(x + i, y + j), GetYForRotation(x + i, y + j), buffer.GetPixel(i, j)); } @@ -1627,11 +1632,11 @@ public virtual void Clear(bool updateDisplay = false) { if (display.DisabledColor == Color.Black) { - pixelBuffer.Clear(); + PixelBuffer.Clear(); } else { - pixelBuffer.Fill(display.DisabledColor); + PixelBuffer.Fill(display.DisabledColor); } if (updateDisplay) @@ -1650,7 +1655,7 @@ public virtual void Clear(bool updateDisplay = false) /// Update the display immediately when true public virtual void Clear(int originX, int originY, int width, int height, bool updateDisplay = false) { - pixelBuffer.Fill(originX, originY, width, height, display.DisabledColor); + PixelBuffer.Fill(originX, originY, width, height, display.DisabledColor); if (updateDisplay) { @@ -1743,10 +1748,12 @@ protected void DrawBitmap(int x, int y, int width, int height, byte[] bitmap, Sc /// public int GetXForRotation(int x, int y) { + if (display is IRotatableDisplay) { return x; } + return Rotation switch { - RotationType._90Degrees => pixelBuffer.Width - y - 1, - RotationType._180Degrees => pixelBuffer.Width - x - 1, + RotationType._90Degrees => PixelBuffer.Width - y - 1, + RotationType._180Degrees => PixelBuffer.Width - x - 1, RotationType._270Degrees => y, _ => x, }; @@ -1760,11 +1767,13 @@ public int GetXForRotation(int x, int y) /// public int GetYForRotation(int x, int y) { + if (display is IRotatableDisplay) { return y; } + return Rotation switch { RotationType._90Degrees => x, - RotationType._180Degrees => pixelBuffer.Height - y - 1, - RotationType._270Degrees => pixelBuffer.Height - x - 1, + RotationType._180Degrees => PixelBuffer.Height - y - 1, + RotationType._270Degrees => PixelBuffer.Height - x - 1, _ => y, }; } @@ -1796,19 +1805,25 @@ void Fill(int x, int y, int width, int height, Color color) if (y + height >= Height) height = Height - y; } + if (display is IRotatableDisplay) + { + PixelBuffer.Fill(x, y, width, height, color); + return; + } + switch (Rotation) { case RotationType.Default: - pixelBuffer.Fill(x, y, width, height, color); + PixelBuffer.Fill(x, y, width, height, color); break; case RotationType._90Degrees: - pixelBuffer.Fill(GetXForRotation(x, y) - height + 1, GetYForRotation(x, y), height, width, color); + PixelBuffer.Fill(GetXForRotation(x, y) - height + 1, GetYForRotation(x, y), height, width, color); break; case RotationType._180Degrees: - pixelBuffer.Fill(GetXForRotation(x, y) - width + 1, GetYForRotation(x, y) - height + 1, width, height, color); + PixelBuffer.Fill(GetXForRotation(x, y) - width + 1, GetYForRotation(x, y) - height + 1, width, height, color); break; case RotationType._270Degrees: - pixelBuffer.Fill(GetXForRotation(x, y), GetYForRotation(x, y) - width + 1, height, width, color); + PixelBuffer.Fill(GetXForRotation(x, y), GetYForRotation(x, y) - width + 1, height, width, color); break; } } diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroGraphics/Samples/ImageLoadSample/ImageLoad_Sample.csproj b/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroGraphics/Samples/ImageLoadSample/ImageLoad_Sample.csproj index 2b966ed4a5..133629e6ad 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroGraphics/Samples/ImageLoadSample/ImageLoad_Sample.csproj +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroGraphics/Samples/ImageLoadSample/ImageLoad_Sample.csproj @@ -29,7 +29,7 @@ - + diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Sensors.Location.Gnss.NmeaProcessor/Driver/Sensors.Location.Gnss.NmeaProcessor.csproj b/Source/Meadow.Foundation.Libraries_and_Frameworks/Sensors.Location.Gnss.NmeaProcessor/Driver/Sensors.Location.Gnss.NmeaProcessor.csproj index 69c68b9d9e..cc66492434 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Sensors.Location.Gnss.NmeaProcessor/Driver/Sensors.Location.Gnss.NmeaProcessor.csproj +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Sensors.Location.Gnss.NmeaProcessor/Driver/Sensors.Location.Gnss.NmeaProcessor.csproj @@ -20,6 +20,6 @@ - + diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Sensors.Location.Gnss.NmeaProcessor/Samples/NmeaProcessor_Sample/NmeaProcessor_Sample.csproj b/Source/Meadow.Foundation.Libraries_and_Frameworks/Sensors.Location.Gnss.NmeaProcessor/Samples/NmeaProcessor_Sample/NmeaProcessor_Sample.csproj index 90d9b56fc1..b09c180581 100644 --- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Sensors.Location.Gnss.NmeaProcessor/Samples/NmeaProcessor_Sample/NmeaProcessor_Sample.csproj +++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Sensors.Location.Gnss.NmeaProcessor/Samples/NmeaProcessor_Sample/NmeaProcessor_Sample.csproj @@ -13,7 +13,7 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Audio.Mp3.Yx5300/Driver/Audio.Mp3.Yx5300.csproj b/Source/Meadow.Foundation.Peripherals/Audio.Mp3.Yx5300/Driver/Audio.Mp3.Yx5300.csproj index 22a753d535..97c48c99db 100644 --- a/Source/Meadow.Foundation.Peripherals/Audio.Mp3.Yx5300/Driver/Audio.Mp3.Yx5300.csproj +++ b/Source/Meadow.Foundation.Peripherals/Audio.Mp3.Yx5300/Driver/Audio.Mp3.Yx5300.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Audio.Mp3.Yx5300/Samples/Yx5300_Sample/Yx5300_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Audio.Mp3.Yx5300/Samples/Yx5300_Sample/Yx5300_Sample.csproj index fabfbad8b5..d0b166c4eb 100644 --- a/Source/Meadow.Foundation.Peripherals/Audio.Mp3.Yx5300/Samples/Yx5300_Sample/Yx5300_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Audio.Mp3.Yx5300/Samples/Yx5300_Sample/Yx5300_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Audio.Radio.Tea5767/Driver/Audio.Radio.Tea5767.csproj b/Source/Meadow.Foundation.Peripherals/Audio.Radio.Tea5767/Driver/Audio.Radio.Tea5767.csproj index 7449e4cf31..06de32f482 100644 --- a/Source/Meadow.Foundation.Peripherals/Audio.Radio.Tea5767/Driver/Audio.Radio.Tea5767.csproj +++ b/Source/Meadow.Foundation.Peripherals/Audio.Radio.Tea5767/Driver/Audio.Radio.Tea5767.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Audio.Radio.Tea5767/Driver/Tea5767.Enums.cs b/Source/Meadow.Foundation.Peripherals/Audio.Radio.Tea5767/Driver/Tea5767.Enums.cs index 8e5481dc86..6367d6f020 100644 --- a/Source/Meadow.Foundation.Peripherals/Audio.Radio.Tea5767/Driver/Tea5767.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Audio.Radio.Tea5767/Driver/Tea5767.Enums.cs @@ -3,9 +3,9 @@ public partial class Tea5767 { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// - public enum Address : byte + public enum Addresses : byte { /// /// I2C address 0 diff --git a/Source/Meadow.Foundation.Peripherals/Audio.Radio.Tea5767/Driver/Tea5767.cs b/Source/Meadow.Foundation.Peripherals/Audio.Radio.Tea5767/Driver/Tea5767.cs index d21d9d3445..066da694e5 100644 --- a/Source/Meadow.Foundation.Peripherals/Audio.Radio.Tea5767/Driver/Tea5767.cs +++ b/Source/Meadow.Foundation.Peripherals/Audio.Radio.Tea5767/Driver/Tea5767.cs @@ -1,20 +1,20 @@  -using System; -using System.Threading; using Meadow.Hardware; using Meadow.Units; +using System; +using System.Threading; namespace Meadow.Foundation.Audio.Radio { /// /// Represents a TEA5767 radio /// - public partial class Tea5767 + public partial class Tea5767 : II2cPeripheral { /// - /// TEA5767 radio. + /// I2C Communication bus used to communicate with the peripheral /// - private readonly II2cPeripheral i2cPeripheral; + protected readonly II2cCommunications i2cComms; byte hiInjection; readonly Memory writeBuffer = new byte[5]; @@ -25,14 +25,19 @@ public partial class Tea5767 /// public bool IsMuted { get; set; } + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + /// /// Create a new TEA5767 object using the default parameters /// /// I2Cbus connected to the radio /// Address of the bus on the I2C display. - public Tea5767(II2cBus i2cBus, byte address = (byte)Address.Default) + public Tea5767(II2cBus i2cBus, byte address = (byte)Addresses.Default) { - i2cPeripheral = new I2cPeripheral(i2cBus, address); + i2cComms = new I2cCommunications(i2cBus, address); InitTEA5767(); } @@ -111,7 +116,7 @@ void SetFrequency(double frequency) void TransmitData() { - i2cPeripheral.Exchange(writeBuffer.Span, readBuffer.Span); + i2cComms.Exchange(writeBuffer.Span, readBuffer.Span); Thread.Sleep(100); } @@ -155,7 +160,7 @@ public void SelectFrequency(Frequency frequency) void ReadStatus() { - i2cPeripheral.Read(readBuffer.Span); + i2cComms.Read(readBuffer.Span); Thread.Sleep(100); } diff --git a/Source/Meadow.Foundation.Peripherals/Audio.Radio.Tea5767/Samples/Tea5767_Sample/Tea5767_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Audio.Radio.Tea5767/Samples/Tea5767_Sample/Tea5767_Sample.csproj index 93b8663c86..0a4bf80da1 100644 --- a/Source/Meadow.Foundation.Peripherals/Audio.Radio.Tea5767/Samples/Tea5767_Sample/Tea5767_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Audio.Radio.Tea5767/Samples/Tea5767_Sample/Tea5767_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Ch1115/Driver/Ch1115.cs b/Source/Meadow.Foundation.Peripherals/Displays.Ch1115/Driver/Ch1115.cs index 9c2ded5a69..3384dba39a 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Ch1115/Driver/Ch1115.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.Ch1115/Driver/Ch1115.cs @@ -1,15 +1,16 @@ using Meadow.Foundation.Graphics; using Meadow.Foundation.Graphics.Buffers; using Meadow.Hardware; +using Meadow.Units; using System; using System.Threading; namespace Meadow.Foundation.Displays { /// - /// Provide an interface to the Ch1115 family of displays. + /// Provide an interface to the Ch1115 family of displays /// - public partial class Ch1115 : IGraphicsDisplay + public partial class Ch1115 : IGraphicsDisplay, ISpiPeripheral { /// /// The display color mode - 1 bit per pixel monochrome @@ -37,18 +38,46 @@ public partial class Ch1115 : IGraphicsDisplay public IPixelBuffer PixelBuffer => imageBuffer; /// - /// SPI peripheral object + /// The default SPI bus speed for the device /// - ISpiPeripheral spiPerihperal; + public Frequency DefaultSpiBusSpeed => new Frequency(375, Frequency.UnitType.Kilohertz); - IDigitalOutputPort dataCommandPort; - IDigitalOutputPort resetPort; + /// + /// The SPI bus speed for the device + /// + public Frequency SpiBusSpeed + { + get => spiComms.BusSpeed; + set => spiComms.BusSpeed = value; + } + + /// + /// The default SPI bus mode for the device + /// + public SpiClockConfiguration.Mode DefaultSpiBusMode => SpiClockConfiguration.Mode.Mode0; + + /// + /// The SPI bus mode for the device + /// + public SpiClockConfiguration.Mode SpiBusMode + { + get => spiComms.BusMode; + set => spiComms.BusMode = value; + } + + /// + /// SPI Communication bus used to communicate with the peripheral + /// + protected readonly ISpiCommunications spiComms; + + readonly IDigitalOutputPort dataCommandPort; + readonly IDigitalOutputPort resetPort; const bool Data = true; const bool Command = false; - Buffer1bpp imageBuffer; - byte[] pageBuffer; + readonly Buffer1bpp imageBuffer; + readonly byte[] pageBuffer; /// /// Create a new Ch1115 object @@ -84,7 +113,7 @@ public Ch1115(ISpiBus spiBus, this.dataCommandPort = dataCommandPort; this.resetPort = resetPort; - spiPerihperal = new SpiPeripheral(spiBus, chipSelectPort); + spiComms = new SpiCommunications(spiBus, chipSelectPort, DefaultSpiBusSpeed, DefaultSpiBusMode); imageBuffer = new Buffer1bpp(width, height); pageBuffer = new byte[PageSize]; @@ -194,7 +223,7 @@ public void SetContrast(byte contrast) private void SendCommand(byte command) { dataCommandPort.State = Command; - spiPerihperal.Write(command); + spiComms.Write(command); } /// @@ -208,7 +237,7 @@ private void SendCommands(byte[] commands) Array.Copy(commands, 0, data, 1, commands.Length); dataCommandPort.State = Command; - spiPerihperal.Write(commands); + spiComms.Write(commands); } const int StartColumnOffset = 0; @@ -228,7 +257,7 @@ public void Show() dataCommandPort.State = Data; Array.Copy(imageBuffer.Buffer, Width * page, pageBuffer, 0, PageSize); - spiPerihperal.Write(pageBuffer); + spiComms.Write(pageBuffer); } } @@ -259,7 +288,7 @@ public void Show(int left, int top, int right, int bottom) dataCommandPort.State = Data; Array.Copy(imageBuffer.Buffer, Width * page, pageBuffer, 0, PageSize); - spiPerihperal.Write(pageBuffer); + spiComms.Write(pageBuffer); } } diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Ch1115/Driver/Displays.Ch1115.csproj b/Source/Meadow.Foundation.Peripherals/Displays.Ch1115/Driver/Displays.Ch1115.csproj index e9d6113de8..dadb73d968 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Ch1115/Driver/Displays.Ch1115.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.Ch1115/Driver/Displays.Ch1115.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Ch1115/Samples/Ch1115_Sample/Ch1115_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.Ch1115/Samples/Ch1115_Sample/Ch1115_Sample.csproj index 9e5b64a30b..ff2e0c050a 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Ch1115/Samples/Ch1115_Sample/Ch1115_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.Ch1115/Samples/Ch1115_Sample/Ch1115_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Ch1115/Samples/Ch1115_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Displays.Ch1115/Samples/Ch1115_Sample/MeadowApp.cs index 90862010c0..2d2d448c9e 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Ch1115/Samples/Ch1115_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.Ch1115/Samples/Ch1115_Sample/MeadowApp.cs @@ -6,7 +6,7 @@ namespace Displays.Ch1115_Sample { - public class MeadowApp : App + public class MeadowApp : App { // diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Gtk/Driver/Displays.Gtk.csproj b/Source/Meadow.Foundation.Peripherals/Displays.Gtk/Driver/Displays.Gtk.csproj index 0454cf7697..256638b403 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Gtk/Driver/Displays.Gtk.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.Gtk/Driver/Displays.Gtk.csproj @@ -25,6 +25,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Lcd.CharacterDisplay/Driver/Displays.Lcd.CharacterDisplay.csproj b/Source/Meadow.Foundation.Peripherals/Displays.Lcd.CharacterDisplay/Driver/Displays.Lcd.CharacterDisplay.csproj index 2ac132c89b..9bb9f0551f 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Lcd.CharacterDisplay/Driver/Displays.Lcd.CharacterDisplay.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.Lcd.CharacterDisplay/Driver/Displays.Lcd.CharacterDisplay.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Lcd.CharacterDisplay/Driver/GroveCharacterDisplay.cs b/Source/Meadow.Foundation.Peripherals/Displays.Lcd.CharacterDisplay/Driver/GroveCharacterDisplay.cs index ab904ea8a6..bcccf0c94b 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Lcd.CharacterDisplay/Driver/GroveCharacterDisplay.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.Lcd.CharacterDisplay/Driver/GroveCharacterDisplay.cs @@ -1,5 +1,5 @@ -using System.Threading; -using Meadow.Hardware; +using Meadow.Hardware; +using System.Threading; namespace Meadow.Foundation.Displays.Lcd { @@ -66,7 +66,7 @@ protected override void Initialize() protected override void Command(byte value) { var data = new byte[] { 0x80, value }; - i2cPeripheral.Write(data); + i2cComms.Write(data); } /// @@ -77,7 +77,7 @@ protected override void Command(byte value) protected override void Send(byte value, byte mode) { var data = new byte[] { 0x40, value }; - i2cPeripheral.Write(data); + i2cComms.Write(data); } } } \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Lcd.CharacterDisplay/Driver/I2cCharacterDisplay.Enums.cs b/Source/Meadow.Foundation.Peripherals/Displays.Lcd.CharacterDisplay/Driver/I2cCharacterDisplay.Enums.cs index 6fe29f48d5..6b44b83894 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Lcd.CharacterDisplay/Driver/I2cCharacterDisplay.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.Lcd.CharacterDisplay/Driver/I2cCharacterDisplay.Enums.cs @@ -3,7 +3,7 @@ public partial class I2cCharacterDisplay { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Lcd.CharacterDisplay/Driver/I2cCharacterDisplay.cs b/Source/Meadow.Foundation.Peripherals/Displays.Lcd.CharacterDisplay/Driver/I2cCharacterDisplay.cs index 30d5941143..54f5b3cae9 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Lcd.CharacterDisplay/Driver/I2cCharacterDisplay.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.Lcd.CharacterDisplay/Driver/I2cCharacterDisplay.cs @@ -7,18 +7,23 @@ namespace Meadow.Foundation.Displays.Lcd /// /// Represents a character display using I2C /// - public partial class I2cCharacterDisplay : ICharacterDisplay + public partial class I2cCharacterDisplay : ICharacterDisplay, II2cPeripheral { /// - /// The I2C peripheral used to communicate with the display + /// The default I2C address for the peripheral /// - protected readonly II2cPeripheral i2cPeripheral; + public byte DefaultI2cAddress => (byte)Addresses.Default; + + /// + /// I2C Communication bus used to communicate with the peripheral + /// + protected readonly II2cCommunications i2cComms; /// /// Display control value /// protected byte displayControl; - + /// /// Display mode value /// @@ -77,7 +82,7 @@ protected enum I2CCommands /// LCD_SETDDRAMADDR = 0x80, } - + // flags for display entry mode internal static byte LCD_ENTRYRIGHT = 0x00; internal static byte LCD_ENTRYLEFT = 0x02; @@ -123,7 +128,7 @@ protected enum I2CCommands /// Number of character columns public I2cCharacterDisplay(II2cBus i2cBus, byte address = (byte)Addresses.Default, byte rows = 4, byte columns = 20) { - i2cPeripheral = new I2cPeripheral(i2cBus, address); + i2cComms = new I2cCommunications(i2cBus, address); DisplayConfig = new TextDisplayConfig() { Width = columns, Height = rows }; backlightValue = LCD_BACKLIGHT; @@ -138,7 +143,7 @@ protected virtual void Initialize() { var displayFunction = (byte)(LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS); - if(DisplayConfig.Height > 1) + if (DisplayConfig.Height > 1) { displayFunction |= LCD_2LINE; } @@ -181,7 +186,7 @@ protected virtual void Initialize() void Home() { Command((byte)I2CCommands.LCD_RETURNHOME); // set cursor position to zero - Thread.Sleep(2); + Thread.Sleep(2); } /// @@ -201,7 +206,7 @@ void Write4Bits(byte value) void ExpanderWrite(byte value) { - i2cPeripheral.Write((byte)(value | backlightValue)); + i2cComms.Write((byte)(value | backlightValue)); } /// @@ -262,7 +267,7 @@ public void SetCursorPosition(byte column, byte line) if (line > DisplayConfig.Height) { - line = (byte)(DisplayConfig.Height - 1); + line = (byte)(DisplayConfig.Height - 1); } Command((byte)((byte)I2CCommands.LCD_SETDDRAMADDR | (column + rowOffsets[line]))); @@ -422,7 +427,7 @@ public void SaveCustomCharacter(byte[] characterMap, byte address) Command((byte)((byte)I2CCommands.LCD_SETCGRAMADDR | (address << 3))); for (int i = 0; i < 8; i++) { - i2cPeripheral.WriteRegister(Rs, characterMap[i]); + i2cComms.WriteRegister(Rs, characterMap[i]); } } diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Lcd.CharacterDisplay/Samples/CharacterDisplay_Sample/CharacterDisplay_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.Lcd.CharacterDisplay/Samples/CharacterDisplay_Sample/CharacterDisplay_Sample.csproj index 3027db4da9..a3072ddbd8 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Lcd.CharacterDisplay/Samples/CharacterDisplay_Sample/CharacterDisplay_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.Lcd.CharacterDisplay/Samples/CharacterDisplay_Sample/CharacterDisplay_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Led.FourDigitSevenSegment/Driver/Displays.Led.FourDigitSevenSegment.csproj b/Source/Meadow.Foundation.Peripherals/Displays.Led.FourDigitSevenSegment/Driver/Displays.Led.FourDigitSevenSegment.csproj index ba3559ad4a..067f6011f4 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Led.FourDigitSevenSegment/Driver/Displays.Led.FourDigitSevenSegment.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.Led.FourDigitSevenSegment/Driver/Displays.Led.FourDigitSevenSegment.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Led.FourDigitSevenSegment/Driver/FourDigitSevenSegment.cs b/Source/Meadow.Foundation.Peripherals/Displays.Led.FourDigitSevenSegment/Driver/FourDigitSevenSegment.cs index 0a8807da19..7df8edc0ae 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Led.FourDigitSevenSegment/Driver/FourDigitSevenSegment.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.Led.FourDigitSevenSegment/Driver/FourDigitSevenSegment.cs @@ -12,8 +12,7 @@ public class FourDigitSevenSegment CancellationTokenSource cts = null; readonly IDigitalOutputPort[] digits; - - SevenSegment[] sevenSegments; + readonly SevenSegment[] sevenSegments; /// /// Creates a SevenSegment connected to the especified IPins to a IODevice diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Led.FourDigitSevenSegment/Samples/FourDigitSevenSegment_Sample/FourDigitSevenSegment_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.Led.FourDigitSevenSegment/Samples/FourDigitSevenSegment_Sample/FourDigitSevenSegment_Sample.csproj index 5ba5b90891..ca22616d61 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Led.FourDigitSevenSegment/Samples/FourDigitSevenSegment_Sample/FourDigitSevenSegment_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.Led.FourDigitSevenSegment/Samples/FourDigitSevenSegment_Sample/FourDigitSevenSegment_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Led.FourteenSegment/Driver/Displays.Led.FourteenSegment.csproj b/Source/Meadow.Foundation.Peripherals/Displays.Led.FourteenSegment/Driver/Displays.Led.FourteenSegment.csproj new file mode 100644 index 0000000000..d2d8f36533 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Displays.Led.FourteenSegment/Driver/Displays.Led.FourteenSegment.csproj @@ -0,0 +1,22 @@ + + + true + icon.png + Wilderness Labs, Inc + netstandard2.1 + Library + FourteenSegment + Wilderness Labs, Inc + http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ + Meadow.Foundation.Displays.Led.FourteenSegment + https://github.com/WildernessLabs/Meadow.Foundation + Meadow.Foundation,FourteenSegment,Fourteen,14,Segment,Display,LED + 0.1.0 + true + Digital Fourteen (14) segment display + + + + + + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Led.FourteenSegment/Driver/FourteenSegment.Ascii.cs b/Source/Meadow.Foundation.Peripherals/Displays.Led.FourteenSegment/Driver/FourteenSegment.Ascii.cs new file mode 100644 index 0000000000..b03711bcd4 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Displays.Led.FourteenSegment/Driver/FourteenSegment.Ascii.cs @@ -0,0 +1,104 @@ +namespace Meadow.Foundation.Displays.Led +{ + public partial class FourteenSegment + { + static ushort[] fourteenSegmentASCII = { + 0b000000000000000, /* (space) */ + 0b100000000000110, /* ! */ + 0b000001000000010, /* " */ + 0b001001011001110, /* # */ + 0b001001011101101, /* $ */ + 0b011111111100100, /* % */ + 0b010001101011001, /* & */ + 0b000001000000000, /* ' */ + 0b010010000000000, /* ( */ + 0b000100100000000, /* ) */ + 0b011111111000000, /* * */ + 0b001001011000000, /* + */ + 0b000100000000000, /* , */ + 0b000000011000000, /* - */ + 0b100000000000000, /* . */ + 0b000110000000000, /* / */ + 0b000110000111111, /* 0 */ + 0b000010000000110, /* 1 */ + 0b000000011011011, /* 2 */ + 0b000000010001111, /* 3 */ + 0b000000011100110, /* 4 */ + 0b010000001101001, /* 5 */ + 0b000000011111101, /* 6 */ + 0b000000000000111, /* 7 */ + 0b000000011111111, /* 8 */ + 0b000000011101111, /* 9 */ + 0b001001000000000, /* : */ + 0b000101000000000, /* ; */ + 0b010010001000000, /* < */ + 0b000000011001000, /* = */ + 0b000100110000000, /* > */ + 0b101000010000011, /* ? */ + 0b000001010111011, /* @ */ + 0b000000011110111, /* A */ + 0b001001010001111, /* B */ + 0b000000000111001, /* C */ + 0b001001000001111, /* D */ + 0b000000001111001, /* E */ + 0b000000001110001, /* F */ + 0b000000010111101, /* G */ + 0b000000011110110, /* H */ + 0b001001000001001, /* I */ + 0b000000000011110, /* J */ + 0b010010001110000, /* K */ + 0b000000000111000, /* L */ + 0b000010100110110, /* M */ + 0b010000100110110, /* N */ + 0b000000000111111, /* O */ + 0b000000011110011, /* P */ + 0b010000000111111, /* Q */ + 0b010000011110011, /* R */ + 0b000000011101101, /* S */ + 0b001001000000001, /* T */ + 0b000000000111110, /* U */ + 0b000110000110000, /* V */ + 0b010100000110110, /* W */ + 0b010110100000000, /* X */ + 0b000000011101110, /* Y */ + 0b000110000001001, /* Z */ + 0b000000000111001, /* [ */ + 0b010000100000000, /* \ */ + 0b000000000001111, /* ] */ + 0b010100000000000, /* ^ */ + 0b000000000001000, /* _ */ + 0b000000100000000, /* ` */ + 0b001000001011000, /* a */ + 0b010000001111000, /* b */ + 0b000000011011000, /* c */ + 0b000100010001110, /* d */ + 0b000100001011000, /* e */ + 0b001010011000000, /* f */ + 0b000010010001110, /* g */ + 0b001000001110000, /* h */ + 0b001000000000000, /* i */ + 0b000101000010000, /* j */ + 0b011011000000000, /* k */ + 0b000000000110000, /* l */ + 0b001000011010100, /* m */ + 0b001000001010000, /* n */ + 0b000000011011100, /* o */ + 0b000000101110000, /* p */ + 0b000010010000110, /* q */ + 0b000000001010000, /* r */ + 0b010000010001000, /* s */ + 0b000000001111000, /* t */ + 0b000000000011100, /* u */ + 0b000100000010000, /* v */ + 0b010100000010100, /* w */ + 0b010110100000000, /* x */ + 0b000001010001110, /* y */ + 0b000100001001000, /* z */ + 0b000100101001001, /* { */ + 0b001001000000000, /* | */ + 0b010010010001001, /* } */ + 0b000110011000000, /* ~ */ + 0b000000000000000, /* (del) */ + }; + } +} diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Led.FourteenSegment/Driver/FourteenSegment.Enums.cs b/Source/Meadow.Foundation.Peripherals/Displays.Led.FourteenSegment/Driver/FourteenSegment.Enums.cs new file mode 100644 index 0000000000..b592aeb17e --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Displays.Led.FourteenSegment/Driver/FourteenSegment.Enums.cs @@ -0,0 +1,72 @@ +namespace Meadow.Foundation.Displays.Led +{ + public partial class FourteenSegment + { + /// + /// The led segments + /// + public enum Segment : byte + { + /// + /// Segment A + /// + A, + /// + /// Segment B + /// + B, + /// + /// Segment C + /// + C, + /// + /// Segment D + /// + D, + /// + /// Segment E + /// + E, + /// + /// Segment F + /// + F, + /// + /// Segment G + /// + G, + /// + /// Segment G2 + /// + G2, + /// + /// Segment H + /// + H, + /// + /// Segment J + /// + J, + /// + /// Segment K + /// + K, + /// + /// Segment L + /// + L, + /// + /// Segment M + /// + M, + /// + /// Segment N + /// + N, + /// + /// Segment decimal + /// + Decimal, + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Led.FourteenSegment/Driver/FourteenSegment.cs b/Source/Meadow.Foundation.Peripherals/Displays.Led.FourteenSegment/Driver/FourteenSegment.cs new file mode 100644 index 0000000000..79ba8c1a7f --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Displays.Led.FourteenSegment/Driver/FourteenSegment.cs @@ -0,0 +1,169 @@ +using Meadow.Hardware; + +namespace Meadow.Foundation.Displays.Led +{ + /// + /// Fourteen Segment Display + /// + public partial class FourteenSegment + { + private readonly IDigitalOutputPort portA; + private readonly IDigitalOutputPort portB; + private readonly IDigitalOutputPort portC; + private readonly IDigitalOutputPort portD; + private readonly IDigitalOutputPort portE; + private readonly IDigitalOutputPort portF; + private readonly IDigitalOutputPort portG; + private readonly IDigitalOutputPort portG2; + private readonly IDigitalOutputPort portH; + private readonly IDigitalOutputPort portJ; + private readonly IDigitalOutputPort portK; + private readonly IDigitalOutputPort portL; + private readonly IDigitalOutputPort portM; + private readonly IDigitalOutputPort portN; + private readonly IDigitalOutputPort portDecimal; + + private readonly bool isCommonCathode; + + /// + /// Creates a FourteenSegment connected to the especified IPins to a IODevice + /// + /// Pin A + /// Pin B + /// Pin C + /// Pin D + /// Pin E + /// Pin F + /// Pin G + /// Pin G2 + /// Pin H + /// Pin J + /// Pin K + /// Pin L + /// Pin M + /// Pin N + /// Pin decimal + /// Is the display using common cathod (true) or common annode (false) + public FourteenSegment( + IPin pinA, IPin pinB, IPin pinC, IPin pinD, IPin pinE, IPin pinF, IPin pinG, + IPin pinG2, IPin pinH, IPin pinJ, IPin pinK, IPin pinL, IPin pinM, IPin pinN, + IPin pinDecimal, + bool isCommonCathode) : + this(pinA.CreateDigitalOutputPort(), + pinB.CreateDigitalOutputPort(), + pinC.CreateDigitalOutputPort(), + pinD.CreateDigitalOutputPort(), + pinE.CreateDigitalOutputPort(), + pinF.CreateDigitalOutputPort(), + pinG.CreateDigitalOutputPort(), + pinG2.CreateDigitalOutputPort(), + pinH.CreateDigitalOutputPort(), + pinJ.CreateDigitalOutputPort(), + pinK.CreateDigitalOutputPort(), + pinL.CreateDigitalOutputPort(), + pinM.CreateDigitalOutputPort(), + pinN.CreateDigitalOutputPort(), + pinDecimal.CreateDigitalOutputPort(), + isCommonCathode) + { } + + /// + /// Creates a FourteenSegment connected to the especified IDigitalOutputPorts + /// + /// Digital input port for pin A + /// Digital input port for pin B + /// Digital input port for pin C + /// Digital input port for pin D + /// Digital input port for pin E + /// Digital input port for pin F + /// Digital input port for pin G + /// Digital input port for pin G2 + /// Digital input port for pin H + /// Digital input port for pin J + /// Digital input port for pin K + /// Digital input port for pin L + /// Digital input port for pin M + /// Digital input port for pin N + /// Digital input port for decimal pin + /// Is the display using common cathod (true) or common annode (false) + public FourteenSegment( + IDigitalOutputPort portA, IDigitalOutputPort portB, IDigitalOutputPort portC, IDigitalOutputPort portD, + IDigitalOutputPort portE, IDigitalOutputPort portF, IDigitalOutputPort portG, IDigitalOutputPort portG2, + IDigitalOutputPort portH, IDigitalOutputPort portJ, IDigitalOutputPort portK, IDigitalOutputPort portL, + IDigitalOutputPort portM, IDigitalOutputPort portN, + IDigitalOutputPort portDecimal, + bool isCommonCathode) + { + this.portA = portA; + this.portB = portB; + this.portC = portC; + this.portD = portD; + this.portE = portE; + this.portF = portF; + this.portG = portG; + this.portG2 = portG2; + this.portH = portH; + this.portJ = portJ; + this.portK = portK; + this.portL = portL; + this.portM = portM; + this.portN = portN; + this.portDecimal = portDecimal; + + this.isCommonCathode = isCommonCathode; + } + + /// + /// Displays the specified ascii character (from 32 to 126) + /// Unsupported ascii values will be blank + /// + public void SetDisplay(char asciiCharacter, bool? showDecimal = null) + { + if (asciiCharacter < 32 || asciiCharacter > 126) + { + asciiCharacter = ' '; + } + + var data = fourteenSegmentASCII[asciiCharacter - 32]; + + portA.State = (data & 1 << 0) != 0; + portB.State = (data & 1 << 1) != 0; + portC.State = (data & 1 << 2) != 0; + portD.State = (data & 1 << 3) != 0; + portE.State = (data & 1 << 4) != 0; + portF.State = (data & 1 << 5) != 0; + portG.State = (data & 1 << 6) != 0; + portG2.State = (data & 1 << 7) != 0; + portH.State = (data & 1 << 8) != 0; + portJ.State = (data & 1 << 9) != 0; + portK.State = (data & 1 << 10) != 0; + portL.State = (data & 1 << 11) != 0; + portM.State = (data & 1 << 12) != 0; + portN.State = (data & 1 << 13) != 0; + portDecimal.State = (data & 1 << 14) != 0; + + if (showDecimal != null) + { + portDecimal.State = isCommonCathode ? showDecimal.Value : !showDecimal.Value; + } + } + + /// + /// Is a specific led segment enabled for an ascii character + /// + /// The led segment + /// The ascii character + /// + public static bool IsEnabled(Segment segment, char asciiCharacter) + { + if (asciiCharacter < 32 || asciiCharacter > 126) + { + return false; + } + + var data = fourteenSegmentASCII[asciiCharacter - 32]; + + return (data & 1 << (int)segment) != 0; + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Led.FourteenSegment/Samples/FourteenSegment_Sample/FourteenSegment_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.Led.FourteenSegment/Samples/FourteenSegment_Sample/FourteenSegment_Sample.csproj new file mode 100644 index 0000000000..587271b4e7 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Displays.Led.FourteenSegment/Samples/FourteenSegment_Sample/FourteenSegment_Sample.csproj @@ -0,0 +1,20 @@ + + + https://github.com/WildernessLabs/Meadow.Foundation + Wilderness Labs, Inc + Wilderness Labs, Inc + true + netstandard2.1 + Library + App + + + + + + + + Always + + + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Led.FourteenSegment/Samples/FourteenSegment_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Displays.Led.FourteenSegment/Samples/FourteenSegment_Sample/MeadowApp.cs new file mode 100644 index 0000000000..0cc3a93fee --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Displays.Led.FourteenSegment/Samples/FourteenSegment_Sample/MeadowApp.cs @@ -0,0 +1,50 @@ +using Meadow; +using Meadow.Devices; +using Meadow.Foundation.Displays.Led; +using System.Threading.Tasks; + +namespace Displays.Led.FourteenSegment_Sample +{ + public class MeadowApp : App + { + // + + FourteenSegment fourteenSegment; + + public override Task Initialize() + { + Resolver.Log.Info("Initializing..."); + + fourteenSegment = new FourteenSegment + ( + portA: Device.CreateDigitalOutputPort(Device.Pins.D00), + portB: Device.CreateDigitalOutputPort(Device.Pins.D01), + portC: Device.CreateDigitalOutputPort(Device.Pins.D02), + portD: Device.CreateDigitalOutputPort(Device.Pins.D03), + portE: Device.CreateDigitalOutputPort(Device.Pins.D04), + portF: Device.CreateDigitalOutputPort(Device.Pins.D05), + portG: Device.CreateDigitalOutputPort(Device.Pins.D06), + portG2: Device.CreateDigitalOutputPort(Device.Pins.D07), + portH: Device.CreateDigitalOutputPort(Device.Pins.D08), + portJ: Device.CreateDigitalOutputPort(Device.Pins.D09), + portK: Device.CreateDigitalOutputPort(Device.Pins.D10), + portL: Device.CreateDigitalOutputPort(Device.Pins.D11), + portM: Device.CreateDigitalOutputPort(Device.Pins.D12), + portN: Device.CreateDigitalOutputPort(Device.Pins.D13), + portDecimal: Device.CreateDigitalOutputPort(Device.Pins.D14), + isCommonCathode: false + ); + + return base.Initialize(); + } + + public override Task Run() + { + fourteenSegment.SetDisplay(asciiCharacter: 'A', showDecimal: true); + + return base.Run(); + } + + // + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Led.FourteenSegment/Samples/FourteenSegment_Sample/meadow.config.yaml b/Source/Meadow.Foundation.Peripherals/Displays.Led.FourteenSegment/Samples/FourteenSegment_Sample/meadow.config.yaml new file mode 100644 index 0000000000..32363cb69c --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Displays.Led.FourteenSegment/Samples/FourteenSegment_Sample/meadow.config.yaml @@ -0,0 +1,2 @@ +MonoControl: + Options: --jit \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Led.SevenSegment/Driver/Displays.Led.SevenSegment.csproj b/Source/Meadow.Foundation.Peripherals/Displays.Led.SevenSegment/Driver/Displays.Led.SevenSegment.csproj index cfac952597..f0ecda2e5c 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Led.SevenSegment/Driver/Displays.Led.SevenSegment.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.Led.SevenSegment/Driver/Displays.Led.SevenSegment.csproj @@ -10,13 +10,13 @@ http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ Meadow.Foundation.Displays.Led.SevenSegment https://github.com/WildernessLabs/Meadow.Foundation - Meadow.Foundation, SevenSegment, Display + Meadow.Foundation,SevenSegment,Seven,7,Segment,Display,LED 0.9.52 true - Ditigal Seven segment displays + Digital Seven (7) segment display - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Led.SevenSegment/Samples/SevenSegment_Sample/SevenSegment_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.Led.SevenSegment/Samples/SevenSegment_Sample/SevenSegment_Sample.csproj index 8ddd30aaae..17d6c70395 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Led.SevenSegment/Samples/SevenSegment_Sample/SevenSegment_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.Led.SevenSegment/Samples/SevenSegment_Sample/SevenSegment_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Sh1106/Driver/Displays.Sh1106.csproj b/Source/Meadow.Foundation.Peripherals/Displays.Led.SixteenSegment/Driver/Displays.Led.SixteenSegment.csproj similarity index 65% rename from Source/Meadow.Foundation.Peripherals/Displays.Sh1106/Driver/Displays.Sh1106.csproj rename to Source/Meadow.Foundation.Peripherals/Displays.Led.SixteenSegment/Driver/Displays.Led.SixteenSegment.csproj index ace950b3bf..c28d4525d0 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Sh1106/Driver/Displays.Sh1106.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.Led.SixteenSegment/Driver/Displays.Led.SixteenSegment.csproj @@ -5,18 +5,18 @@ Wilderness Labs, Inc netstandard2.1 Library - Sh1106 + SixteenSegment Wilderness Labs, Inc http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ - Meadow.Foundation.Displays.Sh1106 + Meadow.Foundation.Displays.Led.SixteenSegment https://github.com/WildernessLabs/Meadow.Foundation - Meadow, Meadow.Foundation, Displays, LCD, Sh1106 + Meadow.Foundation,SixteenSegment,Sixteen,14,Segment,Display,LED 0.1.0 true - Sh1106 SPI monochrome OLED display + Digital Sixteen (16) segment display - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Led.SixteenSegment/Driver/SixteenSegment.Ascii.cs b/Source/Meadow.Foundation.Peripherals/Displays.Led.SixteenSegment/Driver/SixteenSegment.Ascii.cs new file mode 100644 index 0000000000..eaa611fc04 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Displays.Led.SixteenSegment/Driver/SixteenSegment.Ascii.cs @@ -0,0 +1,104 @@ +namespace Meadow.Foundation.Displays.Led +{ + public partial class SixteenSegment + { + static uint[] sixteenSegmentASCII = { + 0b00000000000000000, /* (space) */ + 0b10000000000001100, /* ! */ + 0b00000001000000100, /* " */ + 0b01010101000111100, /* # */ + 0b01010101010111011, /* $ */ + 0b01110111010011001, /* % */ + 0b01001001101110001, /* & */ + 0b00000001000000000, /* ' */ + 0b00001010000000000, /* ( */ + 0b00100000100000000, /* ) */ + 0b01111111100000000, /* * */ + 0b01010101000000000, /* + */ + 0b00100000000000000, /* , */ + 0b01000100000000000, /* - */ + 0b10000000000000000, /* . */ + 0b00100010000000000, /* / */ + 0b00100010011111111, /* 0 */ + 0b00000010000001100, /* 1 */ + 0b01000100001110111, /* 2 */ + 0b00000100000111111, /* 3 */ + 0b01000100010001100, /* 4 */ + 0b01001000010110011, /* 5 */ + 0b01000100011111011, /* 6 */ + 0b00000000000001111, /* 7 */ + 0b01000100011111111, /* 8 */ + 0b01000100010111111, /* 9 */ + 0b00010001000000000, /* : */ + 0b00100001000000000, /* ; */ + 0b01001010000000000, /* < */ + 0b01000100000110000, /* = */ + 0b00100100100000000, /* > */ + 0b10010100000000111, /* ? */ + 0b00000101011110111, /* @ */ + 0b01000100011001111, /* A */ + 0b00010101000111111, /* B */ + 0b00000000011110011, /* C */ + 0b00010001000111111, /* D */ + 0b01000000011110011, /* E */ + 0b01000000011000011, /* F */ + 0b00000100011111011, /* G */ + 0b01000100011001100, /* H */ + 0b00010001000110011, /* I */ + 0b00000000001111100, /* J */ + 0b01001010011000000, /* K */ + 0b00000000011110000, /* L */ + 0b00000010111001100, /* M */ + 0b00001000111001100, /* N */ + 0b00000000011111111, /* O */ + 0b01000100011000111, /* P */ + 0b00001000011111111, /* Q */ + 0b01001100011000111, /* R */ + 0b01000100010111011, /* S */ + 0b00010001000000011, /* T */ + 0b00000000011111100, /* U */ + 0b00100010011000000, /* V */ + 0b00101000011001100, /* W */ + 0b00101010100000000, /* X */ + 0b01000100010111100, /* Y */ + 0b00100010000110011, /* Z */ + 0b00010001000010010, /* [ */ + 0b00001000100000000, /* \ */ + 0b00010001000100001, /* ] */ + 0b00101000000000000, /* ^ */ + 0b00000000000110000, /* _ */ + 0b00000000100000000, /* ` */ + 0b01010000001110000, /* a */ + 0b01010000011100000, /* b */ + 0b01000000001100000, /* c */ + 0b00010100000011100, /* d */ + 0b01100000001100000, /* e */ + 0b01010101000000010, /* f */ + 0b01010001010100001, /* g */ + 0b01010000011000000, /* h */ + 0b00010000000000000, /* i */ + 0b00010001001100000, /* j */ + 0b00011011000000000, /* k */ + 0b00000000011000000, /* l */ + 0b01010100001001000, /* m */ + 0b01010000001000000, /* n */ + 0b01010000001100000, /* o */ + 0b01000001011000001, /* p */ + 0b01010001010000001, /* q */ + 0b01000000001000000, /* r */ + 0b01010000010100001, /* s */ + 0b01000000011100000, /* t */ + 0b00010000001100000, /* u */ + 0b00100000001000000, /* v */ + 0b00101000001001000, /* w */ + 0b00101010100000000, /* x */ + 0b00000101000011100, /* y */ + 0b01100000000100000, /* z */ + 0b01010001000010010, /* { */ + 0b00010001000000000, /* | */ + 0b00010101000100001, /* } */ + 0b01100110000000000, /* ~ */ + 0b00000000000000000, /* (del) */ + }; + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Led.SixteenSegment/Driver/SixteenSegment.Enums.cs b/Source/Meadow.Foundation.Peripherals/Displays.Led.SixteenSegment/Driver/SixteenSegment.Enums.cs new file mode 100644 index 0000000000..7a5e11a350 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Displays.Led.SixteenSegment/Driver/SixteenSegment.Enums.cs @@ -0,0 +1,84 @@ +namespace Meadow.Foundation.Displays.Led +{ + public partial class SixteenSegment + { + /// + /// The led segments + /// + public enum Segment : byte + { + /// + /// Segment A + /// + A, + /// + /// Segment B + /// + B, + /// + /// Segment C + /// + C, + /// + /// Segment D + /// + D, + /// + /// Segment E + /// + E, + /// + /// Segment F + /// + F, + /// + /// Segment G + /// + G, + /// + /// Segment H + /// + H, + /// + /// Segment K + /// + K, + /// + /// Segment L + /// + L, + /// + /// Segment M + /// + M, + /// + /// Segment N + /// + N, + /// + /// Segment P + /// + P, + /// + /// Segment R + /// + R, + /// + /// Segment S + /// + S, + /// + /// Segment T + /// + T, + /// + /// Segment U + /// + U, + /// + /// Segment decimal + /// + Decimal, + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Led.SixteenSegment/Driver/SixteenSegment.cs b/Source/Meadow.Foundation.Peripherals/Displays.Led.SixteenSegment/Driver/SixteenSegment.cs new file mode 100644 index 0000000000..1e36a4cf8e --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Displays.Led.SixteenSegment/Driver/SixteenSegment.cs @@ -0,0 +1,183 @@ +using Meadow.Hardware; + +namespace Meadow.Foundation.Displays.Led +{ + /// + /// Sixteen Segment Display + /// + public partial class SixteenSegment + { + private readonly IDigitalOutputPort portA; + private readonly IDigitalOutputPort portB; + private readonly IDigitalOutputPort portC; + private readonly IDigitalOutputPort portD; + private readonly IDigitalOutputPort portE; + private readonly IDigitalOutputPort portF; + private readonly IDigitalOutputPort portG; + private readonly IDigitalOutputPort portH; + private readonly IDigitalOutputPort portK; + private readonly IDigitalOutputPort portM; + private readonly IDigitalOutputPort portN; + private readonly IDigitalOutputPort portP; + private readonly IDigitalOutputPort portR; + private readonly IDigitalOutputPort portS; + private readonly IDigitalOutputPort portT; + private readonly IDigitalOutputPort portU; + private readonly IDigitalOutputPort portDecimal; + + private readonly bool isCommonCathode; + + /// + /// Creates a SixteenSegment connected to the especified IPins to a IODevice + /// + /// Pin A + /// Pin B + /// Pin C + /// Pin D + /// Pin E + /// Pin F + /// Pin G + /// Pin H + /// Pin K + /// Pin M + /// Pin N + /// Pin P + /// Pin R + /// Pin S + /// Pin T + /// Pin U + /// Pin decimal + /// Is the display using common cathod (true) or common annode (false) + public SixteenSegment( + IPin pinA, IPin pinB, IPin pinC, IPin pinD, + IPin pinE, IPin pinF, IPin pinG, IPin pinH, + IPin pinK, IPin pinM, IPin pinN, IPin pinP, + IPin pinR, IPin pinS, IPin pinT, IPin pinU, + IPin pinDecimal, + bool isCommonCathode) : + this(pinA.CreateDigitalOutputPort(), + pinB.CreateDigitalOutputPort(), + pinC.CreateDigitalOutputPort(), + pinD.CreateDigitalOutputPort(), + pinE.CreateDigitalOutputPort(), + pinF.CreateDigitalOutputPort(), + pinG.CreateDigitalOutputPort(), + pinH.CreateDigitalOutputPort(), + pinK.CreateDigitalOutputPort(), + pinM.CreateDigitalOutputPort(), + pinN.CreateDigitalOutputPort(), + pinP.CreateDigitalOutputPort(), + pinR.CreateDigitalOutputPort(), + pinS.CreateDigitalOutputPort(), + pinT.CreateDigitalOutputPort(), + pinU.CreateDigitalOutputPort(), + pinDecimal.CreateDigitalOutputPort(), + isCommonCathode) + { } + + /// + /// Creates a SixteenSegment connected to the especified IDigitalOutputPorts + /// + /// Digital input port for pin A + /// Digital input port for pin B + /// Digital input port for pin C + /// Digital input port for pin D + /// Digital input port for pin E + /// Digital input port for pin F + /// Digital input port for pin G + /// Digital input port for pin H + /// Digital input port for pin K + /// Digital input port for pin M + /// Digital input port for pin N + /// Digital input port for pin P + /// Digital input port for pin R + /// Digital input port for pin S + /// Digital input port for pin T + /// Digital input port for pin U + /// Digital input port for decimal pin + /// Is the display using common cathod (true) or common annode (false) + public SixteenSegment( + IDigitalOutputPort portA, IDigitalOutputPort portB, IDigitalOutputPort portC, IDigitalOutputPort portD, + IDigitalOutputPort portE, IDigitalOutputPort portF, IDigitalOutputPort portG, IDigitalOutputPort portH, + IDigitalOutputPort portK, IDigitalOutputPort portM, IDigitalOutputPort portN, IDigitalOutputPort portP, + IDigitalOutputPort portR, IDigitalOutputPort portS, IDigitalOutputPort portT, IDigitalOutputPort portU, + IDigitalOutputPort portDecimal, + bool isCommonCathode) + { + this.portA = portA; + this.portB = portB; + this.portC = portC; + this.portD = portD; + this.portE = portE; + this.portF = portF; + this.portG = portG; + this.portH = portH; + this.portK = portK; + this.portM = portM; + this.portN = portN; + this.portP = portP; + this.portR = portR; + this.portS = portS; + this.portT = portT; + this.portU = portU; + this.portDecimal = portDecimal; + + this.isCommonCathode = isCommonCathode; + } + + /// + /// Displays the specified ascii character (from 32 to 126) + /// Unsupported ascii values will be blank + /// + public void SetDisplay(char asciiCharacter, bool? showDecimal = null) + { + if (asciiCharacter < 32 || asciiCharacter > 126) + { + asciiCharacter = ' '; + } + + var data = sixteenSegmentASCII[asciiCharacter - 32]; + + portA.State = (data & 1 << 0) != 0; + portB.State = (data & 1 << 1) != 0; + portC.State = (data & 1 << 2) != 0; + portD.State = (data & 1 << 3) != 0; + portE.State = (data & 1 << 4) != 0; + portF.State = (data & 1 << 5) != 0; + portG.State = (data & 1 << 6) != 0; + portH.State = (data & 1 << 7) != 0; + portK.State = (data & 1 << 8) != 0; + portM.State = (data & 1 << 9) != 0; + portN.State = (data & 1 << 10) != 0; + portP.State = (data & 1 << 11) != 0; + portR.State = (data & 1 << 12) != 0; + portS.State = (data & 1 << 13) != 0; + portT.State = (data & 1 << 14) != 0; + portU.State = (data & 1 << 15) != 0; + portDecimal.State = (data & 1 << 16) != 0; + + if (showDecimal != null) + { + portDecimal.State = isCommonCathode ? showDecimal.Value : !showDecimal.Value; + } + } + + /// + /// Is a specific led segment enabled for an ascii character + /// + /// The led segment + /// The ascii character + /// + public static bool IsEnabled(Segment segment, char asciiCharacter) + { + if (asciiCharacter < 32 || asciiCharacter > 126) + { + return false; + } + + var data = sixteenSegmentASCII[asciiCharacter - 32]; + + return (data & 1 << (int)segment) != 0; + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Led.SixteenSegment/Samples/SixteenSegment_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Displays.Led.SixteenSegment/Samples/SixteenSegment_Sample/MeadowApp.cs new file mode 100644 index 0000000000..e921f28c6c --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Displays.Led.SixteenSegment/Samples/SixteenSegment_Sample/MeadowApp.cs @@ -0,0 +1,52 @@ +using Meadow; +using Meadow.Devices; +using Meadow.Foundation.Displays.Led; +using System.Threading.Tasks; + +namespace Displays.Led.SixteenSegment_Sample +{ + public class MeadowApp : App + { + // + + SixteenSegment sixteenSegment; + + public override Task Initialize() + { + Resolver.Log.Info("Initializing..."); + + sixteenSegment = new SixteenSegment + ( + portA: Device.CreateDigitalOutputPort(Device.Pins.D00), + portB: Device.CreateDigitalOutputPort(Device.Pins.D01), + portC: Device.CreateDigitalOutputPort(Device.Pins.D02), + portD: Device.CreateDigitalOutputPort(Device.Pins.D03), + portE: Device.CreateDigitalOutputPort(Device.Pins.D04), + portF: Device.CreateDigitalOutputPort(Device.Pins.D05), + portG: Device.CreateDigitalOutputPort(Device.Pins.D06), + portH: Device.CreateDigitalOutputPort(Device.Pins.D07), + portK: Device.CreateDigitalOutputPort(Device.Pins.D08), + portM: Device.CreateDigitalOutputPort(Device.Pins.D09), + portN: Device.CreateDigitalOutputPort(Device.Pins.D10), + portP: Device.CreateDigitalOutputPort(Device.Pins.D11), + portR: Device.CreateDigitalOutputPort(Device.Pins.D12), + portS: Device.CreateDigitalOutputPort(Device.Pins.D13), + portT: Device.CreateDigitalOutputPort(Device.Pins.D14), + portU: Device.CreateDigitalOutputPort(Device.Pins.D15), + portDecimal: Device.CreateDigitalOutputPort(Device.Pins.A00), + isCommonCathode: false + ); + + return base.Initialize(); + } + + public override Task Run() + { + sixteenSegment.SetDisplay(asciiCharacter: 'Z', showDecimal: true); + + return base.Run(); + } + + // + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Led.SixteenSegment/Samples/SixteenSegment_Sample/SixteenSegment_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.Led.SixteenSegment/Samples/SixteenSegment_Sample/SixteenSegment_Sample.csproj new file mode 100644 index 0000000000..f0550a6169 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Displays.Led.SixteenSegment/Samples/SixteenSegment_Sample/SixteenSegment_Sample.csproj @@ -0,0 +1,20 @@ + + + https://github.com/WildernessLabs/Meadow.Foundation + Wilderness Labs, Inc + Wilderness Labs, Inc + true + netstandard2.1 + Library + App + + + + + + + + Always + + + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Led.SixteenSegment/Samples/SixteenSegment_Sample/meadow.config.yaml b/Source/Meadow.Foundation.Peripherals/Displays.Led.SixteenSegment/Samples/SixteenSegment_Sample/meadow.config.yaml new file mode 100644 index 0000000000..32363cb69c --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Displays.Led.SixteenSegment/Samples/SixteenSegment_Sample/meadow.config.yaml @@ -0,0 +1,2 @@ +MonoControl: + Options: --jit \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Driver/Displays.Max7219.csproj b/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Driver/Displays.Max7219.csproj index dc491de832..f6c44ef382 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Driver/Displays.Max7219.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Driver/Displays.Max7219.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Driver/Max7219.Display.cs b/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Driver/Max7219.Display.cs index 3291bf7689..f76b4d9f22 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Driver/Max7219.Display.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Driver/Max7219.Display.cs @@ -1,6 +1,5 @@ -using System; +using Meadow.Foundation.Graphics; using Meadow.Foundation.Graphics.Buffers; -using Meadow.Foundation.Graphics; namespace Meadow.Foundation.Displays { @@ -90,7 +89,7 @@ public void DrawPixel(int x, int y, bool enabled) { var index = x % 8; - var display = y / 8 + (x / 8) * DigitRows; + var display = (y >> 3) + (x >> 3) * DigitRows; if (display > DeviceCount) { @@ -116,7 +115,7 @@ public void InvertPixel(int x, int y) { var index = x % 8; - var display = y / 8 + (x / 8) * DigitRows; + var display = (y >> 3) + (x >> 3) * DigitRows; if (display > DeviceCount) { diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Driver/Max7219.PixelBuffer.cs b/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Driver/Max7219.PixelBuffer.cs index 899b9874a4..90b7adc69c 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Driver/Max7219.PixelBuffer.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Driver/Max7219.PixelBuffer.cs @@ -12,7 +12,7 @@ public partial class Max7219 : IPixelBuffer /// /// The total bytes used for the display buffer /// - public int ByteCount => Width * Height / 8; + public int ByteCount => Width * Height >> 3; /// /// The backing buffer for the pixel buffer (not implemented) diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Driver/Max7219.cs b/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Driver/Max7219.cs index 285aa1a316..30c7219e88 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Driver/Max7219.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Driver/Max7219.cs @@ -8,13 +8,8 @@ namespace Meadow.Foundation.Displays /// /// Max7219 LED matrix driver /// - public partial class Max7219 + public partial class Max7219 : ISpiPeripheral { - /// - /// MAX7219 Spi Clock Frequency - /// - public static Frequency DefaultSpiBusSpeed = new Frequency(6000, Frequency.UnitType.Kilohertz); - /// /// Number of digits per Module /// @@ -40,7 +35,38 @@ public partial class Max7219 /// public int Length => DigitRows * DigitColumns; - private readonly ISpiPeripheral max7219; + /// + /// The default SPI bus speed for the device + /// + public Frequency DefaultSpiBusSpeed => new Frequency(10000, Frequency.UnitType.Kilohertz); + + /// + /// The SPI bus speed for the device + /// + public Frequency SpiBusSpeed + { + get => spiComms.BusSpeed; + set => spiComms.BusSpeed = value; + } + + /// + /// The default SPI bus mode for the device + /// + public SpiClockConfiguration.Mode DefaultSpiBusMode => SpiClockConfiguration.Mode.Mode0; + + /// + /// The SPI bus mode for the device + /// + public SpiClockConfiguration.Mode SpiBusMode + { + get => spiComms.BusMode; + set => spiComms.BusMode = value; + } + + /// + /// SPI Communication bus used to communicate with the peripheral + /// + protected ISpiCommunications spiComms; /// /// internal buffer used to write to registers for all devices. @@ -60,7 +86,7 @@ public partial class Max7219 /// SPI bus /// Chip select port /// Number of cascaded devices - /// Display mode of max7219 + /// Display mode public Max7219(ISpiBus spiBus, IDigitalOutputPort chipselectPort, int deviceCount = 1, Max7219Mode maxMode = Max7219Mode.Display) : this(spiBus, chipselectPort, deviceCount, 1, maxMode) { @@ -73,10 +99,10 @@ public Max7219(ISpiBus spiBus, IDigitalOutputPort chipselectPort, int deviceCoun /// Chip select port /// Number of devices cascaded vertically /// Number of devices cascaded horizontally - /// Display mode of max7219 + /// Display mode public Max7219(ISpiBus spiBus, IDigitalOutputPort chipselectPort, int deviceRows, int deviceColumns, Max7219Mode maxMode = Max7219Mode.Display) { - max7219 = new SpiPeripheral(spiBus, chipselectPort); + spiComms = new SpiCommunications(spiBus, chipselectPort, DefaultSpiBusSpeed, DefaultSpiBusMode); DigitRows = deviceRows; DigitColumns = deviceColumns * DigitsPerDevice; @@ -95,7 +121,7 @@ public Max7219(ISpiBus spiBus, IDigitalOutputPort chipselectPort, int deviceRows /// Chip select pin /// Number of devices cascaded vertically /// Number of devices cascaded horizontally - /// Display mode of max7219 + /// Display mode public Max7219(ISpiBus spiBus, IPin chipSelectPin, int deviceRows = 1, int deviceColumns = 1, Max7219Mode maxMode = Max7219Mode.Display) : this(spiBus, chipSelectPin.CreateDigitalOutputPort(), deviceRows, deviceColumns, maxMode) { } @@ -106,7 +132,7 @@ public Max7219(ISpiBus spiBus, IPin chipSelectPin, int deviceRows = 1, int devic /// SPI bus /// Chip select pin /// Number of cascaded devices - /// Display mode of max7219 + /// Display mode public Max7219(ISpiBus spiBus, IPin chipSelectPin, int deviceCount = 1, Max7219Mode maxMode = Max7219Mode.Display) : this(spiBus, chipSelectPin.CreateDigitalOutputPort(), deviceCount, 1, maxMode) { } @@ -191,7 +217,7 @@ public void TestDisplay(TimeSpan time) } /// - /// Set the display mode of the max7219 + /// Set the display mode of the Max7219 /// /// the mode public void SetMode(Max7219Mode maxMode) @@ -211,7 +237,7 @@ internal void SetRegister(Register register, byte data) writeBuffer[i++] = (byte)register; writeBuffer[i++] = data; } - max7219.Write(writeBuffer); + spiComms.Write(writeBuffer); } /// @@ -224,7 +250,7 @@ internal void SetRegister(int deviceId, Register register, byte data) writeBuffer[deviceId * 2] = (byte)register; writeBuffer[deviceId * 2 + 1] = data; - max7219.Write(writeBuffer); + spiComms.Write(writeBuffer); } /// @@ -317,7 +343,7 @@ public void WriteBuffer(byte[,] buffer) writeBuffer[i++] = (byte)((int)Register.Digit0 + digit); writeBuffer[i++] = buffer[deviceId, digit]; } - max7219.Write(writeBuffer); + spiComms.Write(writeBuffer); } } diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Samples/Max7219_8x8x4_Sample/Max7219_8x8x4_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Samples/Max7219_8x8x4_Sample/Max7219_8x8x4_Sample.csproj index 5c2a5c8793..f6e6d249d4 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Samples/Max7219_8x8x4_Sample/Max7219_8x8x4_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Samples/Max7219_8x8x4_Sample/Max7219_8x8x4_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Samples/Max7219_8x8x4_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Samples/Max7219_8x8x4_Sample/MeadowApp.cs index 71739c282a..82c0e9545f 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Samples/Max7219_8x8x4_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Samples/Max7219_8x8x4_Sample/MeadowApp.cs @@ -17,7 +17,7 @@ public override Task Initialize() Resolver.Log.Info("Init..."); display = new Max7219( - Device.CreateSpiBus(Max7219.DefaultSpiBusSpeed), + Device.CreateSpiBus(), Device.Pins.D00, deviceCount: 4, maxMode: Max7219.Max7219Mode.Display); diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Samples/Max7219_8x8x4x2_Sample/Max7219_8x8x4x2_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Samples/Max7219_8x8x4x2_Sample/Max7219_8x8x4x2_Sample.csproj index 5c2a5c8793..f6e6d249d4 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Samples/Max7219_8x8x4x2_Sample/Max7219_8x8x4x2_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Samples/Max7219_8x8x4x2_Sample/Max7219_8x8x4x2_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Samples/Max7219_8x8x4x2_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Samples/Max7219_8x8x4x2_Sample/MeadowApp.cs index 40a1d160c0..275986285e 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Samples/Max7219_8x8x4x2_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Samples/Max7219_8x8x4x2_Sample/MeadowApp.cs @@ -38,7 +38,7 @@ public override Task Initialize() Resolver.Log.Info("Init..."); - var spiBus = Device.CreateSpiBus(Max7219.DefaultSpiBusSpeed); + var spiBus = Device.CreateSpiBus(); display = new Max7219(spiBus, Device.Pins.D01, 4, 2, Max7219.Max7219Mode.Display); @@ -53,8 +53,8 @@ public override Task Initialize() void Show3dCube() { - int originY = (int)display.Width / 2; - int originX = (int)display.Height / 2; + int originY = display.Width / 2; + int originX = display.Height / 2; int angle = 0; while (true) diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Samples/Max7219_Sample/Max7219_7Segment_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Samples/Max7219_Sample/Max7219_7Segment_Sample.csproj index 9643fea42c..8407db89ab 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Samples/Max7219_Sample/Max7219_7Segment_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.Max7219/Samples/Max7219_Sample/Max7219_7Segment_Sample.csproj @@ -10,7 +10,7 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Pcd8544/Datasheet/ArduCAM_Mini_2MP_Camera_Shield_Hardware_Application_Note.pdf b/Source/Meadow.Foundation.Peripherals/Displays.Pcd8544/Datasheet/ArduCAM_Mini_2MP_Camera_Shield_Hardware_Application_Note.pdf deleted file mode 100644 index 0d82c0c6e9..0000000000 Binary files a/Source/Meadow.Foundation.Peripherals/Displays.Pcd8544/Datasheet/ArduCAM_Mini_2MP_Camera_Shield_Hardware_Application_Note.pdf and /dev/null differ diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Pcd8544/Driver/Displays.Pcd8544.csproj b/Source/Meadow.Foundation.Peripherals/Displays.Pcd8544/Driver/Displays.Pcd8544.csproj index 002e791655..7d48ec626e 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Pcd8544/Driver/Displays.Pcd8544.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.Pcd8544/Driver/Displays.Pcd8544.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Pcd8544/Driver/Pcd8544.cs b/Source/Meadow.Foundation.Peripherals/Displays.Pcd8544/Driver/Pcd8544.cs index a476ab1bfb..154a509ad9 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Pcd8544/Driver/Pcd8544.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.Pcd8544/Driver/Pcd8544.cs @@ -1,21 +1,16 @@ -using Meadow.Hardware; +using Meadow.Foundation.Graphics; using Meadow.Foundation.Graphics.Buffers; -using System; -using Meadow.Foundation.Graphics; +using Meadow.Hardware; using Meadow.Units; +using System; namespace Meadow.Foundation.Displays { /// /// Represents a Pcd8544 monochrome display /// - public class Pcd8544 : IGraphicsDisplay + public class Pcd8544 : IGraphicsDisplay, ISpiPeripheral { - /// - /// Default SPI bus speed - /// - public static Frequency DEFAULT_SPEED = new Frequency(4000, Frequency.UnitType.Kilohertz); - /// /// Display color mode /// @@ -46,9 +41,41 @@ public class Pcd8544 : IGraphicsDisplay /// public bool IsDisplayInverted { get; private set; } = false; + /// + /// The default SPI bus speed for the device + /// + public Frequency DefaultSpiBusSpeed => new Frequency(4000, Frequency.UnitType.Kilohertz); + + /// + /// The SPI bus speed for the device + /// + public Frequency SpiBusSpeed + { + get => spiComms.BusSpeed; + set => spiComms.BusSpeed = value; + } + + /// + /// The default SPI bus mode for the device + /// + public SpiClockConfiguration.Mode DefaultSpiBusMode => SpiClockConfiguration.Mode.Mode0; + + /// + /// The SPI bus mode for the device + /// + public SpiClockConfiguration.Mode SpiBusMode + { + get => spiComms.BusMode; + set => spiComms.BusMode = value; + } + readonly IDigitalOutputPort dataCommandPort; readonly IDigitalOutputPort resetPort; - readonly ISpiPeripheral spiPeripheral; + + /// + /// SPI Communication bus used to communicate with the peripheral + /// + protected ISpiCommunications spiComms; /// /// Buffer to hold display data @@ -67,7 +94,7 @@ public class Pcd8544 : IGraphicsDisplay /// Chip select pin /// Data command pin /// Reset pin - public Pcd8544(ISpiBus spiBus, IPin chipSelectPin, IPin dcPin, IPin resetPin): + public Pcd8544(ISpiBus spiBus, IPin chipSelectPin, IPin dcPin, IPin resetPin) : this(spiBus, chipSelectPin?.CreateDigitalOutputPort(), dcPin.CreateDigitalOutputPort(true), resetPin.CreateDigitalOutputPort(true)) { @@ -80,18 +107,20 @@ public Pcd8544(ISpiBus spiBus, IPin chipSelectPin, IPin dcPin, IPin resetPin): /// Chip select output port /// Data command output port /// Reset output port - public Pcd8544(ISpiBus spiBus, + public Pcd8544(ISpiBus spiBus, IDigitalOutputPort chipSelectPort, IDigitalOutputPort dataCommandPort, IDigitalOutputPort resetPort) { + imageBuffer = new Buffer1bpp(Width, Height); + dataCommandPort.State = true; resetPort.State = true; this.dataCommandPort = dataCommandPort; this.resetPort = resetPort; - spiPeripheral = new SpiPeripheral(spiBus, chipSelectPort); + spiComms = new SpiCommunications(spiBus, chipSelectPort, DefaultSpiBusSpeed, DefaultSpiBusMode); Initialize(); } @@ -111,7 +140,7 @@ private void Initialize() commandBuffer.Span[5] = 0x20; commandBuffer.Span[6] = 0x0C; - spiPeripheral.Write(commandBuffer.Span[0..6]); + spiComms.Write(commandBuffer.Span[0..6]); dataCommandPort.State = true; @@ -173,7 +202,7 @@ public void DrawPixel(int x, int y, Color color) /// public void Show() { - spiPeripheral.Write(imageBuffer.Buffer); + spiComms.Write(imageBuffer.Buffer); } /// @@ -199,7 +228,7 @@ public void InvertDisplay(bool inverse) dataCommandPort.State = false; commandBuffer.Span[0] = inverse ? (byte)0x0D : (byte)0x0C; - spiPeripheral.Write(commandBuffer.Span[0]); + spiComms.Write(commandBuffer.Span[0]); dataCommandPort.State = true; } @@ -212,7 +241,7 @@ public void Fill(Color fillColor, bool updateDisplay = false) { imageBuffer.Clear(fillColor.Color1bpp); - if(updateDisplay) { Show(); } + if (updateDisplay) { Show(); } } /// diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Pcd8544/Samples/Pcd8544_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Displays.Pcd8544/Samples/Pcd8544_Sample/MeadowApp.cs index 45fb8973bd..884af1a519 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Pcd8544/Samples/Pcd8544_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.Pcd8544/Samples/Pcd8544_Sample/MeadowApp.cs @@ -2,7 +2,6 @@ using Meadow.Devices; using Meadow.Foundation.Displays; using Meadow.Foundation.Graphics; -using System; using System.Threading.Tasks; namespace Displays.Pcd8854_Sample @@ -17,11 +16,9 @@ public override Task Initialize() { Resolver.Log.Info("Initializing..."); - var config = new Meadow.Hardware.SpiClockConfiguration(Pcd8544.DEFAULT_SPEED, Meadow.Hardware.SpiClockConfiguration.Mode.Mode0); - var display = new Pcd8544 ( - spiBus: Device.CreateSpiBus(Device.Pins.SCK, Device.Pins.MOSI, Device.Pins.MISO, config), + spiBus: Device.CreateSpiBus(), chipSelectPin: Device.Pins.D01, dcPin: Device.Pins.D00, resetPin: Device.Pins.D02 @@ -52,7 +49,7 @@ void CounterDemo(MicroGraphics graphics) graphics.CurrentFont = new Font12x20(); - while(true) + while (true) { graphics.Clear(); graphics.DrawText(0, 0, $"Count:"); diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Pcd8544/Samples/Pcd8544_Sample/Pcd8544_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.Pcd8544/Samples/Pcd8544_Sample/Pcd8544_Sample.csproj index a43e1bcd88..bd40575663 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Pcd8544/Samples/Pcd8544_Sample/Pcd8544_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.Pcd8544/Samples/Pcd8544_Sample/Pcd8544_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Sh1106/Datasheet/SH1106-SINOWEALTH.pdf b/Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Datasheet/SH1106-SINOWEALTH.pdf similarity index 100% rename from Source/Meadow.Foundation.Peripherals/Displays.Sh1106/Datasheet/SH1106-SINOWEALTH.pdf rename to Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Datasheet/SH1106-SINOWEALTH.pdf diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Datasheet/SH1107.pdf b/Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Datasheet/SH1107.pdf new file mode 100644 index 0000000000..9c472f309c Binary files /dev/null and b/Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Datasheet/SH1107.pdf differ diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Driver/Displays.Sh110x.csproj b/Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Driver/Displays.Sh110x.csproj new file mode 100644 index 0000000000..721a5726e4 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Driver/Displays.Sh110x.csproj @@ -0,0 +1,22 @@ + + + true + icon.png + Wilderness Labs, Inc + netstandard2.1 + Library + Sh110x + Wilderness Labs, Inc + http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ + Meadow.Foundation.Displays.Sh1106 + https://github.com/WildernessLabs/Meadow.Foundation + Meadow,Meadow.Foundation,Displays,LCD,Sh1106,SH1107,oled,monochrome + 0.1.0 + true + S1106 and SH1107 SPI and I2C monochrome OLED displays + + + + + + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Driver/Drivers/Sh1106.cs b/Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Driver/Drivers/Sh1106.cs new file mode 100644 index 0000000000..0a4d33f390 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Driver/Drivers/Sh1106.cs @@ -0,0 +1,92 @@ +using Meadow.Hardware; +using System.Threading; + +namespace Meadow.Foundation.Displays +{ + /// + /// Represents the Sh1106 family of displays + /// + public class Sh1106 : Sh110x + { + /// + /// Create a new Sh1106 object + /// + /// I2C bus connected to display + /// I2C address + /// Display width in pixels + /// Display height in pixels + public Sh1106(II2cBus i2cBus, byte address, int width, int height) + : base(i2cBus, address, width, height) + { } + + /// + /// Create a new Sh1106 object + /// + /// SPI bus connected to display + /// Chip select pin + /// Data command pin + /// Reset pin + /// Display width in pixels + /// Display height in pixels + public Sh1106(ISpiBus spiBus, IPin chipSelectPin, IPin dcPin, IPin resetPin, int width = 128, int height = 64) + : base(spiBus, chipSelectPin, dcPin, resetPin, width, height) + { } + + /// + /// Create a new Sh1106 display object + /// + /// SPI bus connected to display + /// Chip select output port + /// Data command output port + /// Reset output port + /// Display width in pixels + /// Display height in pixels + public Sh1106(ISpiBus spiBus, + IDigitalOutputPort chipSelectPort, + IDigitalOutputPort dataCommandPort, + IDigitalOutputPort resetPort, + int width = 128, int height = 64) + : base(spiBus, chipSelectPort, dataCommandPort, resetPort, width, height) + { } + + /// + /// Initialize the Sh1106 + /// + protected override void Initialize() + { + Reset(); + + SendCommand(DisplayCommand.DisplayOff); + SendCommand(DisplayCommand.SetDisplayClockDiv); + SendCommand(0x80); + + SendCommand(DisplayCommand.MultiplexModeSet); + SendCommand(DisplayCommand.MultiplexDataSet); + + SendCommand(DisplayCommand.SetDisplayOffset); + SendCommand((byte)0); + + SendCommand(DisplayCommand.DisplayStartLine); + + SendCommand(DisplayCommand.SegInvNormal); + SendCommand(0xC0); + + SendCommand(DisplayCommand.SetComPins); + SendCommand(0x12); + + SendCommand(DisplayCommand.SetContrast); + SendCommand(0x0F); + + SendCommand(0x30); + SendCommand(DisplayCommand.DisplayOnResume); + + SendCommand(DisplayCommand.SetDisplayClockDiv); + SendCommand(0xF0); + + SendCommand(DisplayCommand.DisplayVideoNormal); + + Thread.Sleep(100); + SendCommand(DisplayCommand.DisplayOn); + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Driver/Drivers/Sh1107.cs b/Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Driver/Drivers/Sh1107.cs new file mode 100644 index 0000000000..f81537e592 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Driver/Drivers/Sh1107.cs @@ -0,0 +1,105 @@ +using Meadow.Hardware; +using System.Threading; + +namespace Meadow.Foundation.Displays +{ + /// + /// Represents the Sh1107 family of displays + /// + public class Sh1107 : Sh110x + { + /// + /// Create a new Sh1107 object + /// + /// I2C bus connected to display + /// I2C address + /// Display width in pixels + /// Display height in pixels + public Sh1107(II2cBus i2cBus, byte address, int width = 128, int height = 128) + : base(i2cBus, address, width, height) + { } + + /// + /// Create a new Sh1107 object + /// + /// SPI bus connected to display + /// Chip select pin + /// Data command pin + /// Reset pin + /// Display width in pixels + /// Display height in pixels + public Sh1107(ISpiBus spiBus, IPin chipSelectPin, IPin dcPin, IPin resetPin, int width = 128, int height = 128) + : base(spiBus, chipSelectPin, dcPin, resetPin, width, height) + { } + + /// + /// Create a new Sh1107 display object + /// + /// SPI bus connected to display + /// Chip select output port + /// Data command output port + /// Reset output port + /// Display width in pixels + /// Display height in pixels + public Sh1107(ISpiBus spiBus, + IDigitalOutputPort chipSelectPort, + IDigitalOutputPort dataCommandPort, + IDigitalOutputPort resetPort, + int width = 128, int height = 128) + : base(spiBus, chipSelectPort, dataCommandPort, resetPort, width, height) + { } + + /// + /// Initialize the Sh1107 + /// + protected override void Initialize() + { + SendCommand(DisplayCommand.DisplayOff); + SendCommand(DisplayCommand.SetDisplayClockDiv); + SendCommand(0x51); + + SendCommand(DisplayCommand.SetContrast); + SendCommand(0x4F); + + SendCommand(DisplayCommand.DCDC); + SendCommand(0x8A); + + SendCommand(DisplayCommand.SetSegmentRemap); + SendCommand(DisplayCommand.ComScanInc); + + SendCommand(DisplayCommand.DisplayStartLine); + SendCommand((byte)0); + + SendCommand(DisplayCommand.SegInvNormal); + SendCommand(0xC0); + + SendCommand(DisplayCommand.SetPrecharge); + SendCommand(0x22); + + SendCommand(DisplayCommand.SetVComDetect); + SendCommand(0x35); + + SendCommand(DisplayCommand.DisplayOnResume); + SendCommand(DisplayCommand.DisplayVideoNormal); + + if (Width == 128 && Height == 128) + { + SendCommand(DisplayCommand.SetDisplayOffset); + SendCommand((byte)0x00); + SendCommand(DisplayCommand.MultiplexModeSet); + SendCommand(0x07F); + } + else + { + SendCommand(DisplayCommand.SetDisplayOffset); + SendCommand(0x60); + SendCommand(DisplayCommand.MultiplexModeSet); + SendCommand(DisplayCommand.MultiplexDataSet); + } + + Thread.Sleep(100); + + SendCommand(DisplayCommand.DisplayOn); + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Sh1106/Driver/Sh1106.Enums.cs b/Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Driver/Sh110x.Enums.cs similarity index 61% rename from Source/Meadow.Foundation.Peripherals/Displays.Sh1106/Driver/Sh1106.Enums.cs rename to Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Driver/Sh110x.Enums.cs index 09599643ec..343c145196 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Sh1106/Driver/Sh1106.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Driver/Sh110x.Enums.cs @@ -1,9 +1,6 @@ namespace Meadow.Foundation.Displays { - /// - /// Provide an interface to the Sh1106 family of displays - /// - public partial class Sh1106 + public partial class Sh110x { /// /// Allow the programmer to set the scroll direction @@ -28,17 +25,17 @@ public enum ScrollDirection LeftAndVertical } - enum DisplayCommand : byte + internal enum DisplayCommand : byte { + DCDC = 0xAD, DisplayOff = 0xAE, DisplayOn = 0xAF, DisplayOnResume = 0xA4, DisplayStartLine = 0x40, - PageAddress = 0xB0, + SetPageAddress = 0xB0, ColumnAddressHigh = 0x10, ColumnAddressLow = 0x02, - SetPageAddress = 0xB0, - ColumnAddress = 0x21, + DisplayVideoNormal = 0xA6, DisplayVideoReverse = 0xA7, AllPixelsOn = 0xA5, @@ -47,6 +44,8 @@ enum DisplayCommand : byte SetDisplayOffset = 0xD3, OutputFollowsRam = 0xA4, MemoryMode = 0x20, + ColumnAddress = 0x21, + PageAddress = 0x22, MultiplexModeSet = 0xA8, MultiplexDataSet = 0x3F, @@ -54,7 +53,7 @@ enum DisplayCommand : byte SetChargePump = 0x8D, SetPrecharge = 0xD9, SetComPins = 0xDA, - SetComDetect = 0xDB, + SetVComDetect = 0xDB, ComScanInc = 0xC0, ComScanDec = 0xC8, @@ -63,5 +62,40 @@ enum DisplayCommand : byte SetSegmentRemap = 0xA1, } + + /// + /// Valid I2C addresses for the display + /// + public enum Addresses : byte + { + /// + /// Bus address 0x3C + /// Commonly used with 128x32 displays + /// + Address_0x3C = 0x3C, + /// + /// Bus address 0x3D + /// + Address_0x3D = 0x3D, + /// + /// Default bus address + /// + Default = Address_0x3D + } + + /// + /// The display connection type + /// + public enum ConnectionType + { + /// + /// SPI + /// + SPI, + /// + /// I2C + /// + I2C, + } } } \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Sh1106/Driver/Sh1106.cs b/Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Driver/Sh110x.cs similarity index 60% rename from Source/Meadow.Foundation.Peripherals/Displays.Sh1106/Driver/Sh1106.cs rename to Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Driver/Sh110x.cs index cf57b60bd3..71269a3b40 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Sh1106/Driver/Sh1106.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Driver/Sh110x.cs @@ -1,15 +1,16 @@ using Meadow.Foundation.Graphics; using Meadow.Foundation.Graphics.Buffers; using Meadow.Hardware; +using Meadow.Units; using System; using System.Threading; namespace Meadow.Foundation.Displays { /// - /// Provide an interface to the Sh1106 family of displays + /// Provide an interface to the Sh110x family of displays /// - public partial class Sh1106 : IGraphicsDisplay + public abstract partial class Sh110x : IGraphicsDisplay, ISpiPeripheral, II2cPeripheral { /// /// The display color mode - 1 bit per pixel monochrome @@ -24,12 +25,50 @@ public partial class Sh1106 : IGraphicsDisplay /// /// The display width in pixels /// - public int Width => 128; + public int Width { get; protected set; } = 128; /// /// The display height in pixels /// - public int Height => 64; + public int Height { get; protected set; } = 64; + + /// + /// The default SPI bus speed for the device + /// + public Frequency DefaultSpiBusSpeed => new Frequency(4000, Frequency.UnitType.Kilohertz); + + /// + /// The SPI bus speed for the device + /// + public Frequency SpiBusSpeed + { + get => spiComms.BusSpeed; + set => spiComms.BusSpeed = value; + } + + /// + /// The default SPI bus mode for the device + /// + public SpiClockConfiguration.Mode DefaultSpiBusMode => SpiClockConfiguration.Mode.Mode0; + + /// + /// The SPI bus mode for the device + /// + public SpiClockConfiguration.Mode SpiBusMode + { + get => spiComms.BusMode; + set => spiComms.BusMode = value; + } + + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + + /// + /// The connection type (I2C or SPI) + /// + protected ConnectionType connectionType; /// /// The buffer the holds the pixel data for the display @@ -37,55 +76,113 @@ public partial class Sh1106 : IGraphicsDisplay public IPixelBuffer PixelBuffer => imageBuffer; /// - /// SPI peripheral object + /// I2C Communication bus used to communicate with the peripheral + /// + protected readonly II2cCommunications i2cComms; + + /// + /// SPI Communication bus used to communicate with the peripheral /// - ISpiPeripheral spiPerihperal; + protected ISpiCommunications spiComms; + + readonly IDigitalOutputPort dataCommandPort; + readonly IDigitalOutputPort resetPort; - IDigitalOutputPort dataCommandPort; - IDigitalOutputPort resetPort; + const int StartColumnOffset = 0; + readonly int PAGE_SIZE; const bool Data = true; const bool Command = false; - Buffer1bpp imageBuffer; - byte[] pageBuffer; + readonly Buffer1bpp imageBuffer; + readonly byte[] pageBuffer; + + /// + /// Display command buffer + /// + protected Memory commandBuffer; + + /// + /// Create a new Sh110x object + /// + /// I2C bus connected to display + /// I2C address + /// Display width in pixels + /// Display height in pixels + public Sh110x(II2cBus i2cBus, byte address, int width, int height) + { + i2cComms = new I2cCommunications(i2cBus, address); + + Width = width; + Height = height; + + connectionType = ConnectionType.I2C; + commandBuffer = new byte[2]; + + imageBuffer = new Buffer1bpp(Width, Height); + PAGE_SIZE = Width; + pageBuffer = new byte[PAGE_SIZE + 1]; + + Initialize(); + } /// - /// Create a new Sh1106 object + /// Create a new Sh110x object /// /// SPI bus connected to display /// Chip select pin /// Data command pin /// Reset pin - public Sh1106(ISpiBus spiBus, IPin chipSelectPin, IPin dcPin, IPin resetPin) : + /// Display width in pixels + /// Display height in pixels + public Sh110x(ISpiBus spiBus, IPin chipSelectPin, IPin dcPin, IPin resetPin, int width, int height) : this(spiBus, chipSelectPin?.CreateDigitalOutputPort(), dcPin.CreateDigitalOutputPort(), - resetPin.CreateDigitalOutputPort()) + resetPin.CreateDigitalOutputPort(), width, height) { } /// - /// Create a new Sh1106 display object + /// Create a new Sh110x display object /// /// SPI bus connected to display /// Chip select output port /// Data command output port /// Reset output port - public Sh1106(ISpiBus spiBus, + /// Display width in pixels + /// Display height in pixels + public Sh110x(ISpiBus spiBus, IDigitalOutputPort chipSelectPort, IDigitalOutputPort dataCommandPort, - IDigitalOutputPort resetPort) + IDigitalOutputPort resetPort, + int width, int height) { + connectionType = ConnectionType.SPI; + this.dataCommandPort = dataCommandPort; this.resetPort = resetPort; - spiPerihperal = new SpiPeripheral(spiBus, chipSelectPort); + spiComms = new SpiCommunications(spiBus, chipSelectPort, DefaultSpiBusSpeed, DefaultSpiBusMode); + + Width = width; + Height = height; imageBuffer = new Buffer1bpp(Width, Height); - pageBuffer = new byte[PageSize]; + pageBuffer = new byte[Width]; Initialize(); } + /// + /// This varies between manufactures + /// If the display is misaligned, try 0 and 0x40 + /// + /// + public void SetDisplayOffset(byte offset) + { + SendCommand(DisplayCommand.SetDisplayOffset); + SendCommand(offset); + } + /// /// Invert the entire display (true) or return to normal mode (false) /// @@ -110,12 +207,10 @@ public void PowerSaveMode() SendCommand(DisplayCommand.AllPixelsOn); } - void SendCommand(DisplayCommand command) - { - SendCommand((byte)command); - } - - void Reset() + /// + /// Reset for SPI displays + /// + protected void Reset() { resetPort.State = true; Thread.Sleep(10); @@ -125,40 +220,10 @@ void Reset() Thread.Sleep(100); } - private void Initialize() - { - Reset(); - - SendCommand(DisplayCommand.DisplayOff); - SendCommand(DisplayCommand.SetDisplayClockDiv); - //128x64 init commands - SendCommand(0x80); - - SendCommand(DisplayCommand.MultiplexModeSet); - SendCommand(DisplayCommand.MultiplexDataSet); - - SendCommand(DisplayCommand.SetDisplayOffset); - SendCommand((byte)0); - - SendCommand(DisplayCommand.DisplayStartLine); - - SendCommand(DisplayCommand.SegInvNormal); - SendCommand(0xC0); - - SendCommand(DisplayCommand.SetComPins); - SendCommand(0x12); - - SendCommand(DisplayCommand.SetContrast); - SendCommand(0x0F); - - SendCommand(0x30); - SendCommand(0xA4); - - SendCommand(DisplayCommand.SetDisplayClockDiv); - SendCommand(0xF0); - - SendCommand(DisplayCommand.DisplayOn); - } + /// + /// Initialize the display + /// + protected abstract void Initialize(); /// /// Set the display contrast @@ -174,46 +239,86 @@ public void SetContrast(byte contrast) /// Send a command to the display /// /// Command byte to send to the display - private void SendCommand(byte command) + internal void SendCommand(byte command) + { + if (connectionType == ConnectionType.SPI) + { + dataCommandPort.State = Command; + spiComms.Write(command); + } + else + { + commandBuffer.Span[0] = 0x00; + commandBuffer.Span[1] = command; + i2cComms.Write(commandBuffer.Span); + } + } + + /// + /// Send a command to the display + /// + /// Command byte to send to the display + internal void SendCommand(DisplayCommand command) { - dataCommandPort.State = Command; - spiPerihperal.Write(command); + SendCommand((byte)command); } /// /// Send a sequence of commands to the display /// /// List of commands to send - private void SendCommands(byte[] commands) + internal void SendCommands(byte[] commands) { - var data = new byte[commands.Length + 1]; - data[0] = 0x00; - Array.Copy(commands, 0, data, 1, commands.Length); - - dataCommandPort.State = Command; - spiPerihperal.Write(commands); + if (connectionType == ConnectionType.SPI) + { + dataCommandPort.State = Command; + spiComms.Write(commands); + } + else + { + Span data = new byte[commands.Length + 1]; + data[0] = 0x00; + commands.CopyTo(data.Slice(1, commands.Length)); + i2cComms.Write(data); + } } - const int StartColumnOffset = 0; - const int PageSize = 128; - /// /// Send the internal pixel buffer to display /// public void Show() { - for (int page = 0; page < 8; page++) + if (connectionType == ConnectionType.SPI) { - SendCommand(DisplayCommand.ColumnAddressLow); - SendCommand(DisplayCommand.ColumnAddressHigh); - SendCommand((byte)((byte)DisplayCommand.PageAddress | page)); + int count = (Height + 7) / 8;//+7 to round up + for (int page = 0; page < count; page++) + { + { + SendCommand(DisplayCommand.ColumnAddressLow); + SendCommand(DisplayCommand.ColumnAddressHigh); + SendCommand((byte)((byte)DisplayCommand.SetPageAddress | page)); - dataCommandPort.State = Data; + dataCommandPort.State = Data; - Array.Copy(imageBuffer.Buffer, Width * page, pageBuffer, 0, PageSize); - spiPerihperal.Write(pageBuffer); + Array.Copy(imageBuffer.Buffer, Width * page, pageBuffer, 0, PAGE_SIZE); + spiComms.Write(pageBuffer); + } + } + } + else //I2C + { + pageBuffer[0] = 0x40; + int count = (Height + 7) / 8;//+7 to round up + for (int page = 0; page < count; page++) + { + SendCommand((byte)0); + SendCommand((byte)((byte)DisplayCommand.SetPageAddress | page)); + SendCommand(0x10 >> 4); + SendCommand((byte)(0x10 & 0xF)); - dataCommandPort.State = Command; + Array.Copy(imageBuffer.Buffer, Width * page, pageBuffer, 1, PAGE_SIZE); + i2cComms.Write(pageBuffer); + } } } @@ -237,14 +342,14 @@ public void Show(int left, int top, int right, int bottom) continue; } - SendCommand((byte)((int)DisplayCommand.PageAddress | page)); + SendCommand((byte)((int)DisplayCommand.SetPageAddress | page)); SendCommand((DisplayCommand.ColumnAddressLow) | (StartColumnOffset & 0x0F)); SendCommand((int)DisplayCommand.ColumnAddressHigh | 0); dataCommandPort.State = Data; - Array.Copy(imageBuffer.Buffer, Width * page, pageBuffer, 0, PageSize); - spiPerihperal.Write(pageBuffer); + Array.Copy(imageBuffer.Buffer, Width * page, pageBuffer, 0, PAGE_SIZE); + spiComms.Write(pageBuffer); } } diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Sh1106/Samples/Sh1106_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Samples/Sh1106_Sample/MeadowApp.cs similarity index 96% rename from Source/Meadow.Foundation.Peripherals/Displays.Sh1106/Samples/Sh1106_Sample/MeadowApp.cs rename to Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Samples/Sh1106_Sample/MeadowApp.cs index 7ad862910f..9e0de1b3c8 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Sh1106/Samples/Sh1106_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Samples/Sh1106_Sample/MeadowApp.cs @@ -6,7 +6,7 @@ namespace Displays.Sh1106_Sample { - public class MeadowApp : App + public class MeadowApp : App { // diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Sh1106/Samples/Sh1106_Sample/Sh1106_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Samples/Sh1106_Sample/Sh1106_Sample.csproj similarity index 77% rename from Source/Meadow.Foundation.Peripherals/Displays.Sh1106/Samples/Sh1106_Sample/Sh1106_Sample.csproj rename to Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Samples/Sh1106_Sample/Sh1106_Sample.csproj index 71e4a4cd37..6f8db894fd 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Sh1106/Samples/Sh1106_Sample/Sh1106_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Samples/Sh1106_Sample/Sh1106_Sample.csproj @@ -9,8 +9,8 @@ App - - + + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Samples/Sh1106_Sample/meadow.config.yaml b/Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Samples/Sh1106_Sample/meadow.config.yaml new file mode 100644 index 0000000000..32363cb69c --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Samples/Sh1106_Sample/meadow.config.yaml @@ -0,0 +1,2 @@ +MonoControl: + Options: --jit \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Samples/Sh1107_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Samples/Sh1107_Sample/MeadowApp.cs new file mode 100644 index 0000000000..ae107cdbc0 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Samples/Sh1107_Sample/MeadowApp.cs @@ -0,0 +1,51 @@ +using Meadow; +using Meadow.Devices; +using Meadow.Foundation.Displays; +using Meadow.Foundation.Graphics; +using System.Threading.Tasks; +using static Meadow.Foundation.Displays.Sh110x; + +namespace Displays.Sh1107_Sample +{ + public class MeadowApp : App + { + // + + MicroGraphics graphics; + + public override Task Initialize() + { + Resolver.Log.Info("Initializing..."); + + var sh1107 = new Sh1107 + ( + i2cBus: Device.CreateI2cBus(), + address: (byte)Addresses.Address_0x3C, + width: 128, + height: 128 + ); + + graphics = new MicroGraphics(sh1107) + { + CurrentFont = new Font12x16(), + Rotation = RotationType._180Degrees + }; + + return base.Initialize(); + } + + public override Task Run() + { + graphics.Clear(); + graphics.DrawRectangle(0, 0, graphics.Width, graphics.Height, false); + graphics.DrawTriangle(10, 10, 50, 50, 10, 50, false); + graphics.DrawRectangle(20, 15, 40, 20, true); + graphics.DrawText(5, 5, "SH1107"); + graphics.Show(); + + return base.Run(); + } + + // + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Samples/Sh1107_Sample/Sh1107_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Samples/Sh1107_Sample/Sh1107_Sample.csproj new file mode 100644 index 0000000000..6f8db894fd --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Samples/Sh1107_Sample/Sh1107_Sample.csproj @@ -0,0 +1,20 @@ + + + https://github.com/WildernessLabs/Meadow.Foundation + Wilderness Labs, Inc + Wilderness Labs, Inc + true + netstandard2.1 + Library + App + + + + + + + + Always + + + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Samples/Sh1107_Sample/meadow.config.yaml b/Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Samples/Sh1107_Sample/meadow.config.yaml new file mode 100644 index 0000000000..32363cb69c --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Displays.Sh110x/Samples/Sh1107_Sample/meadow.config.yaml @@ -0,0 +1,2 @@ +MonoControl: + Options: --jit \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Driver/Displays.Ssd130x.csproj b/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Driver/Displays.Ssd130x.csproj index bd1b3a4ad8..63456de2f7 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Driver/Displays.Ssd130x.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Driver/Displays.Ssd130x.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Driver/Drivers/Ssd1306.cs b/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Driver/Drivers/Ssd1306.cs index cccb671c36..7e2646d664 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Driver/Drivers/Ssd1306.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Driver/Drivers/Ssd1306.cs @@ -4,7 +4,7 @@ namespace Meadow.Foundation.Displays { /// - /// Provide an interface to the SSD1306 family of OLED displays + /// Represents the SSD1306 family of OLED displays /// public partial class Ssd1306 : Ssd130xBase { @@ -17,7 +17,7 @@ public partial class Ssd1306 : Ssd130xBase /// Reset pin /// Type of SSD1306 display (default = 128x64 pixel display) public Ssd1306(ISpiBus spiBus, IPin chipSelectPin, IPin dcPin, IPin resetPin, - DisplayType displayType = DisplayType.OLED128x64): + DisplayType displayType = DisplayType.OLED128x64) : this(spiBus, chipSelectPin?.CreateDigitalOutputPort(false), dcPin.CreateDigitalOutputPort(true), resetPin.CreateDigitalOutputPort(false), displayType) { } @@ -40,7 +40,7 @@ public Ssd1306(ISpiBus spiBus, this.chipSelectPort = chipSelectPort; this.resetPort = resetPort; - spiPeripheral = new SpiPeripheral(spiBus, chipSelectPort); + spiComms = new SpiCommunications(spiBus, chipSelectPort, DefaultSpiBusSpeed, DefaultSpiBusMode); connectionType = ConnectionType.SPI; @@ -59,7 +59,7 @@ public Ssd1306(II2cBus i2cBus, { this.displayType = displayType; - i2cPeripheral = new I2cPeripheral(i2cBus, address); + i2cComms = new I2cCommunications(i2cBus, address); connectionType = ConnectionType.I2C; diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Driver/Drivers/Ssd1309.cs b/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Driver/Drivers/Ssd1309.cs index 7bb8a9dc88..05e69772c8 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Driver/Drivers/Ssd1309.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Driver/Drivers/Ssd1309.cs @@ -1,23 +1,12 @@ using Meadow.Hardware; -using Meadow.Units; namespace Meadow.Foundation.Displays { /// - /// Provide an interface to the SSD1309 family of OLED displays + /// Represents the SSD1309 family of OLED displays /// public class Ssd1309 : Ssd1306 { - /// - /// The default SPI clock mode - /// - public static SpiClockConfiguration.Mode DefaultSpiClockMode = SpiClockConfiguration.Mode.Mode0; - - /// - /// Default SPI frequency - /// - public static Frequency DefaultSpiBusSpeed = new Frequency(12000, Frequency.UnitType.Kilohertz); - /// /// Create a new Ssd1309 object /// @@ -47,7 +36,7 @@ public Ssd1309(ISpiBus spiBus, IDigitalOutputPort chipSelectPort, IDigitalOutput /// /// I2cBus connected to display /// Address of the bus on the I2C display. - public Ssd1309(II2cBus i2cBus, byte address = (byte)Addresses.Default) : + public Ssd1309(II2cBus i2cBus, byte address = (byte)Addresses.Default) : base(i2cBus, address, DisplayType.OLED128x64) { } diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Driver/SSd130xBase.Enums.cs b/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Driver/SSd130xBase.Enums.cs index 9e26717a08..61e5002b9b 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Driver/SSd130xBase.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Driver/SSd130xBase.Enums.cs @@ -1,12 +1,9 @@ namespace Meadow.Foundation.Displays { - /// - /// Provide an interface to the SSD1306 family of OLED displays - /// public abstract partial class Ssd130xBase { /// - /// Valid addresses for the sensor + /// Valid I2C addresses for the display /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Driver/Ssd130xBase.cs b/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Driver/Ssd130xBase.cs index 0496e5b64b..9e5fa6078d 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Driver/Ssd130xBase.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Driver/Ssd130xBase.cs @@ -1,14 +1,15 @@ -using System; -using Meadow.Hardware; +using Meadow.Foundation.Graphics; using Meadow.Foundation.Graphics.Buffers; -using Meadow.Foundation.Graphics; +using Meadow.Hardware; +using Meadow.Units; +using System; namespace Meadow.Foundation.Displays { /// - /// Provide an interface to the SSD130x family of OLED displays + /// Represents the SSD130x family of OLED displays /// - public abstract partial class Ssd130xBase : IGraphicsDisplay + public abstract partial class Ssd130xBase : IGraphicsDisplay, ISpiPeripheral, II2cPeripheral { /// /// The display color mode @@ -36,9 +37,42 @@ public abstract partial class Ssd130xBase : IGraphicsDisplay public IPixelBuffer PixelBuffer => imageBuffer; /// - /// SSD1306 SPI display + /// The default SPI bus speed for the device + /// + public Frequency DefaultSpiBusSpeed => new Frequency(8000, Frequency.UnitType.Kilohertz); + + /// + /// The SPI bus speed for the device + /// + public Frequency SpiBusSpeed + { + get => spiComms.BusSpeed; + set => spiComms.BusSpeed = value; + } + + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + + /// + /// The default SPI bus mode for the device + /// + public SpiClockConfiguration.Mode DefaultSpiBusMode => SpiClockConfiguration.Mode.Mode0; + + /// + /// The SPI bus mode for the device + /// + public SpiClockConfiguration.Mode SpiBusMode + { + get => spiComms.BusMode; + set => spiComms.BusMode = value; + } + + /// + /// SPI Communication bus used to communicate with the peripheral /// - protected ISpiPeripheral spiPeripheral; + protected ISpiCommunications spiComms; /// /// The data command port @@ -76,9 +110,9 @@ public abstract partial class Ssd130xBase : IGraphicsDisplay protected const int PAGE_SIZE = 16; /// - /// SSD1306 I2C display + /// I2C Communication bus used to communicate with the peripheral /// - protected II2cPeripheral i2cPeripheral; + protected II2cCommunications i2cComms; /// /// Buffer holding the pixels in the display @@ -175,13 +209,13 @@ private void SendCommand(byte command) if (connectionType == ConnectionType.SPI) { dataCommandPort.State = Command; - spiPeripheral.Write(command); + spiComms.Write(command); } else { commandBuffer.Span[0] = 0x00; commandBuffer.Span[1] = command; - i2cPeripheral.Write(commandBuffer.Span); + i2cComms.Write(commandBuffer.Span); } } @@ -194,7 +228,7 @@ protected void SendCommands(Span commands) if (connectionType == ConnectionType.SPI) { dataCommandPort.State = Command; - spiPeripheral.Write(commands); + spiComms.Write(commands); } else { //a little heavy but this is only used a couple of times @@ -202,7 +236,7 @@ protected void SendCommands(Span commands) Span data = new byte[commands.Length + 1]; data[0] = 0x00; commands.CopyTo(data.Slice(1, commands.Length)); - i2cPeripheral.Write(data); + i2cComms.Write(data); } } @@ -216,7 +250,7 @@ public void Show() if (connectionType == ConnectionType.SPI) { dataCommandPort.State = Data; - spiPeripheral.Bus.Exchange(chipSelectPort, imageBuffer.Buffer, readBuffer); + spiComms.Bus.Exchange(chipSelectPort, imageBuffer.Buffer, readBuffer); } else// I2C { // Send the buffer page by page @@ -228,7 +262,7 @@ public void Show() if (imageBuffer.ByteCount - index < PAGE_SIZE) { break; } Array.Copy(imageBuffer.Buffer, index, pageBuffer, 1, PAGE_SIZE); - i2cPeripheral.Write(pageBuffer); + i2cComms.Write(pageBuffer); } } } diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Samples/Ssd1039_3DCube_Sample/Ssd1039_3DCube_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Samples/Ssd1039_3DCube_Sample/Ssd1039_3DCube_Sample.csproj index de6076c2e0..146b540624 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Samples/Ssd1039_3DCube_Sample/Ssd1039_3DCube_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Samples/Ssd1039_3DCube_Sample/Ssd1039_3DCube_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Samples/Ssd1306_Sample/Ssd1306_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Samples/Ssd1306_Sample/Ssd1306_Sample.csproj index de6076c2e0..146b540624 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Samples/Ssd1306_Sample/Ssd1306_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Samples/Ssd1306_Sample/Ssd1306_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Samples/Ssd1309_Game_Sample/Ssd1309_Game_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Samples/Ssd1309_Game_Sample/Ssd1309_Game_Sample.csproj index de6076c2e0..146b540624 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Samples/Ssd1309_Game_Sample/Ssd1309_Game_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Samples/Ssd1309_Game_Sample/Ssd1309_Game_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Samples/Ssd1309_Sample/Ssd1309_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Samples/Ssd1309_Sample/Ssd1309_Sample.csproj index de6076c2e0..146b540624 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Samples/Ssd1309_Sample/Ssd1309_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.Ssd130x/Samples/Ssd1309_Sample/Ssd1309_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Ssd1327/Driver/Displays.Ssd1327.csproj b/Source/Meadow.Foundation.Peripherals/Displays.Ssd1327/Driver/Displays.Ssd1327.csproj index 847ba0fd76..9322e47efc 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Ssd1327/Driver/Displays.Ssd1327.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.Ssd1327/Driver/Displays.Ssd1327.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Ssd1327/Driver/Ssd1327.cs b/Source/Meadow.Foundation.Peripherals/Displays.Ssd1327/Driver/Ssd1327.cs index 0f52a9a15a..8749a93282 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Ssd1327/Driver/Ssd1327.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.Ssd1327/Driver/Ssd1327.cs @@ -1,15 +1,16 @@ -using System; -using System.Threading; -using Meadow.Hardware; +using Meadow.Foundation.Graphics; using Meadow.Foundation.Graphics.Buffers; -using Meadow.Foundation.Graphics; +using Meadow.Hardware; +using Meadow.Units; +using System; +using System.Threading; namespace Meadow.Foundation.Displays { /// /// Provides an interface to the Ssd1327 greyscale OLED display /// - public partial class Ssd1327 : IGraphicsDisplay + public partial class Ssd1327 : IGraphicsDisplay, ISpiPeripheral { /// /// The display color mode (4 bit per pixel grayscale) @@ -36,10 +37,41 @@ public partial class Ssd1327 : IGraphicsDisplay /// public IPixelBuffer PixelBuffer => imageBuffer; - readonly ISpiPeripheral spiPeripheral; + /// + /// The default SPI bus speed for the device + /// + public Frequency DefaultSpiBusSpeed => new Frequency(10000, Frequency.UnitType.Kilohertz); + + /// + /// The SPI bus speed for the device + /// + public Frequency SpiBusSpeed + { + get => spiComms.BusSpeed; + set => spiComms.BusSpeed = value; + } + + /// + /// The default SPI bus mode for the device + /// + public SpiClockConfiguration.Mode DefaultSpiBusMode => SpiClockConfiguration.Mode.Mode0; + + /// + /// The SPI bus mode for the device + /// + public SpiClockConfiguration.Mode SpiBusMode + { + get => spiComms.BusMode; + set => spiComms.BusMode = value; + } + + /// + /// SPI Communication bus used to communicate with the peripheral + /// + protected ISpiCommunications spiComms; + readonly IDigitalOutputPort dataCommandPort; readonly IDigitalOutputPort resetPort; - readonly IDigitalOutputPort chipSelectPort; readonly BufferGray4 imageBuffer; @@ -54,16 +86,8 @@ public partial class Ssd1327 : IGraphicsDisplay /// Data command pin /// Reset pin public Ssd1327(ISpiBus spiBus, IPin chipSelectPin, IPin dcPin, IPin resetPin) + : this(spiBus, chipSelectPin?.CreateDigitalOutputPort(false), dcPin?.CreateDigitalOutputPort(false), resetPin?.CreateDigitalOutputPort(true)) { - imageBuffer = new BufferGray4(Width, Height); - - dataCommandPort = dcPin.CreateDigitalOutputPort(false); - if (resetPin != null) { resetPort = resetPin.CreateDigitalOutputPort(true); } - if (chipSelectPin != null) { chipSelectPort = chipSelectPin.CreateDigitalOutputPort(false); } - - spiPeripheral = new SpiPeripheral(spiBus, chipSelectPort); - - Initialize(); } /// @@ -78,11 +102,12 @@ public Ssd1327(ISpiBus spiBus, IDigitalOutputPort dataCommandPort, IDigitalOutputPort resetPort) { + imageBuffer = new BufferGray4(Width, Height); + this.dataCommandPort = dataCommandPort; - this.chipSelectPort = chipSelectPort; this.resetPort = resetPort; - spiPeripheral = new SpiPeripheral(spiBus, chipSelectPort); + spiComms = new SpiCommunications(spiBus, chipSelectPort, DefaultSpiBusSpeed, DefaultSpiBusMode); Initialize(); } @@ -106,7 +131,7 @@ protected void Initialize() dataCommandPort.State = CommandState; - spiPeripheral.Write(init128x128); + spiComms.Write(init128x128); Thread.Sleep(100); // 100ms delay recommended SendCommand(Command.DISPLAYON); // 0xaf @@ -121,7 +146,7 @@ public void Clear(bool updateDisplay = false) { Array.Clear(imageBuffer.Buffer, 0, imageBuffer.ByteCount); - if(updateDisplay == true) + if (updateDisplay == true) { Show(); } @@ -193,14 +218,14 @@ public void Show() dataCommandPort.State = DataState; - spiPeripheral.Write(imageBuffer.Buffer); + spiComms.Write(imageBuffer.Buffer); } void SetAddressWindow(byte x0, byte y0, byte x1, byte y1) { SendCommand(Command.SETCOLUMN); //Set Column Address SendCommand(x0); //Beginning. Note that you must divide the column by 2, since 1 byte in memory is 2 pixels - SendCommand((byte)(x1/2)); //End + SendCommand((byte)(x1 / 2)); //End SendCommand(Command.SETROW); //Set Row Address SendCommand(y0); //Beginning @@ -215,24 +240,7 @@ void SendCommand(Command command) void SendCommand(byte command) { dataCommandPort.State = CommandState; - spiPeripheral.Write(command); - } - - void SendData(int data) - { - SendData((byte)data); - } - - void SendData(byte data) - { - dataCommandPort.State = DataState; - spiPeripheral.Write(data); - } - - void SendData(byte[] data) - { - dataCommandPort.State = DataState; - spiPeripheral.Write(data); + spiComms.Write(command); } /// @@ -281,7 +289,7 @@ public void WriteBuffer(int x, int y, IPixelBuffer displayBuffer) 0x00, // 0xA1, 0x00 (byte)Command.SETDISPLAYOFFSET, 0x00, // 0xA2, 0x00 - (byte)Command.DISPLAYALLOFF, + (byte)Command.DISPLAYALLOFF, (byte)Command.SETMULTIPLEX, 0x7F, // 0xA8, 0x7F (1/64) (byte)Command.PHASELEN, @@ -305,7 +313,7 @@ public void WriteBuffer(int x, int y, IPixelBuffer displayBuffer) 0x62, // 0xD5, 0x62 (byte)Command.CMDLOCK, 0x12, // 0xFD, 0x12 - (byte)Command.NORMALDISPLAY, + (byte)Command.NORMALDISPLAY, (byte)Command.DISPLAYON }; } diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Ssd1327/Samples/Ssd1327_Sample/Ssd1327_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.Ssd1327/Samples/Ssd1327_Sample/Ssd1327_Sample.csproj index 9862eaaa14..6dd495359b 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Ssd1327/Samples/Ssd1327_Sample/Ssd1327_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.Ssd1327/Samples/Ssd1327_Sample/Ssd1327_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.St7565/Driver/Displays.St7565.csproj b/Source/Meadow.Foundation.Peripherals/Displays.St7565/Driver/Displays.St7565.csproj index ab767b3cb9..caf3aef140 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.St7565/Driver/Displays.St7565.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.St7565/Driver/Displays.St7565.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.St7565/Driver/St7565.cs b/Source/Meadow.Foundation.Peripherals/Displays.St7565/Driver/St7565.cs index b622c7c418..59314c9e72 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.St7565/Driver/St7565.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.St7565/Driver/St7565.cs @@ -1,15 +1,16 @@ -using System; -using System.Threading; -using Meadow.Hardware; -using Meadow.Foundation.Graphics; +using Meadow.Foundation.Graphics; using Meadow.Foundation.Graphics.Buffers; +using Meadow.Hardware; +using Meadow.Units; +using System; +using System.Threading; namespace Meadow.Foundation.Displays { /// - /// Provide an interface to the ST7565 family of displays. + /// Provide an interface to the ST7565 family of displays /// - public partial class St7565 : IGraphicsDisplay + public partial class St7565 : IGraphicsDisplay, ISpiPeripheral { /// /// The display color mode - 1 bit per pixel monochrome @@ -37,18 +38,46 @@ public partial class St7565 : IGraphicsDisplay public IPixelBuffer PixelBuffer => imageBuffer; /// - /// SPI peripheral object + /// The default SPI bus speed for the device + /// + public Frequency DefaultSpiBusSpeed => new Frequency(12000, Frequency.UnitType.Kilohertz); + + /// + /// The SPI bus speed for the device + /// + public Frequency SpiBusSpeed + { + get => spiComms.BusSpeed; + set => spiComms.BusSpeed = value; + } + + /// + /// The default SPI bus mode for the device + /// + public SpiClockConfiguration.Mode DefaultSpiBusMode => SpiClockConfiguration.Mode.Mode0; + + /// + /// The SPI bus mode for the device + /// + public SpiClockConfiguration.Mode SpiBusMode + { + get => spiComms.BusMode; + set => spiComms.BusMode = value; + } + + /// + /// SPI Communication bus used to communicate with the peripheral /// - ISpiPeripheral spiPerihperal; + protected ISpiCommunications spiComms; - IDigitalOutputPort dataCommandPort; - IDigitalOutputPort resetPort; + readonly IDigitalOutputPort dataCommandPort; + readonly IDigitalOutputPort resetPort; const bool Data = true; const bool Command = false; - Buffer1bpp imageBuffer; - byte[] pageBuffer; + readonly Buffer1bpp imageBuffer; + readonly byte[] pageBuffer; /// /// Create a new ST7565 object @@ -84,7 +113,7 @@ public St7565(ISpiBus spiBus, this.dataCommandPort = dataCommandPort; this.resetPort = resetPort; - spiPerihperal = new SpiPeripheral(spiBus, chipSelectPort); + spiComms = new SpiCommunications(spiBus, chipSelectPort, DefaultSpiBusSpeed, DefaultSpiBusMode); imageBuffer = new Buffer1bpp(width, height); pageBuffer = new byte[PageSize]; @@ -162,7 +191,7 @@ public void SetContrast(byte contrast) private void SendCommand(byte command) { dataCommandPort.State = Command; - spiPerihperal.Write(command); + spiComms.Write(command); } /// @@ -176,7 +205,7 @@ private void SendCommands(byte[] commands) Array.Copy(commands, 0, data, 1, commands.Length); dataCommandPort.State = Command; - spiPerihperal.Write(commands); + spiComms.Write(commands); } const int StartColumnOffset = 0; @@ -197,7 +226,7 @@ public void Show() dataCommandPort.State = Data; Array.Copy(imageBuffer.Buffer, Width * page, pageBuffer, 0, PageSize); - spiPerihperal.Write(pageBuffer); + spiComms.Write(pageBuffer); } } @@ -216,7 +245,7 @@ public void Show(int left, int top, int right, int bottom) //so interate over all 8 pages and check if they're in range for (int page = 0; page < 8; page++) { - if(top > pageHeight*page || bottom < (page + 1) * pageHeight) + if (top > pageHeight * page || bottom < (page + 1) * pageHeight) { continue; } @@ -229,7 +258,7 @@ public void Show(int left, int top, int right, int bottom) dataCommandPort.State = Data; Array.Copy(imageBuffer.Buffer, Width * page, pageBuffer, 0, PageSize); - spiPerihperal.Write(pageBuffer); + spiComms.Write(pageBuffer); } } @@ -321,7 +350,7 @@ public void StartScrolling(ScrollDirection direction, byte startPage, byte endPa scrollDirection = 0x29; } - commands = new byte[] { 0xa3, 0x00, (byte) Height, scrollDirection, 0x00, startPage, 0x00, endPage, 0x01, 0x2f }; + commands = new byte[] { 0xa3, 0x00, (byte)Height, scrollDirection, 0x00, startPage, 0x00, endPage, 0x01, 0x2f }; } SendCommands(commands); } diff --git a/Source/Meadow.Foundation.Peripherals/Displays.St7565/Samples/St7565_Sample/St7565_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.St7565/Samples/St7565_Sample/St7565_Sample.csproj index f64310cb2a..be8439be9d 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.St7565/Samples/St7565_Sample/St7565_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.St7565/Samples/St7565_Sample/St7565_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Displays.TftSpi.csproj b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Displays.TftSpi.csproj index 52a64f3308..3737d90268 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Displays.TftSpi.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Displays.TftSpi.csproj @@ -19,7 +19,7 @@ - - + + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Gc9a01.cs b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Gc9a01.cs index ca9f1a4178..e54a788052 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Gc9a01.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Gc9a01.cs @@ -11,7 +11,7 @@ public class Gc9a01 : TftSpiBase, IRotatableDisplay /// /// The display default color mode /// - public override ColorMode DefautColorMode => ColorMode.Format16bppRgb565; + public override ColorMode DefaultColorMode => ColorMode.Format16bppRgb565; /// /// The color modes supported by the display @@ -286,32 +286,6 @@ protected override void Initialize() DelayMs(20); } - /// - /// Set address window to update - /// - /// Start x position in pixels - /// End x position in pixels - /// Start y position in pixels - /// End y position in pixels - protected override void SetAddressWindow(int x0, int y0, int x1, int y1) - { - SendCommand(LcdCommand.CASET); // column addr set - dataCommandPort.State = Data; - Write((byte)(x0 >> 8)); - Write((byte)(x0 & 0xff)); // XSTART - Write((byte)(x1 >> 8)); - Write((byte)(x1 & 0xff)); // XEND - - SendCommand(LcdCommand.RASET); // row addr set - dataCommandPort.State = Data; - Write((byte)(y0 >> 8)); - Write((byte)(y0 & 0xff)); // YSTART - Write((byte)(y1 >> 8)); - Write((byte)(y1 & 0xff)); // YEND - - SendCommand(LcdCommand.RAMWR); // write to RAM - } - /// /// Set the rotation of the display /// diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Hx8357d.cs b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Hx8357d.cs index 167998b5c3..a3bcf53de4 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Hx8357d.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Hx8357d.cs @@ -11,7 +11,7 @@ public class Hx8357d : TftSpiBase, IRotatableDisplay /// /// The display default color mode /// - public override ColorMode DefautColorMode => ColorMode.Format16bppRgb565; + public override ColorMode DefaultColorMode => ColorMode.Format16bppRgb565; /// /// The color modes supported by the display @@ -167,32 +167,6 @@ protected override void Initialize() DelayMs(50); } - /// - /// Set addrees window for display updates - /// - /// X start in pixels - /// Y start in pixels - /// X end in pixels - /// Y end in pixels - protected override void SetAddressWindow(int x0, int y0, int x1, int y1) - { - SendCommand(LcdCommand.CASET); // column addr set - dataCommandPort.State = Data; - Write((byte)(x0 >> 8)); - Write((byte)(x0 & 0xff)); // XSTART - Write((byte)(x1 >> 8)); - Write((byte)(x1 & 0xff)); // XEND - - SendCommand(LcdCommand.RASET); // row addr set - dataCommandPort.State = Data; - Write((byte)(y0 >> 8)); - Write((byte)(y0 & 0xff)); // YSTART - Write((byte)(y1 >> 8)); - Write((byte)(y1 & 0xff)); // YEND - - SendCommand(LcdCommand.RAMWR); // write to RAM - } - /// /// Set the display rotation /// @@ -201,7 +175,7 @@ public void SetRotation(RotationType rotation) { SendCommand(Register.MADCTL); - switch (rotation) + switch (Rotation = rotation) { case RotationType.Normal: SendData((byte)(Register.MADCTL_MX | Register.MADCTL_MY | Register.MADCTL_RGB)); diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Ili9163.cs b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Ili9163.cs index 02d713a9a1..4395f73cd1 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Ili9163.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Ili9163.cs @@ -11,7 +11,7 @@ public class Ili9163 : TftSpiBase /// /// The default display color mode /// - public override ColorMode DefautColorMode => ColorMode.Format12bppRgb444; + public override ColorMode DefaultColorMode => ColorMode.Format12bppRgb444; /// /// The color modes supported by the display @@ -186,36 +186,7 @@ protected override void Initialize() Write(0x29); // Set display on DelayMs(10); - SetAddressWindow(0, 0, (Width - 1), (Height - 1)); - - dataCommandPort.State = (Data); - } - - /// - /// Set the address window to update the display - /// - /// X0 - /// Y0 - /// X1 - /// Y1 - protected override void SetAddressWindow(int x0, int y0, int x1, int y1) - { - SendCommand(LcdCommand.CASET); // column addr set dataCommandPort.State = Data; - Write((byte)(x0 >> 8)); - Write((byte)(x0 & 0xff)); // XSTART - Write((byte)(x1 >> 8)); - Write((byte)(x1 & 0xff)); // XEND - - SendCommand(LcdCommand.RASET); // row addr set - dataCommandPort.State = (Data); - Write((byte)(y0 >> 8)); - Write((byte)(y0 & 0xff)); // YSTART - Write((byte)(y1 >> 8)); - Write((byte)(y1 & 0xff)); // YEND - - dataCommandPort.State = (Command); - Write((byte)LcdCommand.RAMWR); // write to RAM */ } } } \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Ili9341.cs b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Ili9341.cs index 1dd8403bdf..101b5fe7fc 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Ili9341.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Ili9341.cs @@ -7,17 +7,17 @@ namespace Meadow.Foundation.Displays /// /// Represents a Ili9341 TFT color display /// - public class Ili9341 : TftSpiBase + public class Ili9341 : TftSpiBase, IRotatableDisplay { /// - /// The default SPI bus frequency + /// SPI bus speed /// - public static Frequency DefaultSpiBusSpeed = new Frequency(24000, Frequency.UnitType.Kilohertz); + public override Frequency DefaultSpiBusSpeed => new Frequency(24000, Frequency.UnitType.Kilohertz); /// /// The default display color mode /// - public override ColorMode DefautColorMode => ColorMode.Format12bppRgb444; + public override ColorMode DefaultColorMode => ColorMode.Format12bppRgb444; /// /// The color modes supported by the display @@ -75,22 +75,22 @@ protected override void Initialize() } else { - DelayMs(150); //Not sure if this is needed but can't hurt + DelayMs(120); //Not sure if this is needed but can't hurt } SendCommand(0xEF, new byte[] { 0x03, 0x80, 0x02 }); SendCommand(0xCF, new byte[] { 0x00, 0xC1, 0x30 }); SendCommand(0xED, new byte[] { 0x64, 0x03, 0x12, 0x81 }); - SendCommand(0xe8, new byte[] { 0x85, 0x00, 0x78 }); + SendCommand(0xE8, new byte[] { 0x85, 0x00, 0x78 }); SendCommand(0xCB, new byte[] { 0x39, 0x2C, 0x00, 0x34, 0x02 }); SendCommand(0xF7, new byte[] { 0x20 }); SendCommand(0xEA, new byte[] { 0x00, 0x00 }); SendCommand(ILI9341_PWCTR1, new byte[] { 0x23 }); SendCommand(ILI9341_PWCTR2, new byte[] { 0x10 }); - SendCommand(ILI9341_VMCTR1, new byte[] { 0x3e, 0x28 }); + SendCommand(ILI9341_VMCTR1, new byte[] { 0x3E, 0x28 }); SendCommand(ILI9341_VMCTR2, new byte[] { 0x86 }); - SendCommand((byte)Register.MADCTL, new byte[] { (byte)(Register.MADCTL_MX | Register.MADCTL_BGR) }); //13 + SendCommand((byte)Register.MADCTL, new byte[] { (byte)(Register.MADCTL_MX | Register.MADCTL_BGR) }); if (ColorMode == ColorMode.Format16bppRgb565) { @@ -110,36 +110,7 @@ protected override void Initialize() DelayMs(120); SendCommand(Register.DISPON); - SetAddressWindow(0, 0, Width - 1, Height - 1); - - dataCommandPort.State = (Data); - } - - /// - /// Set addrees window for display updates - /// - /// X start in pixels - /// Y start in pixels - /// X end in pixels - /// Y end in pixels - protected override void SetAddressWindow(int x0, int y0, int x1, int y1) - { - SendCommand(LcdCommand.CASET); // column addr set - dataCommandPort.State = Data; - Write((byte)(x0 >> 8)); - Write((byte)(x0 & 0xff)); // XSTART - Write((byte)(x1 >> 8)); - Write((byte)(x1 & 0xff)); // XEND - - SendCommand(LcdCommand.RASET); // row addr set dataCommandPort.State = Data; - Write((byte)(y0 >> 8)); - Write((byte)(y0 & 0xff)); // YSTART - Write((byte)(y1 >> 8)); - Write((byte)(y1 & 0xff)); // YEND - - dataCommandPort.State = Command; - Write((byte)LcdCommand.RAMWR); // write to RAM */ } void SendCommand(byte command, byte[] data) @@ -154,6 +125,33 @@ void SendCommand(byte command, byte[] data) } } + /// + /// Set the display rotation + /// + /// The rotation value + public void SetRotation(RotationType rotation) + { + SendCommand(Register.MADCTL); + + switch (Rotation = rotation) + { + case RotationType.Normal: + SendData((byte)Register.MADCTL_MX | (byte)Register.MADCTL_BGR); + break; + case RotationType._90Degrees: + SendData((byte)Register.MADCTL_MV | (byte)Register.MADCTL_BGR); + break; + case RotationType._180Degrees: + SendData((byte)Register.MADCTL_MY | (byte)Register.MADCTL_BGR); + break; + case RotationType._270Degrees: + SendData((byte)Register.MADCTL_MX | (byte)Register.MADCTL_MY | (byte)Register.MADCTL_MV | (byte)Register.MADCTL_BGR); + break; + } + + UpdateBuffer(); + } + static byte ILI9341_GAMMASET = 0x26; static byte ILI9341_DFUNCTR = 0xB6; diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Ili9481.cs b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Ili9481.cs index cd508f8365..abeb45c418 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Ili9481.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Ili9481.cs @@ -11,7 +11,7 @@ public class Ili9481 : TftSpiBase, IRotatableDisplay /// /// The default display color mode /// - public override ColorMode DefautColorMode => ColorMode.Format12bppRgb444; + public override ColorMode DefaultColorMode => ColorMode.Format12bppRgb444; /// /// The color modes supported by the display @@ -134,32 +134,6 @@ protected override void Initialize() DelayMs(25); } - /// - /// Set addrees window for display updates - /// - /// X start in pixels - /// Y start in pixels - /// X end in pixels - /// Y end in pixels - protected override void SetAddressWindow(int x0, int y0, int x1, int y1) - { - SendCommand(LcdCommand.CASET); // column addr set - dataCommandPort.State = Data; - Write((byte)(x0 >> 8)); - Write((byte)(x0 & 0xff)); // XSTART - Write((byte)(x1 >> 8)); - Write((byte)(x1 & 0xff)); // XEND - - SendCommand(LcdCommand.RASET); // row addr set - dataCommandPort.State = Data; - Write((byte)(y0 >> 8)); - Write((byte)(y0 & 0xff)); // YSTART - Write((byte)(y1 >> 8)); - Write((byte)(y1 & 0xff)); // YEND - - SendCommand(LcdCommand.RAMWR); // write to RAM - } - /// /// Set the display rotation /// @@ -168,7 +142,7 @@ public void SetRotation(RotationType rotation) { SendCommand(Register.MADCTL); - switch (rotation) + switch (Rotation = rotation) { case RotationType.Normal: SendData((byte)(Register.MADCTL_SS | Register.MADCTL_BGR)); diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Ili9486.cs b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Ili9486.cs index 0c5e0c70b2..c52665a6e0 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Ili9486.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Ili9486.cs @@ -11,7 +11,7 @@ public class Ili9486 : TftSpiBase, IRotatableDisplay /// /// The default display color mode /// - public override ColorMode DefautColorMode => ColorMode.Format12bppRgb444; + public override ColorMode DefaultColorMode => ColorMode.Format12bppRgb444; /// /// The color modes supported by the display @@ -123,32 +123,6 @@ protected override void Initialize() DelayMs(150); } - /// - /// Set addrees window for display updates - /// - /// X start in pixels - /// Y start in pixels - /// X end in pixels - /// Y end in pixels - protected override void SetAddressWindow(int x0, int y0, int x1, int y1) - { - SendCommand(LcdCommand.CASET); // column addr set - dataCommandPort.State = Data; - Write((byte)(x0 >> 8)); - Write((byte)(x0 & 0xff)); // XSTART - Write((byte)(x1 >> 8)); - Write((byte)(x1 & 0xff)); // XEND - - SendCommand(LcdCommand.RASET); // row addr set - dataCommandPort.State = Data; - Write((byte)(y0 >> 8)); - Write((byte)(y0 & 0xff)); // YSTART - Write((byte)(y1 >> 8)); - Write((byte)(y1 & 0xff)); // YEND - - SendCommand(LcdCommand.RAMWR); // write to RAM - } - /// /// Set the display rotation /// @@ -157,7 +131,7 @@ public void SetRotation(RotationType rotation) { SendCommand(Register.MADCTL); - switch (rotation) + switch (Rotation = rotation) { case RotationType.Normal: SendData((byte)Register.MADCTL_MX | (byte)Register.MADCTL_BGR); diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Ili9488.cs b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Ili9488.cs index bc611976d7..7312d674df 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Ili9488.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Ili9488.cs @@ -11,14 +11,13 @@ public class Ili9488 : TftSpiBase, IRotatableDisplay /// /// The default display color mode /// - public override ColorMode DefautColorMode => ColorMode.Format24bppRgb888; + public override ColorMode DefaultColorMode => ColorMode.Format24bppRgb888; /// /// The color modes supported by the display /// public override ColorMode SupportedColorModes => ColorMode.Format24bppRgb888; - /// /// Create a new Ili9488 display object /// @@ -114,10 +113,10 @@ protected override void Initialize() SendData(0x12); SendData(0x80); - SendCommand((byte)Register.MADCTL); // Memory Access Control - SendData(0x48); // MX, BGR + SendCommand(Register.MADCTL); + SendData(0x48); - SendCommand((byte)Register.COLOR_MODE); // Pixel Interface Format + SendCommand(Register.COLOR_MODE); SendData(0x66); //24bpp SendCommand(0xB0); // Interface Mode Control @@ -153,41 +152,15 @@ protected override void Initialize() DelayMs(25); } - /// - /// Set addrees window for display updates - /// - /// X start in pixels - /// Y start in pixels - /// X end in pixels - /// Y end in pixels - protected override void SetAddressWindow(int x0, int y0, int x1, int y1) - { - SendCommand(LcdCommand.CASET); // column addr set - dataCommandPort.State = Data; - Write((byte)(x0 >> 8)); - Write((byte)(x0 & 0xff)); // XSTART - Write((byte)(x1 >> 8)); - Write((byte)(x1 & 0xff)); // XEND - - SendCommand(LcdCommand.RASET); // row addr set - dataCommandPort.State = Data; - Write((byte)(y0 >> 8)); - Write((byte)(y0 & 0xff)); // YSTART - Write((byte)(y1 >> 8)); - Write((byte)(y1 & 0xff)); // YEND - - SendCommand(LcdCommand.RAMWR); // write to RAM - } - /// /// Set the display rotation /// /// The rotation value public void SetRotation(RotationType rotation) { - SendCommand((byte)Register.MADCTL); + SendCommand(Register.MADCTL); - switch (rotation) + switch (Rotation = rotation) { case RotationType.Normal: SendData((byte)Register.MADCTL_MX | (byte)Register.MADCTL_BGR); diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Rm68140.cs b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Rm68140.cs index 4d6bdc85d7..9193a5d2b9 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Rm68140.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Rm68140.cs @@ -11,7 +11,7 @@ public class Rm68140 : TftSpiBase, IRotatableDisplay /// /// The default display color mode /// - public override ColorMode DefautColorMode => ColorMode.Format12bppRgb444; + public override ColorMode DefaultColorMode => ColorMode.Format12bppRgb444; /// /// The color modes supported by the display @@ -103,10 +103,10 @@ protected override void Initialize() SendData(0x0C); SendData(0x00); - SendCommand((byte)Register.MADCTL); + SendCommand(Register.MADCTL); SendData(0x0A); - SendCommand((byte)Register.COLOR_MODE); + SendCommand(Register.COLOR_MODE); if (ColorMode == ColorMode.Format16bppRgb565) SendData(0x55); //16 bit RGB565 else @@ -129,41 +129,15 @@ protected override void Initialize() DelayMs(25); } - /// - /// Set addrees window for display updates - /// - /// X start in pixels - /// Y start in pixels - /// X end in pixels - /// Y end in pixels - protected override void SetAddressWindow(int x0, int y0, int x1, int y1) - { - SendCommand(LcdCommand.CASET); // column addr set - dataCommandPort.State = Data; - Write((byte)(x0 >> 8)); - Write((byte)(x0 & 0xff)); // XSTART - Write((byte)(x1 >> 8)); - Write((byte)(x1 & 0xff)); // XEND - - SendCommand(LcdCommand.RASET); // row addr set - dataCommandPort.State = Data; - Write((byte)(y0 >> 8)); - Write((byte)(y0 & 0xff)); // YSTART - Write((byte)(y1 >> 8)); - Write((byte)(y1 & 0xff)); // YEND - - SendCommand(LcdCommand.RAMWR); // write to RAM - } - /// /// Set the display rotation /// /// The rotation value public void SetRotation(RotationType rotation) { - SendCommand((byte)Register.MADCTL); + SendCommand(Register.MADCTL); - switch (rotation) + switch (Rotation = rotation) { case RotationType.Normal: SendData((byte)Register.MADCTL_BGR); diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/S6D02A1.cs b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/S6D02A1.cs index 198b06dff2..219ca463ca 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/S6D02A1.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/S6D02A1.cs @@ -11,7 +11,7 @@ public class S6D02A1 : TftSpiBase, IRotatableDisplay /// /// The default display color mode /// - public override ColorMode DefautColorMode => ColorMode.Format12bppRgb444; + public override ColorMode DefaultColorMode => ColorMode.Format12bppRgb444; /// /// The color modes supported by the display @@ -108,7 +108,7 @@ protected override void Initialize() SendCommand(0x36, new byte[] { 0xC8 }); // Memory access data control SendCommand(0x35, new byte[] { 0x00 }); // Tearing effect line on - SendCommand((byte)Register.COLOR_MODE); + SendCommand(Register.COLOR_MODE); if (ColorMode == ColorMode.Format16bppRgb565) SendData(0x05); //16 bit RGB565 else @@ -118,36 +118,7 @@ protected override void Initialize() SendCommand(0x29, null); // Display on SendCommand(0x2c, null); // Memory write - SetAddressWindow(0, 0, (Width - 1), (Height - 1)); - - dataCommandPort.State = (Data); - } - - /// - /// Set addrees window for display updates - /// - /// X start in pixels - /// Y start in pixels - /// X end in pixels - /// Y end in pixels - protected override void SetAddressWindow(int x0, int y0, int x1, int y1) - { - SendCommand(LcdCommand.CASET); // column addr set - dataCommandPort.State = (Data); - Write((byte)(x0 >> 8)); - Write((byte)(x0 & 0xff)); // XSTART - Write((byte)(x1 >> 8)); - Write((byte)(x1 & 0xff)); // XEND - - SendCommand(LcdCommand.RASET); // row addr set - dataCommandPort.State = (Data); - Write((byte)(y0 >> 8)); - Write((byte)(y0 & 0xff)); // YSTART - Write((byte)(y1 >> 8)); - Write((byte)(y1 & 0xff)); // YEND - - dataCommandPort.State = (Command); - Write((byte)LcdCommand.RAMWR); // write to RAM */ + dataCommandPort.State = Data; } /// @@ -156,9 +127,9 @@ protected override void SetAddressWindow(int x0, int y0, int x1, int y1) /// The rotation value public void SetRotation(RotationType rotation) { - SendCommand((byte)Register.MADCTL); + SendCommand(Register.MADCTL); - switch (rotation) + switch (Rotation = rotation) { case RotationType.Normal: SendData((byte)Register.MADCTL_MX | (byte)Register.MADCTL_MY | (byte)Register.MADCTL_BGR); diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Ssd1331.cs b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Ssd1331.cs index 5222db3355..c4f7e20db6 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Ssd1331.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Ssd1331.cs @@ -12,7 +12,7 @@ public class Ssd1331 : TftSpiBase /// /// The default display color mode /// - public override ColorMode DefautColorMode => ColorMode.Format16bppRgb565; + public override ColorMode DefaultColorMode => ColorMode.Format16bppRgb565; /// /// The color modes supported by the display @@ -120,13 +120,11 @@ protected override void Initialize() SendCommand(CMD_DISPLAYON); //--turn on oled panel - SetAddressWindow(0, 0, (Width - 1), (Height - 1)); - dataCommandPort.State = Data; } /// - /// Set addrees window for display updates + /// Set address window for display updates /// /// X start in pixels /// Y start in pixels diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Ssd1351.cs b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Ssd1351.cs index 26b79f7e6a..3db1c56e2c 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Ssd1351.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/Ssd1351.cs @@ -1,6 +1,5 @@ using Meadow.Foundation.Graphics; using Meadow.Hardware; -using Meadow.Units; namespace Meadow.Foundation.Displays { @@ -9,15 +8,10 @@ namespace Meadow.Foundation.Displays /// public class Ssd1351 : TftSpiBase { - /// - /// The default SPI bus frequency - /// - public static Frequency DefaultSpiBusSpeed = new Frequency(12000, Frequency.UnitType.Kilohertz); - /// /// The default display color mode /// - public override ColorMode DefautColorMode => ColorMode.Format16bppRgb565; + public override ColorMode DefaultColorMode => ColorMode.Format16bppRgb565; /// /// The color modes supported by the display @@ -133,8 +127,6 @@ protected override void Initialize() SendCommand(CMD_DISPLAYON); - SetAddressWindow(0, 0, (Width - 1), (Height - 1)); - dataCommandPort.State = Data; } diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/St7735.cs b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/St7735.cs index d3279aa2ad..f72f21109d 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/St7735.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/St7735.cs @@ -1,6 +1,5 @@ using Meadow.Foundation.Graphics; using Meadow.Hardware; -using Meadow.Units; namespace Meadow.Foundation.Displays { @@ -9,15 +8,10 @@ namespace Meadow.Foundation.Displays /// public class St7735 : TftSpiBase { - /// - /// The default SPI bus frequency - /// - public static Frequency DefaultSpiBusSpeed = new Frequency(12000, Frequency.UnitType.Kilohertz); - /// /// The default display color mode /// - public override ColorMode DefautColorMode => ColorMode.Format12bppRgb444; + public override ColorMode DefaultColorMode => ColorMode.Format12bppRgb444; /// /// The color modes supported by the display @@ -153,7 +147,6 @@ protected override void Initialize() if (displayType == DisplayType.ST7735B) { Init7735B(); - SetAddressWindow(0, 0, (Width - 1), (Height - 1)); return; } @@ -177,8 +170,6 @@ protected override void Initialize() SendCommand(Register.INVOFF); } - SetAddressWindow(0, 0, (Width - 1), (Height - 1)); - dataCommandPort.State = Data; } @@ -389,21 +380,7 @@ protected override void SetAddressWindow(int x0, int y0, int x1, int y1) x1 += xOffset; y1 += yOffset; - SendCommand(LcdCommand.CASET); // column addr set - dataCommandPort.State = Data; - Write((byte)(x0 >> 8)); - Write((byte)(x0 & 0xff)); // XSTART - Write((byte)(x1 >> 8)); - Write((byte)(x1 & 0xff)); // XEND - - SendCommand(LcdCommand.RASET); // row addr set - dataCommandPort.State = Data; - Write((byte)(y0 >> 8)); - Write((byte)(y0 & 0xff)); // YSTART - Write((byte)(y1 >> 8)); - Write((byte)(y1 & 0xff)); // YEND - - SendCommand(LcdCommand.RAMWR); // write to RAM + base.SetAddressWindow(x0, y0, x1, y1); } } } \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/St7789.cs b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/St7789.cs index 9a48a3d42c..938e4a2d41 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/St7789.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/St7789.cs @@ -9,21 +9,26 @@ namespace Meadow.Foundation.Displays /// public class St7789 : TftSpiBase, IRotatableDisplay { - /// - /// The default SPI bus frequency - /// - public static Frequency DefaultSpiBusSpeed = new Frequency(48000, Frequency.UnitType.Kilohertz); - /// /// The default display color mode /// - public override ColorMode DefautColorMode => ColorMode.Format16bppRgb565; + public override ColorMode DefaultColorMode => ColorMode.Format16bppRgb565; /// /// The color modes supported by the display /// public override ColorMode SupportedColorModes => ColorMode.Format16bppRgb565 | ColorMode.Format12bppRgb444; + /// + /// SPI bus speed + /// + public override Frequency DefaultSpiBusSpeed => new Frequency(48000, Frequency.UnitType.Kilohertz); + + /// + /// The SPI bus mode for the device + /// + public override SpiClockConfiguration.Mode DefaultSpiBusMode => SpiClockConfiguration.Mode.Mode3; + private byte rowStart, rowStart2; private byte columnStart, columnStart2; @@ -128,9 +133,7 @@ protected override void Initialize() SendCommand(Register.NORON); //normal display DelayMs(10); SendCommand(Register.DISPON); //display on - DelayMs(500); - - SetAddressWindow(0, 0, (Width - 1), (Height - 1)); + DelayMs(120); dataCommandPort.State = Data; } @@ -150,21 +153,7 @@ protected override void SetAddressWindow(int x0, int y0, int x1, int y1) x1 += xOffset; y1 += yOffset; - SendCommand(LcdCommand.CASET); // column addr set - dataCommandPort.State = Data; - Write((byte)(x0 >> 8)); - Write((byte)(x0 & 0xff)); // XSTART - Write((byte)(x1 >> 8)); - Write((byte)(x1 & 0xff)); // XEND - - SendCommand(LcdCommand.RASET); // row addr set - dataCommandPort.State = Data; - Write((byte)(y0 >> 8)); - Write((byte)(y0 & 0xff)); // YSTART - Write((byte)(y1 >> 8)); - Write((byte)(y1 & 0xff)); // YEND - - SendCommand(LcdCommand.RAMWR); // write to RAM + base.SetAddressWindow(x0, y0, x1, y1); } /// @@ -175,7 +164,7 @@ public void SetRotation(RotationType rotation) { SendCommand(Register.MADCTL); - switch (rotation) + switch (Rotation = rotation) { case RotationType.Normal: SendData((byte)Register.MADCTL_MX | (byte)Register.MADCTL_MY | (byte)Register.MADCTL_RGB); diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/St7796s.cs b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/St7796s.cs index 684d7c1d20..e68ef5398c 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/St7796s.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/Drivers/St7796s.cs @@ -11,7 +11,7 @@ public class St7796s : TftSpiBase, IRotatableDisplay /// /// The default display color mode /// - public override ColorMode DefautColorMode => ColorMode.Format12bppRgb444; + public override ColorMode DefaultColorMode => ColorMode.Format12bppRgb444; /// /// The color modes supported by the display @@ -158,41 +158,15 @@ protected override void Initialize() SendCommand(0x29); //Display on } - /// - /// Set addrees window for display updates - /// - /// X start in pixels - /// Y start in pixels - /// X end in pixels - /// Y end in pixels - protected override void SetAddressWindow(int x0, int y0, int x1, int y1) - { - SendCommand(LcdCommand.CASET); // column addr set - dataCommandPort.State = Data; - Write((byte)(x0 >> 8)); - Write((byte)(x0 & 0xff)); // XSTART - Write((byte)(x1 >> 8)); - Write((byte)(x1 & 0xff)); // XEND - - SendCommand(LcdCommand.RASET); // row addr set - dataCommandPort.State = Data; - Write((byte)(y0 >> 8)); - Write((byte)(y0 & 0xff)); // YSTART - Write((byte)(y1 >> 8)); - Write((byte)(y1 & 0xff)); // YEND - - SendCommand(LcdCommand.RAMWR); // write to RAM - } - /// /// Set the display rotation /// /// The rotation value public void SetRotation(RotationType rotation) { - SendCommand((byte)Register.MADCTL); + SendCommand(Register.MADCTL); - switch (rotation) + switch (Rotation = rotation) { case RotationType.Normal: SendData((byte)Register.MADCTL_MX | (byte)Register.MADCTL_BGR); diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/TftSpiBase.Enums.cs b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/TftSpiBase.Enums.cs index 482f583d25..900c15314a 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/TftSpiBase.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/TftSpiBase.Enums.cs @@ -11,11 +11,11 @@ public abstract partial class TftSpiBase protected enum LcdCommand : byte { /// - /// CASET + /// Column address set /// CASET = 0x2A, /// - /// RASET + /// Row address set /// RASET = 0x2B, /// @@ -70,7 +70,7 @@ protected enum Register : byte /// DISPON = 0x29, /// - /// MADCTL + /// Memory access control /// MADCTL = 0x36, /// diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/TftSpiBase.cs b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/TftSpiBase.cs index b76f1efebe..df89f9dc9d 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/TftSpiBase.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Driver/TftSpiBase.cs @@ -1,13 +1,19 @@ using Meadow.Foundation.Graphics; using Meadow.Foundation.Graphics.Buffers; using Meadow.Hardware; +using Meadow.Units; using System; using System.Threading; namespace Meadow.Foundation.Displays { - public abstract partial class TftSpiBase : IGraphicsDisplay + public abstract partial class TftSpiBase : IGraphicsDisplay, ISpiPeripheral { + /// + /// Temporary buffer that can be used to batch set address window buffer commands + /// + protected byte[] SetAddressBuffer { get; } = new byte[4]; + //these displays typically support 16 & 18 bit, some also include 8, 9, 12 and/or 24 bit color /// @@ -23,12 +29,12 @@ public abstract partial class TftSpiBase : IGraphicsDisplay /// /// The current rotation of the display /// - public RotationType Rotation { get; set; } = RotationType.Normal; + public RotationType Rotation { get; protected set; } = RotationType.Normal; /// /// The display default color mode /// - public abstract ColorMode DefautColorMode { get; } + public abstract ColorMode DefaultColorMode { get; } /// /// Width of display in pixels @@ -45,6 +51,34 @@ public abstract partial class TftSpiBase : IGraphicsDisplay /// public IPixelBuffer PixelBuffer => imageBuffer; + /// + /// The default SPI bus speed for the device + /// + public virtual Frequency DefaultSpiBusSpeed => new Frequency(12000, Frequency.UnitType.Kilohertz); + + /// + /// The SPI bus speed for the device + /// + public Frequency SpiBusSpeed + { + get => spiDisplay.BusSpeed; + set => spiDisplay.BusSpeed = value; + } + + /// + /// The default SPI bus mode for the device + /// + public virtual SpiClockConfiguration.Mode DefaultSpiBusMode => SpiClockConfiguration.Mode.Mode0; + + /// + /// The SPI bus mode for the device + /// + public SpiClockConfiguration.Mode SpiBusMode + { + get => spiDisplay.BusMode; + set => spiDisplay.BusMode = value; + } + /// /// The data command port /// @@ -63,7 +97,7 @@ public abstract partial class TftSpiBase : IGraphicsDisplay /// /// The spi peripheral for the display /// - protected ISpiPeripheral spiDisplay; + protected ISpiCommunications spiDisplay; /// /// The offscreen image buffer @@ -100,6 +134,30 @@ public abstract partial class TftSpiBase : IGraphicsDisplay /// protected int nativeWidth; + /// + /// Previous x0 value passed to SetAddressWindow + /// Used for optimization to avoid unnecessary SPI commands + /// + protected int setAddressLastX0 = -1; + + /// + /// Previous x1 value passed to SetAddressWindow + /// Used for optimization to avoid unnecessary SPI commands + /// + protected int setAddressLastX1 = -1; + + /// + /// Previous y0 value passed to SetAddressWindow + /// Used for optimization to avoid unnecessary SPI commands + /// + protected int setAddressLastY0 = -1; + + /// + /// Previous y1 value passed to SetAddressWindow + /// Used for optimization to avoid unnecessary SPI commands + /// + protected int setAddressLastY1 = -1; + /// /// Represents an abstract TftSpiBase object /// @@ -116,7 +174,7 @@ public TftSpiBase(ISpiBus spiBus, IPin chipSelectPin, IPin dcPin, IPin resetPin, spiBus, chipSelectPin?.CreateDigitalOutputPort(), dcPin.CreateDigitalOutputPort(), - resetPin.CreateDigitalOutputPort(), + resetPin?.CreateDigitalOutputPort(), width, height, colorMode ) { @@ -143,7 +201,7 @@ public TftSpiBase(ISpiBus spiBus, this.chipSelectPort = chipSelectPort; this.resetPort = resetPort; - spiDisplay = new SpiPeripheral(spiBus, chipSelectPort); + spiDisplay = new SpiCommunications(spiBus, chipSelectPort, DefaultSpiBusSpeed, DefaultSpiBusMode); CreateBuffer(colorMode, nativeWidth = width, nativeHeight = height); } @@ -156,42 +214,32 @@ public TftSpiBase(ISpiBus spiBus, public virtual bool IsColorTypeSupported(ColorMode colorType) { return (SupportedColorModes | colorType) != 0; - /* - if (SupportedColors) - - - if (mode == ColorType.Format12bppRgb444 || - mode == ColorType.Format16bppRgb565) - { - return true; - } - return false;*/ } /// /// Create an offscreen buffer for the display /// - /// The color mode + /// The color mode /// The width in pixels /// The height in pixels /// Throws an exception if the color mode isn't supported - protected void CreateBuffer(ColorMode colorType, int width, int height) + protected void CreateBuffer(ColorMode colorMode, int width, int height) { - if (IsColorTypeSupported(colorType) == false) + if (IsColorTypeSupported(colorMode) == false) { - throw new ArgumentException($"color mode {colorType} not supported"); + throw new ArgumentException($"color mode {colorMode} not supported"); } - if (colorType == ColorMode.Format24bppRgb888) + if (colorMode == ColorMode.Format24bppRgb888) { imageBuffer = new BufferRgb888(width, height); } - else if (colorType == ColorMode.Format16bppRgb565) + else if (colorMode == ColorMode.Format16bppRgb565) { imageBuffer = new BufferRgb565(width, height); } - else //Rgb444 + else { imageBuffer = new BufferRgb444(width, height); } @@ -199,13 +247,40 @@ protected void CreateBuffer(ColorMode colorType, int width, int height) } /// - /// Set addrees window for display updates + /// Set address window for display updates /// /// X start in pixels /// Y start in pixels /// X end in pixels /// Y end in pixels - protected abstract void SetAddressWindow(int x0, int y0, int x1, int y1); + protected virtual void SetAddressWindow(int x0, int y0, int x1, int y1) + { + if (x0 != setAddressLastX0 || x1 != setAddressLastX1 || y0 != setAddressLastY0 || y1 != setAddressLastY1) + { + setAddressLastX0 = x0; + setAddressLastX1 = x1; + setAddressLastY0 = y0; + setAddressLastY1 = y1; + + SendCommand(LcdCommand.CASET); // column addr set + dataCommandPort.State = Data; + SetAddressBuffer[0] = (byte)(x0 >> 8); + SetAddressBuffer[1] = (byte)(x0 & 0xff); // XSTART + SetAddressBuffer[2] = (byte)(x1 >> 8); + SetAddressBuffer[3] = (byte)(x1 & 0xff); // XEND + Write(SetAddressBuffer); + + SendCommand(LcdCommand.RASET); // row addr set + dataCommandPort.State = Data; + SetAddressBuffer[0] = (byte)(y0 >> 8); + SetAddressBuffer[1] = (byte)(y0 & 0xff); // XEND + SetAddressBuffer[2] = (byte)(y1 >> 8); + SetAddressBuffer[3] = (byte)(y1 & 0xff); // YEND + Write(SetAddressBuffer); + + SendCommand(LcdCommand.RAMWR); // write to RAM + } + } /// /// Clear the display. @@ -308,7 +383,7 @@ public void Fill(int x, int y, int width, int height, Color color) /// public void Show() { - SetAddressWindow(0, 0, Width - 1, Height); + SetAddressWindow(0, 0, Width - 1, Height - 1); dataCommandPort.State = Data; diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Gc9a01_Sample/Gc9a01_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Gc9a01_Sample/Gc9a01_Sample.csproj index 48503a4911..e9e1887334 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Gc9a01_Sample/Gc9a01_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Gc9a01_Sample/Gc9a01_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Gc9a01_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Gc9a01_Sample/MeadowApp.cs index 205e2ec8a7..7a096b9962 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Gc9a01_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Gc9a01_Sample/MeadowApp.cs @@ -2,8 +2,6 @@ using Meadow.Devices; using Meadow.Foundation.Displays; using Meadow.Foundation.Graphics; -using Meadow.Hardware; -using Meadow.Units; using System.Threading.Tasks; namespace Displays.Tft.Gc9a01_Sample @@ -18,8 +16,7 @@ public override Task Initialize() { Resolver.Log.Info("Initializing ..."); - var config = new SpiClockConfiguration(new Frequency(12000, Frequency.UnitType.Kilohertz), SpiClockConfiguration.Mode.Mode0); - var spiBus = Device.CreateSpiBus(Device.Pins.SCK, Device.Pins.MOSI, Device.Pins.MISO, config); + var spiBus = Device.CreateSpiBus(); Resolver.Log.Info("Create display driver instance"); diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Hx8357b_Sample/Hx8357b_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Hx8357b_Sample/Hx8357b_Sample.csproj index 48503a4911..e9e1887334 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Hx8357b_Sample/Hx8357b_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Hx8357b_Sample/Hx8357b_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Hx8357b_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Hx8357b_Sample/MeadowApp.cs index 8bb6f15a1c..3d17ae9d19 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Hx8357b_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Hx8357b_Sample/MeadowApp.cs @@ -3,8 +3,6 @@ using Meadow.Foundation; using Meadow.Foundation.Displays; using Meadow.Foundation.Graphics; -using Meadow.Hardware; -using Meadow.Units; using System; using System.Diagnostics; using System.Threading; @@ -22,8 +20,7 @@ public override Task Initialize() { Resolver.Log.Info("Initializing ..."); - var config = new SpiClockConfiguration(new Frequency(12000, Frequency.UnitType.Kilohertz), SpiClockConfiguration.Mode.Mode0); - var spiBus = Device.CreateSpiBus(Device.Pins.SCK, Device.Pins.MOSI, Device.Pins.MISO, config); + var spiBus = Device.CreateSpiBus(); Resolver.Log.Info("Create display driver instance"); diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Hx8357d_Sample/Hx8357d_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Hx8357d_Sample/Hx8357d_Sample.csproj index 48503a4911..e9e1887334 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Hx8357d_Sample/Hx8357d_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Hx8357d_Sample/Hx8357d_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Hx8357d_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Hx8357d_Sample/MeadowApp.cs index 48d47254e3..612b5a2363 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Hx8357d_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Hx8357d_Sample/MeadowApp.cs @@ -3,8 +3,6 @@ using Meadow.Foundation; using Meadow.Foundation.Displays; using Meadow.Foundation.Graphics; -using Meadow.Hardware; -using Meadow.Units; using System; using System.Diagnostics; using System.Threading; @@ -22,8 +20,7 @@ public override Task Initialize() { Resolver.Log.Info("Initializing ..."); - var config = new SpiClockConfiguration(new Frequency(12000, Frequency.UnitType.Kilohertz), SpiClockConfiguration.Mode.Mode0); - var spiBus = Device.CreateSpiBus(Device.Pins.SCK, Device.Pins.MOSI, Device.Pins.MISO, config); + var spiBus = Device.CreateSpiBus(); Resolver.Log.Info("Create display driver instance"); diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9163_Sample/Ili9163_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9163_Sample/Ili9163_Sample.csproj index 48503a4911..e9e1887334 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9163_Sample/Ili9163_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9163_Sample/Ili9163_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9163_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9163_Sample/MeadowApp.cs index c73a6b656d..e8e2ad9252 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9163_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9163_Sample/MeadowApp.cs @@ -2,8 +2,6 @@ using Meadow.Devices; using Meadow.Foundation.Displays; using Meadow.Foundation.Graphics; -using Meadow.Hardware; -using Meadow.Units; using System.Threading.Tasks; namespace Displays.Tft.Ili9163_Sample @@ -18,8 +16,7 @@ public override Task Initialize() { Resolver.Log.Info("Initializing ..."); - var config = new SpiClockConfiguration(new Frequency(12000, Frequency.UnitType.Kilohertz), SpiClockConfiguration.Mode.Mode0); - var spiBus = Device.CreateSpiBus(Device.Pins.SCK, Device.Pins.MOSI, Device.Pins.MISO, config); + var spiBus = Device.CreateSpiBus(); Resolver.Log.Info("Create display driver instance"); diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9341_Jpg_Sample/Ili9341_Jpg_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9341_Jpg_Sample/Ili9341_Jpg_Sample.csproj index 523f0ef410..09e1200534 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9341_Jpg_Sample/Ili9341_Jpg_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9341_Jpg_Sample/Ili9341_Jpg_Sample.csproj @@ -13,7 +13,7 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9341_Jpg_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9341_Jpg_Sample/MeadowApp.cs index a51c01d0a7..b7c9fba4e9 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9341_Jpg_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9341_Jpg_Sample/MeadowApp.cs @@ -22,7 +22,7 @@ public override Task Initialize() { Resolver.Log.Info("Initializing..."); - var spiBus = Device.CreateSpiBus(Ili9341.DefaultSpiBusSpeed); + var spiBus = Device.CreateSpiBus(); display = new Ili9341 ( diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9341_Sample/Ili9341_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9341_Sample/Ili9341_Sample.csproj index 48503a4911..e9e1887334 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9341_Sample/Ili9341_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9341_Sample/Ili9341_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9341_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9341_Sample/MeadowApp.cs index 709f57ea91..041e20ee90 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9341_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9341_Sample/MeadowApp.cs @@ -3,8 +3,6 @@ using Meadow.Foundation; using Meadow.Foundation.Displays; using Meadow.Foundation.Graphics; -using Meadow.Hardware; -using Meadow.Units; using System; using System.Threading; using System.Threading.Tasks; @@ -22,14 +20,11 @@ public override Task Initialize() { Resolver.Log.Info("Initializing ..."); - var config = new SpiClockConfiguration(new Frequency(12000, Frequency.UnitType.Kilohertz), SpiClockConfiguration.Mode.Mode0); - var spiBus = Device.CreateSpiBus(Device.Pins.SCK, Device.Pins.MOSI, Device.Pins.MISO, config); - Resolver.Log.Info("Create display driver instance"); display = new Ili9341 ( - spiBus: spiBus, + spiBus: Device.CreateSpiBus(), chipSelectPin: Device.Pins.D13, dcPin: Device.Pins.D14, resetPin: Device.Pins.D15, diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9481_Sample/Ili9481_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9481_Sample/Ili9481_Sample.csproj index 48503a4911..e9e1887334 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9481_Sample/Ili9481_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9481_Sample/Ili9481_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9481_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9481_Sample/MeadowApp.cs index 9c7c0d4029..7dc529438d 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9481_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9481_Sample/MeadowApp.cs @@ -2,8 +2,6 @@ using Meadow.Devices; using Meadow.Foundation.Displays; using Meadow.Foundation.Graphics; -using Meadow.Hardware; -using Meadow.Units; using System.Threading.Tasks; namespace Displays.Tft.Ili9481_Sample @@ -18,8 +16,7 @@ public override Task Initialize() { Resolver.Log.Info("Initializing ..."); - var config = new SpiClockConfiguration(new Frequency(12000, Frequency.UnitType.Kilohertz), SpiClockConfiguration.Mode.Mode0); - var spiBus = Device.CreateSpiBus(Device.Pins.SCK, Device.Pins.MOSI, Device.Pins.MISO, config); + var spiBus = Device.CreateSpiBus(); Resolver.Log.Info("Create display driver instance"); diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9486_Sample/Ili9486_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9486_Sample/Ili9486_Sample.csproj index 48503a4911..e9e1887334 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9486_Sample/Ili9486_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9486_Sample/Ili9486_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9486_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9486_Sample/MeadowApp.cs index 76747c5923..aa76b0625b 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9486_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9486_Sample/MeadowApp.cs @@ -2,8 +2,6 @@ using Meadow.Devices; using Meadow.Foundation.Displays; using Meadow.Foundation.Graphics; -using Meadow.Hardware; -using Meadow.Units; using System.Threading.Tasks; namespace Displays.Tft.Ili9486_Sample @@ -18,8 +16,7 @@ public override Task Initialize() { Resolver.Log.Info("Initializing ..."); - var config = new SpiClockConfiguration(new Frequency(12000, Frequency.UnitType.Kilohertz), SpiClockConfiguration.Mode.Mode0); - var spiBus = Device.CreateSpiBus(Device.Pins.SCK, Device.Pins.MOSI, Device.Pins.MISO, config); + var spiBus = Device.CreateSpiBus(); Resolver.Log.Info("Create display driver instance"); diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9488_Sample/Ili9488_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9488_Sample/Ili9488_Sample.csproj index 48503a4911..e9e1887334 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9488_Sample/Ili9488_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9488_Sample/Ili9488_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9488_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9488_Sample/MeadowApp.cs index eb1128b7f1..2c65de9ea8 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9488_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ili9488_Sample/MeadowApp.cs @@ -2,8 +2,6 @@ using Meadow.Devices; using Meadow.Foundation.Displays; using Meadow.Foundation.Graphics; -using Meadow.Hardware; -using Meadow.Units; using System.Threading.Tasks; namespace Displays.Tft.Ili9488_Sample @@ -18,8 +16,7 @@ public override Task Initialize() { Resolver.Log.Info("Initializing ..."); - var config = new SpiClockConfiguration(new Frequency(12000, Frequency.UnitType.Kilohertz), SpiClockConfiguration.Mode.Mode0); - var spiBus = Device.CreateSpiBus(Device.Pins.SCK, Device.Pins.MOSI, Device.Pins.MISO, config); + var spiBus = Device.CreateSpiBus(); Resolver.Log.Info("Create display driver instance"); diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Rm68140_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Rm68140_Sample/MeadowApp.cs index 38d6a4452a..a95d1ecff2 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Rm68140_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Rm68140_Sample/MeadowApp.cs @@ -2,8 +2,6 @@ using Meadow.Devices; using Meadow.Foundation.Displays; using Meadow.Foundation.Graphics; -using Meadow.Hardware; -using Meadow.Units; using System.Threading.Tasks; namespace Displays.Tft.Rm68140_Sample @@ -18,8 +16,7 @@ public override Task Initialize() { Resolver.Log.Info("Initializing ..."); - var config = new SpiClockConfiguration(new Frequency(12000, Frequency.UnitType.Kilohertz), SpiClockConfiguration.Mode.Mode0); - var spiBus = Device.CreateSpiBus(Device.Pins.SCK, Device.Pins.MOSI, Device.Pins.MISO, config); + var spiBus = Device.CreateSpiBus(); Resolver.Log.Info("Create display driver instance"); diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Rm68140_Sample/Rm68140_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Rm68140_Sample/Rm68140_Sample.csproj index 48503a4911..e9e1887334 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Rm68140_Sample/Rm68140_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Rm68140_Sample/Rm68140_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/S6D02A1_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/S6D02A1_Sample/MeadowApp.cs index 48ef960502..ead06e0241 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/S6D02A1_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/S6D02A1_Sample/MeadowApp.cs @@ -2,8 +2,6 @@ using Meadow.Devices; using Meadow.Foundation.Displays; using Meadow.Foundation.Graphics; -using Meadow.Hardware; -using Meadow.Units; using System.Threading.Tasks; namespace Displays.Tft.S6D02A1_Sample @@ -18,8 +16,7 @@ public override Task Initialize() { Resolver.Log.Info("Initializing ..."); - var config = new SpiClockConfiguration(new Frequency(12000, Frequency.UnitType.Kilohertz), SpiClockConfiguration.Mode.Mode0); - var spiBus = Device.CreateSpiBus(Device.Pins.SCK, Device.Pins.MOSI, Device.Pins.MISO, config); + var spiBus = Device.CreateSpiBus(); Resolver.Log.Info("Create display driver instance"); diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/S6D02A1_Sample/S6D02A1_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/S6D02A1_Sample/S6D02A1_Sample.csproj index 48503a4911..e9e1887334 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/S6D02A1_Sample/S6D02A1_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/S6D02A1_Sample/S6D02A1_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/ST7789_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/ST7789_Sample/MeadowApp.cs index d34a9ce65d..8d221beb2f 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/ST7789_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/ST7789_Sample/MeadowApp.cs @@ -4,8 +4,6 @@ using Meadow.Foundation.Displays; using Meadow.Foundation.Graphics; using Meadow.Foundation.Graphics.Buffers; -using Meadow.Hardware; -using Meadow.Units; using System; using System.Diagnostics; using System.Threading; @@ -39,8 +37,7 @@ public override Task Initialize() { Resolver.Log.Info("Initializing ..."); - var config = new SpiClockConfiguration(new Frequency(48000, Frequency.UnitType.Kilohertz), SpiClockConfiguration.Mode.Mode3); - var spiBus = Device.CreateSpiBus(Device.Pins.SCK, Device.Pins.MOSI, Device.Pins.MISO, config); + var spiBus = Device.CreateSpiBus(); display = new St7789( spiBus: spiBus, @@ -312,7 +309,7 @@ void LineTest() for (int i = 1; i < 10; i++) { graphics.Stroke = i; - graphics.DrawHorizontalLine((int)graphics.Width - 5, 20 * i, (int)(10 - graphics.Width), Color.Green); + graphics.DrawHorizontalLine(graphics.Width - 5, 20 * i, 10 - graphics.Width, Color.Green); } graphics.Show(); Thread.Sleep(1500); @@ -325,7 +322,7 @@ void LineTest() for (int i = 1; i < 10; i++) { graphics.Stroke = i; - graphics.DrawVerticalLine(20 * i, 5, (int)(graphics.Height - 10), Color.Orange); + graphics.DrawVerticalLine(20 * i, 5, graphics.Height - 10, Color.Orange); } graphics.Show(); Thread.Sleep(1500); @@ -335,7 +332,7 @@ void LineTest() for (int i = 1; i < 10; i++) { graphics.Stroke = i; - graphics.DrawVerticalLine(20 * i, (int)(graphics.Height - 5), (int)(10 - graphics.Width), Color.Blue); + graphics.DrawVerticalLine(20 * i, graphics.Height - 5, 10 - graphics.Width, Color.Blue); } graphics.Show(); Thread.Sleep(1500); @@ -464,7 +461,7 @@ void StrokeTest() graphics.DrawLine(85, 125, 195, 235, Color.Silver); graphics.Stroke = 2; - graphics.DrawRectangle(2, 2, (int)(graphics.Width - 4), (int)(graphics.Height - 4), Color.DimGray, false); + graphics.DrawRectangle(2, 2, graphics.Width - 4, graphics.Height - 4, Color.DimGray, false); graphics.Show(); } diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/ST7789_Sample/ST7789_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/ST7789_Sample/ST7789_Sample.csproj index 48503a4911..e9e1887334 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/ST7789_Sample/ST7789_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/ST7789_Sample/ST7789_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ssd1331_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ssd1331_Sample/MeadowApp.cs index 2138bf6a13..af1dd5a09a 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ssd1331_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ssd1331_Sample/MeadowApp.cs @@ -2,7 +2,6 @@ using Meadow.Devices; using Meadow.Foundation.Displays; using Meadow.Foundation.Graphics; -using Meadow.Hardware; using System.Threading.Tasks; namespace Displays.Tft.Ssd1331_Sample @@ -17,9 +16,7 @@ public override Task Initialize() { Resolver.Log.Info("Initializing ..."); - var config = new SpiClockConfiguration(new Meadow.Units.Frequency(12000, Meadow.Units.Frequency.UnitType.Kilohertz), - SpiClockConfiguration.Mode.Mode0); - var spiBus = Device.CreateSpiBus(Device.Pins.SCK, Device.Pins.MOSI, Device.Pins.MISO, config); + var spiBus = Device.CreateSpiBus(); Resolver.Log.Info("Create display driver instance"); diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ssd1331_Sample/Ssd1331_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ssd1331_Sample/Ssd1331_Sample.csproj index 48503a4911..e9e1887334 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ssd1331_Sample/Ssd1331_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ssd1331_Sample/Ssd1331_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ssd1351_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ssd1351_Sample/MeadowApp.cs index 79052d7c94..c7c33854a6 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ssd1351_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ssd1351_Sample/MeadowApp.cs @@ -16,7 +16,7 @@ public override Task Initialize() { Resolver.Log.Info("Initializing ..."); - var spiBus = Device.CreateSpiBus(Ssd1351.DefaultSpiBusSpeed); + var spiBus = Device.CreateSpiBus(); var display = new Ssd1351( spiBus: spiBus, diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ssd1351_Sample/Ssd1351_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ssd1351_Sample/Ssd1351_Sample.csproj index 48503a4911..e9e1887334 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ssd1351_Sample/Ssd1351_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/Ssd1351_Sample/Ssd1351_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/St7735_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/St7735_Sample/MeadowApp.cs index 7cb5720756..48ba59b2c9 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/St7735_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/St7735_Sample/MeadowApp.cs @@ -17,7 +17,7 @@ public override Task Initialize() { Resolver.Log.Info("Initializing ..."); - var spiBus = Device.CreateSpiBus(St7735.DefaultSpiBusSpeed); + var spiBus = Device.CreateSpiBus(); //note - you may need to adjust the DisplayType for your specific St7735 var display = new St7735( diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/St7735_Sample/St7735_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/St7735_Sample/St7735_Sample.csproj index 48503a4911..e9e1887334 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/St7735_Sample/St7735_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/St7735_Sample/St7735_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/St7796s_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/St7796s_Sample/MeadowApp.cs index 7b79b082e9..c340fbae6f 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/St7796s_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/St7796s_Sample/MeadowApp.cs @@ -2,7 +2,6 @@ using Meadow.Devices; using Meadow.Foundation.Displays; using Meadow.Foundation.Graphics; -using Meadow.Hardware; using System.Threading.Tasks; namespace Displays.Tft.St7796s_Sample @@ -17,9 +16,7 @@ public override Task Initialize() { Resolver.Log.Info("Initializing ..."); - var config = new SpiClockConfiguration(new Meadow.Units.Frequency(12000, Meadow.Units.Frequency.UnitType.Kilohertz) - , SpiClockConfiguration.Mode.Mode0); - var spiBus = Device.CreateSpiBus(Device.Pins.SCK, Device.Pins.MOSI, Device.Pins.MISO, config); + var spiBus = Device.CreateSpiBus(); Resolver.Log.Info("Create display driver instance"); diff --git a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/St7796s_Sample/St7796s_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/St7796s_Sample/St7796s_Sample.csproj index 48503a4911..e9e1887334 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/St7796s_Sample/St7796s_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.TftSpi/Samples/St7796s_Sample/St7796s_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Tm1637/Driver/Displays.Tm1637.csproj b/Source/Meadow.Foundation.Peripherals/Displays.Tm1637/Driver/Displays.Tm1637.csproj index 66bdc65397..6e5d48837d 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Tm1637/Driver/Displays.Tm1637.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.Tm1637/Driver/Displays.Tm1637.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.Tm1637/Samples/Tm1637_Sample/Tm1637_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.Tm1637/Samples/Tm1637_Sample/Tm1637_Sample.csproj index 82789bbe4a..428001c25b 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.Tm1637/Samples/Tm1637_Sample/Tm1637_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.Tm1637/Samples/Tm1637_Sample/Tm1637_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.WinForms/Driver/Displays.WinForms.csproj b/Source/Meadow.Foundation.Peripherals/Displays.WinForms/Driver/Displays.WinForms.csproj index 7d589dc922..a641691013 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.WinForms/Driver/Displays.WinForms.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.WinForms/Driver/Displays.WinForms.csproj @@ -21,6 +21,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Driver/Displays.ePaper.csproj b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Driver/Displays.ePaper.csproj index 1556a625b5..0ec966ac3b 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Driver/Displays.ePaper.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Driver/Displays.ePaper.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Driver/Drivers/Il0373.cs b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Driver/Drivers/Il0373.cs index df1c93aa7b..ca00098204 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Driver/Drivers/Il0373.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Driver/Drivers/Il0373.cs @@ -108,14 +108,14 @@ protected void SetPartialWindow(byte[] bufferBlack, byte[] bufferColor, int x, i { for (int i = 0; i < width / 8 * height; i++) { - spiPeripheral.Write(bufferBlack[i]); + spiComms.Write(bufferBlack[i]); } } else { for (int i = 0; i < width / 8 * height; i++) { - spiPeripheral.Write(0x00); + spiComms.Write(0x00); } } DelayMs(2); @@ -127,14 +127,14 @@ protected void SetPartialWindow(byte[] bufferBlack, byte[] bufferColor, int x, i { for (int i = 0; i < width / 8 * height; i++) { - spiPeripheral.Write(bufferColor[i]); + spiComms.Write(bufferColor[i]); } } else { for (int i = 0; i < width / 8 * height; i++) { - spiPeripheral.Write(0x00); + spiComms.Write(0x00); } } DelayMs(2); diff --git a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Driver/Drivers/Il91874.cs b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Driver/Drivers/Il91874.cs index 95c7da4320..0cf250eb14 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Driver/Drivers/Il91874.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Driver/Drivers/Il91874.cs @@ -277,7 +277,7 @@ void DisplayFrame(byte[] bufferBlack, byte[] bufferRed) for (int i = 0; i < Width * Height / 8; i++) { - spiPeripheral.Write(bufferBlack[i]); + spiComms.Write(bufferBlack[i]); } } @@ -289,7 +289,7 @@ void DisplayFrame(byte[] bufferBlack, byte[] bufferRed) for (int i = 0; i < Width * Height / 8; i++) { - spiPeripheral.Write((byte)~bufferRed[i]); + spiComms.Write((byte)~bufferRed[i]); } } diff --git a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Driver/Drivers/Ssd1681.cs b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Driver/Drivers/Ssd1681.cs index 1e11f1e5ac..b2047d301c 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Driver/Drivers/Ssd1681.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Driver/Drivers/Ssd1681.cs @@ -141,7 +141,7 @@ void DisplayFrame(byte[] blackBuffer, byte[] colorBuffer) for (int i = 0; i < colorBuffer.Length; i++) { //invert the color data - spiPeripheral.Write((byte)~colorBuffer[i]); + spiComms.Write((byte)~colorBuffer[i]); } DisplayFrame(); diff --git a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Driver/Drivers/Uc8151c.cs b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Driver/Drivers/Uc8151c.cs index a20ec37bee..4093a67c85 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Driver/Drivers/Uc8151c.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Driver/Drivers/Uc8151c.cs @@ -119,14 +119,14 @@ protected void SetPartialWindow(byte[] bufferBlack, byte[] bufferColor, int x, i { for (int i = 0; i < width / 8 * height; i++) { - spiPeripheral.Write(bufferBlack[i]); + spiComms.Write(bufferBlack[i]); } } else { for (int i = 0; i < width / 8 * height; i++) { - spiPeripheral.Write(0x00); + spiComms.Write(0x00); } } DelayMs(2); @@ -138,14 +138,14 @@ protected void SetPartialWindow(byte[] bufferBlack, byte[] bufferColor, int x, i { for (int i = 0; i < width / 8 * height; i++) { - spiPeripheral.Write(bufferColor[i]); + spiComms.Write(bufferColor[i]); } } else { for (int i = 0; i < width / 8 * height; i++) { - spiPeripheral.Write(0x00); + spiComms.Write(0x00); } } DelayMs(2); diff --git a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Driver/EPaperMonoBase.cs b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Driver/EPaperMonoBase.cs index 90f475f3fa..0014e77833 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Driver/EPaperMonoBase.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Driver/EPaperMonoBase.cs @@ -92,7 +92,7 @@ public EPaperMonoBase(ISpiBus spiBus, this.resetPort = resetPort; this.busyPort = busyPort; - spiPeripheral = new SpiPeripheral(spiBus, chipSelectPort); + spiComms = new SpiCommunications(spiBus, chipSelectPort, DefaultSpiBusSpeed, DefaultSpiBusMode); imageBuffer = new Buffer1bppV(width, height); @@ -284,7 +284,7 @@ public virtual void SetFrameMemory(byte[] buffer) dataCommandPort.State = DataState; for (int i = 0; i < Width / 8 * Height; i++) { - spiPeripheral.Write(buffer[i]); + spiComms.Write(buffer[i]); } } diff --git a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Driver/EPaperTriColorBase.cs b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Driver/EPaperTriColorBase.cs index 2792a84571..5fd512d52b 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Driver/EPaperTriColorBase.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Driver/EPaperTriColorBase.cs @@ -103,7 +103,7 @@ public EPaperTriColorBase(ISpiBus spiBus, this.resetPort = resetPort; this.busyPort = busyPort; - spiPeripheral = new SpiPeripheral(spiBus, chipSelectPort); + spiComms = new SpiCommunications(spiBus, chipSelectPort, DefaultSpiBusSpeed, DefaultSpiBusMode); this.width = width; this.height = height; diff --git a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Driver/ePaperBase.cs b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Driver/ePaperBase.cs index b6a1a362dc..f07678cb18 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Driver/ePaperBase.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Driver/ePaperBase.cs @@ -1,4 +1,5 @@ using Meadow.Hardware; +using Meadow.Units; using System.Threading; namespace Meadow.Foundation.Displays @@ -6,8 +7,36 @@ namespace Meadow.Foundation.Displays /// /// Represents a base ePaper display driver /// - public abstract class EPaperBase + public abstract class EPaperBase : ISpiPeripheral { + /// + /// The default SPI bus speed for the device + /// + public Frequency DefaultSpiBusSpeed => new Frequency(375, Frequency.UnitType.Kilohertz); + + /// + /// The SPI bus speed for the device + /// + public Frequency SpiBusSpeed + { + get => spiComms.BusSpeed; + set => spiComms.BusSpeed = value; + } + + /// + /// The default SPI bus mode for the device + /// + public SpiClockConfiguration.Mode DefaultSpiBusMode => SpiClockConfiguration.Mode.Mode0; + + /// + /// The SPI bus mode for the device + /// + public SpiClockConfiguration.Mode SpiBusMode + { + get => spiComms.BusMode; + set => spiComms.BusMode = value; + } + /// /// The command buffer /// @@ -34,9 +63,9 @@ public abstract class EPaperBase protected IDigitalInputPort busyPort; /// - /// The SpiPeripheral object that reprsents the display + /// SPI Communication bus used to communicate with the peripheral /// - protected ISpiPeripheral spiPeripheral; + protected ISpiCommunications spiComms; /// /// Const bool representing the data state @@ -55,7 +84,7 @@ public abstract class EPaperBase protected void Write(byte value) { commandBuffer[0] = value; - spiPeripheral.Write(commandBuffer); + spiComms.Write(commandBuffer); } /// @@ -68,7 +97,7 @@ protected virtual void Reset() resetPort.State = true; DelayMs(200); } - + /// /// Delay for a specified amount of time /// @@ -114,7 +143,7 @@ protected void SendData(byte data) protected void SendData(byte[] data) { dataCommandPort.State = DataState; - spiPeripheral.Write(data); + spiComms.Write(data); } /// diff --git a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/IL0373_Sample/IL0373_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/IL0373_Sample/IL0373_Sample.csproj index c2155c249f..f605c3cd8a 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/IL0373_Sample/IL0373_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/IL0373_Sample/IL0373_Sample.csproj @@ -10,7 +10,7 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/IL0376F_Sample/IL0376F_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/IL0376F_Sample/IL0376F_Sample.csproj index c2155c249f..f605c3cd8a 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/IL0376F_Sample/IL0376F_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/IL0376F_Sample/IL0376F_Sample.csproj @@ -10,7 +10,7 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/IL0398_Sample/IL0398_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/IL0398_Sample/IL0398_Sample.csproj index c2155c249f..f605c3cd8a 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/IL0398_Sample/IL0398_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/IL0398_Sample/IL0398_Sample.csproj @@ -10,7 +10,7 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/IL3897_Sample/IL3897_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/IL3897_Sample/IL3897_Sample.csproj index c2155c249f..f605c3cd8a 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/IL3897_Sample/IL3897_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/IL3897_Sample/IL3897_Sample.csproj @@ -10,7 +10,7 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/IL91874V03_Sample/IL91874V03_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/IL91874V03_Sample/IL91874V03_Sample.csproj index c2155c249f..f605c3cd8a 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/IL91874V03_Sample/IL91874V03_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/IL91874V03_Sample/IL91874V03_Sample.csproj @@ -10,7 +10,7 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/IL91874_Sample/IL91874_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/IL91874_Sample/IL91874_Sample.csproj index c2155c249f..f605c3cd8a 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/IL91874_Sample/IL91874_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/IL91874_Sample/IL91874_Sample.csproj @@ -10,7 +10,7 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/SSD1608_Sample/SSD1608_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/SSD1608_Sample/SSD1608_Sample.csproj index c2155c249f..f605c3cd8a 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/SSD1608_Sample/SSD1608_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/SSD1608_Sample/SSD1608_Sample.csproj @@ -10,7 +10,7 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/SSD1680_Sample/SSD1680_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/SSD1680_Sample/SSD1680_Sample.csproj index c2155c249f..f605c3cd8a 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/SSD1680_Sample/SSD1680_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/SSD1680_Sample/SSD1680_Sample.csproj @@ -10,7 +10,7 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/SSD1681_Sample/SSD1681_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/SSD1681_Sample/SSD1681_Sample.csproj index c2155c249f..f605c3cd8a 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/SSD1681_Sample/SSD1681_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/SSD1681_Sample/SSD1681_Sample.csproj @@ -10,7 +10,7 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/UC8151C_Sample/UC8151C_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/UC8151C_Sample/UC8151C_Sample.csproj index c2155c249f..f605c3cd8a 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/UC8151C_Sample/UC8151C_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.ePaper/Samples/UC8151C_Sample/UC8151C_Sample.csproj @@ -10,7 +10,7 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.ePaperWaveShare/Driver/Displays.ePaperWaveShare.csproj b/Source/Meadow.Foundation.Peripherals/Displays.ePaperWaveShare/Driver/Displays.ePaperWaveShare.csproj index 088ee8c830..6cf5f8cdd4 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.ePaperWaveShare/Driver/Displays.ePaperWaveShare.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.ePaperWaveShare/Driver/Displays.ePaperWaveShare.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.ePaperWaveShare/Driver/Drivers/Epd5in65f.cs b/Source/Meadow.Foundation.Peripherals/Displays.ePaperWaveShare/Driver/Drivers/Epd5in65f.cs index 364336bba4..8447b85c48 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.ePaperWaveShare/Driver/Drivers/Epd5in65f.cs +++ b/Source/Meadow.Foundation.Peripherals/Displays.ePaperWaveShare/Driver/Drivers/Epd5in65f.cs @@ -1,7 +1,6 @@ using Meadow.Foundation.Graphics; using Meadow.Foundation.Graphics.Buffers; using Meadow.Hardware; -using System; namespace Meadow.Foundation.Displays { @@ -86,7 +85,7 @@ public Epd5in65f(ISpiBus spiBus, this.resetPort = resetPort; this.busyPort = busyPort; - spiPeripheral = new SpiPeripheral(spiBus, chipSelectPort); + spiComms = new SpiCommunications(spiBus, chipSelectPort, DefaultSpiBusSpeed, DefaultSpiBusMode); imageBuffer = new BufferIndexed4(Width, Height); @@ -151,7 +150,7 @@ public void Clear(bool updateDisplay = false) { imageBuffer.Clear(); - if(updateDisplay) + if (updateDisplay) { Show(); } @@ -201,7 +200,7 @@ public void Show() dataCommandPort.State = DataState; - spiPeripheral.Write(imageBuffer.Buffer); + spiComms.Write(imageBuffer.Buffer); SendCommand(0x04); WaitForBusyState(true); @@ -233,7 +232,7 @@ public void Show(int left, int top, int right, int bottom) { if (i < bottom && i >= top && j < right / 2 && j >= left / 2) { - spiPeripheral.Write(imageBuffer.Buffer[j + ((Width / 2) * i)]); + spiComms.Write(imageBuffer.Buffer[j + ((Width / 2) * i)]); } else { //no-op @@ -259,7 +258,7 @@ public void Fill(Color fillColor, bool updateDisplay = false) { Fill(fillColor); - if(updateDisplay) + if (updateDisplay) { Show(); } diff --git a/Source/Meadow.Foundation.Peripherals/Displays.ePaperWaveShare/Samples/Epd5in65f_Sample/Epd5in65f_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.ePaperWaveShare/Samples/Epd5in65f_Sample/Epd5in65f_Sample.csproj index e3ffab4558..dec8368b51 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.ePaperWaveShare/Samples/Epd5in65f_Sample/Epd5in65f_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.ePaperWaveShare/Samples/Epd5in65f_Sample/Epd5in65f_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.ePaperWaveShare/Samples/EpdColor_Sample/EpdColor_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.ePaperWaveShare/Samples/EpdColor_Sample/EpdColor_Sample.csproj index e3ffab4558..dec8368b51 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.ePaperWaveShare/Samples/EpdColor_Sample/EpdColor_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.ePaperWaveShare/Samples/EpdColor_Sample/EpdColor_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Displays.ePaperWaveShare/Samples/EpdMonochrome_Sample/EpdMonochrome_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Displays.ePaperWaveShare/Samples/EpdMonochrome_Sample/EpdMonochrome_Sample.csproj index e3ffab4558..dec8368b51 100644 --- a/Source/Meadow.Foundation.Peripherals/Displays.ePaperWaveShare/Samples/EpdMonochrome_Sample/EpdMonochrome_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Displays.ePaperWaveShare/Samples/EpdMonochrome_Sample/EpdMonochrome_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.ADC.Ads1x15/Driver/Ads1x15Base.Enums.cs b/Source/Meadow.Foundation.Peripherals/ICs.ADC.Ads1x15/Driver/Ads1x15Base.Enums.cs index 112545c7f0..021f84d016 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.ADC.Ads1x15/Driver/Ads1x15Base.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/ICs.ADC.Ads1x15/Driver/Ads1x15Base.Enums.cs @@ -3,7 +3,7 @@ public abstract partial class Ads1x15Base { /// - /// Valid addresses for the sensor + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/ICs.ADC.Ads1x15/Driver/Ads1x15Base.cs b/Source/Meadow.Foundation.Peripherals/ICs.ADC.Ads1x15/Driver/Ads1x15Base.cs index d7e748ffac..dc420e47b3 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.ADC.Ads1x15/Driver/Ads1x15Base.cs +++ b/Source/Meadow.Foundation.Peripherals/ICs.ADC.Ads1x15/Driver/Ads1x15Base.cs @@ -1,15 +1,24 @@ -using System.Threading.Tasks; using Meadow.Hardware; using Meadow.Units; +using System.Threading.Tasks; namespace Meadow.Foundation.ICs.ADC { /// /// Encapsulation for ADCs based upon the Ads1x1x family of chips. /// - public abstract partial class Ads1x15Base : PollingSensorBase + public abstract partial class Ads1x15Base : PollingSensorBase, II2cPeripheral { - private readonly II2cPeripheral i2cPeripheral; + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + + /// + /// I2C Communication bus used to communicate with the peripheral + /// + protected readonly II2cCommunications i2cComms; + private ushort config; // These are config register bit offsets @@ -38,8 +47,8 @@ protected Ads1x15Base(II2cBus i2cBus, Addresses address, MeasureMode mode, ChannelSetting channel) - { - i2cPeripheral = new I2cPeripheral(i2cBus, (byte)address, 3, 3); + { + i2cComms = new I2cCommunications(i2cBus, (byte)address, 3, 3); SetConfigRegister(0x8583); // this is the default reset - force it in case it's not been reset config = GetConfigRegister(); @@ -49,7 +58,7 @@ protected Ads1x15Base(II2cBus i2cBus, private ushort GetRegister(Register register) { - var read = i2cPeripheral.ReadRegisterAsUShort((byte)register, ByteOrder.BigEndian); + var read = i2cComms.ReadRegisterAsUShort((byte)register, ByteOrder.BigEndian); return read; } @@ -59,7 +68,7 @@ private void SetRegister(Register register, ushort value) w[0] = (byte)register; w[1] = (byte)(value >> 8); w[2] = (byte)(value & 0xff); - i2cPeripheral.Write(w); + i2cComms.Write(w); config = value; } @@ -137,8 +146,8 @@ public MeasureMode Mode if (value == Mode) return; ushort newConfig; - - if(value == MeasureMode.OneShot) + + if (value == MeasureMode.OneShot) { newConfig = (ushort)(config | (1 << ModeShift)); } @@ -159,7 +168,7 @@ protected override async Task ReadSensor() var raw = await ReadRaw(); var scale = 0d; - switch(Gain) + switch (Gain) { case FsrGain.TwoThirds: scale = 6.144d; diff --git a/Source/Meadow.Foundation.Peripherals/ICs.ADC.Ads1x15/Driver/ICs.ADC.Ads1x15.csproj b/Source/Meadow.Foundation.Peripherals/ICs.ADC.Ads1x15/Driver/ICs.ADC.Ads1x15.csproj index ae6f47a5da..a751b4ee55 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.ADC.Ads1x15/Driver/ICs.ADC.Ads1x15.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.ADC.Ads1x15/Driver/ICs.ADC.Ads1x15.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.ADC.Ads1x15/Samples/Ads1015_Sample/Ads1015_Sample.csproj b/Source/Meadow.Foundation.Peripherals/ICs.ADC.Ads1x15/Samples/Ads1015_Sample/Ads1015_Sample.csproj index f1fa173c58..ac5847f4e9 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.ADC.Ads1x15/Samples/Ads1015_Sample/Ads1015_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.ADC.Ads1x15/Samples/Ads1015_Sample/Ads1015_Sample.csproj @@ -6,7 +6,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.ADC.Ads1x15/Samples/Ads1115_Sample/Ads1115_Sample.csproj b/Source/Meadow.Foundation.Peripherals/ICs.ADC.Ads1x15/Samples/Ads1115_Sample/Ads1115_Sample.csproj index f1fa173c58..ac5847f4e9 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.ADC.Ads1x15/Samples/Ads1115_Sample/Ads1115_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.ADC.Ads1x15/Samples/Ads1115_Sample/Ads1115_Sample.csproj @@ -6,7 +6,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.EEPROM.At24Cxx/Driver/At24Cxx.Enums.cs b/Source/Meadow.Foundation.Peripherals/ICs.EEPROM.At24Cxx/Driver/At24Cxx.Enums.cs index 740aace3e1..25dd0945d6 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.EEPROM.At24Cxx/Driver/At24Cxx.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/ICs.EEPROM.At24Cxx/Driver/At24Cxx.Enums.cs @@ -3,9 +3,9 @@ public partial class At24Cxx { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// - public enum Address : byte + public enum Addresses : byte { /// /// Bus address 0x50 diff --git a/Source/Meadow.Foundation.Peripherals/ICs.EEPROM.At24Cxx/Driver/At24Cxx.cs b/Source/Meadow.Foundation.Peripherals/ICs.EEPROM.At24Cxx/Driver/At24Cxx.cs index a95da43334..75cd6881bb 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.EEPROM.At24Cxx/Driver/At24Cxx.cs +++ b/Source/Meadow.Foundation.Peripherals/ICs.EEPROM.At24Cxx/Driver/At24Cxx.cs @@ -1,26 +1,31 @@ +using Meadow.Hardware; using System; using System.Threading; -using Meadow.Hardware; namespace Meadow.Foundation.ICs.EEPROM { /// - /// Encapsulation for EEPROMs based upon the AT24Cxx family of chips. + /// Encapsulation for EEPROMs based upon the AT24Cxx family of chips /// - public partial class At24Cxx + public partial class At24Cxx : II2cPeripheral { /// - /// Communication bus used to communicate with the EEPROM. + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + + /// + /// I2C Communication bus used to communicate with the peripheral /// - private II2cPeripheral Peripheral { get; } + protected readonly II2cCommunications i2cComms; /// - /// Number of bytes in a page. + /// Number of bytes in a page /// public ushort PageSize { get; } /// - /// Number of bytes in the EEPROM module. + /// Number of bytes in the EEPROM module /// public ushort MemorySize { get; } @@ -35,12 +40,12 @@ public partial class At24Cxx /// Number of bytes in a page (default = 32 - AT24C32). /// Total number of bytes in the EEPROM (default = 8192 - AT24C32). public At24Cxx(II2cBus i2cBus, - byte address = (byte)Address.Default, + byte address = (byte)Addresses.Default, ushort pageSize = 32, ushort memorySize = 8192) { - var device = new I2cPeripheral(i2cBus, address); - Peripheral = device; + var device = new I2cCommunications(i2cBus, address); + i2cComms = device; PageSize = pageSize; MemorySize = memorySize; @@ -77,13 +82,13 @@ public byte[] Read(ushort startAddress, ushort amount) { CheckAddress(startAddress, amount); Span data = WriteBuffer.Span[0..2]; - data[0] = (byte) ((startAddress >> 8) & 0xff); - data[1] = (byte) (startAddress & 0xff); + data[0] = (byte)((startAddress >> 8) & 0xff); + data[1] = (byte)(startAddress & 0xff); var results = new byte[amount]; - Peripheral.Write(data); - Peripheral.Read(results); + i2cComms.Write(data); + i2cComms.Read(results); return results; } @@ -95,18 +100,18 @@ public byte[] Read(ushort startAddress, ushort amount) /// Data to be written to the EEPROM. public void Write(ushort startAddress, params byte[] data) { - CheckAddress(startAddress, (ushort) data.Length); + CheckAddress(startAddress, (ushort)data.Length); // // TODO: Convert to use page writes where possible. // for (ushort index = 0; index < data.Length; index++) { - var address = (ushort) (startAddress + index); + var address = (ushort)(startAddress + index); var addressAndData = new byte[3]; - addressAndData[0] = (byte) ((address >> 8) & 0xff); - addressAndData[1] = (byte) (address & 0xff); + addressAndData[0] = (byte)((address >> 8) & 0xff); + addressAndData[1] = (byte)(address & 0xff); addressAndData[2] = data[index]; - Peripheral.Write(addressAndData); + i2cComms.Write(addressAndData); Thread.Sleep(10); } } diff --git a/Source/Meadow.Foundation.Peripherals/ICs.EEPROM.At24Cxx/Driver/ICs.EEPROM.At24Cxx.csproj b/Source/Meadow.Foundation.Peripherals/ICs.EEPROM.At24Cxx/Driver/ICs.EEPROM.At24Cxx.csproj index 3886fb8bb2..cfacc56ee0 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.EEPROM.At24Cxx/Driver/ICs.EEPROM.At24Cxx.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.EEPROM.At24Cxx/Driver/ICs.EEPROM.At24Cxx.csproj @@ -18,6 +18,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.EEPROM.At24Cxx/Samples/At24Cxx_Sample/At24Cxx_Sample.csproj b/Source/Meadow.Foundation.Peripherals/ICs.EEPROM.At24Cxx/Samples/At24Cxx_Sample/At24Cxx_Sample.csproj index f509d1ffef..05c6946fd7 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.EEPROM.At24Cxx/Samples/At24Cxx_Sample/At24Cxx_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.EEPROM.At24Cxx/Samples/At24Cxx_Sample/At24Cxx_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.FanControllers.Emc2101/Driver/Emc2101.Enums.cs b/Source/Meadow.Foundation.Peripherals/ICs.FanControllers.Emc2101/Driver/Emc2101.Enums.cs index b0afc11f2b..cd4a0c7131 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.FanControllers.Emc2101/Driver/Emc2101.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/ICs.FanControllers.Emc2101/Driver/Emc2101.Enums.cs @@ -131,13 +131,13 @@ public enum DataRate : byte /// /// 32hz /// - _32hz, + _32hz, } /// - /// Valid addresses for the sensor + /// Valid I2C addresses for the sensor /// - public enum Address : byte + public enum Addresses : byte { /// /// Bus address 0x4C @@ -188,4 +188,4 @@ public enum LutIndex : byte Index7, } } -} +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/ICs.FanControllers.Emc2101/Driver/Emc2101.cs b/Source/Meadow.Foundation.Peripherals/ICs.FanControllers.Emc2101/Driver/Emc2101.cs index 59361c35db..80d2837a81 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.FanControllers.Emc2101/Driver/Emc2101.cs +++ b/Source/Meadow.Foundation.Peripherals/ICs.FanControllers.Emc2101/Driver/Emc2101.cs @@ -10,7 +10,8 @@ namespace Meadow.Foundation.ICs.FanControllers /// Represents an EMC2101 fan controller and temperature monitor /// public partial class Emc2101 : - PollingSensorBase<(Temperature? InternalTemperature, Temperature? ExternalTemperature, AngularVelocity? FanSpeed)> + PollingSensorBase<(Temperature? InternalTemperature, Temperature? ExternalTemperature, AngularVelocity? FanSpeed)>, + II2cPeripheral { /// /// Internal Temperature changed event @@ -42,6 +43,11 @@ public partial class Emc2101 : /// public AngularVelocity? FanSpeed => Conditions.FanSpeed; + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + /// /// Get/Set the minimum fan speed for the currently connected fan /// @@ -49,15 +55,15 @@ public AngularVelocity MinimumFanSpeed { get { - byte lsb = i2cPeripheral.ReadRegister((byte)Registers.TachLimitLSB); - byte msb = i2cPeripheral.ReadRegister((byte)Registers.TachLimitMSB); + byte lsb = i2cComms.ReadRegister((byte)Registers.TachLimitLSB); + byte msb = i2cComms.ReadRegister((byte)Registers.TachLimitMSB); ushort speed = (ushort)(msb << 8 | lsb); return new AngularVelocity(FanRpmNumerator / speed, AngularVelocity.UnitType.RevolutionsPerMinute); } set { ushort raw = (ushort)(value.RevolutionsPerMinute * FanRpmNumerator); - i2cPeripheral.WriteRegister((byte)Registers.TachLimitLSB, raw); + i2cComms.WriteRegister((byte)Registers.TachLimitLSB, raw); } } @@ -68,8 +74,8 @@ public AngularVelocity MinimumFanSpeed /// public byte PwmFrequencyScaler { - get => i2cPeripheral.ReadRegister((byte)Registers.PwmFrequency); - set => i2cPeripheral.WriteRegister((byte)Registers.PwmFrequency, Math.Min(value, (byte)0x1F)); + get => i2cComms.ReadRegister((byte)Registers.PwmFrequency); + set => i2cComms.WriteRegister((byte)Registers.PwmFrequency, Math.Min(value, (byte)0x1F)); } /// @@ -78,8 +84,8 @@ public byte PwmFrequencyScaler /// public byte PwmDivisor { - get => i2cPeripheral.ReadRegister((byte)Registers.PwmDivisor); - set => i2cPeripheral.WriteRegister((byte)Registers.PwmDivisor, value); + get => i2cComms.ReadRegister((byte)Registers.PwmDivisor); + set => i2cComms.WriteRegister((byte)Registers.PwmDivisor, value); } /// @@ -87,8 +93,8 @@ public byte PwmDivisor /// public float FanPwmDutyCycle { - get => i2cPeripheral.ReadRegister((byte)Registers.FanSetting) / (float)MaxFanSpeed; - set => i2cPeripheral.WriteRegister((byte)Registers.FanSetting, (byte)(Math.Clamp(value, 0, 1) * MaxFanSpeed)); + get => i2cComms.ReadRegister((byte)Registers.FanSetting) / (float)MaxFanSpeed; + set => i2cComms.WriteRegister((byte)Registers.FanSetting, (byte)(Math.Clamp(value, 0, 1) * MaxFanSpeed)); } /// @@ -98,8 +104,8 @@ public float FanPwmDutyCycle /// The hysteresis temperature value public Temperature Hysteresis { - get => new Temperature(i2cPeripheral.ReadRegister((byte)Registers.LutHysteresis), Temperature.UnitType.Celsius); - set => i2cPeripheral.WriteRegister((byte)Registers.LutHysteresis, (byte)value.Celsius); + get => new Temperature(i2cComms.ReadRegister((byte)Registers.LutHysteresis), Temperature.UnitType.Celsius); + set => i2cComms.WriteRegister((byte)Registers.LutHysteresis, (byte)value.Celsius); } /// @@ -107,8 +113,8 @@ public Temperature Hysteresis /// public DataRate SensorDataRate { - get => (DataRate)i2cPeripheral.ReadRegister((byte)Registers.DataRate); - set => i2cPeripheral.WriteRegister((byte)Registers.DataRate, (byte)value); + get => (DataRate)i2cComms.ReadRegister((byte)Registers.DataRate); + set => i2cComms.WriteRegister((byte)Registers.DataRate, (byte)value); } /// @@ -117,12 +123,12 @@ public DataRate SensorDataRate /// true if enabled bool LutEnabled { - get => BitHelpers.GetBitValue(i2cPeripheral.ReadRegister((byte)Registers.FanConfiguration), 5); + get => BitHelpers.GetBitValue(i2cComms.ReadRegister((byte)Registers.FanConfiguration), 5); set { - byte config = i2cPeripheral.ReadRegister((byte)Registers.FanConfiguration); + byte config = i2cComms.ReadRegister((byte)Registers.FanConfiguration); BitHelpers.SetBit(config, 5, value); - i2cPeripheral.WriteRegister((byte)Registers.FanConfiguration, config); + i2cComms.WriteRegister((byte)Registers.FanConfiguration, config); } } @@ -131,28 +137,28 @@ bool LutEnabled /// public bool DACOutputEnabled { - get => BitHelpers.GetBitValue(i2cPeripheral.ReadRegister((byte)Registers.Configuration), 4); + get => BitHelpers.GetBitValue(i2cComms.ReadRegister((byte)Registers.Configuration), 4); set { - byte config = i2cPeripheral.ReadRegister((byte)Registers.Configuration); + byte config = i2cComms.ReadRegister((byte)Registers.Configuration); config = BitHelpers.SetBit(config, 4, value); - i2cPeripheral.WriteRegister((byte)Registers.Configuration, config); + i2cComms.WriteRegister((byte)Registers.Configuration, config); } } /// - /// Communication bus used to communicate with the Emc2101 + /// I2C Communication bus used to communicate with the peripheral /// - readonly II2cPeripheral i2cPeripheral; + protected readonly II2cCommunications i2cComms; /// /// Create a new EMC2101 object /// /// I2CBus connected to display /// Address of the EMC2101 (default = 0x4C) - public Emc2101(II2cBus i2cBus, byte address = (byte)Address.Default) + public Emc2101(II2cBus i2cBus, byte address = (byte)Addresses.Default) { - i2cPeripheral = new I2cPeripheral(i2cBus, address); + i2cComms = new I2cCommunications(i2cBus, address); Initialize(); } @@ -160,7 +166,7 @@ public Emc2101(II2cBus i2cBus, byte address = (byte)Address.Default) void Initialize() { EnableTachInput(true); - + InvertFanSpeed(false); PwmFrequencyScaler = 0x1F; ConfigurePwmClock(true, false); @@ -185,7 +191,7 @@ protected override void RaiseEventsAndNotify(IChangeResult<(Temperature? Interna { ExternalTemperatureUpdated?.Invoke(this, new ChangeResult(tempEx, changeResult.Old?.ExternalTemperature)); } - if(changeResult.New.FanSpeed is { } fanSpeed) + if (changeResult.New.FanSpeed is { } fanSpeed) { FanSpeedUpdated?.Invoke(this, new ChangeResult(fanSpeed, changeResult.Old?.FanSpeed)); } @@ -199,28 +205,25 @@ protected override void RaiseEventsAndNotify(IChangeResult<(Temperature? Interna /// The latest sensor reading protected override Task<(Temperature? InternalTemperature, Temperature? ExternalTemperature, AngularVelocity? FanSpeed)> ReadSensor() { - return Task.Run(() => - { - (Temperature? InternalTemperature, Temperature? ExternalTemperature, AngularVelocity? FanSpeed) conditions; - - //internal temperature - conditions.InternalTemperature = new Temperature(i2cPeripheral.ReadRegister((byte)Registers.InternalTemperature), Temperature.UnitType.Celsius); - - //external temperature - byte lsb = i2cPeripheral.ReadRegister((byte)Registers.ExternalTemperatureLSB); - byte msb = i2cPeripheral.ReadRegister((byte)Registers.ExternalTemperatureMSB); - short raw = (short)(msb << 8 | lsb); - raw >>= 5; - conditions.ExternalTemperature = new Temperature(raw * TemperatureBit, Temperature.UnitType.Celsius); - - //fan speed - lsb = i2cPeripheral.ReadRegister((byte)Registers.TachLSB); - msb = i2cPeripheral.ReadRegister((byte)Registers.TachMSB); - short speed = (short)(msb << 8 | lsb); - conditions.FanSpeed = new AngularVelocity(FanRpmNumerator / speed, AngularVelocity.UnitType.RevolutionsPerMinute); - - return conditions; - }); + (Temperature? InternalTemperature, Temperature? ExternalTemperature, AngularVelocity? FanSpeed) conditions; + + //internal temperature + conditions.InternalTemperature = new Temperature(i2cComms.ReadRegister((byte)Registers.InternalTemperature), Temperature.UnitType.Celsius); + + //external temperature + byte lsb = i2cComms.ReadRegister((byte)Registers.ExternalTemperatureLSB); + byte msb = i2cComms.ReadRegister((byte)Registers.ExternalTemperatureMSB); + short raw = (short)(msb << 8 | lsb); + raw >>= 5; + conditions.ExternalTemperature = new Temperature(raw * TemperatureBit, Temperature.UnitType.Celsius); + + //fan speed + lsb = i2cComms.ReadRegister((byte)Registers.TachLSB); + msb = i2cComms.ReadRegister((byte)Registers.TachMSB); + short speed = (short)(msb << 8 | lsb); + conditions.FanSpeed = new AngularVelocity(FanRpmNumerator / speed, AngularVelocity.UnitType.RevolutionsPerMinute); + + return Task.FromResult(conditions); } /// @@ -229,11 +232,11 @@ protected override void RaiseEventsAndNotify(IChangeResult<(Temperature? Interna /// true to renable, false to disable public void EnableTachInput(bool enable) { - byte config = i2cPeripheral.ReadRegister((byte)Registers.Configuration); + byte config = i2cComms.ReadRegister((byte)Registers.Configuration); config = BitHelpers.SetBit(config, 2, enable); - i2cPeripheral.WriteRegister((byte)Registers.Configuration, config); + i2cComms.WriteRegister((byte)Registers.Configuration, config); } /// @@ -242,11 +245,11 @@ public void EnableTachInput(bool enable) /// true to invert, false for normal public void InvertFanSpeed(bool invert) { - byte config = i2cPeripheral.ReadRegister((byte)Registers.FanConfiguration); + byte config = i2cComms.ReadRegister((byte)Registers.FanConfiguration); config = BitHelpers.SetBit(config, 4, invert); - i2cPeripheral.WriteRegister((byte)Registers.FanConfiguration, config); + i2cComms.WriteRegister((byte)Registers.FanConfiguration, config); } /// @@ -256,12 +259,12 @@ public void InvertFanSpeed(bool invert) /// true to override the base clock and use the frequency divisor to set the PWM frequency public void ConfigurePwmClock(bool clockSelect, bool clockOverride) { - byte config = i2cPeripheral.ReadRegister((byte)Registers.FanConfiguration); + byte config = i2cComms.ReadRegister((byte)Registers.FanConfiguration); config = BitHelpers.SetBit(config, 3, clockSelect); config = BitHelpers.SetBit(config, 2, clockOverride); - i2cPeripheral.WriteRegister((byte)Registers.FanConfiguration, config); + i2cComms.WriteRegister((byte)Registers.FanConfiguration, config); } /// @@ -271,13 +274,13 @@ public void ConfigurePwmClock(bool clockSelect, bool clockOverride) /// The time taken to spin up to the drive speed public void ConfigureFanSpinup(FanSpinupDrive spinupDrive, FanSpinupTime spinupTime) { - byte config = i2cPeripheral.ReadRegister((byte)Registers.FanSpinup); + byte config = i2cComms.ReadRegister((byte)Registers.FanSpinup); config = (byte)(config & ~0x1F); //zero out the bits config |= (byte)spinupDrive; config |= (byte)spinupTime; - i2cPeripheral.WriteRegister((byte)Registers.FanSpinup, config); + i2cComms.WriteRegister((byte)Registers.FanSpinup, config); } /// @@ -286,13 +289,13 @@ public void ConfigureFanSpinup(FanSpinupDrive spinupDrive, FanSpinupTime spinupT /// The LUT index to set /// the temperature threshhold /// the fan PWM duty cycle - public void SetLookupTable(LutIndex index, - Temperature temperatureThreshhold, + public void SetLookupTable(LutIndex index, + Temperature temperatureThreshhold, float pwmDutyCycle) { pwmDutyCycle = Math.Clamp(pwmDutyCycle, 0, 1); - if(temperatureThreshhold.Celsius > MaxLutTemperature) + if (temperatureThreshhold.Celsius > MaxLutTemperature) { temperatureThreshhold = new Units.Temperature(MaxLutTemperature, Units.Temperature.UnitType.Celsius); } @@ -305,8 +308,8 @@ public void SetLookupTable(LutIndex index, //Oh C# and bytes/enums ... best to leave as an int and cast when it's used int address = (byte)Registers.LutStartRegister + (byte)index * 2; - i2cPeripheral.WriteRegister((byte)address, (byte)temperatureThreshhold.Celsius); - i2cPeripheral.WriteRegister((byte)(address + 1), (byte)(pwmDutyCycle * MaxFanSpeed)); + i2cComms.WriteRegister((byte)address, (byte)temperatureThreshhold.Celsius); + i2cComms.WriteRegister((byte)(address + 1), (byte)(pwmDutyCycle * MaxFanSpeed)); //restore lut state LutEnabled = lutState; diff --git a/Source/Meadow.Foundation.Peripherals/ICs.FanControllers.Emc2101/Driver/ICs.FanControllers.Emc2101.csproj b/Source/Meadow.Foundation.Peripherals/ICs.FanControllers.Emc2101/Driver/ICs.FanControllers.Emc2101.csproj index 70b43660a7..3f726fd349 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.FanControllers.Emc2101/Driver/ICs.FanControllers.Emc2101.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.FanControllers.Emc2101/Driver/ICs.FanControllers.Emc2101.csproj @@ -16,7 +16,7 @@ Emc2101 I2C fan controller and temperature monitor - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.FanControllers.Emc2101/Samples/Emc2101_Sample/Emc2101_Sample.csproj b/Source/Meadow.Foundation.Peripherals/ICs.FanControllers.Emc2101/Samples/Emc2101_Sample/Emc2101_Sample.csproj index 15f0d92735..ff25e07fbb 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.FanControllers.Emc2101/Samples/Emc2101_Sample/Emc2101_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.FanControllers.Emc2101/Samples/Emc2101_Sample/Emc2101_Sample.csproj @@ -9,7 +9,7 @@ App - + 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 index 4eb132edbd..de8eda5123 100644 --- 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 @@ -18,6 +18,6 @@ - + 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 index d45bf7555b..f93e637400 100644 --- 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 @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Driver/As1115.Enums.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Driver/As1115.Enums.cs index dfdd1a420c..b42572fdb6 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Driver/As1115.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Driver/As1115.Enums.cs @@ -3,7 +3,7 @@ public partial class As1115 { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Driver/As1115.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Driver/As1115.cs index dc4840f326..c6f1687e7a 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Driver/As1115.cs +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Driver/As1115.cs @@ -11,7 +11,7 @@ namespace Meadow.Foundation.ICs.IOExpanders /// /// Represents an As1115 led driver and key scanner /// - public partial class As1115 : IGraphicsDisplay, IDisposable + public partial class As1115 : IGraphicsDisplay, II2cPeripheral, IDisposable { /// /// Event raised when any key scan button is pressed @@ -41,9 +41,14 @@ public partial class As1115 : IGraphicsDisplay, IDisposable KeyScanButtonType lastButtonPressed = KeyScanButtonType.None; /// - /// As1115 I2C driver + /// I2C Communication bus used to communicate with the peripheral /// - protected II2cPeripheral i2cPeripheral; + protected readonly II2cCommunications i2cComms; + + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; /// /// The display color mode (1 bit per pixel) @@ -97,7 +102,7 @@ public partial class As1115 : IGraphicsDisplay, IDisposable public As1115(II2cBus i2cBus, IPin buttonInterruptPin, byte address = (byte)Addresses.Default) { - i2cPeripheral = new I2cPeripheral(i2cBus, address); + i2cComms = new I2cCommunications(i2cBus, address); interruptPort = buttonInterruptPin.CreateDigitalInputPort( InterruptMode.EdgeFalling, @@ -120,22 +125,22 @@ void Initialize() KeyScanButtons = new ReadOnlyDictionary(keyDictionary); - i2cPeripheral.WriteRegister(REG_SHUTDOWN, REG_SHUTDOWN_RUNNING | REG_SHUTDOWN_RESET_FEATUREREG); + i2cComms.WriteRegister(REG_SHUTDOWN, REG_SHUTDOWN_RUNNING | REG_SHUTDOWN_RESET_FEATUREREG); - i2cPeripheral.WriteRegister(REG_SCAN_LIMIT, 0x07); + i2cComms.WriteRegister(REG_SCAN_LIMIT, 0x07); SetDecodeMode(DecodeType.Pixel); byte[] data = new byte[2]; //read the key scan registers to clear - i2cPeripheral.ReadRegister(REG_KEYA, data); + i2cComms.ReadRegister(REG_KEYA, data); } private void InterruptPort_Changed(object sender, DigitalPortResult e) { byte[] data = new byte[2]; - i2cPeripheral.ReadRegister(REG_KEYA, data); + i2cComms.ReadRegister(REG_KEYA, data); var keyScanButton = GetButtonFromKeyScanRegister(data[0], data[1]); @@ -206,7 +211,7 @@ KeyScanButtonType GetButtonFromKeyScanRegister(byte keyA, byte keyB) /// True for fast blink (period of 1s), False for slow blink (period of 2s) public void EnableBlink(bool isEnabled, bool fastBlink = true) { - var reg = i2cPeripheral.ReadRegister(REG_FEATURE); + var reg = i2cComms.ReadRegister(REG_FEATURE); byte mask = 1 << REG_FEATURE_BLINK; @@ -229,7 +234,7 @@ public void EnableBlink(bool isEnabled, bool fastBlink = true) reg &= (byte)~mask; } - i2cPeripheral.WriteRegister(REG_FEATURE, reg); + i2cComms.WriteRegister(REG_FEATURE, reg); } /// @@ -247,7 +252,7 @@ void SetDecodeMode(DecodeType mode) switch (mode) { case DecodeType.Pixel: - i2cPeripheral.WriteRegister(REG_DECODE_MODE, 0); + i2cComms.WriteRegister(REG_DECODE_MODE, 0); break; } } @@ -329,7 +334,7 @@ public void SetIntensity(byte intensity) { intensity = Math.Max(intensity, (byte)15); - i2cPeripheral.WriteRegister(REG_GLOBAL_INTEN, intensity); + i2cComms.WriteRegister(REG_GLOBAL_INTEN, intensity); } /// @@ -338,7 +343,7 @@ public void SetIntensity(byte intensity) /// True to enable, false to disable public void TestMode(bool testOn) { - i2cPeripheral.WriteRegister(REG_DECODE_MODE, (byte)(testOn ? 0x01 : 0x00)); + i2cComms.WriteRegister(REG_DECODE_MODE, (byte)(testOn ? 0x01 : 0x00)); } /// @@ -346,14 +351,14 @@ public void TestMode(bool testOn) /// public void Show() { - i2cPeripheral.WriteRegister(REG_DIGIT0, buffer.Buffer[0]); - i2cPeripheral.WriteRegister(REG_DIGIT1, buffer.Buffer[1]); - i2cPeripheral.WriteRegister(REG_DIGIT2, buffer.Buffer[2]); - i2cPeripheral.WriteRegister(REG_DIGIT3, buffer.Buffer[3]); - i2cPeripheral.WriteRegister(REG_DIGIT4, buffer.Buffer[4]); - i2cPeripheral.WriteRegister(REG_DIGIT5, buffer.Buffer[5]); - i2cPeripheral.WriteRegister(REG_DIGIT6, buffer.Buffer[6]); - i2cPeripheral.WriteRegister(REG_DIGIT7, buffer.Buffer[7]); + i2cComms.WriteRegister(REG_DIGIT0, buffer.Buffer[0]); + i2cComms.WriteRegister(REG_DIGIT1, buffer.Buffer[1]); + i2cComms.WriteRegister(REG_DIGIT2, buffer.Buffer[2]); + i2cComms.WriteRegister(REG_DIGIT3, buffer.Buffer[3]); + i2cComms.WriteRegister(REG_DIGIT4, buffer.Buffer[4]); + i2cComms.WriteRegister(REG_DIGIT5, buffer.Buffer[5]); + i2cComms.WriteRegister(REG_DIGIT6, buffer.Buffer[6]); + i2cComms.WriteRegister(REG_DIGIT7, buffer.Buffer[7]); } /// @@ -464,7 +469,7 @@ protected virtual void Dispose(bool disposing) } /// - /// Dispose Peripheral + /// Dispose BusComms /// public void Dispose() { diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Driver/ICs.IOExpanders.As1115.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Driver/ICs.IOExpanders.As1115.csproj index dda8424a4c..5f630ea03a 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Driver/ICs.IOExpanders.As1115.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Driver/ICs.IOExpanders.As1115.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Samples/As1115_Sample/As1115_Sample.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Samples/As1115_Sample/As1115_Sample.csproj index f47ae6a8de..77ed15adc4 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Samples/As1115_Sample/As1115_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Samples/As1115_Sample/As1115_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ds3502/Driver/Ds3502.Enums.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ds3502/Driver/Ds3502.Enums.cs index cf544ca5dd..0e792d0c31 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ds3502/Driver/Ds3502.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ds3502/Driver/Ds3502.Enums.cs @@ -3,7 +3,7 @@ public partial class Ds3502 { /// - /// Valid addresses for the sensor + /// Valid I2C addresses for the sensor /// Controlled by pulling A0 and A1 high or low /// public enum Addresses : byte diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ds3502/Driver/Ds3502.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ds3502/Driver/Ds3502.cs index 4b41e93f78..5e7f635095 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ds3502/Driver/Ds3502.cs +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ds3502/Driver/Ds3502.cs @@ -1,20 +1,28 @@ -using System; +using Meadow.Hardware; +using System; using System.Threading.Tasks; -using Meadow.Hardware; namespace Meadow.Foundation.ICs.IOExpanders { /// /// Represents a DS3502 digital potentiometer /// - public partial class Ds3502 + public partial class Ds3502 : II2cPeripheral { + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + /// /// Default I2C bus speed /// public static I2cBusSpeed DefaultBusSpeed => I2cBusSpeed.Fast; - private readonly II2cPeripheral i2cPeripheral; + /// + /// I2C Communication bus used to communicate with the peripheral + /// + protected readonly II2cCommunications i2cComms; /// /// Create a new Ds3502 object using the default parameters @@ -23,9 +31,9 @@ public partial class Ds3502 /// I2C bus instance public Ds3502(II2cBus i2cBus, byte address = (byte)Addresses.Default) { - i2cPeripheral = new I2cPeripheral(i2cBus, address); + i2cComms = new I2cCommunications(i2cBus, address); - i2cPeripheral.WriteRegister((byte)Register.DS3502_MODE, 0x80); + i2cComms.WriteRegister((byte)Register.DS3502_MODE, 0x80); } /// @@ -34,7 +42,7 @@ public Ds3502(II2cBus i2cBus, byte address = (byte)Addresses.Default) /// the 7-bit wiper value public byte GetWiper() { - return i2cPeripheral.ReadRegister((byte)Register.DS3502_WIPER); + return i2cComms.ReadRegister((byte)Register.DS3502_WIPER); } /// @@ -45,7 +53,7 @@ public void SetWiper(byte value) { value = Math.Min(value, (byte)127); - i2cPeripheral.WriteRegister((byte)Register.DS3502_WIPER, value); + i2cComms.WriteRegister((byte)Register.DS3502_WIPER, value); } /// @@ -55,13 +63,13 @@ public void SetWiper(byte value) public async Task SetWiperDefault(byte value) { value = Math.Min(value, (byte)127); - - i2cPeripheral.WriteRegister((byte)Register.DS3502_MODE, 0x00); - i2cPeripheral.WriteRegister((byte)Register.DS3502_WIPER, value); + + i2cComms.WriteRegister((byte)Register.DS3502_MODE, 0x00); + i2cComms.WriteRegister((byte)Register.DS3502_WIPER, value); await Task.Delay(100).ConfigureAwait(false); - i2cPeripheral.WriteRegister((byte)Register.DS3502_MODE, 0x80); + i2cComms.WriteRegister((byte)Register.DS3502_MODE, 0x80); } } } \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ds3502/Driver/ICs.IOExpanders.Ds3502.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ds3502/Driver/ICs.IOExpanders.Ds3502.csproj index 7657f96667..ea1a94a775 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ds3502/Driver/ICs.IOExpanders.Ds3502.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ds3502/Driver/ICs.IOExpanders.Ds3502.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ds3502/Samples/Ds3502_Sample/Ds3502_Sample.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ds3502/Samples/Ds3502_Sample/Ds3502_Sample.csproj index bb09c86b89..d646735cf3 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ds3502/Samples/Ds3502_Sample/Ds3502_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ds3502/Samples/Ds3502_Sample/Ds3502_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ht16k33/Driver/Ht16k33.14Character.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ht16k33/Driver/Ht16k33.14Character.cs new file mode 100644 index 0000000000..16494adf7b --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ht16k33/Driver/Ht16k33.14Character.cs @@ -0,0 +1,47 @@ +using Meadow.Foundation.Displays.Led; +using System; + +namespace Meadow.Foundation.ICs.IOExpanders +{ + public partial class Ht16k33 + { + /// + /// Set a message on a 14-segment display array + /// + /// The message (up to 4 chracters) + public void Set14SegmentMessage(string message) + { + for (int i = 0; i < Math.Max(message.Length, 4); i++) + { + Set14SegmentDisplay(message[i], i); + } + } + + /// + /// Set a single 14-segment display to a specific character + /// + /// The ascii chracter + /// The display index (0-3) + public void Set14SegmentDisplay(char character, int displayIndex) + { + if (displayIndex < 0 || displayIndex > 3) + { + throw new IndexOutOfRangeException("Set14SegmentDisplay index must be 0, 1, 2 or 3"); + } + + int startIndex = 16 * displayIndex; + + for (int i = 0; i < 16; i++) + { + if (FourteenSegment.IsEnabled((FourteenSegment.Segment)i, character)) + { + SetLed((byte)(startIndex + i), true); + } + else + { + SetLed((byte)(startIndex + i), false); + } + } + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ht16k33/Driver/Ht16k33.Enums.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ht16k33/Driver/Ht16k33.Enums.cs index 1798ad84e4..e97b83d3b6 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ht16k33/Driver/Ht16k33.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ht16k33/Driver/Ht16k33.Enums.cs @@ -5,7 +5,7 @@ public partial class Ht16k33 { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ht16k33/Driver/Ht16k33.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ht16k33/Driver/Ht16k33.cs index 5f9a441fee..4527c4c926 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ht16k33/Driver/Ht16k33.cs +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ht16k33/Driver/Ht16k33.cs @@ -1,17 +1,22 @@ -using System; -using Meadow.Hardware; +using Meadow.Hardware; +using System; namespace Meadow.Foundation.ICs.IOExpanders { /// /// Represents an Ht16k33 128 led driver and 39 key scanner /// - public partial class Ht16k33 + public partial class Ht16k33 : II2cPeripheral { /// - /// HT16K33 LED driver and key scan + /// The default I2C address for the peripheral /// - private readonly II2cPeripheral i2cPeripheral; + public byte DefaultI2cAddress => (byte)Addresses.Default; + + /// + /// I2C Communication bus used to communicate with the peripheral + /// + protected readonly II2cCommunications i2cComms; /// /// Display buffer for 16x8 LEDs @@ -26,20 +31,20 @@ public partial class Ht16k33 /// /// Create a new HT16K33 object using the default parameters /// - /// Address of the bus on the I2C display. + /// Address of the bus on the I2C display /// I2C bus instance public Ht16k33(II2cBus i2cBus, byte address = (byte)Addresses.Default) { - i2cPeripheral = new I2cPeripheral(i2cBus, address, 8, 17); + i2cComms = new I2cCommunications(i2cBus, address, 8, 17); Initialize(); } void Initialize() { - i2cPeripheral.Write(0x21); + i2cComms.Write(0x21); - i2cPeripheral.Write(0x81); + i2cComms.Write(0x81); SetBrightness(Brightness.Maximum); ClearDisplay(); @@ -53,7 +58,7 @@ public void SetIsAwake(bool awake) { byte value = (byte)((byte)Register.HT16K33_SS | (byte)(awake ? 1 : 0)); - i2cPeripheral.Write(value); + i2cComms.Write(value); } /// @@ -64,7 +69,7 @@ public void SetDisplayOn(bool isOn) { byte value = (byte)((byte)Register.HT16K33_DSP | (byte)(isOn ? 1 : 0)); - i2cPeripheral.Write(value); + i2cComms.Write(value); } /// @@ -75,7 +80,7 @@ public void SetBlinkRate(BlinkRate blinkRate) { byte value = (byte)((byte)Register.HT16K33_DSP | (byte)blinkRate); - i2cPeripheral.Write(value); + i2cComms.Write(value); } /// @@ -86,7 +91,7 @@ public void SetBrightness(Brightness brightness) { byte value = (byte)((byte)Register.HT16K33_DIM | (byte)brightness); - i2cPeripheral.Write(value); + i2cComms.Write(value); } /// @@ -105,7 +110,7 @@ public void ClearDisplay() /// public void UpdateDisplay() { - i2cPeripheral.WriteRegister(0x0, displayBuffer.Span); + i2cComms.WriteRegister(0x0, displayBuffer.Span); } /// diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ht16k33/Driver/ICs.IOExpanders.Ht16k33.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ht16k33/Driver/ICs.IOExpanders.Ht16k33.csproj index c8e2001837..74f67d5868 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ht16k33/Driver/ICs.IOExpanders.Ht16k33.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ht16k33/Driver/ICs.IOExpanders.Ht16k33.csproj @@ -17,6 +17,7 @@ - + + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ht16k33/Samples/Ht16k33_Character_Sample/Ht16k33_Character_Sample.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ht16k33/Samples/Ht16k33_Character_Sample/Ht16k33_Character_Sample.csproj new file mode 100644 index 0000000000..64c7e9b299 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ht16k33/Samples/Ht16k33_Character_Sample/Ht16k33_Character_Sample.csproj @@ -0,0 +1,20 @@ + + + https://github.com/WildernessLabs/Meadow.Foundation + Wilderness Labs, Inc + Wilderness Labs, Inc + true + netstandard2.1 + Library + App + + + + + + + + Always + + + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ht16k33/Samples/Ht16k33_Character_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ht16k33/Samples/Ht16k33_Character_Sample/MeadowApp.cs new file mode 100644 index 0000000000..7f05e05f35 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ht16k33/Samples/Ht16k33_Character_Sample/MeadowApp.cs @@ -0,0 +1,53 @@ +using Meadow; +using Meadow.Devices; +using Meadow.Foundation.ICs.IOExpanders; +using System.Threading; +using System.Threading.Tasks; + +namespace ICs.IOExpanders.HT16K33_Sample +{ + public class MeadowApp : App + { + // + + Ht16k33 ht16k33; + + public override Task Initialize() + { + Resolver.Log.Info("Initialize..."); + ht16k33 = new Ht16k33(Device.CreateI2cBus()); + + return base.Initialize(); + } + + public override async Task Run() + { + ht16k33.Set14SegmentDisplay('F', 0); + ht16k33.Set14SegmentDisplay('7', 1); + ht16k33.Set14SegmentDisplay('v', 2); + ht16k33.Set14SegmentDisplay('2', 3); + + ht16k33.UpdateDisplay(); + } + + // + + void LoopCharacters() + { + while (true) + { + for (int i = 32; i < 127; i++) + { + ht16k33.Set14SegmentDisplay((char)i, 0); + ht16k33.Set14SegmentDisplay((char)i, 1); + ht16k33.Set14SegmentDisplay((char)i, 2); + ht16k33.Set14SegmentDisplay((char)i, 3); + + ht16k33.UpdateDisplay(); + + Thread.Sleep(250); + } + } + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ht16k33/Samples/Ht16k33_Character_Sample/meadow.config.yaml b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ht16k33/Samples/Ht16k33_Character_Sample/meadow.config.yaml new file mode 100644 index 0000000000..32363cb69c --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ht16k33/Samples/Ht16k33_Character_Sample/meadow.config.yaml @@ -0,0 +1,2 @@ +MonoControl: + Options: --jit \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ht16k33/Samples/Ht16k33_Sample/Ht16k33_Sample.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ht16k33/Samples/Ht16k33_Sample/Ht16k33_Sample.csproj index 98fa1ad197..64c7e9b299 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ht16k33/Samples/Ht16k33_Sample/Ht16k33_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ht16k33/Samples/Ht16k33_Sample/Ht16k33_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ht16k33/Samples/Ht16k33_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ht16k33/Samples/Ht16k33_Sample/MeadowApp.cs index bfe3940610..b1637c23c3 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ht16k33/Samples/Ht16k33_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Ht16k33/Samples/Ht16k33_Sample/MeadowApp.cs @@ -1,7 +1,6 @@ using Meadow; using Meadow.Devices; using Meadow.Foundation.ICs.IOExpanders; -using System; using System.Threading.Tasks; namespace ICs.IOExpanders.HT16K33_Sample diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Is31fl3731/Driver/ICs.IOExpanders.Is31fl3731.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Is31fl3731/Driver/ICs.IOExpanders.Is31fl3731.csproj index b0e4f86988..a62b6004e4 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Is31fl3731/Driver/ICs.IOExpanders.Is31fl3731.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Is31fl3731/Driver/ICs.IOExpanders.Is31fl3731.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Is31fl3731/Driver/Is31fl3731.Enums.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Is31fl3731/Driver/Is31fl3731.Enums.cs index 9eb0011ac7..fb7d64b86d 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Is31fl3731/Driver/Is31fl3731.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Is31fl3731/Driver/Is31fl3731.Enums.cs @@ -3,7 +3,7 @@ public partial class Is31fl3731 { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Is31fl3731/Driver/Is31fl3731.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Is31fl3731/Driver/Is31fl3731.cs index b4b98c0057..4414a9f443 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Is31fl3731/Driver/Is31fl3731.cs +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Is31fl3731/Driver/Is31fl3731.cs @@ -9,26 +9,28 @@ namespace Meadow.Foundation.ICs.IOExpanders /// The Is31fl3731 is a compact LED driver for 144 single LEDs /// /// Based on https://github.com/adafruit/Adafruit_IS31FL3731 - public partial class Is31fl3731 + public partial class Is31fl3731 : II2cPeripheral { const byte RegConfig = 0x00; const byte RegConfigPictureMode = 0x00; - //const byte RegConfigAutoPlayMode = 0x08; - //const byte RegConfigAudioPlayMode = 0x18; - //const byte ConfPictureMode = 0x00; - //const byte ConfAutoFrameMode = 0x04; - //const byte ConfAudioMode = 0x08; const byte DisplayOptionRegister = 0x05; const byte PictureFrameReg = 0x01; const byte RegShutdown = 0x0A; - //const byte RegAudioSync = 0x06; const byte CommandRegister = 0xFD; - const byte CommandFunctionReg = 0x0B; //'page nine' + const byte CommandFunctionReg = 0x0B; - readonly II2cPeripheral i2cPeripheral; + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + + /// + /// I2C Communication bus used to communicate with the peripheral + /// + protected readonly II2cCommunications i2cComms; /// /// The current frame @@ -42,7 +44,7 @@ public partial class Is31fl3731 /// The I2C address public Is31fl3731(II2cBus i2cBus, byte address = (byte)Addresses.Default) { - i2cPeripheral = new I2cPeripheral(i2cBus, address); + i2cComms = new I2cCommunications(i2cBus, address); Frame = 0; } @@ -120,7 +122,7 @@ protected virtual void WriteRegister(byte frame, byte register, byte data) { SelectPage(frame); - i2cPeripheral.WriteRegister(register, data); + i2cComms.WriteRegister(register, data); } /// @@ -173,7 +175,7 @@ public virtual void Clear(byte frame) /// public virtual void ClearAllFrames() { - for(byte i = 0; i < 7; i++) + for (byte i = 0; i < 7; i++) { Clear(i); } @@ -268,7 +270,7 @@ public virtual void SetBlinkFunctionOnAllLeds(byte frame, bool on) /// page/frame # protected virtual void SelectPage(byte page) { - i2cPeripheral.WriteRegister(CommandRegister, page); + i2cComms.WriteRegister(CommandRegister, page); } } } \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Is31fl3731/Samples/Is31fl3731_Sample/Is31fl3731_Sample.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Is31fl3731/Samples/Is31fl3731_Sample/Is31fl3731_Sample.csproj index f95b958a0d..667efbf6b0 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Is31fl3731/Samples/Is31fl3731_Sample/Is31fl3731_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Is31fl3731/Samples/Is31fl3731_Sample/Is31fl3731_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/Drivers/Extras/Mcp23x0x.PinDefinitions.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/Drivers/Extras/Mcp23x0x.PinDefinitions.cs index 5812cda889..8d26e13828 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/Drivers/Extras/Mcp23x0x.PinDefinitions.cs +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/Drivers/Extras/Mcp23x0x.PinDefinitions.cs @@ -11,6 +11,9 @@ public abstract partial class Mcp23x0x /// public class PinDefinitions : IPinDefinitions { + /// + /// The controller for the pins + /// public IPinController Controller { get; set; } /// @@ -19,7 +22,7 @@ public class PinDefinitions : IPinDefinitions public IList AllPins { get; } = new List(); /// - /// GP0 + /// Pin GP0 /// public IPin GP0 => new Pin( Controller, @@ -30,7 +33,7 @@ public class PinDefinitions : IPinDefinitions ); /// - /// GP1 + /// Pin GP1 /// public IPin GP1 => new Pin( Controller, @@ -41,7 +44,7 @@ public class PinDefinitions : IPinDefinitions ); /// - /// GP2 + /// Pin GP2 /// public IPin GP2 => new Pin( Controller, @@ -52,7 +55,7 @@ public class PinDefinitions : IPinDefinitions ); /// - /// GP3 + /// Pin GP3 /// public IPin GP3 => new Pin( Controller, @@ -63,7 +66,7 @@ public class PinDefinitions : IPinDefinitions ); /// - /// GP4 + /// Pin GP4 /// public IPin GP4 => new Pin( Controller, @@ -74,7 +77,7 @@ public class PinDefinitions : IPinDefinitions ); /// - /// GP5 + /// Pin GP5 /// public IPin GP5 => new Pin( Controller, @@ -85,7 +88,7 @@ public class PinDefinitions : IPinDefinitions ); /// - /// GP6 + /// Pin GP6 /// public IPin GP6 => new Pin( Controller, @@ -96,7 +99,7 @@ public class PinDefinitions : IPinDefinitions ); /// - /// GP7 + /// Pin GP7 /// public IPin GP7 => new Pin( Controller, @@ -111,7 +114,7 @@ public class PinDefinitions : IPinDefinitions /// public PinDefinitions(Mcp23x0x controller) { - controller = controller; + Controller = controller; InitAllPins(); } diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/Drivers/Extras/Mcp23x0x.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/Drivers/Extras/Mcp23x0x.cs index be7e0c0ed3..e5c79903e1 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/Drivers/Extras/Mcp23x0x.cs +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/Drivers/Extras/Mcp23x0x.cs @@ -49,7 +49,7 @@ protected Mcp23x0x(II2cBus i2cBus, byte address = 32, IDigitalInputPort interrup /// optional interupt port, needed for input interrupts /// Optional Meadow output port used to reset the mcp expander protected Mcp23x0x(ISpiBus spiBus, IDigitalOutputPort chipSelectPort, IDigitalInputPort interruptPort = null, IDigitalOutputPort resetPort = null) : - base(new SpiMcpDeviceComms(spiBus, chipSelectPort), interruptPort, resetPort) // use the internal constructor that takes an IMcpDeviceComms + base(spiBus, chipSelectPort, interruptPort, resetPort) { Pins = new PinDefinitions(this) { diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/Drivers/Extras/Mcp23x1x.PinDefinitions.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/Drivers/Extras/Mcp23x1x.PinDefinitions.cs index 8288113e33..95464f6d03 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/Drivers/Extras/Mcp23x1x.PinDefinitions.cs +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/Drivers/Extras/Mcp23x1x.PinDefinitions.cs @@ -11,6 +11,9 @@ public abstract partial class Mcp23x1x /// public class PinDefinitions : IPinDefinitions { + /// + /// The controller for the pins + /// public IPinController Controller { get; set; } /// @@ -19,7 +22,7 @@ public class PinDefinitions : IPinDefinitions public IList AllPins { get; } = new List(); /// - /// GPA0 + /// Pin GPA0 /// public IPin GPA0 => new Pin( Controller, @@ -30,7 +33,7 @@ public class PinDefinitions : IPinDefinitions ); /// - /// GPA1 + /// Pin GPA1 /// public IPin GPA1 => new Pin( Controller, @@ -41,7 +44,7 @@ public class PinDefinitions : IPinDefinitions ); /// - /// GPA2 + /// Pin GPA2 /// public IPin GPA2 => new Pin( Controller, @@ -52,7 +55,7 @@ public class PinDefinitions : IPinDefinitions ); /// - /// GPA3 + /// Pin GPA3 /// public IPin GPA3 => new Pin( Controller, @@ -63,7 +66,7 @@ public class PinDefinitions : IPinDefinitions ); /// - /// GPA4 + /// Pin GPA4 /// public IPin GPA4 => new Pin( Controller, @@ -74,7 +77,7 @@ public class PinDefinitions : IPinDefinitions ); /// - /// GPA5 + /// Pin GPA5 /// public IPin GPA5 => new Pin( Controller, @@ -85,7 +88,7 @@ public class PinDefinitions : IPinDefinitions ); /// - /// GPA6 + /// Pin GPA6 /// public IPin GPA6 => new Pin( Controller, @@ -96,7 +99,7 @@ public class PinDefinitions : IPinDefinitions ); /// - /// GPA7 + /// Pin GPA7 /// public IPin GPA7 => new Pin( Controller, @@ -107,7 +110,7 @@ public class PinDefinitions : IPinDefinitions ); /// - /// GPB0 + /// Pin GPB0 /// public IPin GPB0 => new Pin( Controller, @@ -118,7 +121,7 @@ public class PinDefinitions : IPinDefinitions ); /// - /// GPB1 + /// Pin GPB1 /// public IPin GPB1 => new Pin( Controller, @@ -129,7 +132,7 @@ public class PinDefinitions : IPinDefinitions ); /// - /// GPB2 + /// Pin GPB2 /// public IPin GPB2 => new Pin( Controller, @@ -140,7 +143,7 @@ public class PinDefinitions : IPinDefinitions ); /// - /// GPB3 + /// Pin GPB3 /// public IPin GPB3 => new Pin( Controller, @@ -151,7 +154,7 @@ public class PinDefinitions : IPinDefinitions ); /// - /// GPB4 + /// Pin GPB4 /// public IPin GPB4 => new Pin( Controller, @@ -162,7 +165,7 @@ public class PinDefinitions : IPinDefinitions ); /// - /// GPB5 + /// Pin GPB5 /// public IPin GPB5 => new Pin( Controller, @@ -173,7 +176,7 @@ public class PinDefinitions : IPinDefinitions ); /// - /// GPB6 + /// Pin GPB6 /// public IPin GPB6 => new Pin( Controller, @@ -184,7 +187,7 @@ public class PinDefinitions : IPinDefinitions ); /// - /// GPB7 + /// Pin GPB7 /// public IPin GPB7 => new Pin( Controller, diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/ICs.IOExpanders.Mcp23xxx.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/ICs.IOExpanders.Mcp23xxx.csproj index 42ee840691..4e77ce41a1 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/ICs.IOExpanders.Mcp23xxx.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/ICs.IOExpanders.Mcp23xxx.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/Mcp23xxx.Enums.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/Mcp23xxx.Enums.cs index 972ef67f6a..46ece3624d 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/Mcp23xxx.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/Mcp23xxx.Enums.cs @@ -92,7 +92,7 @@ public enum PortBankType : byte /// /// /// 16-bit controllers are logically separated into two 8-bit ports. 8-bit - /// controllers only have one "port" of GPIO pins and ingore the bank setting + /// controllers only have one "port" of GPIO pins and ignore the bank setting /// public enum PortBank { diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/Mcp23xxx.I2cMcpDeviceComms.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/Mcp23xxx.I2cMcpDeviceComms.cs deleted file mode 100644 index 8d3715adaf..0000000000 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/Mcp23xxx.I2cMcpDeviceComms.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Meadow.Hardware; - -namespace Meadow.Foundation.ICs.IOExpanders -{ - public partial class Mcp23xxx - { - internal class I2cMcpDeviceComms : I2cPeripheral, IMcpDeviceComms - { - public I2cMcpDeviceComms(II2cBus i2cBus, byte peripheralAddress) - : base(i2cBus, peripheralAddress) - { - } - } - } -} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/Mcp23xxx.IMcpDeviceComms.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/Mcp23xxx.IMcpDeviceComms.cs deleted file mode 100644 index e40b026ff6..0000000000 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/Mcp23xxx.IMcpDeviceComms.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; - -namespace Meadow.Foundation.ICs.IOExpanders -{ - public partial class Mcp23xxx - { - internal interface IMcpDeviceComms - { - byte ReadRegister(byte address); - void WriteRegister(byte address, byte value); - - void WriteRegister(byte address, Span writeBuffer, ByteOrder order = ByteOrder.LittleEndian); - } - } -} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/Mcp23xxx.SpiMcpDeviceComms.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/Mcp23xxx.SpiMcpDeviceComms.cs deleted file mode 100644 index 22995c38ef..0000000000 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/Mcp23xxx.SpiMcpDeviceComms.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Meadow.Hardware; - -namespace Meadow.Foundation.ICs.IOExpanders -{ - public partial class Mcp23xxx - { - internal class SpiMcpDeviceComms : SpiPeripheral, IMcpDeviceComms - { - public SpiMcpDeviceComms(ISpiBus spiBus, IDigitalOutputPort chipSelectPort) - : base(spiBus, chipSelectPort) - { - } - } - } -} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/Mcp23xxx.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/Mcp23xxx.cs index b4e9d92bf5..3fe3365e07 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/Mcp23xxx.cs +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Driver/Mcp23xxx.cs @@ -1,16 +1,16 @@ using Meadow.Hardware; +using Meadow.Units; using Meadow.Utilities; using System; using System.Collections.Generic; using System.Threading; -using static Meadow.Foundation.ICs.IOExpanders.Mcp23xxx; namespace Meadow.Foundation.ICs.IOExpanders { /// /// Provide an interface to connect to a MCP2xxx port expander /// - abstract partial class Mcp23xxx : IDigitalInputOutputController + abstract partial class Mcp23xxx : IDigitalInputOutputController, ISpiPeripheral, II2cPeripheral { /// /// Raised when the value of any pin configured for input interrupts changes @@ -24,14 +24,45 @@ abstract partial class Mcp23xxx : IDigitalInputOutputController /// public abstract int NumberOfPins { get; } - private readonly IMcpDeviceComms mcpDevice; - private readonly IDigitalInputPort interruptPort; - private readonly IDigitalOutputPort resetPort; - private readonly IDictionary inputPorts; + /// + /// The default SPI bus speed for the device + /// + public Frequency DefaultSpiBusSpeed => new Frequency(375, Frequency.UnitType.Kilohertz); + + /// + /// The SPI bus speed for the device + /// + public Frequency SpiBusSpeed + { + get => (mcpDevice as ISpiCommunications).BusSpeed; + set => (mcpDevice as ISpiCommunications).BusSpeed = value; + } + + /// + /// The default SPI bus mode for the device + /// + public SpiClockConfiguration.Mode DefaultSpiBusMode => SpiClockConfiguration.Mode.Mode0; + + /// + /// The SPI bus mode for the device + /// + public SpiClockConfiguration.Mode SpiBusMode + { + get => (mcpDevice as ISpiCommunications).BusMode; + set => (mcpDevice as ISpiCommunications).BusMode = value; + } - // state - byte ioDirA, ioDirB; - byte olatA, olatB; + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + + private readonly IByteCommunications mcpDevice; + private IDigitalOutputPort resetPort; + private IDictionary inputPorts; + + private byte ioDirA, ioDirB; + private byte olatA, olatB; /// /// object for using lock() to do thread sync @@ -46,9 +77,11 @@ abstract partial class Mcp23xxx : IDigitalInputOutputController /// Optional interupt port, needed for input interrupts (pins 1-8) /// Optional Meadow output port used to reset the mcp expander protected Mcp23xxx(II2cBus i2cBus, byte address, - IDigitalInputPort interruptPort = null, IDigitalOutputPort resetPort = null) : - this(new I2cMcpDeviceComms(i2cBus, address), interruptPort, resetPort) // use the internal constructor that takes an IMcpDeviceComms - { } + IDigitalInputPort interruptPort = null, IDigitalOutputPort resetPort = null) + { + mcpDevice = new I2cCommunications(i2cBus, address); + Initialize(interruptPort, resetPort); + } /// /// Mcpxxx base class contructor @@ -60,39 +93,74 @@ protected Mcp23xxx(II2cBus i2cBus, byte address, protected Mcp23xxx(ISpiBus spiBus, IDigitalOutputPort chipSelectPort, IDigitalInputPort interruptPort = null, - IDigitalOutputPort resetPort = null) : - this(new SpiMcpDeviceComms(spiBus, chipSelectPort), interruptPort, resetPort) // use the internal constructor that takes an IMcpDeviceComms - { } + IDigitalOutputPort resetPort = null) + { + mcpDevice = new SpiCommunications(spiBus, chipSelectPort, DefaultSpiBusSpeed, DefaultSpiBusMode); + Initialize(interruptPort, resetPort); + } /// - /// Mcp23xxx base class + /// Initializes the Mcp23xxx /// - /// /// optional interupt port, needed for input interrupts (pins 1-8) /// Optional Meadow output port used to reset the mcp expander - internal Mcp23xxx(IMcpDeviceComms device, - IDigitalInputPort interruptPort = null, - IDigitalOutputPort resetPort = null) + void Initialize(IDigitalInputPort interruptPort = null, + IDigitalOutputPort resetPort = null) { - if (resetPort != null) - { //disable and enable the mcp before initializing - this.resetPort = resetPort; - ResetMcp(); - } - // TODO: more interrupt // check the interrupt mode and make sure it's correct // raise an exception if not. also, doc in constructor what we expect from an interrupt port if (interruptPort != null) { - this.interruptPort = interruptPort; interruptPort.Changed += InterruptPortChanged; } + if (resetPort != null) + { + this.resetPort = resetPort; + ResetMcp(); + } + inputPorts = new Dictionary(); - mcpDevice = device; - Initialize(); + mcpDevice.WriteRegister(MapRegister(Registers.IODIR_IODirection, PortBank.A), 0xFF); + mcpDevice.WriteRegister(MapRegister(Registers.GPIO, PortBank.A), 0x00); + mcpDevice.WriteRegister(MapRegister(Registers.IPOL_InputPolarity, PortBank.A), 0x00); + mcpDevice.WriteRegister(MapRegister(Registers.GPINTEN_InterruptOnChange), 0x00); + + if (NumberOfPins == 16) + { //write the following registers as well (assume device is interleaving) + mcpDevice.WriteRegister(MapRegister(Registers.IODIR_IODirection, PortBank.B), 0xFF); + mcpDevice.WriteRegister(MapRegister(Registers.GPIO, PortBank.B), 0x00); + mcpDevice.WriteRegister(MapRegister(Registers.IPOL_InputPolarity, PortBank.B), 0x00); + mcpDevice.WriteRegister(MapRegister(Registers.GPINTEN_InterruptOnChange, PortBank.B), 0x00); + } + + // save our state + ioDirA = ioDirB = 0xFF; + olatA = olatB = 0x00; + + if (interruptPort != null) + { + bool intHigh = true; + + if (interruptPort.Resistor == ResistorMode.InternalPullUp || + interruptPort.Resistor == ResistorMode.ExternalPullUp) + { + intHigh = false; + } + + byte iocon = 0x00; + iocon = BitHelpers.SetBit(iocon, 0x01, intHigh); //set interrupt pin to active high (true), low (false) + iocon = BitHelpers.SetBit(iocon, 0x02, false); //don't set interrupt to open drain (should be the default) + + mcpDevice.WriteRegister(MapRegister(Registers.IOCON_IOConfiguration), iocon); + + if (NumberOfPins == 16) + { + mcpDevice.WriteRegister(MapRegister(Registers.IOCON_IOConfiguration, PortBank.B), iocon); + } + } } /// @@ -138,51 +206,6 @@ private void InterruptPortChanged(object sender, DigitalPortResult e) InputChanged?.Invoke(this, new IOExpanderInputChangedEventArgs(interruptFlag, (ushort)(currentStatesB << 8 | currentStates))); } - /// - /// Initializes the Mcp23xxx - /// - protected virtual void Initialize() - { - mcpDevice.WriteRegister(MapRegister(Registers.IODIR_IODirection, PortBank.A), 0xFF); - mcpDevice.WriteRegister(MapRegister(Registers.GPIO, PortBank.A), 0x00); - mcpDevice.WriteRegister(MapRegister(Registers.IPOL_InputPolarity, PortBank.A), 0x00); - mcpDevice.WriteRegister(MapRegister(Registers.GPINTEN_InterruptOnChange), 0x00); - - if (NumberOfPins == 16) - { //write the following registers as well (assume device is interleaving) - mcpDevice.WriteRegister(MapRegister(Registers.IODIR_IODirection, PortBank.B), 0xFF); - mcpDevice.WriteRegister(MapRegister(Registers.GPIO, PortBank.B), 0x00); - mcpDevice.WriteRegister(MapRegister(Registers.IPOL_InputPolarity, PortBank.B), 0x00); - mcpDevice.WriteRegister(MapRegister(Registers.GPINTEN_InterruptOnChange, PortBank.B), 0x00); - } - - // save our state - ioDirA = ioDirB = 0xFF; - olatA = olatB = 0x00; - - if (interruptPort != null) - { - bool intHigh = true; - - if (interruptPort.Resistor == ResistorMode.InternalPullUp || - interruptPort.Resistor == ResistorMode.ExternalPullUp) - { - intHigh = false; - } - - byte iocon = 0x00; - iocon = BitHelpers.SetBit(iocon, 0x01, intHigh); //set interrupt pin to active high (true), low (false) - iocon = BitHelpers.SetBit(iocon, 0x02, false); //don't set interrupt to open drain (should be the default) - - mcpDevice.WriteRegister(MapRegister(Registers.IOCON_IOConfiguration), iocon); - - if (NumberOfPins == 16) - { - mcpDevice.WriteRegister(MapRegister(Registers.IOCON_IOConfiguration, PortBank.B), iocon); - } - } - } - /// /// Checks if a pin exists on the Mcpxxxxx /// @@ -290,7 +313,7 @@ public IDigitalInputPort CreateDigitalInputPort( private void SetRegisterBit(byte register, int bit) { - if (bit >= 7 || bit < 0) { throw new ArgumentOutOfRangeException(); } + if (bit > 7 || bit < 0) { throw new ArgumentOutOfRangeException(); } var value = mcpDevice.ReadRegister(register); value |= (byte)(1 << bit); @@ -299,7 +322,7 @@ private void SetRegisterBit(byte register, int bit) private void ClearRegisterBit(byte register, int bit) { - if (bit >= 7 || bit < 0) { throw new ArgumentOutOfRangeException(); } + if (bit > 7 || bit < 0) { throw new ArgumentOutOfRangeException(); } var value = mcpDevice.ReadRegister(register); value &= (byte)~(1 << bit); mcpDevice.WriteRegister(register, value); @@ -538,7 +561,7 @@ byte MapRegister(byte address, PortBank port = PortBank.A, PortBankType bankStyl PortBank GetPortBankForPin(IPin pin) { //hard coded ... verify in Mcp23x1x.PinDefinitions.cs - if (pin.Name.StartsWith("GPB")) + if ((byte)pin.Key >= 8) { return PortBank.B; } diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23008_Sample/Mcp23008_Sample.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23008_Sample/Mcp23008_Sample.csproj index a2ab40e1d0..7124be98ad 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23008_Sample/Mcp23008_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23008_Sample/Mcp23008_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23009_Sample/Mcp23009_Sample.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23009_Sample/Mcp23009_Sample.csproj index a2ab40e1d0..7124be98ad 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23009_Sample/Mcp23009_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23009_Sample/Mcp23009_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23017_Sample/Mcp23017_Sample.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23017_Sample/Mcp23017_Sample.csproj index a2ab40e1d0..7124be98ad 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23017_Sample/Mcp23017_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23017_Sample/Mcp23017_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23018_Sample/Mcp23018_Sample.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23018_Sample/Mcp23018_Sample.csproj index a2ab40e1d0..7124be98ad 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23018_Sample/Mcp23018_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23018_Sample/Mcp23018_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23s08_Sample/Mcp23s08_Sample.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23s08_Sample/Mcp23s08_Sample.csproj index a2ab40e1d0..7124be98ad 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23s08_Sample/Mcp23s08_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23s08_Sample/Mcp23s08_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23s09_Sample/Mcp23s09_Sample.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23s09_Sample/Mcp23s09_Sample.csproj index a2ab40e1d0..7124be98ad 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23s09_Sample/Mcp23s09_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23s09_Sample/Mcp23s09_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23s17_Sample/Mcp23s17_Sample.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23s17_Sample/Mcp23s17_Sample.csproj index a2ab40e1d0..7124be98ad 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23s17_Sample/Mcp23s17_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23s17_Sample/Mcp23s17_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23s18_Sample/Mcp23s18_Sample.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23s18_Sample/Mcp23s18_Sample.csproj index a2ab40e1d0..7124be98ad 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23s18_Sample/Mcp23s18_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23s18_Sample/Mcp23s18_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23x08_Input_Sample/Mcp23x08_Input_Sample.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23x08_Input_Sample/Mcp23x08_Input_Sample.csproj index 6c41472925..771d3570a2 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23x08_Input_Sample/Mcp23x08_Input_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23x08_Input_Sample/Mcp23x08_Input_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23x08_Input_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23x08_Input_Sample/MeadowApp.cs index 844eeafbf5..db00ba212b 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23x08_Input_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23x08_Input_Sample/MeadowApp.cs @@ -20,7 +20,7 @@ public override Task Initialize() { Resolver.Log.Info("Initializing..."); - + IDigitalInputPort interruptPort = Device.CreateDigitalInputPort(Device.Pins.D00, InterruptMode.EdgeBoth, ResistorMode.InternalPullDown); IDigitalOutputPort resetPort = Device.CreateDigitalOutputPort(Device.Pins.D01); @@ -28,10 +28,10 @@ public override Task Initialize() return base.Initialize(); } - + public override Task Run() { - // TestInterrupts(); + // TestInterrupts(); return TestDigitalInputPorts(1000); @@ -40,19 +40,19 @@ public override Task Run() void TestBulkPinReads(int loopCount) { - for (int l = 0; l < loopCount; l++) + for (int l = 0; l < loopCount; l++) { byte mask = mcp.ReadFromPorts(); var bits = new BitArray(new byte[] { mask }); var bitsString = new StringBuilder(); - - foreach (var bit in bits) + + foreach (var bit in bits) { - bitsString.Append((bool)bit ? "1":"0"); + bitsString.Append((bool)bit ? "1" : "0"); } - Resolver.Log.Info($"Port Values, raw:{mask:X}, bits: { bitsString}"); + Resolver.Log.Info($"Port Values, raw:{mask:X}, bits: {bitsString}"); Thread.Sleep(100); } @@ -69,7 +69,7 @@ async Task TestDigitalInputPorts(int loopCount) var in06 = mcp.CreateDigitalInputPort(mcp.Pins.GP6, InterruptMode.EdgeFalling, ResistorMode.InternalPullUp); var in07 = mcp.CreateDigitalInputPort(mcp.Pins.GP7, InterruptMode.EdgeFalling, ResistorMode.InternalPullUp); - var inputPorts = new List() + var inputPorts = new List() { in00, in01, in02, in03, in04, in05, in06, in07 }; @@ -77,11 +77,11 @@ async Task TestDigitalInputPorts(int loopCount) string output; // read all the ports, sleep for 100ms and repeat a few times. - for (int l = 0; l < loopCount; l++) + for (int l = 0; l < loopCount; l++) { output = string.Empty; - foreach (var inputPort in inputPorts) + foreach (var inputPort in inputPorts) { //Resolver.Log.Info($"InputPort {inputPort.Pin.Name} Read: {inputPort.State}"); output += $"{(inputPort.State ? 1 : 0)}"; @@ -91,7 +91,7 @@ async Task TestDigitalInputPorts(int loopCount) } // cleanup - for (int i = 0; i < inputPorts.Count; i++) + for (int i = 0; i < inputPorts.Count; i++) { inputPorts[i].Dispose(); } diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23x17_Input_Sample/Mcp23x17_Input_Sample.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23x17_Input_Sample/Mcp23x17_Input_Sample.csproj index 6c41472925..771d3570a2 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23x17_Input_Sample/Mcp23x17_Input_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23x17_Input_Sample/Mcp23x17_Input_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23x17_Input_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23x17_Input_Sample/MeadowApp.cs index 0946c28f13..4ee0acb267 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23x17_Input_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Mcp23xxx/Samples/Mcp23x17_Input_Sample/MeadowApp.cs @@ -39,26 +39,26 @@ public override Task Run() { TestInterrupts(); - // return TestDigitalInputPorts(1000); + // return TestDigitalInputPorts(1000); return base.Run(); } void TestBulkPinReads(int loopCount) { - for (int l = 0; l < loopCount; l++) + for (int l = 0; l < loopCount; l++) { byte mask = mcp.ReadFromPorts(); var bits = new BitArray(new byte[] { mask }); var bitsString = new StringBuilder(); - - foreach (var bit in bits) + + foreach (var bit in bits) { - bitsString.Append((bool)bit ? "1":"0"); + bitsString.Append((bool)bit ? "1" : "0"); } - Resolver.Log.Info($"Port Values, raw:{mask:X}, bits: { bitsString}"); + Resolver.Log.Info($"Port Values, raw:{mask:X}, bits: {bitsString}"); Thread.Sleep(100); } @@ -84,20 +84,20 @@ async Task TestDigitalInputPorts(int loopCount) var in14 = mcp.CreateDigitalInputPort(mcp.Pins.GPB6, InterruptMode.EdgeBoth, ResistorMode.InternalPullUp); var in15 = mcp.CreateDigitalInputPort(mcp.Pins.GPB7, InterruptMode.EdgeBoth, ResistorMode.InternalPullUp); - var inputPorts = new List() + var inputPorts = new List() { - in00, in01, in02, in03, in04, in05, in06, in07, + in00, in01, in02, in03, in04, in05, in06, in07, in08, in09, in10, in11, in12, in13, in14, in15, }; string output; // read all the ports, sleep for 100ms and repeat a few times. - for (int l = 0; l < loopCount; l++) + for (int l = 0; l < loopCount; l++) { output = string.Empty; - foreach (var inputPort in inputPorts) + foreach (var inputPort in inputPorts) { //Resolver.Log.Info($"InputPort {inputPort.Pin.Name} Read: {inputPort.State}"); output += $"{(inputPort.State ? 1 : 0)}"; @@ -107,7 +107,7 @@ async Task TestDigitalInputPorts(int loopCount) } // cleanup - for (int i = 0; i < inputPorts.Count; i++) + for (int i = 0; i < inputPorts.Count; i++) { inputPorts[i].Dispose(); } @@ -127,7 +127,7 @@ void TestInterrupts() var inputPort05 = mcp.CreateDigitalInputPort(mcp.Pins.GPA5, InterruptMode.EdgeBoth, ResistorMode.InternalPullUp, debounceTime); var inputPort06 = mcp.CreateDigitalInputPort(mcp.Pins.GPA6, InterruptMode.EdgeBoth, ResistorMode.InternalPullUp, debounceTime); var inputPort07 = mcp.CreateDigitalInputPort(mcp.Pins.GPA7, InterruptMode.EdgeBoth, ResistorMode.InternalPullUp, debounceTime); - + var inputPort08 = mcp.CreateDigitalInputPort(mcp.Pins.GPB0, InterruptMode.EdgeBoth, ResistorMode.InternalPullUp, debounceTime); var inputPort09 = mcp.CreateDigitalInputPort(mcp.Pins.GPB1, InterruptMode.EdgeBoth, ResistorMode.InternalPullUp, debounceTime); var inputPort10 = mcp.CreateDigitalInputPort(mcp.Pins.GPB2, InterruptMode.EdgeBoth, ResistorMode.InternalPullUp, debounceTime); diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pca9685/Driver/ICs.IOExpanders.Pca9685.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pca9685/Driver/ICs.IOExpanders.Pca9685.csproj index b00455f5d5..2b38a713ff 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pca9685/Driver/ICs.IOExpanders.Pca9685.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pca9685/Driver/ICs.IOExpanders.Pca9685.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pca9685/Driver/Pca9685.Enums.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pca9685/Driver/Pca9685.Enums.cs index 93911d8870..4d14780ab3 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pca9685/Driver/Pca9685.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pca9685/Driver/Pca9685.Enums.cs @@ -3,7 +3,7 @@ public partial class Pca9685 { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pca9685/Driver/Pca9685.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pca9685/Driver/Pca9685.cs index 1bdf16ae49..91a1dd51d3 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pca9685/Driver/Pca9685.cs +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pca9685/Driver/Pca9685.cs @@ -9,12 +9,20 @@ namespace Meadow.Foundation.ICs.IOExpanders /// Represents PCA9685 IC /// /// All PWM channels run at the same Frequency - public partial class Pca9685 + public partial class Pca9685 : II2cPeripheral { - private readonly II2cPeripheral i2cPeripheral; + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + + /// + /// I2C Communication bus used to communicate with the peripheral + /// + protected readonly II2cCommunications i2cComms; + private readonly Frequency frequency; - //# Registers/etc. const byte Mode1 = 0x00; const byte Mode2 = 0x01; const byte SubAdr1 = 0x02; @@ -55,7 +63,7 @@ public Pca9685(II2cBus i2cBus, Frequency frequency, byte address = (byte)Address { i2CBus = i2cBus; this.address = address; - i2cPeripheral = new I2cPeripheral(i2CBus, address); + i2cComms = new I2cCommunications(i2CBus, address); this.frequency = frequency; } @@ -160,7 +168,7 @@ void Write(byte register, byte ledXOnL, byte ledXOnH, byte ledXOffL, byte ledXOf void Write(byte register, byte value) { - i2cPeripheral.WriteRegister(register, value); + i2cComms.WriteRegister(register, value); } void SetFrequency(Frequency frequency) @@ -171,7 +179,7 @@ void SetFrequency(Frequency frequency) prescaleval -= 1.0; double prescale = Math.Floor(prescaleval + 0.5); - byte oldmode = i2cPeripheral.ReadRegister(Mode1); + byte oldmode = i2cComms.ReadRegister(Mode1); byte newmode = (byte)((oldmode & 0x7F) | 0x10); // # sleep Write(Mode1, newmode);// # go to sleep diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pca9685/Samples/Pca9685_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pca9685/Samples/Pca9685_Sample/MeadowApp.cs index 38500ce0f9..99d4de22d0 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pca9685/Samples/Pca9685_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pca9685/Samples/Pca9685_Sample/MeadowApp.cs @@ -2,7 +2,6 @@ using Meadow.Devices; using Meadow.Foundation.ICs.IOExpanders; using Meadow.Hardware; -using System; using System.Threading.Tasks; namespace ICs.IOExpanders.Pca9685_Sample diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pca9685/Samples/Pca9685_Sample/Pca9685_Sample.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pca9685/Samples/Pca9685_Sample/Pca9685_Sample.csproj index 40e6a94252..222f95eb3a 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pca9685/Samples/Pca9685_Sample/Pca9685_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pca9685/Samples/Pca9685_Sample/Pca9685_Sample.csproj @@ -10,7 +10,7 @@ ICs.IOExpanders - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Driver/Drivers/Sw18AB.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Driver/Drivers/Sw18AB.cs index a25be8f709..fe49cf9453 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Driver/Drivers/Sw18AB.cs +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Driver/Drivers/Sw18AB.cs @@ -14,7 +14,7 @@ public class Sw18AB : SerialWombatBase /// The I2C bus connected to the wombat /// The I2C address /// Meadow logger (optional) - public Sw18AB(II2cBus i2cBus, Address address = SerialWombatBase.Address.Default, Logger? logger = null) + public Sw18AB(II2cBus i2cBus, Addresses address = SerialWombatBase.Addresses.Default, Logger? logger = null) : base(i2cBus, address, logger) { } } diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Driver/ICs.IOExpanders.SerialWombat.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Driver/ICs.IOExpanders.SerialWombat.csproj index 4e3f5589cb..48d8891285 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Driver/ICs.IOExpanders.SerialWombat.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Driver/ICs.IOExpanders.SerialWombat.csproj @@ -18,8 +18,8 @@ - - - + + + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Driver/SerialWombatBase.Enums.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Driver/SerialWombatBase.Enums.cs index e47849fa27..451357bbed 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Driver/SerialWombatBase.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Driver/SerialWombatBase.Enums.cs @@ -6,9 +6,9 @@ public partial class SerialWombatBase { /// - /// Valid addresses for the Chip. + /// Valid I2C addresses for the device /// - public enum Address : byte + public enum Addresses : byte { /// /// Bus address 0x6a diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Driver/SerialWombatBase.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Driver/SerialWombatBase.cs index 5da3fcac57..30e3269545 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Driver/SerialWombatBase.cs +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Driver/SerialWombatBase.cs @@ -9,17 +9,23 @@ namespace Meadow.Foundation.ICs.IOExpanders { - public abstract partial class SerialWombatBase : IDigitalInputOutputController, IPwmOutputController, IAnalogInputController + public abstract partial class SerialWombatBase : IDigitalInputOutputController, IPwmOutputController, + IAnalogInputController, II2cPeripheral { - private II2cBus _bus; // TODO: add uart support - private WombatVersion _version = null!; - private WombatInfo? _info; - private Guid? _uuid; + private readonly II2cBus i2cBus; + private WombatVersion version = null!; + private WombatInfo? wombatInfo; + private Guid? uuid; /// - /// The I2C address + /// The default I2C address for the peripheral /// - public Address _address { get; } + public byte DefaultI2cAddress => (byte)Addresses.Default; + + /// + /// The current I2C address for the peripheral + /// + public Addresses I2cAddress { get; } /// /// The sync root object @@ -34,11 +40,10 @@ public abstract partial class SerialWombatBase : IDigitalInputOutputController, /// /// Create SerialWombatBase object /// - protected SerialWombatBase(II2cBus bus, Address address = SerialWombatBase.Address.Default, Logger? logger = null) + protected SerialWombatBase(II2cBus bus, Addresses address = Addresses.Default, Logger? logger = null) { Pins = new PinDefinitions(this); - _bus = bus; - _address = address; + i2cBus = bus; Logger = logger; } @@ -52,7 +57,7 @@ protected SerialWombatBase(II2cBus bus, Address address = SerialWombatBase.Addre /// protected void SendPacket(Span tx, Span rx) { - _bus.Exchange((byte)_address, tx, rx); + i2cBus.Exchange((byte)I2cAddress, tx, rx); } /// @@ -62,12 +67,12 @@ public WombatVersion Version { get { - if (_version == null) // lazy load + if (version == null) // lazy load { try { var response = SendCommand(Commands.GetVersion); - _version = new WombatVersion(Encoding.ASCII.GetString(response)); + version = new WombatVersion(Encoding.ASCII.GetString(response)); } catch (Exception ex) { @@ -75,7 +80,7 @@ public WombatVersion Version } } - return _version ?? new WombatVersion("0"); + return version ?? new WombatVersion("0"); } } @@ -86,13 +91,13 @@ public WombatInfo Info { get { - if (_info == null) // lazy load + if (wombatInfo == null) // lazy load { try { var id = (ushort)ReadFlash(FlashRegister18.DeviceID); var rev = (ushort)(ReadFlash(FlashRegister18.DeviceRevision) & 0xf); - _info = new WombatInfo(id, rev); + wombatInfo = new WombatInfo(id, rev); } catch (Exception ex) { @@ -100,7 +105,7 @@ public WombatInfo Info } } - return _info ?? new WombatInfo(0, 0); + return wombatInfo ?? new WombatInfo(0, 0); } } @@ -111,7 +116,7 @@ public Guid Uuid { get { - if (_uuid == null) // lazy load + if (uuid == null) // lazy load { var address = FlashRegister18.DeviceUuid; @@ -126,10 +131,10 @@ public Guid Uuid bytes[index++] = (byte)(data & 0xff >> 16); } - _uuid = new Guid(bytes); + uuid = new Guid(bytes); } - return _uuid.Value; + return uuid.Value; } } @@ -141,7 +146,7 @@ protected byte[] SendCommand(in Span command) lock (SyncRoot) { var rx = new byte[8] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - _bus.Exchange((byte)_address, command, rx); + i2cBus.Exchange((byte)I2cAddress, command, rx); Logger?.Trace($"SW: TX {BitConverter.ToString(command.ToArray())}"); Logger?.Trace($"SW: RX {BitConverter.ToString(rx)}"); @@ -447,7 +452,7 @@ public IPwmPort CreatePwmPort(IPin pin, Frequency frequency, float dutyCycle = 0 { var channel = pin.SupportedChannels.OfType().FirstOrDefault(); - if (channel == null) throw new NotSupportedException($"Pin {pin.Name} Does not support PWM"); + if (channel == null) { throw new NotSupportedException($"Pin {pin.Name} Does not support PWM"); } return new PwmPort(this, pin, channel); } @@ -457,7 +462,7 @@ public IPwmPort CreatePwmPort(IPin pin, Frequency frequency, float dutyCycle = 0 /// public IAnalogInputPort CreateAnalogInputPort(IPin pin, int sampleCount = 64) { - return CreateAnalogInputPort((IPin)pin, sampleCount, TimeSpan.FromSeconds(1), new Voltage(0)); + return CreateAnalogInputPort(pin, sampleCount, TimeSpan.FromSeconds(1), new Voltage(0)); } /// @@ -467,7 +472,7 @@ public IAnalogInputPort CreateAnalogInputPort(IPin pin, int sampleCount, TimeSpa { var channel = pin.SupportedChannels.OfType().FirstOrDefault(); - if (channel == null) throw new NotSupportedException($"Pin {pin.Name} Does not support ADC"); + if (channel == null) { throw new NotSupportedException($"Pin {pin.Name} Does not support ADC"); } return new AnalogInputPort(this, pin, channel, sampleCount); } diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Samples/Sw18AB_ADC_Sample/Sw18AB_ADC_Sample.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Samples/Sw18AB_ADC_Sample/Sw18AB_ADC_Sample.csproj index 915b63566c..ecac6aa1f4 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Samples/Sw18AB_ADC_Sample/Sw18AB_ADC_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Samples/Sw18AB_ADC_Sample/Sw18AB_ADC_Sample.csproj @@ -17,7 +17,7 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Samples/Sw18AB_Core_Sample/Sw18AB_Core_Sample.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Samples/Sw18AB_Core_Sample/Sw18AB_Core_Sample.csproj index ed7da98a43..859e298e47 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Samples/Sw18AB_Core_Sample/Sw18AB_Core_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Samples/Sw18AB_Core_Sample/Sw18AB_Core_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Samples/Sw18AB_PWM_Sample/Sw18AB_PWM_Sample.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Samples/Sw18AB_PWM_Sample/Sw18AB_PWM_Sample.csproj index ed7da98a43..859e298e47 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Samples/Sw18AB_PWM_Sample/Sw18AB_PWM_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Samples/Sw18AB_PWM_Sample/Sw18AB_PWM_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Samples/Sw18AB_Sample/Sw18AB_Sample.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Samples/Sw18AB_Sample/Sw18AB_Sample.csproj index ed7da98a43..859e298e47 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Samples/Sw18AB_Sample/Sw18AB_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Samples/Sw18AB_Sample/Sw18AB_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Samples/Sw18AB_Ultrasonic_Sample/Sw18AB_Ultrasonic_Sample.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Samples/Sw18AB_Ultrasonic_Sample/Sw18AB_Ultrasonic_Sample.csproj index 915b63566c..ecac6aa1f4 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Samples/Sw18AB_Ultrasonic_Sample/Sw18AB_Ultrasonic_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.SerialWombat/Samples/Sw18AB_Ultrasonic_Sample/Sw18AB_Ultrasonic_Sample.csproj @@ -17,7 +17,7 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.TCA9548A/Driver/ICs.IOExpanders.Tca9548a.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.TCA9548A/Driver/ICs.IOExpanders.Tca9548a.csproj index 6b7b424a49..b4e0ed65f8 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.TCA9548A/Driver/ICs.IOExpanders.Tca9548a.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.TCA9548A/Driver/ICs.IOExpanders.Tca9548a.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.TCA9548A/Driver/Tca9548A.Addresses.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.TCA9548A/Driver/Tca9548A.Addresses.cs index a76df3502e..cb0512005f 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.TCA9548A/Driver/Tca9548A.Addresses.cs +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.TCA9548A/Driver/Tca9548A.Addresses.cs @@ -3,7 +3,7 @@ public partial class Tca9548a { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.TCA9548A/Driver/Tca9548A.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.TCA9548A/Driver/Tca9548A.cs index 91c64f1d0e..446420f620 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.TCA9548A/Driver/Tca9548A.cs +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.TCA9548A/Driver/Tca9548A.cs @@ -10,7 +10,7 @@ namespace Meadow.Foundation.ICs.IOExpanders /// /// A TCA9548A i2c multiplexer /// - public partial class Tca9548a : II2cPeripheral + public partial class Tca9548a : II2cCommunications { internal SemaphoreSlim BusSelectorSemaphore = new SemaphoreSlim(1, 1); diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.TCA9548A/Samples/Tca9548a_Sample/Tca9548a_Sample.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.TCA9548A/Samples/Tca9548a_Sample/Tca9548a_Sample.csproj index 544a40a07f..2bd2057f64 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.TCA9548A/Samples/Tca9548a_Sample/Tca9548a_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.TCA9548A/Samples/Tca9548a_Sample/Tca9548a_Sample.csproj @@ -11,7 +11,7 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.x74595/Driver/ICs.IOExpanders.x74595.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.x74595/Driver/ICs.IOExpanders.x74595.csproj index d5bae06a84..1624a49a57 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.x74595/Driver/ICs.IOExpanders.x74595.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.x74595/Driver/ICs.IOExpanders.x74595.csproj @@ -13,10 +13,10 @@ Meadow.Foundation, IOExpanders, x74595 0.1.52 true - x74595 I2C shift register digital output expander + x74595 SPI shift register digital output expander - + diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.x74595/Driver/x74595.Enums.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.x74595/Driver/x74595.Enums.cs deleted file mode 100644 index 957a8ac305..0000000000 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.x74595/Driver/x74595.Enums.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System; - -namespace Meadow.Foundation.ICs.IOExpanders -{ - public partial class x74595 - { - - } -} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.x74595/Driver/x74595.PinDefinitions.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.x74595/Driver/x74595.PinDefinitions.cs index a9eb18b06f..f074d4e064 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.x74595/Driver/x74595.PinDefinitions.cs +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.x74595/Driver/x74595.PinDefinitions.cs @@ -11,6 +11,9 @@ public partial class x74595 /// public class PinDefinitions : IPinDefinitions { + /// + /// The controller for the pin definitions + /// public IPinController Controller { get; set; } /// diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.x74595/Driver/x74595.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.x74595/Driver/x74595.cs index 3fd9d39d0f..b7c9f76aca 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.x74595/Driver/x74595.cs +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.x74595/Driver/x74595.cs @@ -1,4 +1,5 @@ using Meadow.Hardware; +using Meadow.Units; using Meadow.Utilities; using System; using System.Linq; @@ -6,13 +7,13 @@ namespace Meadow.Foundation.ICs.IOExpanders { /// - /// Provide an interface to connect to a 74595 shift register. + /// Provide an interface to connect to a 74595 shift register /// /// /// Control the outputs from a 74595 shift register (or a chain of shift registers) - /// using a SPI interface. + /// using a SPI interface /// - public partial class x74595 : IDigitalOutputController + public partial class x74595 : IDigitalOutputController, ISpiPeripheral { /// /// The pin definitions @@ -20,22 +21,50 @@ public partial class x74595 : IDigitalOutputController public PinDefinitions Pins { get; } /// - /// Number of chips required to implement this ShiftRegister. + /// The default SPI bus speed for the device + /// + public Frequency DefaultSpiBusSpeed => new Frequency(10000, Frequency.UnitType.Kilohertz); + + /// + /// The SPI bus speed for the device + /// + public Frequency SpiBusSpeed + { + get => spiComms.BusSpeed; + set => spiComms.BusSpeed = value; + } + + /// + /// The default SPI bus mode for the device + /// + public SpiClockConfiguration.Mode DefaultSpiBusMode => SpiClockConfiguration.Mode.Mode0; + + /// + /// The SPI bus mode for the device + /// + public SpiClockConfiguration.Mode SpiBusMode + { + get => spiComms.BusMode; + set => spiComms.BusMode = value; + } + + /// + /// Number of chips required to implement this ShiftRegister /// private readonly int numberOfChips; private byte[] latchData; /// - /// SPI interface used to communicate with the shift registers. + /// SPI Communication bus used to communicate with the peripheral /// - private readonly ISpiPeripheral spiPeripheral; + protected ISpiCommunications spiComms; /// /// Default constructor. /// /// - /// This is private to prevent the programmer from calling it explicitly. + /// This is private to prevent the programmer from calling it explicitly /// private x74595() { @@ -51,14 +80,13 @@ public x74595(ISpiBus spiBus, IPin pinChipSelect, int pins = 8) { Pins = new PinDefinitions(this); - // if ((pins > 0) && ((pins % 8) == 0)) if (pins == 8) { numberOfChips = pins / 8; latchData = new byte[numberOfChips]; - spiPeripheral = new SpiPeripheral(spiBus, pinChipSelect?.CreateDigitalOutputPort()); + spiComms = new SpiCommunications(spiBus, pinChipSelect?.CreateDigitalOutputPort(), DefaultSpiBusSpeed, DefaultSpiBusMode); } else { @@ -95,7 +123,7 @@ public void Clear(bool update = true) if (update) { - spiPeripheral.Write(latchData); + spiComms.Write(latchData); } } @@ -115,7 +143,7 @@ public void WriteToPin(IPin pin, bool value) { throw new Exception("Pin is out of range"); } - spiPeripheral.Write(latchData); + spiComms.Write(latchData); } /// diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.x74595/Samples/x74595_Sample/x74595_Sample.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.x74595/Samples/x74595_Sample/x74595_Sample.csproj index 6c6988c7c7..7853e8be9c 100644 --- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.x74595/Samples/x74595_Sample/x74595_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.x74595/Samples/x74595_Sample/x74595_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Driver/Apa102.Enums.cs b/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Driver/Apa102.Enums.cs index c1e4ceadd7..f7d595d8d5 100644 --- a/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Driver/Apa102.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Driver/Apa102.Enums.cs @@ -33,4 +33,4 @@ public enum PixelOrder BGR } } -} +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Driver/Apa102.cs b/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Driver/Apa102.cs index aec36a96cb..5a67cf5016 100644 --- a/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Driver/Apa102.cs +++ b/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Driver/Apa102.cs @@ -5,20 +5,42 @@ namespace Meadow.Foundation.Leds { /// - /// Represents APA102/Dotstar Led(s). + /// Represents APA102/Dotstar Led(s) /// - /// Based on logic from https://github.com/adafruit/Adafruit_CircuitPython_DotStar/blob/master/adafruit_dotstar.py - public partial class Apa102 : IApa102 + public partial class Apa102 : IApa102, ISpiPeripheral { /// - /// Default SPI bus speed + /// The default SPI bus speed for the device /// - public static Frequency DefaultSpiBusSpeed = new Frequency(6000, Frequency.UnitType.Kilohertz); + public Frequency DefaultSpiBusSpeed => new Frequency(6000, Frequency.UnitType.Kilohertz); /// - /// SpiPeripheral object + /// The SPI bus speed for the device /// - protected ISpiPeripheral spiPeripheral; + public Frequency SpiBusSpeed + { + get => spiComms.BusSpeed; + set => spiComms.BusSpeed = value; + } + + /// + /// The default SPI bus mode for the device + /// + public SpiClockConfiguration.Mode DefaultSpiBusMode => SpiClockConfiguration.Mode.Mode0; + + /// + /// The SPI bus mode for the device + /// + public SpiClockConfiguration.Mode SpiBusMode + { + get => spiComms.BusMode; + set => spiComms.BusMode = value; + } + + /// + /// SPI Communication bus used to communicate with the peripheral + /// + protected ISpiCommunications spiComms; const short StartHeaderSize = 4; const byte LedStart = 0b11100000; @@ -73,7 +95,7 @@ public Apa102(ISpiBus spiBus, IPin chipSelectPin, int numberOfLeds, PixelOrder p /// SPI chip select port (optional) public Apa102(ISpiBus spiBus, int numberOfLeds, PixelOrder pixelOrder = PixelOrder.BGR, IDigitalOutputPort chipSelectPort = null) { - spiPeripheral = new SpiPeripheral(spiBus, chipSelectPort); + spiComms = new SpiCommunications(spiBus, chipSelectPort, DefaultSpiBusSpeed, DefaultSpiBusMode); this.numberOfLeds = numberOfLeds; endHeaderSize = this.numberOfLeds / 16; Brightness = 1.0f; @@ -206,7 +228,7 @@ public void Clear(bool update = false) /// public void Show() { - spiPeripheral.Write(buffer); + spiComms.Write(buffer); } /// diff --git a/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Driver/Leds.Apa102.csproj b/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Driver/Leds.Apa102.csproj index 2db2652af1..ef20ea02d0 100644 --- a/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Driver/Leds.Apa102.csproj +++ b/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Driver/Leds.Apa102.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Driver/SparkFunQwiicLEDStick.Enums.cs b/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Driver/SparkFunQwiicLEDStick.Enums.cs index 331f90738b..d64f842745 100644 --- a/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Driver/SparkFunQwiicLEDStick.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Driver/SparkFunQwiicLEDStick.Enums.cs @@ -3,7 +3,7 @@ public partial class SparkFunQwiicLEDStick { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Driver/SparkFunQwiicLEDStick.cs b/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Driver/SparkFunQwiicLEDStick.cs index d454710aa1..a805fe621b 100644 --- a/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Driver/SparkFunQwiicLEDStick.cs +++ b/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Driver/SparkFunQwiicLEDStick.cs @@ -6,7 +6,7 @@ namespace Meadow.Foundation.Leds /// /// Represents a SparkFunQwiicLEDStick that uses APA102 leds /// - public partial class SparkFunQwiicLEDStick : I2cPeripheral, IApa102 + public partial class SparkFunQwiicLEDStick : I2cCommunications, IApa102 { /// /// Enable or disable autowrite to update the LEDs as they're set diff --git a/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Samples/Apa102_Display_Sample/Apa102_Display_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Samples/Apa102_Display_Sample/Apa102_Display_Sample.csproj index 711507f815..f0ec3ac486 100644 --- a/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Samples/Apa102_Display_Sample/Apa102_Display_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Samples/Apa102_Display_Sample/Apa102_Display_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Samples/Apa102_Display_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Samples/Apa102_Display_Sample/MeadowApp.cs index fa94a611da..aeb01d8647 100644 --- a/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Samples/Apa102_Display_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Samples/Apa102_Display_Sample/MeadowApp.cs @@ -3,8 +3,6 @@ using Meadow.Foundation; using Meadow.Foundation.Graphics; using Meadow.Foundation.Leds; -using System; -using System.Threading; using System.Threading.Tasks; namespace Leds.Apa102_Display_Sample @@ -19,7 +17,7 @@ public override Task Initialize() { Resolver.Log.Info("Initialize..."); - display = new Apa102(Device.CreateSpiBus(Apa102.DefaultSpiBusSpeed), 32, 8, Apa102.PixelOrder.BGR); + display = new Apa102(Device.CreateSpiBus(), 32, 8, Apa102.PixelOrder.BGR); canvas = new MicroGraphics(display); Resolver.Log.Info("Hardware intitialized."); @@ -50,22 +48,28 @@ public override async Task Run() static class Colors { - public static Color AzureBlue { - get { + public static Color AzureBlue + { + get + { var azureBlue = Color.FromHex("#23abe3"); // make it way less bright return Color.FromHsba(azureBlue.Hue, azureBlue.Saturation, 0.025); } } - public static Color ChileanFire { - get { + public static Color ChileanFire + { + get + { var chileanFire = Color.FromHex("#ef7d3b"); // make it way less bright return Color.FromHsba(chileanFire.Hue, chileanFire.Saturation, 0.025); } } - public static Color PearGreen { - get { + public static Color PearGreen + { + get + { var PearGreen = Color.FromHex("#c9db31"); // make it way less bright return Color.FromHsba(PearGreen.Hue, PearGreen.Saturation, 0.025); diff --git a/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Samples/Apa102_Sample/Apa102_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Samples/Apa102_Sample/Apa102_Sample.csproj index c1ec7ea573..93a26db4d2 100644 --- a/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Samples/Apa102_Sample/Apa102_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Samples/Apa102_Sample/Apa102_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Samples/Apa102_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Samples/Apa102_Sample/MeadowApp.cs index 29f31bcbdf..f98bf474c8 100644 --- a/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Samples/Apa102_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Leds.Apa102/Samples/Apa102_Sample/MeadowApp.cs @@ -2,7 +2,6 @@ using Meadow.Devices; using Meadow.Foundation; using Meadow.Foundation.Leds; -using System; using System.Threading; using System.Threading.Tasks; @@ -19,7 +18,7 @@ public class MeadowApp : App public override Task Initialize() { Resolver.Log.Info("Initialize..."); - apa102 = new Apa102(Device.CreateSpiBus(Apa102.DefaultSpiBusSpeed), numberOfLeds, Apa102.PixelOrder.BGR); + apa102 = new Apa102(Device.CreateSpiBus(), numberOfLeds, Apa102.PixelOrder.BGR); return base.Initialize(); } @@ -65,7 +64,7 @@ void SetColor(Color color, float brightness) { Resolver.Log.Info($"SetColor(color:{color}"); - for (int i = 0; i < apa102.NumberOfLeds; i++) + for (int i = 0; i < apa102.NumberOfLeds; i++) { apa102.SetLed(i, color, brightness); } @@ -133,13 +132,13 @@ void WalkTheStrip(Color color, int numberOfTraverses) apa102.SetLed(index, color); last = index; - if(forward) { index++; } + if (forward) { index++; } else { index--; } apa102.Show(); - if(index == apa102.NumberOfLeds - 1) { forward = false; } - if(index == 0) { forward = true; } + if (index == apa102.NumberOfLeds - 1) { forward = false; } + if (index == 0) { forward = true; } Thread.Sleep(50); } @@ -157,13 +156,13 @@ void Start() apa102.SetLed(2, Color.Blue); apa102.Show(); Thread.Sleep(2000); - + apa102.SetLed(0, Color.Green); apa102.SetLed(1, Color.Yellow); apa102.SetLed(2, Color.Pink); apa102.Show(); Thread.Sleep(5000); - + apa102.Clear(true); } diff --git a/Source/Meadow.Foundation.Peripherals/Leds.Pca9633/Driver/Leds.Pca9633.csproj b/Source/Meadow.Foundation.Peripherals/Leds.Pca9633/Driver/Leds.Pca9633.csproj index e2b70e8581..f4d6acce70 100644 --- a/Source/Meadow.Foundation.Peripherals/Leds.Pca9633/Driver/Leds.Pca9633.csproj +++ b/Source/Meadow.Foundation.Peripherals/Leds.Pca9633/Driver/Leds.Pca9633.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Leds.Pca9633/Driver/Pca9633.Enums.cs b/Source/Meadow.Foundation.Peripherals/Leds.Pca9633/Driver/Pca9633.Enums.cs index a027732ae4..2a0fb8a64a 100644 --- a/Source/Meadow.Foundation.Peripherals/Leds.Pca9633/Driver/Pca9633.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Leds.Pca9633/Driver/Pca9633.Enums.cs @@ -3,7 +3,7 @@ public partial class Pca9633 { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Leds.Pca9633/Driver/Pca9633.cs b/Source/Meadow.Foundation.Peripherals/Leds.Pca9633/Driver/Pca9633.cs index 077537a5ba..e421033edc 100644 --- a/Source/Meadow.Foundation.Peripherals/Leds.Pca9633/Driver/Pca9633.cs +++ b/Source/Meadow.Foundation.Peripherals/Leds.Pca9633/Driver/Pca9633.cs @@ -5,12 +5,17 @@ namespace Meadow.Foundation.Leds /// /// Represents a Pca9633 led driver /// - public partial class Pca9633 + public partial class Pca9633 : II2cPeripheral { /// - /// Pca9633 i2c peripheral object + /// The default I2C address for the peripheral /// - readonly II2cPeripheral i2CPeripheral; + public byte DefaultI2cAddress => (byte)Addresses.Default; + + /// + /// I2C Communication bus used to communicate with the peripheral + /// + protected readonly II2cCommunications i2cComms; /// /// Red LED location - used for RGB control @@ -31,7 +36,7 @@ public partial class Pca9633 public bool IsOn { get => isOn; - set => i2CPeripheral.WriteRegister((byte)Registers.LEDOUT, (byte)(value == true?1:0)); + set => i2cComms.WriteRegister((byte)Registers.LEDOUT, (byte)(value == true ? 1 : 0)); } bool isOn = true; @@ -40,7 +45,7 @@ public bool IsOn /// /// i2c bus /// i2c address - public Pca9633(II2cBus i2cBus, Addresses address) + public Pca9633(II2cBus i2cBus, Addresses address = Addresses.Default) : this(i2cBus, (byte)address) { } @@ -50,9 +55,9 @@ public Pca9633(II2cBus i2cBus, Addresses address) /// /// i2c bus /// i2c address - public Pca9633(II2cBus i2cBus, byte address = (byte)Addresses.Default) + public Pca9633(II2cBus i2cBus, byte address) { - i2CPeripheral = new I2cPeripheral(i2cBus, address); + i2cComms = new I2cCommunications(i2cBus, address); Initialize(); } @@ -60,10 +65,10 @@ public Pca9633(II2cBus i2cBus, byte address = (byte)Addresses.Default) void Initialize() { // backlight init - i2CPeripheral.WriteRegister((byte)Registers.MODE1, 0); + i2cComms.WriteRegister((byte)Registers.MODE1, 0); // set LEDs controllable by both PWM and GRPPWM registers - i2CPeripheral.WriteRegister(8, 0xFF); - i2CPeripheral.WriteRegister((byte)Registers.MODE2, 20); + i2cComms.WriteRegister(8, 0xFF); + i2cComms.WriteRegister((byte)Registers.MODE2, 20); } /// @@ -71,19 +76,19 @@ void Initialize() /// public void Wake() { - var value = i2CPeripheral.ReadRegister((byte)Registers.MODE1); + var value = i2cComms.ReadRegister((byte)Registers.MODE1); value = (byte)(value & ~(1 << BIT_SLEEP)); - i2CPeripheral.WriteRegister((byte)Registers.MODE1, value); + i2cComms.WriteRegister((byte)Registers.MODE1, value); } - + /// /// Put device into sleep state /// public void Sleep() { - var value = i2CPeripheral.ReadRegister((byte)Registers.MODE1); + var value = i2cComms.ReadRegister((byte)Registers.MODE1); value = (byte)(value | (1 << BIT_SLEEP)); - i2CPeripheral.WriteRegister((byte)Registers.MODE1, value); + i2cComms.WriteRegister((byte)Registers.MODE1, value); } /// @@ -107,15 +112,15 @@ public void SetColor(Color color) { if (LedRed != LedPosition.Undefined) { - i2CPeripheral.WriteRegister((byte)LedRed, (byte)(255 - color.R)); + i2cComms.WriteRegister((byte)LedRed, (byte)(255 - color.R)); } if (LedGreen != LedPosition.Undefined) { - i2CPeripheral.WriteRegister((byte)LedGreen, (byte)(255 - color.G)); + i2cComms.WriteRegister((byte)LedGreen, (byte)(255 - color.G)); } if (LedBlue != LedPosition.Undefined) { - i2CPeripheral.WriteRegister((byte)LedBlue, (byte)(255 - color.B)); + i2cComms.WriteRegister((byte)LedBlue, (byte)(255 - color.B)); } } @@ -126,7 +131,7 @@ public void SetColor(Color color) /// brightness (0-255) public void SetLedBrightness(LedPosition led, byte brightness) { - i2CPeripheral.WriteRegister((byte)led, (byte)(255 - brightness)); + i2cComms.WriteRegister((byte)led, (byte)(255 - brightness)); } /// @@ -135,7 +140,7 @@ public void SetLedBrightness(LedPosition led, byte brightness) /// brightness (0-255) public void SetGroupBrightess(byte brightness) { - i2CPeripheral.WriteRegister((byte)Registers.GRPPWM, (byte)(255 - brightness)); + i2cComms.WriteRegister((byte)Registers.GRPPWM, (byte)(255 - brightness)); } /// @@ -145,10 +150,10 @@ public void SetGroupBrightess(byte brightness) /// public void SetDriveMode(DriveType drive) { - var value = i2CPeripheral.ReadRegister((byte)Registers.MODE2); + var value = i2cComms.ReadRegister((byte)Registers.MODE2); value = (byte)(value & ~(1 << BIT_OUTDRV)); value |= (byte)((byte)drive << BIT_OUTDRV); - i2CPeripheral.WriteRegister((byte)Registers.MODE2, value); + i2cComms.WriteRegister((byte)Registers.MODE2, value); } /// @@ -165,7 +170,7 @@ public void SetAutoIncrementMode(AutoIncrement mode) AutoIncrement.IndividualAndGlobalRegisters => 1 << 7 | 1 << 6 | 1 << 5, _ => 0, }; - i2CPeripheral.WriteRegister((byte)Registers.MODE1, (byte)value); + i2cComms.WriteRegister((byte)Registers.MODE1, (byte)value); } diff --git a/Source/Meadow.Foundation.Peripherals/Leds.Pca9633/Samples/Pca9633_Sample/Pca9633_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Leds.Pca9633/Samples/Pca9633_Sample/Pca9633_Sample.csproj index a709d767fc..8ff278dd6e 100644 --- a/Source/Meadow.Foundation.Peripherals/Leds.Pca9633/Samples/Pca9633_Sample/Pca9633_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Leds.Pca9633/Samples/Pca9633_Sample/Pca9633_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Motors.ElectronicSpeedController/Driver/Motors.ElectronicSpeedController.csproj b/Source/Meadow.Foundation.Peripherals/Motors.ElectronicSpeedController/Driver/Motors.ElectronicSpeedController.csproj index 846b30dbf2..a2b24edada 100644 --- a/Source/Meadow.Foundation.Peripherals/Motors.ElectronicSpeedController/Driver/Motors.ElectronicSpeedController.csproj +++ b/Source/Meadow.Foundation.Peripherals/Motors.ElectronicSpeedController/Driver/Motors.ElectronicSpeedController.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Motors.ElectronicSpeedController/Samples/ElectronicSpeedController_Sample/ElectronicSpeedController_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Motors.ElectronicSpeedController/Samples/ElectronicSpeedController_Sample/ElectronicSpeedController_Sample.csproj index 94450ae30e..a2b1a31d42 100644 --- a/Source/Meadow.Foundation.Peripherals/Motors.ElectronicSpeedController/Samples/ElectronicSpeedController_Sample/ElectronicSpeedController_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Motors.ElectronicSpeedController/Samples/ElectronicSpeedController_Sample/ElectronicSpeedController_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Motors.Stepper.A4988/Driver/Motors.Stepper.A4988.csproj b/Source/Meadow.Foundation.Peripherals/Motors.Stepper.A4988/Driver/Motors.Stepper.A4988.csproj index 5d021738c9..3129cb4391 100644 --- a/Source/Meadow.Foundation.Peripherals/Motors.Stepper.A4988/Driver/Motors.Stepper.A4988.csproj +++ b/Source/Meadow.Foundation.Peripherals/Motors.Stepper.A4988/Driver/Motors.Stepper.A4988.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Motors.Stepper.A4988/Samples/A4988_Sample/A4988_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Motors.Stepper.A4988/Samples/A4988_Sample/A4988_Sample.csproj index e465643087..af1a3ec6b0 100644 --- a/Source/Meadow.Foundation.Peripherals/Motors.Stepper.A4988/Samples/A4988_Sample/A4988_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Motors.Stepper.A4988/Samples/A4988_Sample/A4988_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Motors.Stepper.Uln2003/Driver/Motors.Stepper.Uln2003.csproj b/Source/Meadow.Foundation.Peripherals/Motors.Stepper.Uln2003/Driver/Motors.Stepper.Uln2003.csproj index ed89d08425..91edeacd57 100644 --- a/Source/Meadow.Foundation.Peripherals/Motors.Stepper.Uln2003/Driver/Motors.Stepper.Uln2003.csproj +++ b/Source/Meadow.Foundation.Peripherals/Motors.Stepper.Uln2003/Driver/Motors.Stepper.Uln2003.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Motors.Stepper.Uln2003/Samples/Uln2003_Sample/Uln2003_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Motors.Stepper.Uln2003/Samples/Uln2003_Sample/Uln2003_Sample.csproj index 103d18896b..9642084eb8 100644 --- a/Source/Meadow.Foundation.Peripherals/Motors.Stepper.Uln2003/Samples/Uln2003_Sample/Uln2003_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Motors.Stepper.Uln2003/Samples/Uln2003_Sample/Uln2003_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Motors.Tb67h420ftg/Driver/Motors.Tb67h420ftg.csproj b/Source/Meadow.Foundation.Peripherals/Motors.Tb67h420ftg/Driver/Motors.Tb67h420ftg.csproj index 03fbcdec08..64353463a9 100644 --- a/Source/Meadow.Foundation.Peripherals/Motors.Tb67h420ftg/Driver/Motors.Tb67h420ftg.csproj +++ b/Source/Meadow.Foundation.Peripherals/Motors.Tb67h420ftg/Driver/Motors.Tb67h420ftg.csproj @@ -10,19 +10,16 @@ http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ Meadow.Foundation.Motors.Tb67h420ftg https://github.com/WildernessLabs/Meadow.Foundation - Meadow, Meadow.Foundation, Motor, HBridge, Tb67h420ftg + Meadow,Meadow.Foundation,Motor,HBridge,Tb67h420ftg 0.1.22 true Tb67h420ftg digital input motor controller - - 8.0 - - - 8.0 + + 10.0 - + diff --git a/Source/Meadow.Foundation.Peripherals/Motors.Tb67h420ftg/Samples/Tb67h420ftg_Encoder_Sample/Tb67h420ftg_Encoder_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Motors.Tb67h420ftg/Samples/Tb67h420ftg_Encoder_Sample/Tb67h420ftg_Encoder_Sample.csproj index 3cbd61dc1c..8f2dd29c8d 100644 --- a/Source/Meadow.Foundation.Peripherals/Motors.Tb67h420ftg/Samples/Tb67h420ftg_Encoder_Sample/Tb67h420ftg_Encoder_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Motors.Tb67h420ftg/Samples/Tb67h420ftg_Encoder_Sample/Tb67h420ftg_Encoder_Sample.csproj @@ -10,7 +10,7 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Motors.Tb67h420ftg/Samples/Tb67h420ftg_Sample/Tb67h420ftg_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Motors.Tb67h420ftg/Samples/Tb67h420ftg_Sample/Tb67h420ftg_Sample.csproj index de3746657b..2fe4806d8c 100644 --- a/Source/Meadow.Foundation.Peripherals/Motors.Tb67h420ftg/Samples/Tb67h420ftg_Sample/Tb67h420ftg_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Motors.Tb67h420ftg/Samples/Tb67h420ftg_Sample/Tb67h420ftg_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/RTCs.Ds1307/Driver/Ds1307.Enums.cs b/Source/Meadow.Foundation.Peripherals/RTCs.Ds1307/Driver/Ds1307.Enums.cs index f14a713c14..2a5c0a459c 100644 --- a/Source/Meadow.Foundation.Peripherals/RTCs.Ds1307/Driver/Ds1307.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/RTCs.Ds1307/Driver/Ds1307.Enums.cs @@ -3,9 +3,9 @@ public partial class Ds1307 { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// - public enum Address : byte + public enum Addresses : byte { /// /// Bus address 0x68 diff --git a/Source/Meadow.Foundation.Peripherals/RTCs.Ds1307/Driver/Ds1307.cs b/Source/Meadow.Foundation.Peripherals/RTCs.Ds1307/Driver/Ds1307.cs index 01ce3fd1ab..82f2fdbec8 100644 --- a/Source/Meadow.Foundation.Peripherals/RTCs.Ds1307/Driver/Ds1307.cs +++ b/Source/Meadow.Foundation.Peripherals/RTCs.Ds1307/Driver/Ds1307.cs @@ -7,8 +7,13 @@ namespace Meadow.Foundation.RTCs /// /// Represents a DS1307 real-time clock /// - public partial class Ds1307 + public partial class Ds1307 : II2cPeripheral { + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + const int OriginYear = 1980; readonly II2cBus i2cBus; @@ -31,15 +36,15 @@ public bool IsRunning get { // read 1 byte starting from 0x00 var reg = new byte[1]; - i2cBus.Write((byte)Address.Default, new byte[] { 0 }); - i2cBus.Read((byte)Address.Default, reg); + i2cBus.Write((byte)Addresses.Default, new byte[] { 0 }); + i2cBus.Read((byte)Addresses.Default, reg); return (reg[0] & (1 << 7)) != 0; } set { // read the seconds register var reg = new byte[1]; - i2cBus.Write((byte)Address.Default, new byte[] { 0 }); - i2cBus.Read((byte)Address.Default, reg); + i2cBus.Write((byte)Addresses.Default, new byte[] { 0 }); + i2cBus.Read((byte)Addresses.Default, reg); var current = (reg[0] & (1 << 7)) != 0; if ((value && current) || (!value && !current)) return; @@ -54,7 +59,7 @@ public bool IsRunning } // and write it back to register 0x00 - i2cBus.Write((byte)Address.Default, reg); + i2cBus.Write((byte)Addresses.Default, reg); } } @@ -65,8 +70,8 @@ public bool IsRunning public DateTime GetTime() { var data = new byte[7]; - i2cBus.Write((byte)Address.Default, new byte[] { 0 }); - i2cBus.Read((byte)Address.Default, data); + i2cBus.Write((byte)Addresses.Default, new byte[] { 0 }); + i2cBus.Read((byte)Addresses.Default, data); return FromRTCTime(data); } @@ -76,11 +81,10 @@ public DateTime GetTime() /// The new time public void SetTime(DateTime time) { - var data = new List(); - data.Add(0); + var data = new List { 0 }; data.AddRange(ToRTCTime(time)); - i2cBus.Write((byte)Address.Default, data.ToArray()); + i2cBus.Write((byte)Addresses.Default, data.ToArray()); } /// @@ -90,9 +94,9 @@ public void SetTime(DateTime time) /// The number of bytes to read public byte[] ReadRAM(int offset, int count) { - var data = new byte[count]; - i2cBus.Write((byte)Address.Default, new byte[] { (byte)(0x08 + offset) }); - i2cBus.Read((byte)Address.Default, data); + var data = new byte[count]; + i2cBus.Write((byte)Addresses.Default, new byte[] { (byte)(0x08 + offset) }); + i2cBus.Read((byte)Addresses.Default, data); return data; } @@ -104,11 +108,13 @@ public byte[] ReadRAM(int offset, int count) /// public void WriteRAM(int offset, params byte[] data) { - var d = new List(); - d.Add((byte)(0x08 + offset)); // target start register offset + var d = new List + { + (byte)(0x08 + offset) // target start register offset + }; d.AddRange(data); - i2cBus.Write((byte)Address.Default, d.ToArray()); + i2cBus.Write((byte)Addresses.Default, d.ToArray()); } /// @@ -118,34 +124,19 @@ public void WriteRAM(int offset, params byte[] data) /// Throw if invalid frequency is selected public void SquareWaveOutput(SquareWaveFrequency freq) { - byte registerData; - - switch (freq) + var registerData = freq switch { - case SquareWaveFrequency.Wave_1000Hz: - registerData = (1 << 4); - break; - case SquareWaveFrequency.Wave_4096Hz: - registerData = (1 << 4) | (1 << 0); - break; - case SquareWaveFrequency.Wave_8192Hz: - registerData = (1 << 4) | (1 << 1); - break; - case SquareWaveFrequency.Wave_32768Hz: - registerData = (1 << 4) | (1 << 0) | (1 << 1); - break; - case SquareWaveFrequency.Wave_Low: - registerData = 0; - break; - case SquareWaveFrequency.Wave_High: - registerData = (1 << 7); - break; - default: - throw new NotSupportedException(); - } + SquareWaveFrequency.Wave_1000Hz => (byte)(1 << 4), + SquareWaveFrequency.Wave_4096Hz => (byte)((1 << 4) | (1 << 0)), + SquareWaveFrequency.Wave_8192Hz => (byte)((1 << 4) | (1 << 1)), + SquareWaveFrequency.Wave_32768Hz => (byte)((1 << 4) | (1 << 0) | (1 << 1)), + SquareWaveFrequency.Wave_Low => (byte)0, + SquareWaveFrequency.Wave_High => (byte)(1 << 7), + _ => throw new NotSupportedException(), + }; // control register is at 0x07 - i2cBus.Write((byte)Address.Default, new byte[] { 0x07, registerData }); //register and value + i2cBus.Write((byte)Addresses.Default, new byte[] { 0x07, registerData }); //register and value } static byte ToBCD(ushort i) diff --git a/Source/Meadow.Foundation.Peripherals/RTCs.Ds1307/Driver/RTCs.Ds1307.csproj b/Source/Meadow.Foundation.Peripherals/RTCs.Ds1307/Driver/RTCs.Ds1307.csproj index 42947d433e..50b9c86ed3 100644 --- a/Source/Meadow.Foundation.Peripherals/RTCs.Ds1307/Driver/RTCs.Ds1307.csproj +++ b/Source/Meadow.Foundation.Peripherals/RTCs.Ds1307/Driver/RTCs.Ds1307.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/RTCs.Ds1307/Samples/Ds1307_Sample/Ds1307_Sample.csproj b/Source/Meadow.Foundation.Peripherals/RTCs.Ds1307/Samples/Ds1307_Sample/Ds1307_Sample.csproj index 60d7492d84..80dc4abef1 100644 --- a/Source/Meadow.Foundation.Peripherals/RTCs.Ds1307/Samples/Ds1307_Sample/Ds1307_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/RTCs.Ds1307/Samples/Ds1307_Sample/Ds1307_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/RTCs.Ds323x/Driver/Ds3231.Enums.cs b/Source/Meadow.Foundation.Peripherals/RTCs.Ds323x/Driver/Ds3231.Enums.cs deleted file mode 100644 index 1273ab15c6..0000000000 --- a/Source/Meadow.Foundation.Peripherals/RTCs.Ds323x/Driver/Ds3231.Enums.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace Meadow.Foundation.RTCs -{ - public partial class Ds3231 : Ds323x - { - /// - /// Valid addresses for the sensor. - /// - public enum Address : byte - { - /// - /// Bus address 0x68 - /// - Address_0x68 = 0x68, - /// - /// Default bus address - /// - Default = Address_0x68 - } - } -} diff --git a/Source/Meadow.Foundation.Peripherals/RTCs.Ds323x/Driver/Ds3231.cs b/Source/Meadow.Foundation.Peripherals/RTCs.Ds323x/Driver/Ds3231.cs index c8fbf5d88b..c4dc836559 100644 --- a/Source/Meadow.Foundation.Peripherals/RTCs.Ds323x/Driver/Ds3231.cs +++ b/Source/Meadow.Foundation.Peripherals/RTCs.Ds323x/Driver/Ds3231.cs @@ -13,11 +13,8 @@ public partial class Ds3231 : Ds323x /// Digital pin connected to the alarm interrupt pin on the RTC. /// The I2C Bus the peripheral is connected to /// I2C Bus address of the peripheral - public Ds3231( - II2cBus i2cBus, - IPin interruptPin = null, - byte address = (byte)Address.Default) - : base(new I2cPeripheral(i2cBus, address), interruptPin) + public Ds3231(II2cBus i2cBus, IPin interruptPin = null, byte address = (byte)Addresses.Default) + : base(new I2cCommunications(i2cBus, address), interruptPin) { } /// @@ -29,8 +26,8 @@ public Ds3231( public Ds3231( II2cBus i2cBus, IDigitalInputPort interruptPort = null, - byte address = (byte)Address.Default) - : base(new I2cPeripheral(i2cBus, address), interruptPort) + byte address = (byte)Addresses.Default) + : base(new I2cCommunications(i2cBus, address), interruptPort) { } } diff --git a/Source/Meadow.Foundation.Peripherals/RTCs.Ds323x/Driver/Ds323x.Enums.cs b/Source/Meadow.Foundation.Peripherals/RTCs.Ds323x/Driver/Ds323x.Enums.cs index 878ba0d47f..ff5a192471 100644 --- a/Source/Meadow.Foundation.Peripherals/RTCs.Ds323x/Driver/Ds323x.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/RTCs.Ds323x/Driver/Ds323x.Enums.cs @@ -2,6 +2,21 @@ { public partial class Ds323x { + /// + /// Valid I2C addresses for the sensor + /// + public enum Addresses : byte + { + /// + /// Bus address 0x68 + /// + Address_0x68 = 0x68, + /// + /// Default bus address + /// + Default = Address_0x68 + } + /// /// Possible values for the alarm that can be set or alarm that has been raised /// diff --git a/Source/Meadow.Foundation.Peripherals/RTCs.Ds323x/Driver/Ds323x.Registers.cs b/Source/Meadow.Foundation.Peripherals/RTCs.Ds323x/Driver/Ds323x.Registers.cs new file mode 100644 index 0000000000..bd95f825ab --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/RTCs.Ds323x/Driver/Ds323x.Registers.cs @@ -0,0 +1,31 @@ +namespace Meadow.Foundation.RTCs +{ + public partial class Ds323x + { + /// + /// Register addresses in the sensor + /// + static class Registers + { + public static readonly byte Seconds = 0x00; + public static readonly byte Minutes = 0x01; + public static readonly byte Hours = 0x02; + public static readonly byte Day = 0x03; + public static readonly byte Date = 0x04; + public static readonly byte Month = 0x05; + public static readonly byte Year = 0x06; + public static readonly byte Alarm1Seconds = 0x07; + public static readonly byte Alarm1Minutes = 0x08; + public static readonly byte Alarm1Hours = 0x09; + public static readonly byte Alarm1DayDate = 0x0a; + public static readonly byte Alarm2Minutes = 0x0b; + public static readonly byte Alarm2Hours = 0x0c; + public static readonly byte Alarm2DayDate = 0x0d; + public static readonly byte Control = 0x0e; + public static readonly byte ControlStatus = 0x0f; + public static readonly byte AgingOffset = 0x10; + public static readonly byte TemperatureMSB = 0x11; + public static readonly byte TemperatureLSB = 0x12; + } + } +} diff --git a/Source/Meadow.Foundation.Peripherals/RTCs.Ds323x/Driver/Ds323x.cs b/Source/Meadow.Foundation.Peripherals/RTCs.Ds323x/Driver/Ds323x.cs index d3dd5d40a2..1a7e8ab4b8 100644 --- a/Source/Meadow.Foundation.Peripherals/RTCs.Ds323x/Driver/Ds323x.cs +++ b/Source/Meadow.Foundation.Peripherals/RTCs.Ds323x/Driver/Ds323x.cs @@ -7,33 +7,12 @@ namespace Meadow.Foundation.RTCs /// /// DS323X real-time clock /// - public partial class Ds323x : IDisposable + public partial class Ds323x : II2cPeripheral, IDisposable { /// - /// Register addresses in the sensor + /// The default I2C address for the peripheral /// - static class Registers - { - public static readonly byte Seconds = 0x00; - public static readonly byte Minutes = 0x01; - public static readonly byte Hours = 0x02; - public static readonly byte Day = 0x03; - public static readonly byte Date = 0x04; - public static readonly byte Month = 0x05; - public static readonly byte Year = 0x06; - public static readonly byte Alarm1Seconds = 0x07; - public static readonly byte Alarm1Minutes = 0x08; - public static readonly byte Alarm1Hours = 0x09; - public static readonly byte Alarm1DayDate = 0x0a; - public static readonly byte Alarm2Minutes = 0x0b; - public static readonly byte Alarm2Hours = 0x0c; - public static readonly byte Alarm2DayDate = 0x0d; - public static readonly byte Control = 0x0e; - public static readonly byte ControlStatus = 0x0f; - public static readonly byte AgingOffset = 0x10; - public static readonly byte TemperatureMSB = 0x11; - public static readonly byte TemperatureLSB = 0x12; - } + public byte DefaultI2cAddress => (byte)Addresses.Default; /// /// Number of registers that hold the date and time information. @@ -83,15 +62,14 @@ static class Registers AlarmRaised alarm1Delegate; AlarmRaised alarm2Delegate; bool interruptCreatedInternally; - - Memory readBuffer; + readonly Memory readBuffer; /// /// Create a new Ds323x object /// - protected Ds323x(I2cPeripheral peripheral, IPin interruptPin) + protected Ds323x(I2cCommunications i2cComms, IPin interruptPin) { - ds323x = peripheral; + this.i2cComms = i2cComms; if (interruptPin != null) { @@ -107,9 +85,9 @@ protected Ds323x(I2cPeripheral peripheral, IPin interruptPin) /// /// Create a new Ds323x object /// - protected Ds323x(I2cPeripheral peripheral, IDigitalInputPort interruptPort) + protected Ds323x(I2cCommunications i2cComms, IDigitalInputPort interruptPort) { - ds323x = peripheral; + this.i2cComms = i2cComms; Initialize(interruptPort); } @@ -205,12 +183,12 @@ public DateTime CurrentDateTime get { var data = readBuffer.Span[0..DATE_TIME_REGISTERS_SIZE]; - ds323x.ReadRegister(Registers.Seconds, data); + i2cComms.ReadRegister(Registers.Seconds, data); return DecodeDateTimeRegisters(data); } set { - ds323x.WriteRegister(Registers.Seconds, EncodeDateTimeRegisters(value)); + i2cComms.WriteRegister(Registers.Seconds, EncodeDateTimeRegisters(value)); } } @@ -222,16 +200,16 @@ public Units.Temperature Temperature get { var data = readBuffer.Span[0..2]; - ds323x.ReadRegister(Registers.TemperatureMSB, data); + i2cComms.ReadRegister(Registers.TemperatureMSB, data); var temperature = (ushort)((data[0] << 2) | (data[1] >> 6)); return new Units.Temperature(temperature * 0.25, Units.Temperature.UnitType.Celsius); } } /// - /// DS323x Real Time Clock object. + /// I2C Communication bus used to communicate with the i2cComms /// - protected II2cPeripheral ds323x { get; } + protected II2cCommunications i2cComms; /// /// Interrupt port attached to the DS323x RTC module. @@ -247,8 +225,8 @@ public Units.Temperature Temperature /// protected byte ControlRegister { - get { return ds323x.ReadRegister(Registers.Control); } - set { ds323x.WriteRegister(Registers.Control, value); } + get { return i2cComms.ReadRegister(Registers.Control); } + set { i2cComms.WriteRegister(Registers.Control, value); } } /// @@ -260,8 +238,8 @@ protected byte ControlRegister /// protected byte ControlStatusRegister { - get { return ds323x.ReadRegister(Registers.ControlStatus); } - set { ds323x.WriteRegister(Registers.ControlStatus, value); } + get { return i2cComms.ReadRegister(Registers.ControlStatus); } + set { i2cComms.WriteRegister(Registers.ControlStatus, value); } } /// @@ -300,7 +278,8 @@ protected DateTime DecodeDateTimeRegisters(Span data) { var seconds = Converters.BCDToByte(data[0]); var minutes = Converters.BCDToByte(data[1]); - byte hour = 0; + byte hour; + if ((data[2] & 0x40) != 0) { hour = Converters.BCDToByte((byte)(data[2] & 0x1f)); @@ -313,7 +292,7 @@ protected DateTime DecodeDateTimeRegisters(Span data) { hour = Converters.BCDToByte((byte)(data[2] & 0x3f)); } - var wday = data[3]; + var day = Converters.BCDToByte(data[4]); var month = Converters.BCDToByte((byte)(data[5] & 0x7f)); var year = (ushort)(1900 + Converters.BCDToByte(data[6])); @@ -394,7 +373,7 @@ protected byte DayOfWeekToByte(DayOfWeek day) /// Type of alarm to set. public void SetAlarm(Alarm alarm, DateTime time, AlarmType type) { - byte[] data = null; + byte[] data; var register = Registers.Alarm1Seconds; var element = 0; @@ -468,7 +447,7 @@ public void SetAlarm(Alarm alarm, DateTime time, AlarmType type) data[2] |= 0x40; break; } - ds323x.WriteRegister(register, data); + i2cComms.WriteRegister(register, data); // // Turn the relevant alarm on. // @@ -545,7 +524,7 @@ public void ClearInterrupt(Alarm alarm) public void DisplayRegisters() { var data = readBuffer.Span[0..0x12]; - ds323x.ReadRegister(0, data); + i2cComms.ReadRegister(0, data); DebugInformation.DisplayRegisters(0, data); } } diff --git a/Source/Meadow.Foundation.Peripherals/RTCs.Ds323x/Driver/RTCs.Ds323x.csproj b/Source/Meadow.Foundation.Peripherals/RTCs.Ds323x/Driver/RTCs.Ds323x.csproj index 5bd57930d0..42ebda30c8 100644 --- a/Source/Meadow.Foundation.Peripherals/RTCs.Ds323x/Driver/RTCs.Ds323x.csproj +++ b/Source/Meadow.Foundation.Peripherals/RTCs.Ds323x/Driver/RTCs.Ds323x.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/RTCs.Ds323x/Samples/Ds323x_Sample/Ds323x_Sample.csproj b/Source/Meadow.Foundation.Peripherals/RTCs.Ds323x/Samples/Ds323x_Sample/Ds323x_Sample.csproj index 21cde7cfae..e551c88435 100644 --- a/Source/Meadow.Foundation.Peripherals/RTCs.Ds323x/Samples/Ds323x_Sample/Ds323x_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/RTCs.Ds323x/Samples/Ds323x_Sample/Ds323x_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.AdafruitMPRLS/Driver/AdafruitMPRLS.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.AdafruitMPRLS/Driver/AdafruitMPRLS.Enums.cs index 48fab5431f..f0cf2c078f 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.AdafruitMPRLS/Driver/AdafruitMPRLS.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.AdafruitMPRLS/Driver/AdafruitMPRLS.Enums.cs @@ -3,7 +3,7 @@ public partial class AdafruitMPRLS { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { @@ -17,4 +17,4 @@ public enum Addresses : byte Default = Address_0x18 } } -} +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.AdafruitMPRLS/Driver/AdafruitMPRLS.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.AdafruitMPRLS/Driver/AdafruitMPRLS.cs index f868283c67..af9fa08623 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.AdafruitMPRLS/Driver/AdafruitMPRLS.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.AdafruitMPRLS/Driver/AdafruitMPRLS.cs @@ -3,22 +3,22 @@ using Meadow.Units; using Meadow.Utilities; using System; +using System.Threading; using System.Threading.Tasks; namespace Meadow.Foundation.Sensors.Atmospheric { /// /// Device driver for the Adafruit MPRLS Ported Pressure Sensor Breakout - /// https://www.adafruit.com/product/3965 - /// Device datasheets also available here: https://sensing.honeywell.com/micropressure-mpr-series /// - public partial class AdafruitMPRLS : ByteCommsSensorBase<(Pressure? Pressure, Pressure? RawPsiMeasurement)>, IBarometricPressureSensor + public partial class AdafruitMPRLS : + ByteCommsSensorBase<(Pressure? Pressure, Pressure? RawPsiMeasurement)>, + II2cPeripheral, IBarometricPressureSensor { - //Defined in section 6.6.1 of the datasheet. - private readonly byte[] mprlsMeasurementCommand = { 0xAA, 0x00, 0x00 }; - - private const int MINIMUM_PSI = 0; - private const int MAXIMUM_PSI = 25; + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; /// /// Raised when a new reading has been made. Events will only be raised @@ -57,6 +57,11 @@ public partial class AdafruitMPRLS : ByteCommsSensorBase<(Pressure? Pressure, Pr /// public bool InternalMathSaturated { get; set; } + private readonly byte[] mprlsMeasurementCommand = { 0xAA, 0x00, 0x00 }; + + private const int MINIMUM_PSI = 0; + private const int MAXIMUM_PSI = 25; + /// /// Represents an Adafruit MPRLS Ported Pressure Sensor /// @@ -82,21 +87,18 @@ protected override void RaiseEventsAndNotify(IChangeResult<(Pressure? Pressure, /// Convenience method to get the current Pressure. For frequent reads, use /// StartSampling() and StopSampling() in conjunction with the SampleBuffer. /// - protected override async Task<(Pressure? Pressure, Pressure? RawPsiMeasurement)> ReadSensor() + protected override Task<(Pressure? Pressure, Pressure? RawPsiMeasurement)> ReadSensor() { - return await Task.Run(async () => + return Task.Run(() => { - //Send the command to the sensor to tell it to do the thing. - Peripheral.Write(mprlsMeasurementCommand); + BusComms.Write(mprlsMeasurementCommand); - //Datasheet says wait 5 ms. - await Task.Delay(5); + Thread.Sleep(5); while (true) { - Peripheral.Read(ReadBuffer.Span[0..1]); + BusComms.Read(ReadBuffer.Span[0..1]); - //From section 6.5 of the datasheet. IsDevicePowered = BitHelpers.GetBitValue(ReadBuffer.Span[0], 6); IsDeviceBusy = BitHelpers.GetBitValue(ReadBuffer.Span[0], 5); HasMemoryIntegrityFailed = BitHelpers.GetBitValue(ReadBuffer.Span[0], 2); @@ -106,23 +108,20 @@ protected override void RaiseEventsAndNotify(IChangeResult<(Pressure? Pressure, { throw new InvalidOperationException("Sensor pressure has exceeded max value!"); } - if (HasMemoryIntegrityFailed) { throw new InvalidOperationException("Sensor internal memory integrity check failed!"); } - - if (!(IsDeviceBusy)) + if (!IsDeviceBusy) { break; } } - Peripheral.Read(ReadBuffer.Span[0..4]); + BusComms.Read(ReadBuffer.Span[0..4]); var rawPSIMeasurement = (ReadBuffer.Span[1] << 16) | (ReadBuffer.Span[2] << 8) | ReadBuffer.Span[3]; - //From Section 8.0 of the datasheet. var calculatedPSIMeasurement = (rawPSIMeasurement - 1677722) * (MAXIMUM_PSI - MINIMUM_PSI); calculatedPSIMeasurement /= 15099494 - 1677722; calculatedPSIMeasurement += MINIMUM_PSI; diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.AdafruitMPRLS/Driver/Sensors.Atmospheric.AdafruitMPRLS.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.AdafruitMPRLS/Driver/Sensors.Atmospheric.AdafruitMPRLS.csproj index 57e451e87c..9e932b1491 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.AdafruitMPRLS/Driver/Sensors.Atmospheric.AdafruitMPRLS.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.AdafruitMPRLS/Driver/Sensors.Atmospheric.AdafruitMPRLS.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.AdafruitMPRLS/Samples/AdafruitMPRLS_Sample/AdafruitMPRLS_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.AdafruitMPRLS/Samples/AdafruitMPRLS_Sample/AdafruitMPRLS_Sample.csproj index 46752a6b39..c97e7de334 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.AdafruitMPRLS/Samples/AdafruitMPRLS_Sample/AdafruitMPRLS_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.AdafruitMPRLS/Samples/AdafruitMPRLS_Sample/AdafruitMPRLS_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bh1900Nux/Driver/Bh1900Nux.Address.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bh1900Nux/Driver/Bh1900Nux.Address.cs index 73108a76ca..7ab8d4ff68 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bh1900Nux/Driver/Bh1900Nux.Address.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bh1900Nux/Driver/Bh1900Nux.Address.cs @@ -56,9 +56,9 @@ public enum MeasurementModes } /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// - public enum Address : byte + public enum Addresses : byte { /// /// Bus address 0x48 diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bh1900Nux/Driver/Bh1900Nux.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bh1900Nux/Driver/Bh1900Nux.cs index 6d0576862c..1026a6e232 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bh1900Nux/Driver/Bh1900Nux.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bh1900Nux/Driver/Bh1900Nux.cs @@ -1,6 +1,5 @@ using Meadow.Hardware; using Meadow.Peripherals.Sensors; -using Meadow.Units; using System; using System.Threading.Tasks; @@ -9,7 +8,7 @@ namespace Meadow.Foundation.Sensors.Atmospheric /// /// Represents a Bh1900Nux temperature sensor /// - public partial class Bh1900Nux : ByteCommsSensorBase, ITemperatureSensor + public partial class Bh1900Nux : ByteCommsSensorBase, ITemperatureSensor, II2cPeripheral { /// /// Raised when the temperature value changes @@ -21,15 +20,20 @@ public partial class Bh1900Nux : ByteCommsSensorBase, ITemper /// public Units.Temperature? Temperature => Conditions; + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + /// /// Create a new Bh1900Nux object /// /// The I2C bus /// The I2C address - public Bh1900Nux(II2cBus i2cBus, Address address) + public Bh1900Nux(II2cBus i2cBus, Addresses address) : base(i2cBus, (byte)address, 2, 2) { - if (address < Address.Address_0x48 || address > Address.Address_0x4f) + if (address < Addresses.Address_0x48 || address > Addresses.Address_0x4f) { throw new ArgumentOutOfRangeException("Bh1900Nux address must be in the range of 0x48-0x4f"); } @@ -43,7 +47,7 @@ public Bh1900Nux(II2cBus i2cBus, Address address) /// The I2C bus /// The I2C address public Bh1900Nux(II2cBus i2cBus, byte address) - : this(i2cBus, (Address)address) + : this(i2cBus, (Addresses)address) { } /// @@ -51,18 +55,18 @@ public Bh1900Nux(II2cBus i2cBus, byte address) /// public void Reset() { - Peripheral?.WriteRegister((byte)Register.Reset, 0x01); + BusComms?.WriteRegister((byte)Register.Reset, 0x01); } int GetConfig() { - Peripheral?.ReadRegister((byte)Register.Configuration, ReadBuffer.Span[0..2]); + BusComms?.ReadRegister((byte)Register.Configuration, ReadBuffer.Span[0..2]); return ReadBuffer.Span[0] << 8 | ReadBuffer.Span[1]; } void SetConfig(int cfg) { - Peripheral?.WriteRegister((byte)Register.Configuration, new byte[] { (byte)(cfg >> 8), (byte)(cfg & 0xff) }); + BusComms?.WriteRegister((byte)Register.Configuration, new byte[] { (byte)(cfg >> 8), (byte)(cfg & 0xff) }); } /// @@ -156,13 +160,13 @@ public Units.Temperature LowLimit { get { - Peripheral?.ReadRegister((byte)Register.TLow, ReadBuffer.Span[0..2]); + BusComms?.ReadRegister((byte)Register.TLow, ReadBuffer.Span[0..2]); return RegisterToTemp(ReadBuffer); } set { - Peripheral?.WriteRegister((byte)Register.TLow, TempToBytes(value)); + BusComms?.WriteRegister((byte)Register.TLow, TempToBytes(value)); } } @@ -173,13 +177,13 @@ public Units.Temperature HighLimit { get { - Peripheral?.ReadRegister((byte)Register.THigh, ReadBuffer.Span[0..2]); + BusComms?.ReadRegister((byte)Register.THigh, ReadBuffer.Span[0..2]); return RegisterToTemp(ReadBuffer); } set { - Peripheral?.WriteRegister((byte)Register.THigh, TempToBytes(value)); + BusComms?.WriteRegister((byte)Register.THigh, TempToBytes(value)); } } @@ -208,19 +212,16 @@ private Units.Temperature RegisterToTemp(Memory data) /// Read the temperature /// /// The current temperature value - protected override async Task ReadSensor() + protected override Task ReadSensor() { - return await Task.Run(() => - { - // 12-bit data - // Negative numbers are represented in binary twos complement format. The - // Temperature Register is 0x0000 until the first conversion complete after a software - // reset or power - on. - // Measurement Temperature Value [°C] = Temperature Data [11:0] x 0.0625 - Peripheral?.ReadRegister((byte)Register.Temperature, ReadBuffer.Span[0..2]); + // 12-bit data + // Negative numbers are represented in binary twos complement format. The + // Temperature Register is 0x0000 until the first conversion complete after a software + // reset or power - on. + // Measurement Temperature Value [°C] = Temperature Data [11:0] x 0.0625 + BusComms?.ReadRegister((byte)Register.Temperature, ReadBuffer.Span[0..2]); - return RegisterToTemp(ReadBuffer); - }); + return Task.FromResult(RegisterToTemp(ReadBuffer)); } /// diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bh1900Nux/Driver/Sensors.Atmospheric.Bh1900Nux.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bh1900Nux/Driver/Sensors.Atmospheric.Bh1900Nux.csproj index ce7f600d98..d62e2c62de 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bh1900Nux/Driver/Sensors.Atmospheric.Bh1900Nux.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bh1900Nux/Driver/Sensors.Atmospheric.Bh1900Nux.csproj @@ -23,6 +23,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bh1900Nux/Samples/Bh1900Nux_Sample/Bh1900Nux_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bh1900Nux/Samples/Bh1900Nux_Sample/Bh1900Nux_Sample.csproj index 2eea9cb741..fb31b7cdd8 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bh1900Nux/Samples/Bh1900Nux_Sample/Bh1900Nux_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bh1900Nux/Samples/Bh1900Nux_Sample/Bh1900Nux_Sample.csproj @@ -12,7 +12,7 @@ 8.0 - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bh1900Nux/Samples/Bh1900Nux_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bh1900Nux/Samples/Bh1900Nux_Sample/MeadowApp.cs index d3c1476524..e3b76d4bab 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bh1900Nux/Samples/Bh1900Nux_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bh1900Nux/Samples/Bh1900Nux_Sample/MeadowApp.cs @@ -17,7 +17,7 @@ public override Task Initialize() { Resolver.Log.Info("Initializing..."); - _sensor = new Bh1900Nux(Device.CreateI2cBus(), Bh1900Nux.Address.Default); + _sensor = new Bh1900Nux(Device.CreateI2cBus(), Bh1900Nux.Addresses.Default); var consumer = Bh1900Nux.CreateObserver( handler: result => diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.Addresses.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.Address.cs similarity index 92% rename from Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.Addresses.cs rename to Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.Address.cs index 29136e0326..d252eafac3 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.Addresses.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.Address.cs @@ -3,7 +3,7 @@ public partial class Bme280 { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.Register.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.Register.cs new file mode 100644 index 0000000000..d490a4b996 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.Register.cs @@ -0,0 +1,15 @@ +namespace Meadow.Foundation.Sensors.Atmospheric +{ + public partial class Bme280 + { + internal enum Register : byte + { + ChipID = 0xd0, + Reset = 0xe0, + Humidity = 0xf2, + Status = 0xf3, + Measurement = 0xf4, + Configuration = 0xf5, + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.cs index a5c46e7676..0b841337f8 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.cs @@ -9,24 +9,6 @@ namespace Meadow.Foundation.Sensors.Atmospheric { - // TODO: for standby durations of 1,000ms and less, the sensor - // will actually handle the reading loop. you put it into `Normal` - // mode and set it to one of the known `StandbyDuration`s. - // - // So perhaps this should be an option. From a method signature - // standpoint, i think that we would add an overload that took - // a known `StandbyDuration` instead of an int. - // - // With that said, however, as far as I can tell, the sensor won't - // send an interrupt when a new reading is taken, so i'm not sure - // how we would synchronize with it, since the time that each read - // takes is determined by the samples, filter, etc. -b - // - // TODO: for longer standby durations, we should put the sensor into - // Modes.Sleep to save power. Need to figure out what the stanby - // duration threshold is for that. i'm guessing 5 seconds might be a - // good value. - /// /// BME280 Temperature, Pressure and Humidity Sensor /// @@ -36,7 +18,7 @@ namespace Meadow.Foundation.Sensors.Atmospheric /// public partial class Bme280 : PollingSensorBase<(Units.Temperature? Temperature, RelativeHumidity? Humidity, Pressure? Pressure)>, - ITemperatureSensor, IHumiditySensor, IBarometricPressureSensor + ITemperatureSensor, IHumiditySensor, IBarometricPressureSensor, ISpiPeripheral, II2cPeripheral { /// /// Temperature changed event @@ -79,9 +61,9 @@ public partial class Bme280 : public Oversample HumiditySampleCount { get; set; } = Oversample.OversampleX8; /// - /// Communication bus used to read and write to the BME280 sensor. + /// Communication bus used to read and write to the BME280 sensor /// - private readonly Bme280Comms bme280Comms; + private readonly IByteCommunications bme280Comms; /// /// Compensation data from the sensor @@ -109,6 +91,39 @@ public partial class Bme280 : /// public RelativeHumidity? Humidity => Conditions.Humidity; + /// + /// The default SPI bus speed for the device + /// + public Frequency DefaultSpiBusSpeed => new Frequency(10000, Frequency.UnitType.Kilohertz); + + /// + /// The SPI bus speed for the device + /// + public Frequency SpiBusSpeed + { + get => ((ISpiCommunications)bme280Comms).BusSpeed; + set => ((ISpiCommunications)bme280Comms).BusSpeed = value; + } + + /// + /// The default SPI bus mode for the device + /// + public SpiClockConfiguration.Mode DefaultSpiBusMode => SpiClockConfiguration.Mode.Mode0; + + /// + /// The SPI bus mode for the device + /// + public SpiClockConfiguration.Mode SpiBusMode + { + get => ((ISpiCommunications)bme280Comms).BusMode; + set => ((ISpiCommunications)bme280Comms).BusMode = value; + } + + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + /// /// Initializes a new instance of the BME280 class /// @@ -116,7 +131,7 @@ public partial class Bme280 : /// I2C address of the sensor (default = 0x77) public Bme280(II2cBus i2cBus, byte address = (byte)Addresses.Default) { - bme280Comms = new Bme280I2C(i2cBus, address); + bme280Comms = new I2cCommunications(i2cBus, address); configuration = new Configuration(); // here to avoid the warning Initialize(); } @@ -137,7 +152,7 @@ public Bme280(ISpiBus spiBus, IPin chipSelectPin) : /// The port for the chip select pin public Bme280(ISpiBus spiBus, IDigitalOutputPort chipSelectPort) { - bme280Comms = new Bme280Spi(spiBus, chipSelectPort); + bme280Comms = new SpiCommunications(spiBus, chipSelectPort, DefaultSpiBusSpeed, DefaultSpiBusMode); configuration = new Configuration(); // here to avoid the warning Initialize(); } @@ -192,7 +207,6 @@ protected override void RaiseEventsAndNotify(IChangeResult<(Units.Temperature? T { //TODO: set an update flag on the oversample properties and set // these once, unless the update flag has been set. - // update configuration configuration.TemperatureOverSampling = TemperatureSampleCount; configuration.PressureOversampling = PressureSampleCount; configuration.HumidityOverSampling = HumiditySampleCount; @@ -206,131 +220,55 @@ protected override void RaiseEventsAndNotify(IChangeResult<(Units.Temperature? T await Task.Delay(100); //give the BME280 time to read new values } - return await Task.Run(() => + (Units.Temperature Temperature, RelativeHumidity Humidity, Pressure Pressure) conditions; + + bme280Comms.ReadRegister(0xf7, readBuffer.Span[0..8]); + + var adcTemperature = (readBuffer.Span[3] << 12) | (readBuffer.Span[4] << 4) | ((readBuffer.Span[5] >> 4) & 0x0f); + var tvar1 = (((adcTemperature >> 3) - (compensationData.T1 << 1)) * compensationData.T2) >> 11; + var tvar2 = (((((adcTemperature >> 4) - compensationData.T1) * + ((adcTemperature >> 4) - compensationData.T1)) >> 12) * compensationData.T3) >> 14; + var tfine = tvar1 + tvar2; + + conditions.Temperature = new Units.Temperature((float)(((tfine * 5) + 128) >> 8) / 100, TU.Celsius); + + long pvar1 = tfine - 128000; + var pvar2 = pvar1 * pvar1 * compensationData.P6; + pvar2 += (pvar1 * compensationData.P5) << 17; + pvar2 += (long)compensationData.P4 << 35; + pvar1 = ((pvar1 * pvar1 * compensationData.P8) >> 8) + ((pvar1 * compensationData.P2) << 12); + pvar1 = ((((long)1 << 47) + pvar1) * compensationData.P1) >> 33; + if (pvar1 == 0) { + conditions.Pressure = new Pressure(0, PU.Pascal); + } + else + { + var adcPressure = (readBuffer.Span[0] << 12) | (readBuffer.Span[1] << 4) | ((readBuffer.Span[2] >> 4) & 0x0f); + long pressure = 1048576 - adcPressure; + pressure = (((pressure << 31) - pvar2) * 3125) / pvar1; + pvar1 = (compensationData.P9 * (pressure >> 13) * (pressure >> 13)) >> 25; + pvar2 = (compensationData.P8 * pressure) >> 19; + pressure = ((pressure + pvar1 + pvar2) >> 8) + ((long)compensationData.P7 << 4); + conditions.Pressure = new Pressure((double)pressure / 256, PU.Pascal); + } + + var adcHumidity = (readBuffer.Span[6] << 8) | readBuffer.Span[7]; + var v_x1_u32r = tfine - 76800; + + v_x1_u32r = ((((adcHumidity << 14) - (compensationData.H4 << 20) - (compensationData.H5 * v_x1_u32r)) + + 16384) >> 15) * + ((((((((v_x1_u32r * compensationData.H6) >> 10) * + (((v_x1_u32r * compensationData.H3) >> 11) + 32768)) >> 10) + 2097152) * + compensationData.H2) + 8192) >> 14); + v_x1_u32r = v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * compensationData.H1) >> 4); + + v_x1_u32r = v_x1_u32r < 0 ? 0 : v_x1_u32r; + v_x1_u32r = v_x1_u32r > 419430400 ? 419430400 : v_x1_u32r; + + conditions.Humidity = new RelativeHumidity((v_x1_u32r >> 12) / 1024, HU.Percent); - (Units.Temperature Temperature, RelativeHumidity Humidity, Pressure Pressure) conditions; - - // readily read the readings from the reading register into the read buffer - bme280Comms.ReadRegisters(0xf7, readBuffer.Span[0..8]); - // - // Temperature calculation from section 4.2.3 of the datasheet. - // - // Returns temperature in DegC, resolution is 0.01 DegC. Output value of “5123” equals 51.23 DegC. - // t_fine carries fine temperature as global value: - // - // BME280_S32_t t_fine; - // BME280_S32_t BME280_compensate_T_int32(BME280_S32_t adc_T) - // { - // BME280_S32_t var1, var2, T; - // var1 = ((((adc_T>>3) - ((BME280_S32_t)dig_T1<<1))) * ((BME280_S32_t)dig_T2)) >> 11; - // var2 = (((((adc_T>>4) - ((BME280_S32_t)dig_T1)) * ((adc_T>>4) - ((BME280_S32_t)dig_T1))) >> 12) * - // ((BME280_S32_t)dig_T3)) >> 14; - // t_fine = var1 + var2; - // T = (t_fine * 5 + 128) >> 8; - // return T; - // } - // - var adcTemperature = (readBuffer.Span[3] << 12) | (readBuffer.Span[4] << 4) | ((readBuffer.Span[5] >> 4) & 0x0f); - var tvar1 = (((adcTemperature >> 3) - (compensationData.T1 << 1)) * compensationData.T2) >> 11; - var tvar2 = (((((adcTemperature >> 4) - compensationData.T1) * - ((adcTemperature >> 4) - compensationData.T1)) >> 12) * compensationData.T3) >> 14; - var tfine = tvar1 + tvar2; - // - conditions.Temperature = new Units.Temperature((float)(((tfine * 5) + 128) >> 8) / 100, TU.Celsius); - // - // Pressure calculation from section 4.2.3 of the datasheet. - // - // Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits). - // Output value of “24674867” represents 24674867/256 = 96386.2 Pa = 963.862 hPa - // - // BME280_U32_t BME280_compensate_P_int64(BME280_S32_t adc_P) - // { - // BME280_S64_t var1, var2, p; - // var1 = ((BME280_S64_t)t_fine) - 128000; - // var2 = var1 * var1 * (BME280_S64_t)dig_P6; - // var2 = var2 + ((var1*(BME280_S64_t)dig_P5)<<17); - // var2 = var2 + (((BME280_S64_t)dig_P4)<<35); - // var1 = ((var1 * var1 * (BME280_S64_t)dig_P3)>>8) + ((var1 * (BME280_S64_t)dig_P2)<<12); - // var1 = (((((BME280_S64_t)1)<<47)+var1))*((BME280_S64_t)dig_P1)>>33; - // if (var1 == 0) - // { - // return 0; // avoid exception caused by division by zero - // } - // p = 1048576-adc_P; - // p = (((p<<31)-var2)*3125)/var1; - // var1 = (((BME280_S64_t)dig_P9) * (p>>13) * (p>>13)) >> 25; - // var2 = (((BME280_S64_t)dig_P8) * p) >> 19; - // p = ((p + var1 + var2) >> 8) + (((BME280_S64_t)dig_P7)<<4); - // return (BME280_U32_t)p; - // } - // - long pvar1 = tfine - 128000; - var pvar2 = pvar1 * pvar1 * compensationData.P6; - pvar2 += (pvar1 * compensationData.P5) << 17; - pvar2 += (long)compensationData.P4 << 35; - pvar1 = ((pvar1 * pvar1 * compensationData.P8) >> 8) + ((pvar1 * compensationData.P2) << 12); - pvar1 = ((((long)1 << 47) + pvar1) * compensationData.P1) >> 33; - if (pvar1 == 0) - { - conditions.Pressure = new Pressure(0, PU.Pascal); - } - else - { - var adcPressure = (readBuffer.Span[0] << 12) | (readBuffer.Span[1] << 4) | ((readBuffer.Span[2] >> 4) & 0x0f); - long pressure = 1048576 - adcPressure; - pressure = (((pressure << 31) - pvar2) * 3125) / pvar1; - pvar1 = (compensationData.P9 * (pressure >> 13) * (pressure >> 13)) >> 25; - pvar2 = (compensationData.P8 * pressure) >> 19; - pressure = ((pressure + pvar1 + pvar2) >> 8) + ((long)compensationData.P7 << 4); - // - conditions.Pressure = new Pressure((double)pressure / 256, PU.Pascal); - } - // - // Humidity calculations from section 4.2.3 of the datasheet. - // - // Returns humidity in %RH as unsigned 32 bit integer in Q22.10 format (22 integer and 10 fractional bits). - // Output value of “47445” represents 47445/1024 = 46.333 %RH - // - // BME280_U32_t bme280_compensate_H_int32(BME280_S32_t adc_H) - // { - // BME280_S32_t v_x1_u32r; - // v_x1_u32r = (t_fine - ((BME280_S32_t)76800)); - // v_x1_u32r = (((((adc_H << 14) - (((BME280_S32_t)dig_H4) << 20) - (((BME280_S32_t)dig_H5) * v_x1_u32r)) + - // ((BME280_S32_t)16384)) >> 15) * (((((((v_x1_u32r * ((BME280_S32_t)dig_H6)) >> 10) * (((v_x1_u32r * - // ((BME280_S32_t)dig_H3)) >> 11) + ((BME280_S32_t)32768))) >> 10) + ((BME280_S32_t)2097152)) * - // ((BME280_S32_t)dig_H2) + 8192) >> 14)); - // v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * ((BME280_S32_t)dig_H1)) >> 4)); - // v_x1_u32r = (v_x1_u32r < 0 ? 0 : v_x1_u32r); - // v_x1_u32r = (v_x1_u32r > 419430400 ? 419430400 : v_x1_u32r); - // return (BME280_U32_t)(v_x1_u32r>>12); - // } - // - var adcHumidity = (readBuffer.Span[6] << 8) | readBuffer.Span[7]; - var v_x1_u32r = tfine - 76800; - - v_x1_u32r = ((((adcHumidity << 14) - (compensationData.H4 << 20) - (compensationData.H5 * v_x1_u32r)) + - 16384) >> 15) * - ((((((((v_x1_u32r * compensationData.H6) >> 10) * - (((v_x1_u32r * compensationData.H3) >> 11) + 32768)) >> 10) + 2097152) * - compensationData.H2) + 8192) >> 14); - v_x1_u32r = v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * compensationData.H1) >> 4); - - //v_x1_u32r = (((((adcHumidity << 14) - (((int) _compensationData.H4) << 20) - (((int) _compensationData.H5) * v_x1_u32r)) + - // ((int) 16384)) >> 15) * (((((((v_x1_u32r * ((int) _compensationData.H6)) >> 10) * (((v_x1_u32r * - // ((int) _compensationData.H3)) >> 11) + ((int) 32768))) >> 10) + ((int) 2097152)) * - // ((int) _compensationData.H2) + 8192) >> 14)); - //v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * ((int) _compensationData.H1)) >> 4)); - // - // Makes sure the humidity reading is in the range [0..100]. - // - v_x1_u32r = v_x1_u32r < 0 ? 0 : v_x1_u32r; - v_x1_u32r = v_x1_u32r > 419430400 ? 419430400 : v_x1_u32r; - // - conditions.Humidity = new RelativeHumidity((v_x1_u32r >> 12) / 1024, HU.Percent); - - return conditions; - }); + return conditions; } /// /// Update the configuration for the BME280. @@ -350,16 +288,16 @@ protected void UpdateConfiguration(Configuration configuration) // // Put to sleep to allow the configuration to be changed. // - bme280Comms.WriteRegister(Bme280Comms.Register.Measurement, 0x00); + bme280Comms.WriteRegister((byte)Register.Measurement, 0x00); var data = (byte)((((byte)configuration.Standby << 5) & 0xe0) | (((byte)configuration.Filter << 2) & 0x1c)); - bme280Comms.WriteRegister(Bme280Comms.Register.Configuration, data); + bme280Comms.WriteRegister((byte)Register.Configuration, data); data = (byte)((byte)configuration.HumidityOverSampling & 0x07); - bme280Comms.WriteRegister(Bme280Comms.Register.Humidity, data); + bme280Comms.WriteRegister((byte)Register.Humidity, data); data = (byte)((((byte)configuration.TemperatureOverSampling << 5) & 0xe0) | (((byte)configuration.PressureOversampling << 2) & 0x1c) | ((byte)configuration.Mode & 0x03)); - bme280Comms.WriteRegister(Bme280Comms.Register.Measurement, data); + bme280Comms.WriteRegister((byte)Register.Measurement, data); } /// @@ -370,7 +308,7 @@ protected void UpdateConfiguration(Configuration configuration) /// public void Reset() { - bme280Comms.WriteRegister(Bme280Comms.Register.Reset, 0xb6); + bme280Comms.WriteRegister((byte)Register.Reset, 0xb6); UpdateConfiguration(configuration); } @@ -389,7 +327,7 @@ public void Reset() protected void ReadCompensationData() { // read the temperature and pressure data into the internal read buffer - bme280Comms.ReadRegisters(0x88, readBuffer.Span[0..24]); + bme280Comms.ReadRegister(0x88, readBuffer.Span[0..24]); // Temperature compensationData.T1 = (ushort)(readBuffer.Span[0] + (readBuffer.Span[1] << 8)); @@ -410,10 +348,10 @@ protected void ReadCompensationData() // non-sequential registers // first one - bme280Comms.ReadRegisters(0xa1, readBuffer.Span[0..1]); + bme280Comms.ReadRegister(0xa1, readBuffer.Span[0..1]); compensationData.H1 = readBuffer.Span[0]; // 2-6 - bme280Comms.ReadRegisters(0xe1, readBuffer.Span[0..7]); + bme280Comms.ReadRegister(0xe1, readBuffer.Span[0..7]); compensationData.H2 = (short)(readBuffer.Span[0] + (readBuffer.Span[1] << 8)); compensationData.H3 = readBuffer.Span[2]; compensationData.H4 = (short)((readBuffer.Span[3] << 4) + (readBuffer.Span[4] & 0xf)); @@ -427,7 +365,7 @@ protected void ReadCompensationData() /// public byte GetChipID() { - bme280Comms.ReadRegisters((byte)Bme280Comms.Register.ChipID, readBuffer.Span[0..1]); + bme280Comms.ReadRegister((byte)Register.ChipID, readBuffer.Span[0..1]); return readBuffer.Span[0]; } diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280Comms.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280Comms.cs deleted file mode 100644 index 5d5ff042d1..0000000000 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280Comms.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; - -namespace Meadow.Foundation.Sensors.Atmospheric -{ - internal abstract class Bme280Comms - { - /// - /// Registers used to control the BME280. - /// - internal enum Register : byte - { - ChipID = 0xd0, - Reset = 0xe0, - Humidity = 0xf2, - Status = 0xf3, - Measurement = 0xf4, - Configuration = 0xf5, - } - - public abstract void WriteRegister(Register register, byte value); - public abstract void ReadRegisters(byte startRegister, Span readBuffer); - } -} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280I2C.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280I2C.cs deleted file mode 100644 index 99c82800d4..0000000000 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280I2C.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using Meadow.Hardware; - -namespace Meadow.Foundation.Sensors.Atmospheric -{ - internal class Bme280I2C : Bme280Comms - { - protected I2cPeripheral i2CPeripheral; - - internal Bme280I2C(II2cBus i2c, byte busAddress) - { - if ((busAddress != 0x76) && (busAddress != 0x77)) - { - throw new ArgumentOutOfRangeException(nameof(busAddress), "Address should be 0x76 or 0x77"); - } - i2CPeripheral = new I2cPeripheral(i2c, busAddress); - } - - public override void ReadRegisters(byte startRegister, Span readBuffer) - { - i2CPeripheral.ReadRegister(startRegister, readBuffer); - } - - public override void WriteRegister(Register register, byte value) - { - i2CPeripheral.WriteRegister((byte)register, value); - } - } -} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280SPI.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280SPI.cs deleted file mode 100644 index d8546153c5..0000000000 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280SPI.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.Linq; -using Meadow.Hardware; - -namespace Meadow.Foundation.Sensors.Atmospheric -{ - internal class Bme280Spi : Bme280Comms - { - ISpiPeripheral spiPeripheral; - - internal Bme280Spi(ISpiBus spi, IDigitalOutputPort? chipSelect = null) - { - spiPeripheral = new SpiPeripheral(spi, chipSelect); - } - - public override void ReadRegisters(byte startRegister, Span readBuffer) - { - spiPeripheral.ReadRegister(startRegister, readBuffer); - - // skip past the byte where we clocked out the register address - for (int i = 1; i < readBuffer.Length; i++) { - readBuffer[i - 1] = readBuffer[i]; - } - } - - public override void WriteRegister(Register register, byte value) - { - spiPeripheral.WriteRegister(((byte)register), value); - } - } -} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Sensors.Atmospheric.Bme280.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Sensors.Atmospheric.Bme280.csproj index b046cdc658..3b63737624 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Sensors.Atmospheric.Bme280.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Sensors.Atmospheric.Bme280.csproj @@ -26,6 +26,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Samples/Bme280_Sample/Bme280_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Samples/Bme280_Sample/Bme280_Sample.csproj index 84fc1b96db..410dc88451 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Samples/Bme280_Sample/Bme280_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Samples/Bme280_Sample/Bme280_Sample.csproj @@ -12,7 +12,7 @@ 8.0 - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Bme68x.Calibration.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Bme68x.Calibration.cs index 27e5cc6e89..07fee937c9 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Bme68x.Calibration.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Bme68x.Calibration.cs @@ -1,4 +1,6 @@ -namespace Meadow.Foundation.Sensors.Atmospheric +using Meadow.Hardware; + +namespace Meadow.Foundation.Sensors.Atmospheric { partial class Bme68x { @@ -41,43 +43,43 @@ internal class Calibration public sbyte ResHeatVal { get; set; } public sbyte RangeSwErr { get; set; } - public void LoadCalibrationDataFromSensor(Bme68xComms sensor) + public void LoadCalibrationDataFromSensor(IByteCommunications byteComms) { // Read temperature calibration data. - T1 = sensor.ReadRegisterAsUShort((byte)Registers.T1); - T2 = (short)sensor.ReadRegisterAsUShort((byte)Registers.T2); - T3 = sensor.ReadRegister((byte)Registers.T3); + T1 = byteComms.ReadRegisterAsUShort((byte)Registers.T1); + T2 = (short)byteComms.ReadRegisterAsUShort((byte)Registers.T2); + T3 = byteComms.ReadRegister((byte)Registers.T3); // Read humidity calibration data. - H1 = (ushort)((sensor.ReadRegister((byte)Registers.H1_MSB) << 4) | (sensor.ReadRegister((byte)Registers.H1_LSB) & 0x0F)); - H2 = (ushort)((sensor.ReadRegister((byte)Registers.H2_MSB) << 4) | (sensor.ReadRegister((byte)Registers.H2_LSB) >> 4)); - H3 = (sbyte)sensor.ReadRegister((byte)Registers.H3); - H4 = (sbyte)sensor.ReadRegister((byte)Registers.H4); - H5 = (sbyte)sensor.ReadRegister((byte)Registers.H5); - H6 = sensor.ReadRegister((byte)Registers.H6); - H7 = (sbyte)(sensor.ReadRegister((byte)Registers.H7)); + H1 = (ushort)((byteComms.ReadRegister((byte)Registers.H1_MSB) << 4) | (byteComms.ReadRegister((byte)Registers.H1_LSB) & 0x0F)); + H2 = (ushort)((byteComms.ReadRegister((byte)Registers.H2_MSB) << 4) | (byteComms.ReadRegister((byte)Registers.H2_LSB) >> 4)); + H3 = (sbyte)byteComms.ReadRegister((byte)Registers.H3); + H4 = (sbyte)byteComms.ReadRegister((byte)Registers.H4); + H5 = (sbyte)byteComms.ReadRegister((byte)Registers.H5); + H6 = byteComms.ReadRegister((byte)Registers.H6); + H7 = (sbyte)(byteComms.ReadRegister((byte)Registers.H7)); // Read pressure calibration data. - P1 = sensor.ReadRegisterAsUShort((byte)Registers.P1_LSB); - P2 = (short)sensor.ReadRegisterAsUShort((byte)Registers.P2_LSB); - P3 = sensor.ReadRegister((byte)Registers.P3); - P4 = (short)sensor.ReadRegisterAsUShort((byte)Registers.P4_LSB); - P5 = (short)sensor.ReadRegisterAsUShort((byte)Registers.P5_LSB); - P6 = sensor.ReadRegister((byte)Registers.P6); - P7 = sensor.ReadRegister((byte)Registers.P7); - P8 = (short)sensor.ReadRegisterAsUShort((byte)Registers.P8_LSB); - P9 = (short)sensor.ReadRegisterAsUShort((byte)Registers.P9_LSB); - P10 = sensor.ReadRegister((byte)Registers.P10); + P1 = byteComms.ReadRegisterAsUShort((byte)Registers.P1_LSB); + P2 = (short)byteComms.ReadRegisterAsUShort((byte)Registers.P2_LSB); + P3 = byteComms.ReadRegister((byte)Registers.P3); + P4 = (short)byteComms.ReadRegisterAsUShort((byte)Registers.P4_LSB); + P5 = (short)byteComms.ReadRegisterAsUShort((byte)Registers.P5_LSB); + P6 = byteComms.ReadRegister((byte)Registers.P6); + P7 = byteComms.ReadRegister((byte)Registers.P7); + P8 = (short)byteComms.ReadRegisterAsUShort((byte)Registers.P8_LSB); + P9 = (short)byteComms.ReadRegisterAsUShort((byte)Registers.P9_LSB); + P10 = byteComms.ReadRegister((byte)Registers.P10); // read gas calibration data. - Gh1 = (sbyte)sensor.ReadRegister((byte)Registers.GH1); - Gh2 = (short)sensor.ReadRegisterAsUShort((byte)Registers.GH2); - Gh3 = (sbyte)sensor.ReadRegister((byte)Registers.GH3); + Gh1 = (sbyte)byteComms.ReadRegister((byte)Registers.GH1); + Gh2 = (short)byteComms.ReadRegisterAsUShort((byte)Registers.GH2); + Gh3 = (sbyte)byteComms.ReadRegister((byte)Registers.GH3); // read heater calibration data - ResHeatRange = (byte)(sensor.ReadRegister(((byte)Registers.RES_HEAT_RANGE) & 0x30) >> 4); - RangeSwErr = (sbyte)(sensor.ReadRegister(((byte)Registers.RANGE_SW_ERR) & 0xF0) >> 4); - ResHeatVal = (sbyte)sensor.ReadRegister((byte)Registers.RES_HEAT_VAL); + ResHeatRange = (byte)(byteComms.ReadRegister(((byte)Registers.RES_HEAT_RANGE) & 0x30) >> 4); + RangeSwErr = (sbyte)(byteComms.ReadRegister(((byte)Registers.RANGE_SW_ERR) & 0xF0) >> 4); + ResHeatVal = (sbyte)byteComms.ReadRegister((byte)Registers.RES_HEAT_VAL); } } } diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Bme68x.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Bme68x.Enums.cs index 7e3399012c..cd479c7b00 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Bme68x.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Bme68x.Enums.cs @@ -3,7 +3,7 @@ partial class Bme68x { /// - /// Valid addresses for the sensor + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Bme68x.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Bme68x.cs index 49a43a4116..6a7f3c4f0c 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Bme68x.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Bme68x.cs @@ -21,7 +21,7 @@ public abstract partial class Bme68x : RelativeHumidity? Humidity, Pressure? Pressure, Resistance? GasResistance)>, - ITemperatureSensor, IHumiditySensor, IBarometricPressureSensor + ITemperatureSensor, IHumiditySensor, IBarometricPressureSensor, ISpiPeripheral, II2cPeripheral { /// /// Raised when the temperature value changes @@ -85,10 +85,10 @@ public HeaterProfileType HeaterProfile throw new ArgumentOutOfRangeException(nameof(value)); } - var profile = sensor.ReadRegister((byte)Registers.CTRL_GAS_1); + var profile = busComms.ReadRegister((byte)Registers.CTRL_GAS_1); profile = (byte)((profile & 0x0F) | (byte)value); - sensor.WriteRegister((byte)Registers.CTRL_GAS_1, profile); + busComms.WriteRegister((byte)Registers.CTRL_GAS_1, profile); heaterProfile = value; } @@ -109,11 +109,11 @@ public FilteringMode FilterMode throw new ArgumentOutOfRangeException(nameof(value)); } - var filter = sensor.ReadRegister((byte)Registers.CONFIG); + var filter = busComms.ReadRegister((byte)Registers.CONFIG); byte mask = 0x1C; filter = (byte)((filter & (byte)~mask) | (byte)value << 2); - sensor.WriteRegister((byte)Registers.CONFIG, filter); + busComms.WriteRegister((byte)Registers.CONFIG, filter); filterMode = value; } } @@ -127,11 +127,11 @@ public bool HeaterIsEnabled get => heaterIsEnabled; set { - var heaterStatus = sensor.ReadRegister((byte)Registers.CTRL_GAS_0); + var heaterStatus = busComms.ReadRegister((byte)Registers.CTRL_GAS_0); var mask = 0x08; heaterStatus = (byte)((heaterStatus & (byte)~mask) | Convert.ToByte(!value) << 3); - sensor.WriteRegister((byte)Registers.CTRL_GAS_0, heaterStatus); + busComms.WriteRegister((byte)Registers.CTRL_GAS_0, heaterStatus); heaterIsEnabled = value; } } @@ -145,24 +145,53 @@ public bool GasConversionIsEnabled get => gasConversionIsEnabled; set { - var gasConversion = sensor.ReadRegister((byte)Registers.CTRL_GAS_1); + var gasConversion = busComms.ReadRegister((byte)Registers.CTRL_GAS_1); byte mask = 0x10; gasConversion = (byte)((gasConversion & (byte)~mask) | Convert.ToByte(value) << 4); - sensor.WriteRegister((byte)Registers.CTRL_GAS_1, gasConversion); + busComms.WriteRegister((byte)Registers.CTRL_GAS_1, gasConversion); gasConversionIsEnabled = value; } } bool gasConversionIsEnabled = false; + /// + /// The default SPI bus speed for the device + /// + public Frequency DefaultSpiBusSpeed => new Frequency(10000, Frequency.UnitType.Kilohertz); + + /// + /// The SPI bus speed for the device + /// + public Frequency SpiBusSpeed + { + get => ((Bme68xSpiCommunications)busComms).BusSpeed; + set => ((Bme68xSpiCommunications)busComms).BusSpeed = value; + } + + /// + /// The default SPI bus mode for the device + /// + public SpiClockConfiguration.Mode DefaultSpiBusMode => SpiClockConfiguration.Mode.Mode0; + + /// + /// The SPI bus mode for the device + /// + public SpiClockConfiguration.Mode SpiBusMode + { + get => ((Bme68xSpiCommunications)busComms).BusMode; + set => ((Bme68xSpiCommunications)busComms).BusMode = value; + } + + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + /// /// Communication bus used to read and write to the BME68x sensor /// - /// - /// The BME has both I2C and SPI interfaces. The ICommunicationBus allows the - /// selection to be made in the constructor. - /// - readonly Bme68xComms sensor; + readonly IByteCommunications busComms; /// /// The current temperature @@ -204,11 +233,11 @@ public bool GasConversionIsEnabled /// Creates a new instance of the BME68x class /// /// I2C Bus to use for communicating with the sensor - /// I2C address of the sensor. + /// I2C address protected Bme68x(II2cBus i2cBus, byte address = (byte)Addresses.Default) { configuration = new Configuration(); - sensor = new Bme68xI2C(i2cBus, address); + busComms = new I2cCommunications(i2cBus, address); Initialize(); } @@ -230,11 +259,11 @@ protected Bme68x(ISpiBus spiBus, IPin chipSelectPin) : /// The BMP68x configuration (optional) protected Bme68x(ISpiBus spiBus, IDigitalOutputPort chipSelectPort, Configuration? configuration = null) { - sensor = new Bme68xSPI(spiBus, chipSelectPort); + busComms = new Bme68xSpiCommunications(spiBus, chipSelectPort, DefaultSpiBusSpeed, DefaultSpiBusMode); this.configuration = configuration ?? new Configuration(); - byte value = sensor.ReadRegister((byte)Registers.STATUS); - sensor.WriteRegister((byte)Registers.STATUS, value); + byte value = busComms.ReadRegister((byte)Registers.STATUS); + busComms.WriteRegister((byte)Registers.STATUS, value); Initialize(); } @@ -247,17 +276,17 @@ protected void Initialize() Reset(); calibration = new Calibration(); - calibration.LoadCalibrationDataFromSensor(sensor); + calibration.LoadCalibrationDataFromSensor(busComms); // Init the temp and pressure registers var status = (byte)((((byte)configuration.TemperatureOversample << 5) & 0xe0) | (((byte)configuration.PressureOversample << 2) & 0x1c)); - sensor.WriteRegister((byte)Registers.CTRL_MEAS, status); + busComms.WriteRegister((byte)Registers.CTRL_MEAS, status); // Init the humidity registers status = (byte)((byte)configuration.HumidityOversample & 0x07); - sensor.WriteRegister((byte)Registers.CTRL_HUM, status); + busComms.WriteRegister((byte)Registers.CTRL_HUM, status); //enable gas readings GasConversionIsEnabled = true; @@ -268,7 +297,7 @@ protected void Initialize() /// public void Reset() { - sensor.WriteRegister((byte)Registers.RESET, 0xB6); + busComms.WriteRegister((byte)Registers.RESET, 0xB6); } /// @@ -284,8 +313,8 @@ public void ConfigureHeatingProfile(HeaterProfileType profile, Units.Temperature var heaterResistance = CalculateHeaterResistance(targetTemperature, ambientTemperature); var heaterDuration = CalculateHeaterDuration(duration); - sensor.WriteRegister((byte)(Registers.GAS_WAIT_0 + (byte)profile), heaterDuration); - sensor.WriteRegister((byte)(Registers.RES_HEAT_0 + (byte)profile), heaterResistance); + busComms.WriteRegister((byte)(Registers.GAS_WAIT_0 + (byte)profile), heaterDuration); + busComms.WriteRegister((byte)(Registers.RES_HEAT_0 + (byte)profile), heaterResistance); // cache heater configuration if (heaterConfigs.Exists(config => config.HeaterProfile == profile)) @@ -302,7 +331,7 @@ public void ConfigureHeatingProfile(HeaterProfileType profile, Units.Temperature /// The power mode public PowerMode GetPowerMode() { - var status = sensor.ReadRegister((byte)Registers.CTRL_MEAS); + var status = busComms.ReadRegister((byte)Registers.CTRL_MEAS); return (PowerMode)(status & 0x03); } @@ -313,10 +342,10 @@ public PowerMode GetPowerMode() /// The to set. public void SetPowerMode(PowerMode powerMode) { - var status = sensor.ReadRegister((byte)Registers.CTRL_MEAS); + var status = busComms.ReadRegister((byte)Registers.CTRL_MEAS); byte mask = 0x03; status = (byte)((status & (byte)~mask) | (byte)powerMode); - sensor.WriteRegister((byte)Registers.CTRL_MEAS, status); + busComms.WriteRegister((byte)Registers.CTRL_MEAS, status); } /// @@ -386,42 +415,42 @@ protected override void RaiseEventsAndNotify(IChangeResult<(Units.Temperature? T /// Reads data from the sensor /// /// The latest sensor reading - protected override async Task<(Units.Temperature? Temperature, RelativeHumidity? Humidity, Pressure? Pressure, Resistance? GasResistance)> ReadSensor() + protected override Task<(Units.Temperature? Temperature, RelativeHumidity? Humidity, Pressure? Pressure, Resistance? GasResistance)> ReadSensor() { configuration.TemperatureOversample = TemperatureOversampleMode; configuration.PressureOversample = PressureOversampleMode; configuration.HumidityOversample = HumidityOversampleMode; - return await Task.Run(() => + return Task.Run(() => { - (Units.Temperature Temperature, RelativeHumidity Humidity, Pressure Pressure, Resistance GasResistance) conditions; + (Units.Temperature? Temperature, RelativeHumidity? Humidity, Pressure? Pressure, Resistance? GasResistance) conditions; //set onetime measurement SetPowerMode(PowerMode.Forced); // Read the current control register - var status = sensor.ReadRegister((byte)Registers.CTRL_MEAS); + var status = busComms.ReadRegister((byte)Registers.CTRL_MEAS); // Force a sample status = BitHelpers.SetBit(status, 0x00, true); - sensor.WriteRegister((byte)Registers.CTRL_MEAS, status); + busComms.WriteRegister((byte)Registers.CTRL_MEAS, status); // Wait for the sample to be taken. do { - status = sensor.ReadRegister((byte)Registers.CTRL_MEAS); + status = busComms.ReadRegister((byte)Registers.CTRL_MEAS); } while (BitHelpers.GetBitValue(status, 0x00)); //read temperature byte[] data = new byte[3]; - sensor.ReadRegister((byte)Registers.TEMPDATA, data); + busComms.ReadRegister((byte)Registers.TEMPDATA, data); var rawTemperature = (data[0] << 12) | (data[1] << 4) | ((data[2] >> 4) & 0x0); //read humidity - var rawHumidity = sensor.ReadRegisterAsUShort((byte)Registers.HUMIDITYDATA, ByteOrder.BigEndian); + var rawHumidity = busComms.ReadRegisterAsUShort((byte)Registers.HUMIDITYDATA, ByteOrder.BigEndian); //read pressure - sensor.ReadRegister((byte)Registers.PRESSUREDATA, data); + busComms.ReadRegister((byte)Registers.PRESSUREDATA, data); var rawPressure = (data[0] << 12) | (data[1] << 4) | ((data[2] >> 4) & 0x0); if (GasConversionIsEnabled) @@ -429,8 +458,8 @@ protected override void RaiseEventsAndNotify(IChangeResult<(Units.Temperature? T Thread.Sleep(GetMeasurementDuration(HeaterProfile)); // Read 10 bit gas resistance value from registers - var gasResRaw = sensor.ReadRegister((byte)Registers.GAS_RES); - var gasRange = sensor.ReadRegister((byte)Registers.GAS_RANGE); + var gasResRaw = busComms.ReadRegister((byte)Registers.GAS_RES); + var gasRange = busComms.ReadRegister((byte)Registers.GAS_RANGE); var gasRes = (ushort)((ushort)(gasResRaw << 2) + (byte)(gasRange >> 6)); gasRange &= 0x0F; conditions.GasResistance = CalculateGasResistance(gasRes, gasRange); @@ -444,7 +473,6 @@ protected override void RaiseEventsAndNotify(IChangeResult<(Units.Temperature? T conditions.Pressure = CompensatePressure(rawPressure); conditions.Humidity = CompensateHumidity(rawHumidity); - return conditions; }); } diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Bme68xComms.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Bme68xComms.cs deleted file mode 100644 index 37da523603..0000000000 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Bme68xComms.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; - -namespace Meadow.Foundation.Sensors.Atmospheric -{ - internal abstract class Bme68xComms - { - public abstract void WriteRegister(byte address, byte value); - - public abstract void ReadRegister(byte address, Span readBuffer); - - public abstract byte ReadRegister(byte address); - - public abstract ushort ReadRegisterAsUShort(byte address, ByteOrder order = ByteOrder.LittleEndian); - } -} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Bme68xI2C.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Bme68xI2C.cs deleted file mode 100644 index b281ee5d1e..0000000000 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Bme68xI2C.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using Meadow.Hardware; - -namespace Meadow.Foundation.Sensors.Atmospheric -{ - internal class Bme68xI2C : Bme68xComms - { - protected I2cPeripheral i2CPeripheral; - - internal Bme68xI2C(II2cBus i2c, byte busAddress) - { - i2CPeripheral = new I2cPeripheral(i2c, busAddress); - } - - public override byte ReadRegister(byte address) => i2CPeripheral.ReadRegister(address); - - public override ushort ReadRegisterAsUShort(byte address, ByteOrder order = ByteOrder.LittleEndian) => i2CPeripheral.ReadRegisterAsUShort(address, order); - - public override void ReadRegister(byte address, Span readBuffer) - { - i2CPeripheral.ReadRegister(address, readBuffer); - } - - public override void WriteRegister(byte register, byte value) - { - i2CPeripheral.WriteRegister(register, value); - } - } -} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Bme68xSPI.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Bme68xSpiCommunications.cs similarity index 79% rename from Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Bme68xSPI.cs rename to Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Bme68xSpiCommunications.cs index 39bc03ceda..e82dc1b9d9 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Bme68xSPI.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Bme68xSpiCommunications.cs @@ -1,9 +1,10 @@ -using System; -using Meadow.Hardware; +using Meadow.Hardware; +using Meadow.Units; +using System; namespace Meadow.Foundation.Sensors.Atmospheric { - internal class Bme68xSPI : Bme68xComms + internal class Bme68xSpiCommunications : SpiCommunications { /// /// Register pages (for SPI only) @@ -26,13 +27,11 @@ internal enum SpiRegisterPage : byte Page1 = 0x00, } - ISpiPeripheral spiPeripheral; - SpiRegisterPage currentPage = SpiRegisterPage.Page1; - internal Bme68xSPI(ISpiBus spi, IDigitalOutputPort? chipSelect = null) + internal Bme68xSpiCommunications(ISpiBus spiBus, IDigitalOutputPort? chipSelect, Frequency busSpeed, SpiClockConfiguration.Mode busMode) + : base(spiBus, chipSelect, busSpeed, busMode, 32, 32) { - spiPeripheral = new SpiPeripheral(spi, chipSelect, 32, 32); } public override byte ReadRegister(byte address) @@ -42,7 +41,7 @@ public override byte ReadRegister(byte address) //adjust register for paging if (address > 0x7F) { address -= 0x7F; } - return spiPeripheral.ReadRegister(address); + return base.ReadRegister(address); } public override ushort ReadRegisterAsUShort(byte address, ByteOrder order = ByteOrder.LittleEndian) @@ -52,7 +51,7 @@ public override ushort ReadRegisterAsUShort(byte address, ByteOrder order = Byte //adjust register for paging if (address > 0x7F) { address -= 0x7F; } - return spiPeripheral.ReadRegisterAsUShort(address, order); + return base.ReadRegisterAsUShort(address, order); } public override void ReadRegister(byte startRegister, Span readBuffer) @@ -62,9 +61,7 @@ public override void ReadRegister(byte startRegister, Span readBuffer) //adjust register for paging if (startRegister > 0x7F) { startRegister -= 0x7F; } - spiPeripheral.ReadRegister(startRegister, readBuffer); - - return; + base.ReadRegister(startRegister, readBuffer); } public override void WriteRegister(byte register, byte value) @@ -74,7 +71,7 @@ public override void WriteRegister(byte register, byte value) //adjust register for paging if (register > 0x7F) { register -= 0x7F; } - spiPeripheral.WriteRegister(register, value); + base.WriteRegister(register, value); } void SetPageForRegister(byte register) @@ -85,7 +82,7 @@ void SetPageForRegister(byte register) //swap the page currentPage = (currentPage == SpiRegisterPage.Page0) ? SpiRegisterPage.Page1 : SpiRegisterPage.Page0; //write the page to the status register - spiPeripheral.WriteRegister(0x73, (byte)currentPage); + base.WriteRegister(0x73, (byte)currentPage); } } diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Drivers/Bme680.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Drivers/Bme680.cs index 2441006989..5024dc58e4 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Drivers/Bme680.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Drivers/Bme680.cs @@ -3,7 +3,7 @@ namespace Meadow.Foundation.Sensors.Atmospheric { /// - /// BME680 Temperature, Pressure, Humidity and gas sensor + /// BME680 Temperature, Pressure, Humidity and gas busComms /// /// /// This class implements the functionality necessary to read the temperature, pressure, humidity and VOS @@ -13,8 +13,8 @@ public partial class Bme680 : Bme68x /// /// Creates a new instance of the Bme680 class /// - /// I2C Bus to use for communicating with the sensor - /// I2C address of the sensor + /// I2C Bus to use for communicating with the busComms + /// I2C address of the busComms public Bme680(II2cBus i2cBus, byte address = (byte)Addresses.Default) : base(i2cBus, address) { } diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Drivers/Bme688.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Drivers/Bme688.cs index 1d4d20cc49..388dc6e385 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Drivers/Bme688.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Drivers/Bme688.cs @@ -3,7 +3,7 @@ namespace Meadow.Foundation.Sensors.Atmospheric { /// - /// BME688 Temperature, Pressure, Humidity and gas sensor + /// BME688 Temperature, Pressure, Humidity and gas busComms /// /// /// This class implements the functionality necessary to read the temperature, pressure, humidity and VOS @@ -13,8 +13,8 @@ public partial class Bme688 : Bme68x /// /// Creates a new instance of the BME688 class /// - /// I2C Bus to use for communicating with the sensor - /// I2C address of the sensor + /// I2C Bus to use for communicating with the busComms + /// I2C address of the busComms public Bme688(II2cBus i2cBus, byte address = (byte)Addresses.Default) : base(i2cBus, address) { } diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Sensors.Atmospheric.Bme68x.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Sensors.Atmospheric.Bme68x.csproj index e6c1297e25..8df91d23c0 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Sensors.Atmospheric.Bme68x.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Driver/Sensors.Atmospheric.Bme68x.csproj @@ -21,6 +21,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Samples/Bme680_Sample/Bme680_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Samples/Bme680_Sample/Bme680_Sample.csproj index 83f1e815c1..fa9f774f7d 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Samples/Bme680_Sample/Bme680_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Samples/Bme680_Sample/Bme680_Sample.csproj @@ -13,7 +13,7 @@ 8.0 - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Samples/Bme680_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Samples/Bme680_Sample/MeadowApp.cs index 8348ce5884..a8cdef775a 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Samples/Bme680_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Samples/Bme680_Sample/MeadowApp.cs @@ -32,7 +32,7 @@ public override Task Initialize() //c# 8 pattern match syntax. checks for !null and assigns var. if (result.Old?.Temperature is { } oldTemp && result.Old?.Humidity is { } oldHumidity && - result.New.Temperature is { } newTemp && + result.New.Temperature is { } newTemp && result.New.Humidity is { } newHumidity) { return ((newTemp - oldTemp).Abs().Celsius > 0.5 && @@ -44,7 +44,7 @@ result.New.Temperature is { } newTemp && sensor?.Subscribe(consumer); - if(sensor != null) + if (sensor != null) { sensor.Updated += (sender, result) => { @@ -67,7 +67,7 @@ result.New.Temperature is { } newTemp && void EnableGasHeater() { - if(sensor != null) + if (sensor != null) { sensor.GasConversionIsEnabled = true; sensor.HeaterIsEnabled = true; @@ -94,7 +94,7 @@ void CreateI2CSensor() async Task ReadConditions() { - if(sensor == null) { return; } + if (sensor == null) { return; } var (Temperature, Humidity, Pressure, Resistance) = await sensor.Read(); diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Samples/Bme688_Sample/Bme688_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Samples/Bme688_Sample/Bme688_Sample.csproj index 83f1e815c1..fa9f774f7d 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Samples/Bme688_Sample/Bme688_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Samples/Bme688_Sample/Bme688_Sample.csproj @@ -13,7 +13,7 @@ 8.0 - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Samples/Bme688_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Samples/Bme688_Sample/MeadowApp.cs index 2ad5b80e25..176ee63502 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Samples/Bme688_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme68x/Samples/Bme688_Sample/MeadowApp.cs @@ -33,7 +33,7 @@ public override Task Initialize() //c# 8 pattern match syntax. checks for !null and assigns var. if (result.Old?.Temperature is { } oldTemp && result.Old?.Humidity is { } oldHumidity && - result.New.Temperature is { } newTemp && + result.New.Temperature is { } newTemp && result.New.Humidity is { } newHumidity) { return ((newTemp - oldTemp).Abs().Celsius > 0.5 && @@ -45,7 +45,7 @@ result.New.Temperature is { } newTemp && sensor?.Subscribe(consumer); - if(sensor != null) + if (sensor != null) { sensor.Updated += (sender, result) => { @@ -95,7 +95,7 @@ void CreateI2CSensor() async Task ReadConditions() { - if(sensor == null) { return; } + if (sensor == null) { return; } var (Temperature, Humidity, Pressure, Resistance) = await sensor.Read(); diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmp085/Driver/Bmp085.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmp085/Driver/Bmp085.Enums.cs index 7d5e91e036..d7c56df4b7 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmp085/Driver/Bmp085.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmp085/Driver/Bmp085.Enums.cs @@ -3,7 +3,7 @@ public partial class Bmp085 { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmp085/Driver/Bmp085.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmp085/Driver/Bmp085.cs index 4a071ad2a7..c1dc593e84 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmp085/Driver/Bmp085.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmp085/Driver/Bmp085.cs @@ -1,9 +1,9 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using Meadow.Hardware; +using Meadow.Hardware; using Meadow.Peripherals.Sensors; using Meadow.Units; +using System; +using System.Threading; +using System.Threading.Tasks; namespace Meadow.Foundation.Sensors.Atmospheric { @@ -12,23 +12,28 @@ namespace Meadow.Foundation.Sensors.Atmospheric /// public partial class Bmp085 : ByteCommsSensorBase<(Units.Temperature? Temperature, Pressure? Pressure)>, - ITemperatureSensor, IBarometricPressureSensor + ITemperatureSensor, IBarometricPressureSensor, II2cPeripheral { /// /// Raised when the temperature value changes /// public event EventHandler> TemperatureUpdated = delegate { }; - + /// /// Raised when the pressure value changes /// public event EventHandler> PressureUpdated = delegate { }; - // Oversampling for measurements. Please see the datasheet for this sensor for more information. - byte oversamplingSetting; + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + + readonly byte oversamplingSetting; - // These wait times correspond to the oversampling settings. - // Please see the datasheet for this sensor for more information. + /// + /// These wait times correspond to the oversampling settings + /// readonly byte[] pressureWaitTime = { 5, 8, 14, 26 }; // Calibration data backing stores @@ -45,12 +50,12 @@ public partial class Bmp085 : private short _md; /// - /// Last value read from the Pressure sensor. + /// Last value read from the Pressure sensor /// public Units.Temperature? Temperature => Conditions.Temperature; /// - /// Last value read from the Pressure sensor. + /// Last value read from the Pressure sensor /// public Pressure? Pressure => Conditions.Pressure; @@ -87,13 +92,13 @@ protected override void RaiseEventsAndNotify(IChangeResult<(Units.Temperature? T } /// - /// Calculates the compensated pressure and temperature. + /// Calculates the compensated pressure and temperature /// protected override Task<(Units.Temperature? Temperature, Pressure? Pressure)> ReadSensor() { (Units.Temperature? Temperature, Pressure? Pressure) conditions; - long x1, x2, x3, b3, b4, b5, b6, b7, p; + long x1, x2, x3, b4, b5, b6, b7, p; long ut = ReadUncompensatedTemperature(); @@ -111,24 +116,15 @@ protected override void RaiseEventsAndNotify(IChangeResult<(Units.Temperature? T x1 = (_b2 * (b6 * b6 >> 12)) >> 11; x2 = _ac2 * b6 >> 11; x3 = x1 + x2; - - switch (oversamplingSetting) + var b3 = oversamplingSetting switch { - case 0: - b3 = ((_ac1 * 4 + x3) + 2) >> 2; - break; - case 1: - b3 = ((_ac1 * 4 + x3) + 2) >> 1; - break; - case 2: - b3 = ((_ac1 * 4 + x3) + 2); - break; - case 3: - b3 = ((_ac1 * 4 + x3) + 2) << 1; - break; - default: - throw new Exception("Oversampling setting must be 0-3"); - } + 0 => (_ac1 * 4 + x3 + 2) >> 2, + 1 => (_ac1 * 4 + x3 + 2) >> 1, + 2 => (_ac1 * 4 + x3 + 2), + 3 => (_ac1 * 4 + x3 + 2) << 1, + _ => throw new Exception("Oversampling setting must be 0-3"), + }; + x1 = _ac3 * b6 >> 13; x2 = (_b1 * (b6 * b6 >> 12)) >> 16; x3 = ((x1 + x2) + 2) >> 2; @@ -148,53 +144,34 @@ protected override void RaiseEventsAndNotify(IChangeResult<(Units.Temperature? T private long ReadUncompensatedTemperature() { - // write register address - // TODO: delete after validating - //Peripheral.WriteBytes(new byte[] { 0xF4, 0x2E }); WriteBuffer.Span[0] = 0xf4; WriteBuffer.Span[1] = 0x2e; - Peripheral?.Write(WriteBuffer.Span[0..2]); + BusComms?.Write(WriteBuffer.Span[0..2]); - // Required as per datasheet. Thread.Sleep(5); - // write register address - // TODO: Delete after validating - //Peripheral.WriteBytes(new byte[] { 0xF6 }); WriteBuffer.Span[0] = 0xf6; - Peripheral?.Write(WriteBuffer.Span[0]); + BusComms?.Write(WriteBuffer.Span[0]); - // get MSB and LSB result - // TODO: Delete after validating - //byte[] data = new byte[2]; - //data = Peripheral.ReadBytes(2); - Peripheral?.Read(ReadBuffer.Span[0..2]); + BusComms?.Read(ReadBuffer.Span[0..2]); - return ((ReadBuffer.Span[0] << 8) | ReadBuffer.Span[1]); + return (ReadBuffer.Span[0] << 8) | ReadBuffer.Span[1]; } private long ReadUncompensatedPressure() { - // write register address - // TODO: Delete after validating - //Peripheral.WriteBytes(new byte[] { 0xF4, (byte)(0x34 + (oversamplingSetting << 6)) }); WriteBuffer.Span[0] = 0xf4; WriteBuffer.Span[1] = (byte)(0x34 + (oversamplingSetting << 6)); - // insert pressure waittime using oversampling setting as index. Thread.Sleep(pressureWaitTime[oversamplingSetting]); - // get MSB and LSB result - // TODO: delete after validating - //byte[] data = new byte[3]; - //data = Peripheral.ReadRegisters(0xF6, 3); - Peripheral?.ReadRegister(0xf6, ReadBuffer.Span[0..3]); + BusComms?.ReadRegister(0xf6, ReadBuffer.Span[0..3]); return ((ReadBuffer.Span[0] << 16) | (ReadBuffer.Span[1] << 8) | (ReadBuffer.Span[2])) >> (8 - oversamplingSetting); } /// - /// Retrieves the factory calibration data stored in the sensor. + /// Retrieves the factory calibration data stored in the sensor /// private void GetCalibrationData() { @@ -213,14 +190,7 @@ private void GetCalibrationData() private short ReadShort(byte address) { - // TODO: i think we already have a method that does this. I'm just not sure - // which endian it is. not sure what the last statement here is dooing - - // get MSB and LSB result - // TODO: delete after validating - //byte[] data = new byte[2]; - //data = Peripheral.ReadRegisters(address, 2); - Peripheral?.ReadRegister(address, ReadBuffer.Span[0..2]); + BusComms?.ReadRegister(address, ReadBuffer.Span[0..2]); return (short)((ReadBuffer.Span[0] << 8) | ReadBuffer.Span[1]); } @@ -231,4 +201,4 @@ private short ReadShort(byte address) async Task ISensor.Read() => (await Read()).Pressure.Value; } -} +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmp085/Driver/Sensors.Atmospheric.Bmp085.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmp085/Driver/Sensors.Atmospheric.Bmp085.csproj index fbd33386c7..295379a480 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmp085/Driver/Sensors.Atmospheric.Bmp085.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmp085/Driver/Sensors.Atmospheric.Bmp085.csproj @@ -16,14 +16,11 @@ Bosch BMP085 I2C barometric pressure sensor enable - - 8.0 - - - 8.0 + + 10.0 - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmp085/Samples/Bmp085_Sample/Bmp085_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmp085/Samples/Bmp085_Sample/Bmp085_Sample.csproj index 97286583d6..c0fa8e1c7f 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmp085/Samples/Bmp085_Sample/Bmp085_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmp085/Samples/Bmp085_Sample/Bmp085_Sample.csproj @@ -16,7 +16,7 @@ 8.0 - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmp180/Driver/Bmp180.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmp180/Driver/Bmp180.Enums.cs index 5e165926b6..8dd4755e8a 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmp180/Driver/Bmp180.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmp180/Driver/Bmp180.Enums.cs @@ -2,42 +2,42 @@ { public partial class Bmp180 { - /// - /// Valid addresses for the sensor - /// - public enum Addresses : byte - { - /// - /// Bus address 0x77 - /// - Address_0x77 = 0x77, - /// - /// Default bus address - /// - Default = Address_0x77 - } + /// + /// Valid I2C addresses for the sensor + /// + public enum Addresses : byte + { + /// + /// Bus address 0x77 + /// + Address_0x77 = 0x77, + /// + /// Default bus address + /// + Default = Address_0x77 + } - /// - /// BMP180 device mode - /// - public enum DeviceMode - { - /// - /// Ultra low power mode - /// - UltraLowPower = 0, - /// - /// Standard / normal mode - /// - Standard = 1, - /// - /// High resolution mode - /// - HighResolution = 2, - /// - /// Ultra high resolution mode - /// - UltraHighResolution = 3 - } - } + /// + /// BMP180 device mode + /// + public enum DeviceMode + { + /// + /// Ultra low power mode + /// + UltraLowPower = 0, + /// + /// Standard / normal mode + /// + Standard = 1, + /// + /// High resolution mode + /// + HighResolution = 2, + /// + /// Ultra high resolution mode + /// + UltraHighResolution = 3 + } + } } \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmp180/Driver/Bmp180.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmp180/Driver/Bmp180.cs index 407e13a8e1..45b4b686fa 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmp180/Driver/Bmp180.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmp180/Driver/Bmp180.cs @@ -1,9 +1,9 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using Meadow.Hardware; +using Meadow.Hardware; using Meadow.Peripherals.Sensors; using Meadow.Units; +using System; +using System.Threading; +using System.Threading.Tasks; namespace Meadow.Foundation.Sensors.Atmospheric { @@ -12,22 +12,26 @@ namespace Meadow.Foundation.Sensors.Atmospheric /// public partial class Bmp180 : ByteCommsSensorBase<(Units.Temperature? Temperature, Pressure? Pressure)>, - ITemperatureSensor, IBarometricPressureSensor + ITemperatureSensor, IBarometricPressureSensor, II2cPeripheral { /// /// Raised when the temperature value changes /// public event EventHandler> TemperatureUpdated = delegate { }; - + /// /// Raised when the pressure value changes /// public event EventHandler> PressureUpdated = delegate { }; - // Oversampling for measurements - private byte oversamplingSetting; + /// + /// Oversampling for measurements + /// + private readonly byte oversamplingSetting; - // These wait times correspond to the oversampling settings + /// + /// These wait times correspond to the oversampling settings + /// private readonly byte[] pressureWaitTime = { 5, 8, 14, 26 }; // Calibration data backing stores @@ -54,9 +58,9 @@ public partial class Bmp180 : public Pressure? Pressure => Conditions.Pressure; /// - /// Default SPI bus speed + /// The default I2C address for the peripheral /// - public static Frequency DEFAULT_SPEED = new Frequency(40000, Frequency.UnitType.Kilohertz); + public byte DefaultI2cAddress => (byte)Addresses.Default; /// /// Create a new BMP180 object @@ -95,113 +99,79 @@ protected override void RaiseEventsAndNotify(IChangeResult<(Units.Temperature? T /// protected override Task<(Units.Temperature? Temperature, Pressure? Pressure)> ReadSensor() { - return Task.Run(() => + (Units.Temperature? Temperature, Pressure? Pressure) conditions; + + long x1, x2, x3, b4, b5, b6, b7, p; + long ut = ReadUncompensatedTemperature(); + long up = ReadUncompensatedPressure(); + + // calculate the compensated temperature + x1 = (ut - _ac6) * _ac5 >> 15; + x2 = (_mc << 11) / (x1 + _md); + b5 = x1 + x2; + + conditions.Temperature = new Units.Temperature((float)((b5 + 8) >> 4) / 10, Units.Temperature.UnitType.Celsius); + + // calculate the compensated pressure + b6 = b5 - 4000; + x1 = (_b2 * (b6 * b6 >> 12)) >> 11; + x2 = _ac2 * b6 >> 11; + x3 = x1 + x2; + var b3 = oversamplingSetting switch { - (Units.Temperature? Temperature, Pressure? Pressure) conditions; - - long x1, x2, x3, b3, b4, b5, b6, b7, p; - - long ut = ReadUncompensatedTemperature(); - - long up = ReadUncompensatedPressure(); - - // calculate the compensated temperature - x1 = (ut - _ac6) * _ac5 >> 15; - x2 = (_mc << 11) / (x1 + _md); - b5 = x1 + x2; - - conditions.Temperature = new Units.Temperature((float)((b5 + 8) >> 4) / 10, Units.Temperature.UnitType.Celsius); - - // calculate the compensated pressure - b6 = b5 - 4000; - x1 = (_b2 * (b6 * b6 >> 12)) >> 11; - x2 = _ac2 * b6 >> 11; - x3 = x1 + x2; - - switch (oversamplingSetting) - { - case 0: - b3 = ((_ac1 * 4 + x3) + 2) >> 2; - break; - case 1: - b3 = ((_ac1 * 4 + x3) + 2) >> 1; - break; - case 2: - b3 = ((_ac1 * 4 + x3) + 2); - break; - case 3: - b3 = ((_ac1 * 4 + x3) + 2) << 1; - break; - default: - throw new Exception("Oversampling setting must be 0-3"); - } - x1 = _ac3 * b6 >> 13; - x2 = (_b1 * (b6 * b6 >> 12)) >> 16; - x3 = ((x1 + x2) + 2) >> 2; - b4 = (_ac4 * (x3 + 32768)) >> 15; - b7 = (up - b3) * (50000 >> oversamplingSetting); - p = (b7 < 0x80000000 ? (b7 * 2) / b4 : (b7 / b4) * 2); - x1 = (p >> 8) * (p >> 8); - x1 = (x1 * 3038) >> 16; - x2 = (-7357 * p) >> 16; - - int value = (int)(p + ((x1 + x2 + 3791) >> 4)); - - conditions.Pressure = new Pressure(value, Units.Pressure.UnitType.Pascal); - - return conditions; - }); + 0 => ((_ac1 * 4 + x3) + 2) >> 2, + 1 => ((_ac1 * 4 + x3) + 2) >> 1, + 2 => ((_ac1 * 4 + x3) + 2), + 3 => ((_ac1 * 4 + x3) + 2) << 1, + _ => throw new Exception("Oversampling setting must be 0-3"), + }; + x1 = _ac3 * b6 >> 13; + x2 = (_b1 * (b6 * b6 >> 12)) >> 16; + x3 = ((x1 + x2) + 2) >> 2; + b4 = (_ac4 * (x3 + 32768)) >> 15; + b7 = (up - b3) * (50000 >> oversamplingSetting); + p = (b7 < 0x80000000 ? (b7 * 2) / b4 : (b7 / b4) * 2); + x1 = (p >> 8) * (p >> 8); + x1 = (x1 * 3038) >> 16; + x2 = (-7357 * p) >> 16; + + int value = (int)(p + ((x1 + x2 + 3791) >> 4)); + + conditions.Pressure = new Pressure(value, Units.Pressure.UnitType.Pascal); + + return Task.FromResult(conditions); } private long ReadUncompensatedTemperature() { - // write register address - // TODO: delete after validating - //Peripheral.WriteBytes(new byte[] { 0xF4, 0x2E }); WriteBuffer.Span[0] = 0xf4; WriteBuffer.Span[1] = 0x2e; - Peripheral?.Write(WriteBuffer.Span[0..2]); + BusComms?.Write(WriteBuffer.Span[0..2]); - // Required as per datasheet. Thread.Sleep(5); - // write register address - // TODO: Delete after validating - //Peripheral.WriteBytes(new byte[] { 0xF6 }); WriteBuffer.Span[0] = 0xf6; - Peripheral?.Write(WriteBuffer.Span[0]); + BusComms?.Write(WriteBuffer.Span[0]); - // get MSB and LSB result - // TODO: Delete after validating - //byte[] data = new byte[2]; - //data = Peripheral.ReadBytes(2); - Peripheral?.Read(ReadBuffer.Span[0..2]); + BusComms?.Read(ReadBuffer.Span[0..2]); return ((ReadBuffer.Span[0] << 8) | ReadBuffer.Span[1]); } private long ReadUncompensatedPressure() { - // write register address - // TODO: Delete after validating - //Peripheral.WriteBytes(new byte[] { 0xF4, (byte)(0x34 + (oversamplingSetting << 6)) }); WriteBuffer.Span[0] = 0xf4; WriteBuffer.Span[1] = (byte)(0x34 + (oversamplingSetting << 6)); - // insert pressure waittime using oversampling setting as index. Thread.Sleep(pressureWaitTime[oversamplingSetting]); - // get MSB and LSB result - // TODO: delete after validating - //byte[] data = new byte[3]; - //data = Peripheral.ReadRegisters(0xF6, 3); - Peripheral?.ReadRegister(0xf6, ReadBuffer.Span[0..3]); + BusComms?.ReadRegister(0xf6, ReadBuffer.Span[0..3]); return ((ReadBuffer.Span[0] << 16) | (ReadBuffer.Span[1] << 8) | (ReadBuffer.Span[2])) >> (8 - oversamplingSetting); } /// - /// Retrieves the factory calibration data stored in the sensor. + /// Retrieves the factory calibration data stored in the sensor /// private void GetCalibrationData() { @@ -220,14 +190,7 @@ private void GetCalibrationData() private short ReadShort(byte address) { - // TODO: i think we already have a method that does this. I'm just not sure - // which endian it is. not sure what the last statement here is dooing - - // get MSB and LSB result - // TODO: delete after validating - //byte[] data = new byte[2]; - //data = Peripheral.ReadRegisters(address, 2); - Peripheral?.ReadRegister(address, ReadBuffer.Span[0..2]); + BusComms?.ReadRegister(address, ReadBuffer.Span[0..2]); return (short)((ReadBuffer.Span[0] << 8) | ReadBuffer.Span[1]); } diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmp180/Driver/Sensors.Atmospheric.Bmp180.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmp180/Driver/Sensors.Atmospheric.Bmp180.csproj index 0dcc7dc105..537f9e191d 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmp180/Driver/Sensors.Atmospheric.Bmp180.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmp180/Driver/Sensors.Atmospheric.Bmp180.csproj @@ -24,6 +24,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmp180/Samples/Bmp180_Sample/Bmp180_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmp180/Samples/Bmp180_Sample/Bmp180_Sample.csproj index ea5e26fc25..6b63eb8208 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmp180/Samples/Bmp180_Sample/Bmp180_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmp180/Samples/Bmp180_Sample/Bmp180_Sample.csproj @@ -15,7 +15,7 @@ 8.0 - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ccs811/Driver/Ccs811.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ccs811/Driver/Ccs811.Enums.cs index 97ad3a3e15..fe5fe1dffd 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ccs811/Driver/Ccs811.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ccs811/Driver/Ccs811.Enums.cs @@ -3,7 +3,7 @@ public partial class Ccs811 { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ccs811/Driver/Ccs811.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ccs811/Driver/Ccs811.cs index 82ba5f3317..93cbc51566 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ccs811/Driver/Ccs811.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ccs811/Driver/Ccs811.cs @@ -12,7 +12,7 @@ namespace Meadow.Foundation.Sensors.Atmospheric /// public partial class Ccs811 : ByteCommsSensorBase<(Concentration? Co2, Concentration? Voc)>, - ICo2Sensor, IVocSensor + ICo2Sensor, IVocSensor, II2cPeripheral { private const int ReadBufferSize = 10; private const int WriteBufferSize = 8; @@ -39,6 +39,11 @@ public partial class Ccs811 : /// public Concentration? Voc => Conditions.Voc; + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + /// /// Create a new Ccs811 object /// @@ -79,31 +84,31 @@ protected void Initialize() Thread.Sleep(100); - var id = Peripheral?.ReadRegister((byte)Register.HW_ID); + var id = BusComms?.ReadRegister((byte)Register.HW_ID); if (id != 0x81) { throw new Exception("Hardware is not identifying as a CCS811"); } - Peripheral?.Write((byte)BootloaderCommand.APP_START); + BusComms?.Write((byte)BootloaderCommand.APP_START); SetMeasurementMode(MeasurementMode.ConstantPower1s); - var mode = Peripheral?.ReadRegister((byte)Register.MEAS_MODE); + var mode = BusComms?.ReadRegister((byte)Register.MEAS_MODE); } private void ShowDebugInfo() { - var ver = Peripheral?.ReadRegister((byte)Register.HW_VERSION); + var ver = BusComms?.ReadRegister((byte)Register.HW_VERSION); Resolver.Log.Info($"hardware version A = 0x{ver:x2}"); - var fwb = Peripheral?.ReadRegister((byte)Register.FW_BOOT_VERSION); + var fwb = BusComms?.ReadRegister((byte)Register.FW_BOOT_VERSION); Resolver.Log.Info($"FWB version = 0x{fwb:x4}"); - var fwa = Peripheral?.ReadRegister((byte)Register.FW_APP_VERSION); + var fwa = BusComms?.ReadRegister((byte)Register.FW_APP_VERSION); Resolver.Log.Info($"FWA version = 0x{fwa:x4}"); // read status - var status = Peripheral?.ReadRegister((byte)Register.STATUS); + var status = BusComms?.ReadRegister((byte)Register.STATUS); Resolver.Log.Info($"status = 0x{status:x2}"); } @@ -113,7 +118,7 @@ private void ShowDebugInfo() /// The baseline value public ushort GetBaseline() { - return Peripheral?.ReadRegister((byte)Register.BASELINE) ?? 0; + return BusComms?.ReadRegister((byte)Register.BASELINE) ?? 0; } /// @@ -122,7 +127,7 @@ public ushort GetBaseline() /// The new baseline public void SetBaseline(ushort value) { - Peripheral?.WriteRegister((byte)Register.BASELINE, (byte)value); + BusComms?.WriteRegister((byte)Register.BASELINE, (byte)value); } /// @@ -131,7 +136,7 @@ public void SetBaseline(ushort value) /// The measurement mode public MeasurementMode GetMeasurementMode() { - return (MeasurementMode)(Peripheral?.ReadRegister((byte)Register.MEAS_MODE) ?? 0); + return (MeasurementMode)(BusComms?.ReadRegister((byte)Register.MEAS_MODE) ?? 0); } /// @@ -141,31 +146,28 @@ public MeasurementMode GetMeasurementMode() public void SetMeasurementMode(MeasurementMode mode) { var m = (byte)mode; - Peripheral?.WriteRegister((byte)Register.MEAS_MODE, m); + BusComms?.WriteRegister((byte)Register.MEAS_MODE, m); } void Reset() { - Peripheral?.Write(new byte[] { (byte)Register.SW_RESET, 0x11, 0xE5, 0x72, 0x8A }); + BusComms?.Write(new byte[] { (byte)Register.SW_RESET, 0x11, 0xE5, 0x72, 0x8A }); } /// /// Reads data from the sensor /// /// The latest sensor reading - protected override async Task<(Concentration? Co2, Concentration? Voc)> ReadSensor() + protected override Task<(Concentration? Co2, Concentration? Voc)> ReadSensor() { - return await Task.Run(() => - { - // data is really in just the first 4, but this gets us status and raw data as well - Peripheral?.ReadRegister((byte)Register.ALG_RESULT_DATA, _readingBuffer); + // data is really in just the first 4, but this gets us status and raw data as well + BusComms?.ReadRegister((byte)Register.ALG_RESULT_DATA, _readingBuffer); - (Concentration co2, Concentration voc) state; - state.co2 = new Concentration(_readingBuffer[0] << 8 | _readingBuffer[1], Concentration.UnitType.PartsPerMillion); - state.voc = new Concentration(_readingBuffer[2] << 8 | _readingBuffer[3], Concentration.UnitType.PartsPerBillion); + (Concentration? co2, Concentration? voc) state; + state.co2 = new Concentration(_readingBuffer[0] << 8 | _readingBuffer[1], Concentration.UnitType.PartsPerMillion); + state.voc = new Concentration(_readingBuffer[2] << 8 | _readingBuffer[3], Concentration.UnitType.PartsPerBillion); - return state; - }); + return Task.FromResult(state); } /// diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ccs811/Driver/Sensors.Atmospheric.Ccs811.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ccs811/Driver/Sensors.Atmospheric.Ccs811.csproj index 6fecfbc9bd..b483343bec 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ccs811/Driver/Sensors.Atmospheric.Ccs811.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ccs811/Driver/Sensors.Atmospheric.Ccs811.csproj @@ -8,7 +8,7 @@ http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ Meadow.Foundation.Sensors.Atmospheric.Ccs811 https://github.com/WildernessLabs/Meadow.Foundation - Meadow.Foundation, VOC, Air, Ccs811 + Meadow.Foundation,VOC,Air,quality,Ccs811 0.1.17 true Ccs811 I2C VOC Air Quality Sensor @@ -21,6 +21,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ccs811/Samples/Ccs811_Sample/Ccs811_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ccs811/Samples/Ccs811_Sample/Ccs811_Sample.csproj index c97ba8a43c..dd489af886 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ccs811/Samples/Ccs811_Sample/Ccs811_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ccs811/Samples/Ccs811_Sample/Ccs811_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ccs811/Samples/Ccs811_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ccs811/Samples/Ccs811_Sample/MeadowApp.cs index 3a261bfe60..c6c29d3add 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ccs811/Samples/Ccs811_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ccs811/Samples/Ccs811_Sample/MeadowApp.cs @@ -16,8 +16,8 @@ public override Task Initialize() { Resolver.Log.Info("Initializing..."); - var i2c = Device.CreateI2cBus(Meadow.Hardware.I2cBusSpeed.Fast); - sensor = new Ccs811(i2c); + var i2cBus = Device.CreateI2cBus(Meadow.Hardware.I2cBusSpeed.Fast); + sensor = new Ccs811(i2cBus); var consumer = Ccs811.CreateObserver( handler: result => diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Dhtxx/Driver/DhtBase.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Dhtxx/Driver/DhtBase.Enums.cs index d7859084cd..75422d5c88 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Dhtxx/Driver/DhtBase.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Dhtxx/Driver/DhtBase.Enums.cs @@ -8,7 +8,7 @@ public abstract partial class DhtBase { /// - /// Valid addresses for the sensor + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Dhtxx/Driver/DhtBase.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Dhtxx/Driver/DhtBase.cs index ca8d9b6ee8..f1c2f21b64 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Dhtxx/Driver/DhtBase.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Dhtxx/Driver/DhtBase.cs @@ -1,17 +1,16 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using Meadow.Hardware; +using Meadow.Hardware; using Meadow.Peripherals.Sensors; using Meadow.Units; +using System; +using System.Threading; +using System.Threading.Tasks; namespace Meadow.Foundation.Sensors.Atmospheric { /// - /// Provide a mechanism for reading the Temperature and Humidity from - /// a DHT temperature and Humidity sensor. + /// Base class for th DHT family Temperature and Humidity sensors /// - public abstract partial class DhtBase : + public abstract partial class DhtBase : ByteCommsSensorBase<(Units.Temperature? Temperature, RelativeHumidity? Humidity)>, ITemperatureSensor, IHumiditySensor { @@ -26,25 +25,24 @@ public abstract partial class DhtBase : public event EventHandler> HumidityUpdated = delegate { }; private readonly BusType protocol; - private int lastMeasurement = 0; /// - /// The temperature + /// The current temperature /// public Units.Temperature? Temperature => Conditions.Temperature; /// - /// The relative humidity + /// The current relative humidity /// public RelativeHumidity? Humidity => Conditions.Humidity; /// - /// How last read went, true for success, false for failure + /// Was the last sensor read succesful, true for success, false for failure /// public bool WasLastReadSuccessful { get; internal set; } /// - /// Create a DHT sensor through I2C (Only DHT12) + /// Create a DHT sensor through I2C /// /// The I2C bus connected to the sensor /// The I2C address @@ -62,11 +60,11 @@ public DhtBase(II2cBus i2cBus, byte address = (byte)Addresses.Default) /// internal virtual void ReadData() { - if (protocol == BusType.OneWire) + if (protocol == BusType.OneWire) { ReadDataOneWire(); - } - else + } + else { ReadDataI2c(); } @@ -85,16 +83,14 @@ internal virtual void ReadDataOneWire() /// internal virtual void ReadDataI2c() { - Peripheral?.Write(0x00); - Peripheral?.Read(ReadBuffer.Span[0..5]); + BusComms?.Write(0x00); + BusComms?.Read(ReadBuffer.Span[0..5]); - lastMeasurement = Environment.TickCount; - - if ((ReadBuffer.Span[4] == ((ReadBuffer.Span[0] + ReadBuffer.Span[1] + ReadBuffer.Span[2] + ReadBuffer.Span[3]) & 0xFF))) + if ((ReadBuffer.Span[4] == ((ReadBuffer.Span[0] + ReadBuffer.Span[1] + ReadBuffer.Span[2] + ReadBuffer.Span[3]) & 0xFF))) { WasLastReadSuccessful = (ReadBuffer.Span[0] != 0) || (ReadBuffer.Span[2] != 0); - } - else + } + else { WasLastReadSuccessful = false; } @@ -118,10 +114,12 @@ internal virtual void ReadDataI2c() /// The updated sensor data protected override void RaiseEventsAndNotify(IChangeResult<(Units.Temperature? Temperature, RelativeHumidity? Humidity)> changeResult) { - if (changeResult.New.Temperature is { } temp) { + if (changeResult.New.Temperature is { } temp) + { TemperatureUpdated?.Invoke(this, new ChangeResult(temp, changeResult.Old?.Temperature)); } - if (changeResult.New.Humidity is { } humidity) { + if (changeResult.New.Humidity is { } humidity) + { HumidityUpdated?.Invoke(this, new ChangeResult(humidity, changeResult.Old?.Humidity)); } base.RaiseEventsAndNotify(changeResult); @@ -135,11 +133,11 @@ protected override void RaiseEventsAndNotify(IChangeResult<(Units.Temperature? T { (Units.Temperature? Temperature, RelativeHumidity? Humidity) conditions; - if (protocol == BusType.I2C) + if (protocol == BusType.I2C) { ReadDataI2c(); - } - else + } + else { ReadDataOneWire(); } diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Dhtxx/Driver/Drivers/Dht10.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Dhtxx/Driver/Drivers/Dht10.cs index df78623d84..f10e36019f 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Dhtxx/Driver/Drivers/Dht10.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Dhtxx/Driver/Drivers/Dht10.cs @@ -11,11 +11,9 @@ namespace Meadow.Foundation.Sensors.Atmospheric /// public class Dht10 : DhtBase { - private const byte CMD_INIT = 0b_1110_0001; - private const byte CMD_START = 0b_1010_1100; - private const byte CMD_SOFTRESET = 0b_1011_1010; - - //private new byte[] _readBuffer = new byte[6]; + private const byte CMD_INIT = 0b_1110_0001; + private const byte CMD_START = 0b_1010_1100; + private const byte CMD_SOFTRESET = 0b_1011_1010; /// /// Create a new Dht10 object. @@ -25,20 +23,20 @@ public class Dht10 : DhtBase public Dht10(II2cBus i2cBus, byte address = (byte)Addresses.Default) : base(i2cBus, address) { - Peripheral?.Write(CMD_SOFTRESET); + BusComms?.Write(CMD_SOFTRESET); Thread.Sleep(20); - Peripheral?.Write(CMD_INIT); + BusComms?.Write(CMD_INIT); } internal override void ReadDataI2c() { WasLastReadSuccessful = true; - Peripheral?.Write(CMD_START); + BusComms?.Write(CMD_START); Thread.Sleep(75); - + //data stored in the read buffer - Peripheral?.Read(ReadBuffer.Span); + BusComms?.Read(ReadBuffer.Span); } internal override float GetHumidity() diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Dhtxx/Driver/Drivers/Dht12.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Dhtxx/Driver/Drivers/Dht12.cs index 2b6e38a371..36818a7258 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Dhtxx/Driver/Drivers/Dht12.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Dhtxx/Driver/Drivers/Dht12.cs @@ -8,8 +8,13 @@ namespace Meadow.Foundation.Sensors.Atmospheric /// 0 - 95% humidity +/- 4% /// Currently only supports I2C /// - public class Dht12 : DhtBase + public class Dht12 : DhtBase, II2cPeripheral { + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + /// /// Create a new Dht12 object /// diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Dhtxx/Driver/Sensors.Atmospheric.Dhtxx.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Dhtxx/Driver/Sensors.Atmospheric.Dhtxx.csproj index 069e5093c9..3d2c5706c7 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Dhtxx/Driver/Sensors.Atmospheric.Dhtxx.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Dhtxx/Driver/Sensors.Atmospheric.Dhtxx.csproj @@ -24,6 +24,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Dhtxx/Samples/Dht10_Sample/Dht10_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Dhtxx/Samples/Dht10_Sample/Dht10_Sample.csproj index 817e4fd8ce..a6ac2afe10 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Dhtxx/Samples/Dht10_Sample/Dht10_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Dhtxx/Samples/Dht10_Sample/Dht10_Sample.csproj @@ -13,7 +13,7 @@ 8.0 - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Dhtxx/Samples/Dht12_Sample/Dht12_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Dhtxx/Samples/Dht12_Sample/Dht12_Sample.csproj index 817e4fd8ce..a6ac2afe10 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Dhtxx/Samples/Dht12_Sample/Dht12_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Dhtxx/Samples/Dht12_Sample/Dht12_Sample.csproj @@ -13,7 +13,7 @@ 8.0 - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Hih6130/Driver/Hih6130.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Hih6130/Driver/Hih6130.Enums.cs index 9fc95a27e4..c087fed902 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Hih6130/Driver/Hih6130.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Hih6130/Driver/Hih6130.Enums.cs @@ -3,7 +3,7 @@ public partial class Hih6130 { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Hih6130/Driver/Hih6130.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Hih6130/Driver/Hih6130.cs index 443f7d2a49..3a4510fb9d 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Hih6130/Driver/Hih6130.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Hih6130/Driver/Hih6130.cs @@ -1,25 +1,23 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using Meadow.Hardware; +using Meadow.Hardware; using Meadow.Peripherals.Sensors; using Meadow.Units; +using System; +using System.Threading.Tasks; namespace Meadow.Foundation.Sensors.Atmospheric { /// - /// Provide a mechanism for reading the Temperature and Humidity from - /// a HIH6130 temperature and Humidity sensor. + /// Represents an HIH6130 Temperature and Humidity sensor /// public partial class Hih6130 : ByteCommsSensorBase<(Units.Temperature? Temperature, RelativeHumidity? Humidity)>, - ITemperatureSensor, IHumiditySensor + ITemperatureSensor, IHumiditySensor, II2cPeripheral { /// /// Raised when the temperature value changes /// public event EventHandler> TemperatureUpdated = delegate { }; - + /// /// Raised when the humidity value changes /// @@ -35,6 +33,11 @@ public partial class Hih6130 : /// public RelativeHumidity? Humidity => Conditions.Humidity; + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + /// /// Create a new HIH6130 object using the default parameters for the component. /// @@ -51,10 +54,12 @@ public Hih6130(II2cBus i2cBus, byte address = (byte)Addresses.Default) /// protected override void RaiseEventsAndNotify(IChangeResult<(Units.Temperature? Temperature, RelativeHumidity? Humidity)> changeResult) { - if (changeResult.New.Temperature is { } temp) { + if (changeResult.New.Temperature is { } temp) + { TemperatureUpdated?.Invoke(this, new ChangeResult(temp, changeResult.Old?.Temperature)); } - if (changeResult.New.Humidity is { } humidity) { + if (changeResult.New.Humidity is { } humidity) + { HumidityUpdated?.Invoke(this, new ChangeResult(humidity, changeResult.Old?.Humidity)); } base.RaiseEventsAndNotify(changeResult); @@ -68,12 +73,12 @@ protected override void RaiseEventsAndNotify(IChangeResult<(Units.Temperature? T (Units.Temperature Temperature, RelativeHumidity Humidity) conditions; // send a start signal on the I2C bus to notify the sensor to read. - Peripheral?.Write(0); + BusComms?.Write(0); // Sensor takes 35ms to make a valid reading. await Task.Delay(40); // read data from the sensor - Peripheral?.Read(base.ReadBuffer.Span); + BusComms?.Read(base.ReadBuffer.Span); // // Data format: // @@ -82,7 +87,7 @@ protected override void RaiseEventsAndNotify(IChangeResult<(Units.Temperature? T // Byte 2: T13 T12 T11 T10 T9 T8 T7 T6 // Byte 4: T5 T4 T3 T2 T1 T0 XX XX // - if ((ReadBuffer.Span[0] & 0xc0) != 0) + if ((ReadBuffer.Span[0] & 0xc0) != 0) { throw new Exception("Status indicates readings are invalid."); } diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Hih6130/Driver/Sensors.Atmospheric.Hih6130.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Hih6130/Driver/Sensors.Atmospheric.Hih6130.csproj index 96166010f9..fd1e126a99 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Hih6130/Driver/Sensors.Atmospheric.Hih6130.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Hih6130/Driver/Sensors.Atmospheric.Hih6130.csproj @@ -24,6 +24,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Hih6130/Samples/Hih6130_Sample/Hih6130_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Hih6130/Samples/Hih6130_Sample/Hih6130_Sample.csproj index 7bc56e1bd4..44c5f7a8a5 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Hih6130/Samples/Hih6130_Sample/Hih6130_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Hih6130/Samples/Hih6130_Sample/Hih6130_Sample.csproj @@ -16,7 +16,7 @@ 8.0 - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Htu2xd/Driver/Drivers/Extras/Htu31d.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Htu2xd/Driver/Drivers/Extras/Htu31d.Enums.cs index ded356fe6b..d8e3e61c56 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Htu2xd/Driver/Drivers/Extras/Htu31d.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Htu2xd/Driver/Drivers/Extras/Htu31d.Enums.cs @@ -3,7 +3,7 @@ public partial class Htu31d { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Htu2xd/Driver/Drivers/Htu21d.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Htu2xd/Driver/Drivers/Htu21d.cs index d8b228e476..df61f72e6c 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Htu2xd/Driver/Drivers/Htu21d.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Htu2xd/Driver/Drivers/Htu21d.cs @@ -33,11 +33,11 @@ public Htu21d(II2cBus i2cBus, byte address = (byte)Addresses.Default, TimeSpan? /// /// Initialize HTU21D /// - protected void Initialize () + protected void Initialize() { - Peripheral?.Write((byte)Registers.SOFT_RESET); - - Thread.Sleep(100); + BusComms?.Write((byte)Registers.SOFT_RESET); + + Thread.Sleep(100); SetResolution(SensorResolution.TEMP11_HUM11); } @@ -48,51 +48,46 @@ protected void Initialize () /// The latest sensor reading protected override async Task<(Units.Temperature? Temperature, RelativeHumidity? Humidity)> ReadSensor() { - (Units.Temperature Temperature, RelativeHumidity Humidity) conditions; + (Units.Temperature? Temperature, RelativeHumidity? Humidity) conditions; - return await Task.Run(() => - { - // humidity - Peripheral?.Write((byte)Registers.HUMDITY_MEASURE_NOHOLD); - Thread.Sleep(20); // Maximum conversion time is 12ms (page 5 of the datasheet) - - Peripheral?.Read(ReadBuffer.Span[0..2]);// 2 data bytes plus a checksum (we ignore the checksum here) - var humidityReading = (ushort)((ReadBuffer.Span[0] << 8) + ReadBuffer.Span[1]); - var humidity = (125 * (float)humidityReading / 65536) - 6; - humidity = Math.Clamp(humidity, 0, 100); - conditions.Humidity = new RelativeHumidity(humidity, HU.Percent); - - // temperature - Peripheral?.Write((byte)Registers.TEMPERATURE_MEASURE_NOHOLD); - Thread.Sleep(20); // Maximum conversion time is 12ms (page 5 of the datasheet) - - Peripheral?.Read(ReadBuffer.Span[0..2]);// 2 data bytes plus a checksum (we ignore the checksum here) - var temperatureReading = (short)((ReadBuffer.Span[0] << 8) + ReadBuffer.Span[1]); - conditions.Temperature = new Units.Temperature((float)(((175.72 * temperatureReading) / 65536) - 46.85), Units.Temperature.UnitType.Celsius); - - return conditions; - }); + BusComms?.Write((byte)Registers.HUMDITY_MEASURE_NOHOLD); + await Task.Delay(20); // Maximum conversion time is 12ms (page 5 of the datasheet) + + BusComms?.Read(ReadBuffer.Span[0..2]);// 2 data bytes plus a checksum (we ignore the checksum here) + var humidityReading = (ushort)((ReadBuffer.Span[0] << 8) + ReadBuffer.Span[1]); + var humidity = (125 * (float)humidityReading / 65536) - 6; + humidity = Math.Clamp(humidity, 0, 100); + conditions.Humidity = new RelativeHumidity(humidity, HU.Percent); + + BusComms?.Write((byte)Registers.TEMPERATURE_MEASURE_NOHOLD); + await Task.Delay(20); // Maximum conversion time is 12ms (page 5 of the datasheet) + + BusComms?.Read(ReadBuffer.Span[0..2]);// 2 data bytes plus a checksum (we ignore the checksum here) + var temperatureReading = (short)((ReadBuffer.Span[0] << 8) + ReadBuffer.Span[1]); + conditions.Temperature = new Units.Temperature((float)(((175.72 * temperatureReading) / 65536) - 46.85), Units.Temperature.UnitType.Celsius); + + return conditions; } - - /// - /// Turn the heater on or off + + /// + /// Turn the heater on or off /// /// Heater status, true = turn heater on, false = turn heater off. public void Heater(bool heaterOn) { - if (Peripheral == null) return; + if (BusComms == null) return; - var register = Peripheral.ReadRegister((byte)Registers.READ_HEATER_REGISTER); + var register = BusComms.ReadRegister((byte)Registers.READ_HEATER_REGISTER); register &= 0xfd; if (heaterOn) { register |= 0x02; } - Peripheral.WriteRegister((byte)Registers.WRITE_HEATER_REGISTER, register); + BusComms.WriteRegister((byte)Registers.WRITE_HEATER_REGISTER, register); } - - //Set sensor resolution + + //Set sensor resolution /*******************************************************************************************/ //Sets the sensor resolution to one of four levels //Page 12: @@ -103,9 +98,9 @@ public void Heater(bool heaterOn) //Power on default is 0/0 void SetResolution(SensorResolution resolution) { - if (Peripheral == null) return; + if (BusComms == null) return; - var register = Peripheral.ReadRegister((byte)Registers.READ_USER_REGISTER); + var register = BusComms.ReadRegister((byte)Registers.READ_USER_REGISTER); var res = (byte)resolution; @@ -114,7 +109,7 @@ void SetResolution(SensorResolution resolution) register |= res; //Mask in the requested resolution bits //Request a write to user register - Peripheral.WriteRegister((byte)Registers.WRITE_USER_REGISTER, register); //Write the new resolution bits + BusComms.WriteRegister((byte)Registers.WRITE_USER_REGISTER, register); //Write the new resolution bits } } } \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Htu2xd/Driver/Drivers/Htu31d.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Htu2xd/Driver/Drivers/Htu31d.cs index 8ee64cdfda..c8cd0cdd4c 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Htu2xd/Driver/Drivers/Htu31d.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Htu2xd/Driver/Drivers/Htu31d.cs @@ -29,63 +29,58 @@ public Htu31d(II2cBus i2cBus, byte address = (byte)Addresses.Default, TimeSpan? /// Read atmospheric data from sensor /// /// - protected override async Task<(Units.Temperature? Temperature, RelativeHumidity? Humidity)> ReadSensor() + protected async override Task<(Units.Temperature? Temperature, RelativeHumidity? Humidity)> ReadSensor() { - (Units.Temperature Temperature, RelativeHumidity Humidity) conditions; + (Units.Temperature? Temperature, RelativeHumidity? Humidity) conditions; - return await Task.Run(() => - { - Peripheral?.Write((byte)Commands.Conversion); - Thread.Sleep(20); // Maximum conversion time is 20ms - Peripheral?.ReadRegister((byte)Commands.ReadTempHumidity, ReadBuffer.Span[0..5]);// 2 bytes for temp, checksum, 2 bytes humidity, checksum + BusComms?.Write((byte)Commands.Conversion); + await Task.Delay(20); // Maximum conversion time is 20ms + BusComms?.ReadRegister((byte)Commands.ReadTempHumidity, ReadBuffer.Span[0..5]);// 2 bytes for temp, checksum, 2 bytes humidity, checksum - // temperature - var temperatureReading = (ushort)((ReadBuffer.Span[0] << 8) + ReadBuffer.Span[1]); - conditions.Temperature = new Units.Temperature((float)(((175.72 * temperatureReading) / 65536) - 46.85), Units.Temperature.UnitType.Celsius); + var temperatureReading = (ushort)((ReadBuffer.Span[0] << 8) + ReadBuffer.Span[1]); + conditions.Temperature = new Units.Temperature((float)(((175.72 * temperatureReading) / 65536) - 46.85), Units.Temperature.UnitType.Celsius); - // humidity - var humidityReading = (ushort)((ReadBuffer.Span[3] << 8) + ReadBuffer.Span[4]); - var humidity = (125 * (float)humidityReading / 65536) - 6; - humidity = Math.Clamp(humidity, 0, 100); - conditions.Humidity = new RelativeHumidity(humidity, HU.Percent); + var humidityReading = (ushort)((ReadBuffer.Span[3] << 8) + ReadBuffer.Span[4]); + var humidity = (125 * (float)humidityReading / 65536) - 6; + humidity = Math.Clamp(humidity, 0, 100); + conditions.Humidity = new RelativeHumidity(humidity, HU.Percent); - return conditions; - }); + return conditions; } - + /// - /// Turn the heater on or off + /// Turn the heater on or off /// /// Heater status, true = turn heater on, false = turn heater off public void Heater(bool heaterOn) { - if(heaterOn) - { - Peripheral?.WriteRegister((byte)Commands.HeaterOn, 1); - } - else + if (heaterOn) { - Peripheral?.WriteRegister((byte)Commands.HeaterOff, 1); + BusComms?.WriteRegister((byte)Commands.HeaterOn, 1); + } + else + { + BusComms?.WriteRegister((byte)Commands.HeaterOff, 1); } } - + /// /// Reset the sensor /// - public void Reset() + public void Reset() { - Peripheral?.WriteRegister((byte)Commands.Reset, 1); + BusComms?.WriteRegister((byte)Commands.Reset, 1); Thread.Sleep(15); //could make this async ... } private UInt32 GetSerial() { - if (Peripheral == null) return 0; + if (BusComms == null) return 0; var data = new byte[4]; - Peripheral.ReadRegister((byte)Commands.ReadSerial, data); + BusComms.ReadRegister((byte)Commands.ReadSerial, data); UInt32 serial; diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Htu2xd/Driver/Htux1dBase.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Htu2xd/Driver/Htux1dBase.cs index 01b6f6a939..b8b530164b 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Htu2xd/Driver/Htux1dBase.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Htu2xd/Driver/Htux1dBase.cs @@ -7,7 +7,7 @@ namespace Meadow.Foundation.Sensors.Atmospheric { /// - /// Valid addresses for the sensor + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { @@ -26,7 +26,7 @@ public enum Addresses : byte /// public abstract class Htux1dBase : ByteCommsSensorBase<(Units.Temperature? Temperature, RelativeHumidity? Humidity)>, - ITemperatureSensor, IHumiditySensor + ITemperatureSensor, IHumiditySensor, II2cPeripheral { /// /// Temperature changed event @@ -38,6 +38,11 @@ public abstract class Htux1dBase : /// public event EventHandler> HumidityUpdated = delegate { }; + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + /// /// Default I2C bus speed /// @@ -70,7 +75,7 @@ public Htux1dBase(II2cBus i2cBus, byte address = (byte)Addresses.Default, TimeSp } /// - /// Inheritance-safe way to raise events and notify observers. + /// Inheritance-safe way to raise events and notify observers /// /// New temperature and humidity values protected override void RaiseEventsAndNotify(IChangeResult<(Units.Temperature? Temperature, RelativeHumidity? Humidity)> changeResult) diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Htu2xd/Driver/Sensors.Atmospheric.Htux1d.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Htu2xd/Driver/Sensors.Atmospheric.Htux1d.csproj index 133d810927..ec728f1170 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Htu2xd/Driver/Sensors.Atmospheric.Htux1d.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Htu2xd/Driver/Sensors.Atmospheric.Htux1d.csproj @@ -21,6 +21,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Htu2xd/Samples/Htu21d_Sample/Htu21d_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Htu2xd/Samples/Htu21d_Sample/Htu21d_Sample.csproj index 1aea63c6d8..d85e67fc66 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Htu2xd/Samples/Htu21d_Sample/Htu21d_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Htu2xd/Samples/Htu21d_Sample/Htu21d_Sample.csproj @@ -13,7 +13,7 @@ 9.0 - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Htu2xd/Samples/Htu31d_Sample/Htu31d_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Htu2xd/Samples/Htu31d_Sample/Htu31d_Sample.csproj index 1aea63c6d8..d85e67fc66 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Htu2xd/Samples/Htu31d_Sample/Htu31d_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Htu2xd/Samples/Htu31d_Sample/Htu31d_Sample.csproj @@ -13,7 +13,7 @@ 9.0 - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Mpl3115a2/Driver/Mpl3115a2.Addresses.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Mpl3115a2/Driver/Mpl3115a2.Addresses.cs index 0ee5b7501a..76a03b1658 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Mpl3115a2/Driver/Mpl3115a2.Addresses.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Mpl3115a2/Driver/Mpl3115a2.Addresses.cs @@ -3,7 +3,7 @@ public partial class Mpl3115a2 { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Mpl3115a2/Driver/Mpl3115a2.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Mpl3115a2/Driver/Mpl3115a2.cs index 6472078044..284a7281e6 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Mpl3115a2/Driver/Mpl3115a2.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Mpl3115a2/Driver/Mpl3115a2.cs @@ -1,9 +1,8 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using Meadow.Hardware; +using Meadow.Hardware; using Meadow.Peripherals.Sensors; using Meadow.Units; +using System; +using System.Threading.Tasks; namespace Meadow.Foundation.Sensors.Atmospheric { @@ -12,7 +11,7 @@ namespace Meadow.Foundation.Sensors.Atmospheric /// public partial class Mpl3115a2 : ByteCommsSensorBase<(Units.Temperature? Temperature, Pressure? Pressure)>, - ITemperatureSensor, IBarometricPressureSensor + ITemperatureSensor, IBarometricPressureSensor, II2cPeripheral { /// /// Event raised when temperature value changes @@ -43,10 +42,10 @@ public partial class Mpl3115a2 : /// public bool Standby { - get => (Peripheral?.ReadRegister(Registers.Control1) & 0x01) > 0; + get => (BusComms?.ReadRegister(Registers.Control1) & 0x01) > 0; set { - var status = Peripheral?.ReadRegister(Registers.Control1) ?? 0; + var status = BusComms?.ReadRegister(Registers.Control1) ?? 0; if (value) { status &= (byte)~ControlRegisterBits.Active; @@ -55,14 +54,19 @@ public bool Standby { status |= ControlRegisterBits.Active; } - Peripheral?.WriteRegister(Registers.Control1, status); + BusComms?.WriteRegister(Registers.Control1, status); } } /// /// Get the status register from the sensor /// - public byte Status => Peripheral?.ReadRegister(Registers.Status) ?? 0; + public byte Status => BusComms?.ReadRegister(Registers.Status) ?? 0; + + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; /// /// Create a new MPL3115A2 object with the default address and speed settings @@ -72,15 +76,15 @@ public bool Standby public Mpl3115a2(II2cBus i2cBus, byte address = (byte)Addresses.Default) : base(i2cBus, address) { - if (Peripheral?.ReadRegister(Registers.WhoAmI) != 0xc4) + if (BusComms?.ReadRegister(Registers.WhoAmI) != 0xc4) { throw new Exception("Unexpected device ID, expected 0xc4"); } - Peripheral?.WriteRegister(Registers.Control1, + BusComms?.WriteRegister(Registers.Control1, (byte)(ControlRegisterBits.Active | ControlRegisterBits.OverSample128)); - Peripheral?.WriteRegister(Registers.DataConfiguration, + BusComms?.WriteRegister(Registers.DataConfiguration, (byte)(ConfigurationRegisterBits.DataReadyEvent | ConfigurationRegisterBits.EnablePressureEvent | ConfigurationRegisterBits.EnableTemperatureEvent)); @@ -91,29 +95,22 @@ public Mpl3115a2(II2cBus i2cBus, byte address = (byte)Addresses.Default) /// protected override async Task<(Units.Temperature? Temperature, Pressure? Pressure)> ReadSensor() { - return await Task.Run(() => + (Units.Temperature? Temperature, Pressure? Pressure) conditions; + // Force the sensor to make a reading by setting the OST bit in Control + // register 1 (see 7.17.1 of the datasheet). + Standby = false; + // Pause until both temperature and pressure readings are available + while ((Status & 0x06) != 0x06) { - (Units.Temperature? Temperature, Pressure? Pressure) conditions; - // - // Force the sensor to make a reading by setting the OST bit in Control - // register 1 (see 7.17.1 of the datasheet). - // - Standby = false; - // - // Pause until both temperature and pressure readings are available. - // - while ((Status & 0x06) != 0x06) - { - Thread.Sleep(5); - } + await Task.Delay(5); + } - Thread.Sleep(100); - Peripheral?.ReadRegister(Registers.PressureMSB, ReadBuffer.Span); - conditions.Pressure = new Pressure(DecodePresssure(ReadBuffer.Span[0], ReadBuffer.Span[1], ReadBuffer.Span[2]), Units.Pressure.UnitType.Pascal); - conditions.Temperature = new Units.Temperature(DecodeTemperature(ReadBuffer.Span[3], ReadBuffer.Span[4]), Units.Temperature.UnitType.Celsius); + await Task.Delay(100); + BusComms?.ReadRegister(Registers.PressureMSB, ReadBuffer.Span); + conditions.Pressure = new Pressure(DecodePresssure(ReadBuffer.Span[0], ReadBuffer.Span[1], ReadBuffer.Span[2]), Units.Pressure.UnitType.Pascal); + conditions.Temperature = new Units.Temperature(DecodeTemperature(ReadBuffer.Span[3], ReadBuffer.Span[4]), Units.Temperature.UnitType.Celsius); - return conditions; - }); + return conditions; } /// @@ -152,25 +149,6 @@ private float DecodePresssure(byte msb, byte csb, byte lsb) return (float)(pressure / 64.0); } - /// - /// Encode the pressure into the sensor reading byes. - /// This method is used to allow the target pressure and pressure window - /// properties to be set. - /// - /// Pressure in Pascals to encode. - /// Array holding the three byte values for the sensor. - private byte[] EncodePressure(double pressure) - { - var result = new byte[3]; - var temp = (uint)(pressure * 64); - result[2] = (byte)(temp & 0xff); - temp >>= 8; - result[1] = (byte)(temp & 0xff); - temp >>= 8; - result[0] = (byte)(temp & 0xff); - return result; - } - /// /// Decode the two bytes representing the temperature into degrees C. /// @@ -185,31 +163,14 @@ private float DecodeTemperature(byte msb, byte lsb) return (float)(temperature / 256.0); } - /// - /// Encode a temperature into sensor reading bytes. - /// This method is needed in order to allow the temperature target - /// and window properties to work. - /// - /// Temperature to encode. - /// Temperature tuple containing the two bytes for the sensor. - private byte[] EncodeTemperature(double temperature) - { - var result = new byte[2]; - var temp = (ushort)(temperature * 256); - result[1] = (byte)(temp & 0xff); - temp >>= 8; - result[0] = (byte)(temp & 0xff); - return result; - } - /// /// Reset the sensor /// public void Reset() { - var data = Peripheral?.ReadRegister(Registers.Control1) ?? 0; + var data = BusComms?.ReadRegister(Registers.Control1) ?? 0; data |= 0x04; - Peripheral?.WriteRegister(Registers.Control1, data); + BusComms?.WriteRegister(Registers.Control1, data); } async Task ISensor.Read() diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Mpl3115a2/Driver/Sensors.Atmospheric.Mpl3115a2.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Mpl3115a2/Driver/Sensors.Atmospheric.Mpl3115a2.csproj index 53aed54aa5..175b7eb156 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Mpl3115a2/Driver/Sensors.Atmospheric.Mpl3115a2.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Mpl3115a2/Driver/Sensors.Atmospheric.Mpl3115a2.csproj @@ -25,6 +25,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Mpl3115a2/Samples/Mpl3115a2_Sample/Mpl3115a2_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Mpl3115a2/Samples/Mpl3115a2_Sample/Mpl3115a2_Sample.csproj index 96dea2fbfd..d6ca5cf127 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Mpl3115a2/Samples/Mpl3115a2_Sample/Mpl3115a2_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Mpl3115a2/Samples/Mpl3115a2_Sample/Mpl3115a2_Sample.csproj @@ -16,7 +16,7 @@ 8.0 - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ms5611/Driver/Ms5611.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ms5611/Driver/Ms5611.Enums.cs index f613f650cb..97688decd5 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ms5611/Driver/Ms5611.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ms5611/Driver/Ms5611.Enums.cs @@ -3,7 +3,7 @@ public partial class Ms5611 { /// - /// Valid addresses for the sensor + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { @@ -43,5 +43,13 @@ public enum Resolution /// OSR_4096 = 4 } + + enum Commands : byte + { + Reset = 0x1e, + ConvertD1 = 0x40, + ConvertD2 = 0x50, + ReadADC = 0x00, + } } } diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ms5611/Driver/Ms5611.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ms5611/Driver/Ms5611.cs index dff77efe67..910600ab03 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ms5611/Driver/Ms5611.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ms5611/Driver/Ms5611.cs @@ -10,9 +10,9 @@ namespace Meadow.Foundation.Sensors.Atmospheric /// /// Represents an Ms5611 pressure and temperature sensor /// - public partial class Ms5611: + public partial class Ms5611 : ByteCommsSensorBase<(Units.Temperature? Temperature, Pressure? Pressure)>, - ITemperatureSensor, IBarometricPressureSensor + ITemperatureSensor, IBarometricPressureSensor, II2cPeripheral { /// /// Temperature changed event @@ -25,17 +25,26 @@ public partial class Ms5611: public event EventHandler> PressureUpdated = delegate { }; /// - /// The temperature, in degrees celsius (°C), from the last reading + /// The current temperature /// public Units.Temperature? Temperature => Conditions.Temperature; /// - /// The pressure, in hectopascals (hPa), from the last reading. 1 hPa - /// is equal to one millibar, or 1/10th of a kilopascal (kPa)/centibar + /// The current pressure /// public Pressure? Pressure => Conditions.Pressure; - private Ms5611Base ms5611; + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + + /// + /// I2C Communication bus used to communicate with the peripheral + /// + protected readonly II2cCommunications i2cComms; + + readonly Resolution resolution; /// /// Connect to the Ms5611 using I2C @@ -45,7 +54,8 @@ public partial class Ms5611: /// public Ms5611(II2cBus i2cBus, byte address = (byte)Addresses.Default, Resolution resolution = Resolution.OSR_1024) { - ms5611 = new Ms5611I2c(i2cBus, address, resolution); + i2cComms = new I2cCommunications(i2cBus, address); + this.resolution = resolution; } /// @@ -69,17 +79,14 @@ protected override void RaiseEventsAndNotify(IChangeResult<(Units.Temperature? T /// Reads data from the sensor /// /// The latest sensor reading - protected override async Task<(Units.Temperature? Temperature, Pressure? Pressure)> ReadSensor() + protected override Task<(Units.Temperature? Temperature, Pressure? Pressure)> ReadSensor() { - return await Task.Run(() => { + (Units.Temperature? Temperature, Pressure? Pressure) conditions; - (Units.Temperature Temperature, Pressure Pressure) conditions; + conditions.Temperature = new Units.Temperature(ReadTemperature(), Units.Temperature.UnitType.Celsius); + conditions.Pressure = new Pressure(ReadPressure(), Units.Pressure.UnitType.Millibar); - conditions.Temperature = new Units.Temperature(ReadTemperature(), Units.Temperature.UnitType.Celsius); - conditions.Pressure = new Pressure(ReadPressure(), Units.Pressure.UnitType.Millibar); - - return conditions; - }); + return Task.FromResult(conditions); } /// @@ -87,31 +94,37 @@ protected override void RaiseEventsAndNotify(IChangeResult<(Units.Temperature? T /// public void Reset() { - ms5611.Reset(); + var cmd = (byte)Commands.Reset; + + i2cComms.Write(cmd); } private void BeginTempConversion() { - ms5611.BeginTempConversion(); + var cmd = (byte)((byte)Commands.ConvertD2 + 2 * (byte)resolution); + i2cComms.Write(cmd); } private void BeginPressureConversion() { - ms5611.BeginPressureConversion(); + var cmd = (byte)((byte)Commands.ConvertD1 + 2 * (byte)resolution); + i2cComms.Write(cmd); } private byte[] ReadData() { - return ms5611.ReadData(); + var data = new byte[3]; + i2cComms.ReadRegister((byte)Commands.ReadADC, data); + return data; } int ReadTemperature() { - ms5611.BeginTempConversion(); + BeginTempConversion(); Thread.Sleep(10); // 1 + 2 * Resolution // we get back 24 bits (3 bytes), regardless of the resolution we're asking for - var data = ms5611.ReadData(); + var data = ReadData(); var result = data[2] | data[1] << 8 | data[0] << 16; @@ -120,12 +133,12 @@ int ReadTemperature() int ReadPressure() { - ms5611.BeginPressureConversion(); + BeginPressureConversion(); Thread.Sleep(10); // 1 + 2 * Resolution // we get back 24 bits (3 bytes), regardless of the resolution we're asking for - var data = ms5611.ReadData(); + var data = ReadData(); var result = data[2] | data[1] << 8 | data[0] << 16; diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ms5611/Driver/Ms5611Base.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ms5611/Driver/Ms5611Base.cs deleted file mode 100644 index 09242ad794..0000000000 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ms5611/Driver/Ms5611Base.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace Meadow.Foundation.Sensors.Atmospheric -{ - internal abstract class Ms5611Base - { - protected Ms5611.Resolution Resolution { get; set; } - - public abstract void Reset(); - public abstract void BeginTempConversion(); - public abstract void BeginPressureConversion(); - public abstract byte[] ReadData(); - - protected enum Commands : byte - { - Reset = 0x1e, - ConvertD1 = 0x40, - ConvertD2 = 0x50, - ReadADC = 0x00, - } - - internal Ms5611Base(Ms5611.Resolution resolution) - { - Resolution = resolution; - } - } -} diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ms5611/Driver/Ms5611I2c.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ms5611/Driver/Ms5611I2c.cs deleted file mode 100644 index bab6e42bda..0000000000 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ms5611/Driver/Ms5611I2c.cs +++ /dev/null @@ -1,41 +0,0 @@ -using Meadow.Hardware; - -namespace Meadow.Foundation.Sensors.Atmospheric -{ - internal class Ms5611I2c : Ms5611Base - { - private I2cPeripheral i2CPeripheral; - - internal Ms5611I2c(II2cBus i2cBus, byte address, Ms5611.Resolution resolution) - : base(resolution) - { - i2CPeripheral = new I2cPeripheral(i2cBus, address); - } - - public override void Reset() - { - var cmd = (byte)Commands.Reset; - - i2CPeripheral.Write(cmd); - } - - public override void BeginTempConversion() - { - var cmd = (byte)((byte)Commands.ConvertD2 + 2 * (byte)Resolution); - i2CPeripheral.Write(cmd); - } - - public override void BeginPressureConversion() - { - var cmd = (byte)((byte)Commands.ConvertD1 + 2 * (byte)Resolution); - i2CPeripheral.Write(cmd); - } - - public override byte[] ReadData() - { - var data = new byte[3]; - i2CPeripheral.ReadRegister((byte)Commands.ReadADC, data); - return data; - } - } -} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ms5611/Driver/Ms5611Spi.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ms5611/Driver/Ms5611Spi.cs deleted file mode 100644 index f289527ec2..0000000000 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ms5611/Driver/Ms5611Spi.cs +++ /dev/null @@ -1,42 +0,0 @@ -using Meadow.Hardware; -using System; - -/* -namespace Meadow.Foundation.Sensors.Atmospheric -{ - internal class Ms5611Spi : Ms5611Base - { - private ISpiBus spiBus; - private IPin chipSelect; - - internal Ms5611Spi(ISpiBus spi, IPin chipSelect, Ms5611.Resolution resolution) - : base(resolution) - { - spiBus = spi; - this.chipSelect = chipSelect; - - throw new NotImplementedException(); - } - - public override void BeginPressureConversion() - { - throw new NotImplementedException(); - } - - public override void BeginTempConversion() - { - throw new NotImplementedException(); - } - - public override byte[] ReadData() - { - throw new NotImplementedException(); - } - - public override void Reset() - { - throw new NotImplementedException(); - } - } -} -*/ diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ms5611/Driver/Sensors.Atmospheric.Ms5611.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ms5611/Driver/Sensors.Atmospheric.Ms5611.csproj index 458403c40f..6042b50e48 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ms5611/Driver/Sensors.Atmospheric.Ms5611.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ms5611/Driver/Sensors.Atmospheric.Ms5611.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ms5611/Samples/Ms5611_Sample/Ms5611_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ms5611/Samples/Ms5611_Sample/Ms5611_Sample.csproj index dc31d63b0c..3bf81b3e91 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ms5611/Samples/Ms5611_Sample/Ms5611_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Ms5611/Samples/Ms5611_Sample/Ms5611_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sgp40/Driver/Sensors.Atmospheric.Sgp40.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sgp40/Driver/Sensors.Atmospheric.Sgp40.csproj index 713dc1301f..22f7dd3466 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sgp40/Driver/Sensors.Atmospheric.Sgp40.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sgp40/Driver/Sensors.Atmospheric.Sgp40.csproj @@ -21,6 +21,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sgp40/Driver/Sgp40.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sgp40/Driver/Sgp40.Enums.cs index 7cfd7dfbb9..6cfe42ba6e 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sgp40/Driver/Sgp40.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sgp40/Driver/Sgp40.Enums.cs @@ -5,9 +5,9 @@ namespace Meadow.Foundation.Sensors.Atmospheric public partial class Sgp40 { /// - /// Valid addresses for the sensor + /// Valid I2C addresses for the sensor /// - public enum Address : byte + public enum Addresses : byte { /// /// Bus address 0x59 diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sgp40/Driver/Sgp40.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sgp40/Driver/Sgp40.cs index c45f354849..b53405a698 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sgp40/Driver/Sgp40.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sgp40/Driver/Sgp40.cs @@ -1,38 +1,43 @@ -using System; +using Meadow.Hardware; +using Meadow.Units; +using System; using System.Threading; using System.Threading.Tasks; -using Meadow.Hardware; -using Meadow.Units; namespace Meadow.Foundation.Sensors.Atmospheric { /// /// Provides access to the Sensiron SGP40 VOC sensor /// - public partial class Sgp40 : ByteCommsSensorBase + public partial class Sgp40 : ByteCommsSensorBase, II2cPeripheral { /// /// public event EventHandler> VocIndexUpdated = delegate { }; /// - /// The VOC Index, from the last reading. + /// The VOC Index, from the last reading /// public int VocIndex => Conditions; /// - /// Serial number of the device. + /// Serial number of the device /// public ulong SerialNumber { get; private set; } - private byte[]? _compensationData = null; + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + + private byte[]? compensationData = null; /// /// Creates a new SGP40 VOC sensor. /// /// Sensor address (default to 0x40). /// I2CBus. - public Sgp40(II2cBus i2cBus, byte address = (byte)Address.Default) + public Sgp40(II2cBus i2cBus, byte address = (byte)Addresses.Default) : base(i2cBus, address, 9, 8) { Initialize(); @@ -43,14 +48,11 @@ public Sgp40(II2cBus i2cBus, byte address = (byte)Address.Default) /// protected void Initialize() { - // write buffer for initialization commands only can be two bytes. - Span tx = WriteBuffer.Span[0..2]; - - Peripheral?.Write(sgp4x_get_serial_number); + BusComms?.Write(sgp4x_get_serial_number); - Thread.Sleep(1); // per the data sheet + Thread.Sleep(1); - Peripheral?.Read(ReadBuffer.Span[0..9]); + BusComms?.Read(ReadBuffer.Span[0..9]); var bytes = ReadBuffer.ToArray(); @@ -63,11 +65,11 @@ protected void Initialize() /// true on sucessful test, otherwise false public bool RunSelfTest() { - Peripheral?.Write(sgp40_execute_self_test); + BusComms?.Write(sgp40_execute_self_test); Thread.Sleep(325); // test requires 320ms to complete - Peripheral?.Read(ReadBuffer.Span[0..3]); + BusComms?.Read(ReadBuffer.Span[0..3]); return ReadBuffer.Span[0..1][0] == 0xd4; } @@ -76,27 +78,24 @@ public bool RunSelfTest() /// Reads data from the sensor /// /// The latest sensor reading - protected async override Task ReadSensor() + protected override Task ReadSensor() { - return await Task.Run(() => + if (compensationData != null) { - if(_compensationData != null) - { - Peripheral?.Write(_compensationData); - } - else - { - Peripheral?.Write(sgp40_measure_raw_signal_uncompensated); - } + BusComms?.Write(compensationData); + } + else + { + BusComms?.Write(sgp40_measure_raw_signal_uncompensated); + } - Thread.Sleep(30); // per the data sheet + Thread.Sleep(30); // per the data sheet - Peripheral?.Read(ReadBuffer.Span[0..3]); + BusComms?.Read(ReadBuffer.Span[0..3]); - var data = ReadBuffer.Span[0..3].ToArray(); + var data = ReadBuffer.Span[0..3].ToArray(); - return data[0] << 8 | data[1]; - }); + return Task.FromResult(data[0] << 8 | data[1]); } /// @@ -115,7 +114,7 @@ protected override void RaiseEventsAndNotify(IChangeResult changeResult) /// public void TurnHeaterOff() { - Peripheral?.Write(sgp4x_turn_heater_off); + BusComms?.Write(sgp4x_turn_heater_off); } /// @@ -125,19 +124,19 @@ public void TurnHeaterOff() /// Temperature compensation public void SetCompensationData(RelativeHumidity humidity, Units.Temperature temperature) { - _compensationData = new byte[8]; + compensationData = new byte[8]; - Array.Copy(sgp40_measure_raw_signal, 0, _compensationData, 0, 2); + Array.Copy(sgp40_measure_raw_signal, 0, compensationData, 0, 2); var rh = BitConverter.GetBytes(System.Net.IPAddress.HostToNetworkOrder((ushort)(humidity.Percent * 65535 / 100))); - _compensationData[2] = rh[0]; - _compensationData[3] = rh[1]; - _compensationData[4] = Crc(rh); + compensationData[2] = rh[0]; + compensationData[3] = rh[1]; + compensationData[4] = Crc(rh); var t = BitConverter.GetBytes(System.Net.IPAddress.HostToNetworkOrder((ushort)(temperature.Celsius * 65535 / 175))); - _compensationData[5] = t[0]; - _compensationData[6] = t[1]; - _compensationData[7] = Crc(t); + compensationData[5] = t[0]; + compensationData[6] = t[1]; + compensationData[7] = Crc(t); } /// @@ -145,7 +144,7 @@ public void SetCompensationData(RelativeHumidity humidity, Units.Temperature tem /// public void ClearCompensationData() { - _compensationData = null; + compensationData = null; } private byte Crc(byte[] data) 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 a5f3503b2f..2b30bdac49 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 @@ -16,7 +16,7 @@ 8.0 - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sht31D/Driver/Sensors.Atmospheric.Sht31d.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sht31D/Driver/Sensors.Atmospheric.Sht31d.csproj index c74c923e1b..7a5fea5a38 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sht31D/Driver/Sensors.Atmospheric.Sht31d.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sht31D/Driver/Sensors.Atmospheric.Sht31d.csproj @@ -21,6 +21,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sht31D/Driver/Sht31d.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sht31D/Driver/Sht31d.Enums.cs index 3a0967e913..45e166d7ef 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sht31D/Driver/Sht31d.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sht31D/Driver/Sht31d.Enums.cs @@ -3,7 +3,7 @@ public partial class Sht31d { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sht31D/Driver/Sht31d.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sht31D/Driver/Sht31d.cs index b158aad366..ba269dba85 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sht31D/Driver/Sht31d.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sht31D/Driver/Sht31d.cs @@ -1,21 +1,17 @@ -using System; -using System.Threading.Tasks; -using Meadow.Hardware; +using Meadow.Hardware; using Meadow.Peripherals.Sensors; using Meadow.Units; +using System; +using System.Threading.Tasks; namespace Meadow.Foundation.Sensors.Atmospheric { /// - /// Provide a mechanism for reading the temperature and humidity from - /// a SHT31D temperature / humidity sensor. + /// Represents a SHT31 Dtemperature and humidity sensor /// - /// - /// Readings from the sensor are made in Single-shot mode. - /// public partial class Sht31d : ByteCommsSensorBase<(Units.Temperature? Temperature, RelativeHumidity? Humidity)>, - ITemperatureSensor, IHumiditySensor + ITemperatureSensor, IHumiditySensor, II2cPeripheral { /// /// Temperature changed event @@ -28,19 +24,24 @@ public partial class Sht31d : public event EventHandler> HumidityUpdated = delegate { }; /// - /// The temperature, in degrees celsius (°C), from the last reading. + /// The temperature from the last reading /// public Units.Temperature? Temperature => Conditions.Temperature; /// - /// The humidity, in percent relative humidity, from the last reading.. + /// The humidity, in percent relative humidity, from the last reading /// public RelativeHumidity? Humidity => Conditions.Humidity; /// - /// Create a new SHT31D object. + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + + /// + /// Create a new SHT31D object /// - /// Sensor address (should be 0x44 or 0x45). + /// Sensor address (should be 0x44 or 0x45) /// I2cBus (0-1000 KHz). public Sht31d(II2cBus i2cBus, byte address = (byte)Addresses.Default) : base(i2cBus, address, readBufferSize: 6, writeBufferSize: 2) @@ -74,7 +75,7 @@ protected override void RaiseEventsAndNotify(IChangeResult<(Units.Temperature? T WriteBuffer.Span[0] = 0x2c; WriteBuffer.Span[1] = 0x06; - Peripheral?.Exchange(WriteBuffer.Span, ReadBuffer.Span); + BusComms?.Exchange(WriteBuffer.Span, ReadBuffer.Span); var humidity = (100 * (float)((ReadBuffer.Span[3] << 8) + ReadBuffer.Span[4])) / 65535; var tempC = ((175 * (float)((ReadBuffer.Span[0] << 8) + ReadBuffer.Span[1])) / 65535) - 45; diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sht31d/Samples/Sht31d_Sample/Sht31d_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sht31d/Samples/Sht31d_Sample/Sht31d_Sample.csproj index 3071051cb0..ef2dfaeaae 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sht31d/Samples/Sht31d_Sample/Sht31d_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sht31d/Samples/Sht31d_Sample/Sht31d_Sample.csproj @@ -15,7 +15,7 @@ 8.0 - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sht4x/Driver/Sensors.Atmospheric.Sht4x.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sht4x/Driver/Sensors.Atmospheric.Sht4x.csproj index 6a3dea1f4c..c1fc3bf958 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sht4x/Driver/Sensors.Atmospheric.Sht4x.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sht4x/Driver/Sensors.Atmospheric.Sht4x.csproj @@ -21,6 +21,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sht4x/Driver/Sht4x.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sht4x/Driver/Sht4x.Enums.cs index d4fc18e4ab..182b23105a 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sht4x/Driver/Sht4x.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sht4x/Driver/Sht4x.Enums.cs @@ -3,7 +3,7 @@ public partial class Sht4x { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sht4x/Driver/Sht4x.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sht4x/Driver/Sht4x.cs index 262a873aac..888cab9f6d 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sht4x/Driver/Sht4x.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sht4x/Driver/Sht4x.cs @@ -1,22 +1,18 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using Meadow.Hardware; +using Meadow.Hardware; using Meadow.Peripherals.Sensors; using Meadow.Units; +using System; +using System.Threading; +using System.Threading.Tasks; namespace Meadow.Foundation.Sensors.Atmospheric { /// - /// Provide a mechanism for reading the temperature and humidity from - /// a SHT4x temperature / humidity sensor (SHT40, SHT41, SHT45, etc.) + /// Represent a SHT4x temperature and humidity sensor (SHT40, SHT41, SHT45, etc.) /// - /// - /// Readings from the sensor are made in Single-shot mode. - /// public partial class Sht4x : ByteCommsSensorBase<(Units.Temperature? Temperature, RelativeHumidity? Humidity)>, - ITemperatureSensor, IHumiditySensor + ITemperatureSensor, IHumiditySensor, II2cPeripheral { /// /// Precision of sensor reading @@ -34,24 +30,28 @@ public partial class Sht4x : public event EventHandler> HumidityUpdated = delegate { }; /// - /// The curren temperature -from the last reading. + /// The current temperature /// public Units.Temperature? Temperature => Conditions.Temperature; /// - /// The humidity, in percent relative humidity, from the last reading + /// The current humidity /// public RelativeHumidity? Humidity => Conditions.Humidity; + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + /// /// Create a new SHT4x object /// - /// Sensor address (0x44 or 0x45) + /// Sensor address /// I2cBus public Sht4x(II2cBus i2cBus, byte address = (byte)Addresses.Default) : base(i2cBus, address, readBufferSize: 6, writeBufferSize: 2) - { - } + { } /// /// Raise events for subscribers @@ -108,24 +108,21 @@ protected int GetDelayForPrecision(Precision precision) /// /// Get a reading from the sensor and set the Temperature and Humidity properties. /// - protected async override Task<(Units.Temperature? Temperature, RelativeHumidity? Humidity)> ReadSensor() + protected override Task<(Units.Temperature? Temperature, RelativeHumidity? Humidity)> ReadSensor() { - (Units.Temperature Temperature, RelativeHumidity Humidity) conditions; + (Units.Temperature? Temperature, RelativeHumidity? Humidity) conditions; - return await Task.Run(() => - { - Peripheral?.Write((byte)ReadPrecision); - Thread.Sleep(GetDelayForPrecision(ReadPrecision)); - Peripheral?.Read(ReadBuffer.Span[0..5]); + BusComms?.Write((byte)ReadPrecision); + Thread.Sleep(GetDelayForPrecision(ReadPrecision)); + BusComms?.Read(ReadBuffer.Span[0..5]); - var temperature = (175 * (float)((ReadBuffer.Span[0] << 8) + ReadBuffer.Span[1]) / 65535) - 45; - var humidity = (125 * (float)((ReadBuffer.Span[3] << 8) + ReadBuffer.Span[4]) / 65535) - 6; + var temperature = (175 * (float)((ReadBuffer.Span[0] << 8) + ReadBuffer.Span[1]) / 65535) - 45; + var humidity = (125 * (float)((ReadBuffer.Span[3] << 8) + ReadBuffer.Span[4]) / 65535) - 6; - conditions.Humidity = new RelativeHumidity(humidity); - conditions.Temperature = new Units.Temperature(temperature, Units.Temperature.UnitType.Celsius); + conditions.Humidity = new RelativeHumidity(humidity); + conditions.Temperature = new Units.Temperature(temperature, Units.Temperature.UnitType.Celsius); - return conditions; - }); + return Task.FromResult(conditions); } async Task ISensor.Read() diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sht4x/Samples/Sht4x_Sample/Sht4x_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sht4x/Samples/Sht4x_Sample/Sht4x_Sample.csproj index 6c79440e11..e7c9fd8b45 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sht4x/Samples/Sht4x_Sample/Sht4x_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Sht4x/Samples/Sht4x_Sample/Sht4x_Sample.csproj @@ -12,7 +12,7 @@ 9.0 - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Si70xx/Driver/Sensors.Atmospheric.Si70xx.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Si70xx/Driver/Sensors.Atmospheric.Si70xx.csproj index cb277ca00b..5fc42134c2 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Si70xx/Driver/Sensors.Atmospheric.Si70xx.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Si70xx/Driver/Sensors.Atmospheric.Si70xx.csproj @@ -25,6 +25,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Si70xx/Driver/Si70xx.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Si70xx/Driver/Si70xx.Enums.cs index a482d5a057..9ccc39f6fb 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Si70xx/Driver/Si70xx.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Si70xx/Driver/Si70xx.Enums.cs @@ -3,9 +3,9 @@ public partial class Si70xx { /// - /// Valid addresses for the sensor + /// Valid I2C addresses for the sensor /// - public enum Address : byte + public enum Addresses : byte { /// /// Bus address 0x40 diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Si70xx/Driver/Si70xx.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Si70xx/Driver/Si70xx.cs index 6d98648bd1..97825e052e 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Si70xx/Driver/Si70xx.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Si70xx/Driver/Si70xx.cs @@ -1,9 +1,9 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using Meadow.Hardware; +using Meadow.Hardware; using Meadow.Peripherals.Sensors; using Meadow.Units; +using System; +using System.Threading; +using System.Threading.Tasks; using HU = Meadow.Units.RelativeHumidity.UnitType; using TU = Meadow.Units.Temperature.UnitType; @@ -11,29 +11,24 @@ namespace Meadow.Foundation.Sensors.Atmospheric { /// /// Provide access to the Si70xx series (Si7020, Si7021, and Si7030) - /// temperature and humidity sensors. + /// temperature and humidity sensors /// public partial class Si70xx : ByteCommsSensorBase<(Units.Temperature? Temperature, RelativeHumidity? Humidity)>, - ITemperatureSensor, IHumiditySensor + ITemperatureSensor, IHumiditySensor, II2cPeripheral { /// /// Raised when the temperature value changes /// public event EventHandler> TemperatureUpdated = delegate { }; - + /// /// Raised when the humidity value changes /// public event EventHandler> HumidityUpdated = delegate { }; /// - /// Default SPI bus speed - /// - public static Frequency DEFAULT_SPEED = new Frequency(400, Frequency.UnitType.Kilohertz); - - /// - /// The temperature, from the last reading + /// The temperature from the last reading /// public Units.Temperature? Temperature => Conditions.Temperature; @@ -57,12 +52,17 @@ public partial class Si70xx : /// public byte FirmwareRevision { get; private set; } + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + /// /// Create a new SI7021 temperature and humidity sensor /// /// I2CBus /// I2C address (default to 0x40) - public Si70xx(II2cBus i2cBus, byte address = (byte)Address.Default) + public Si70xx(II2cBus i2cBus, byte address = (byte)Addresses.Default) : base(i2cBus, address, 8, 3) { Initialize(); @@ -72,7 +72,7 @@ public Si70xx(II2cBus i2cBus, byte address = (byte)Address.Default) /// protected void Reset() { - Peripheral?.Write(CMD_RESET); + BusComms?.Write(CMD_RESET); Thread.Sleep(100); } @@ -89,7 +89,7 @@ protected void Initialize() tx[0] = READ_ID_PART1; tx[1] = READ_ID_PART2; - Peripheral?.Exchange(tx, ReadBuffer.Span); + BusComms?.Exchange(tx, ReadBuffer.Span); for (var index = 0; index < 4; index++) { SerialNumber <<= 8; @@ -98,7 +98,7 @@ protected void Initialize() tx[0] = READ_2ND_ID_PART1; tx[1] = READ_2ND_ID_PART2; - Peripheral?.Exchange(tx, ReadBuffer.Span); + BusComms?.Exchange(tx, ReadBuffer.Span); SerialNumber <<= 8; SerialNumber += ReadBuffer.Span[0]; @@ -128,33 +128,30 @@ protected void Initialize() { (Units.Temperature Temperature, RelativeHumidity Humidity) conditions; - return await Task.Run(() => + BusComms?.Write(HUMDITY_MEASURE_NOHOLD); + await Task.Delay(25); // Maximum conversion time is 12ms (page 5 of the datasheet). + BusComms?.Read(ReadBuffer.Span); // 2 data bytes plus a checksum (we ignore the checksum here) + var humidityReading = (ushort)((ReadBuffer.Span[0] << 8) + ReadBuffer.Span[1]); + conditions.Humidity = new RelativeHumidity(((125 * (float)humidityReading) / 65536) - 6, HU.Percent); + if (conditions.Humidity < new RelativeHumidity(0, HU.Percent)) { - Peripheral?.Write(HUMDITY_MEASURE_NOHOLD); - Thread.Sleep(25); // Maximum conversion time is 12ms (page 5 of the datasheet). - Peripheral?.Read(ReadBuffer.Span); // 2 data bytes plus a checksum (we ignore the checksum here) - var humidityReading = (ushort)((ReadBuffer.Span[0] << 8) + ReadBuffer.Span[1]); - conditions.Humidity = new RelativeHumidity(((125 * (float)humidityReading) / 65536) - 6, HU.Percent); - if (conditions.Humidity < new RelativeHumidity(0, HU.Percent)) - { - conditions.Humidity = new RelativeHumidity(0, HU.Percent); - } - else + conditions.Humidity = new RelativeHumidity(0, HU.Percent); + } + else + { + if (conditions.Humidity > new RelativeHumidity(100, HU.Percent)) { - if (conditions.Humidity > new RelativeHumidity(100, HU.Percent)) - { - conditions.Humidity = new RelativeHumidity(100, HU.Percent); - } + conditions.Humidity = new RelativeHumidity(100, HU.Percent); } + } - Peripheral?.Write(TEMPERATURE_MEASURE_NOHOLD); - Thread.Sleep(25); // Maximum conversion time is 12ms (page 5 of the datasheet). - Peripheral?.Read(ReadBuffer.Span); // 2 data bytes plus a checksum (we ignore the checksum here) - var temperatureReading = (short)((ReadBuffer.Span[0] << 8) + ReadBuffer.Span[1]); - conditions.Temperature = new Units.Temperature((float)(((175.72 * temperatureReading) / 65536) - 46.85), TU.Celsius); + BusComms?.Write(TEMPERATURE_MEASURE_NOHOLD); + Thread.Sleep(25); // Maximum conversion time is 12ms (page 5 of the datasheet). + BusComms?.Read(ReadBuffer.Span); // 2 data bytes plus a checksum (we ignore the checksum here) + var temperatureReading = (short)((ReadBuffer.Span[0] << 8) + ReadBuffer.Span[1]); + conditions.Temperature = new Units.Temperature((float)((175.72 * temperatureReading / 65536) - 46.85), TU.Celsius); - return conditions; - }); + return conditions; } /// @@ -181,14 +178,14 @@ protected override void RaiseEventsAndNotify(IChangeResult<(Units.Temperature? T /// Heater status, true = turn heater on, false = turn heater off. public void Heater(bool onOrOff) { - var register = Peripheral?.ReadRegister((byte)Register.USER_REG_1) ?? 0; + var register = BusComms?.ReadRegister((byte)Register.USER_REG_1) ?? 0; register &= 0xfd; if (onOrOff) { register |= 0x02; } - Peripheral?.WriteRegister((byte)Register.USER_REG_1, register); + BusComms?.WriteRegister((byte)Register.USER_REG_1, register); } /// @@ -203,7 +200,7 @@ public void Heater(bool onOrOff) /// The resolution to set void SetResolution(SensorResolution resolution) { - var register = Peripheral?.ReadRegister((byte)Register.USER_REG_1) ?? 0; + var register = BusComms?.ReadRegister((byte)Register.USER_REG_1) ?? 0; var res = (byte)resolution; @@ -212,7 +209,7 @@ void SetResolution(SensorResolution resolution) register |= res; //Mask in the requested resolution bits //Request a write to user register - Peripheral?.WriteRegister((byte)Register.USER_REG_1, register); //Write the new resolution bits + BusComms?.WriteRegister((byte)Register.USER_REG_1, register); //Write the new resolution bits } async Task ISensor.Read() diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Si70xx/Samples/Si70xx_Sample/Si70xx_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Si70xx/Samples/Si70xx_Sample/Si70xx_Sample.csproj index 40a7e040f3..7dfadf704a 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Si70xx/Samples/Si70xx_Sample/Si70xx_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Si70xx/Samples/Si70xx_Sample/Si70xx_Sample.csproj @@ -16,7 +16,7 @@ 8.0 - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Th02/Driver/Sensors.Atmospheric.Th02.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Th02/Driver/Sensors.Atmospheric.Th02.csproj index da6600897e..2ca53c1ae0 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Th02/Driver/Sensors.Atmospheric.Th02.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Th02/Driver/Sensors.Atmospheric.Th02.csproj @@ -21,6 +21,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Th02/Driver/Th02.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Th02/Driver/Th02.Enums.cs index 4bff8370ec..a6b4a83752 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Th02/Driver/Th02.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Th02/Driver/Th02.Enums.cs @@ -3,7 +3,7 @@ public partial class Th02 { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Th02/Driver/Th02.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Th02/Driver/Th02.cs index 66333be82b..a6df4dbe01 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Th02/Driver/Th02.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Th02/Driver/Th02.cs @@ -1,9 +1,9 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using Meadow.Hardware; +using Meadow.Hardware; using Meadow.Peripherals.Sensors; using Meadow.Units; +using System; +using System.Threading; +using System.Threading.Tasks; namespace Meadow.Foundation.Sensors.Atmospheric { @@ -13,7 +13,7 @@ namespace Meadow.Foundation.Sensors.Atmospheric /// public partial class Th02 : ByteCommsSensorBase<(Units.Temperature? Temperature, RelativeHumidity? Humidity)>, - ITemperatureSensor, IHumiditySensor + ITemperatureSensor, IHumiditySensor, II2cPeripheral { /// /// Event raised when the temperature changes @@ -26,23 +26,27 @@ public partial class Th02 : public event EventHandler> HumidityUpdated = delegate { }; /// - /// Last value read from the Temperature sensor. + /// The current temperatute /// public Units.Temperature? Temperature => Conditions.Temperature; /// - /// Last value read from the Pressure sensor. + /// The current humidity /// public RelativeHumidity? Humidity => Conditions.Humidity; + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + /// /// Provide a mechanism for reading the temperature and humidity from /// a Th02 temperature / humidity sensor /// public Th02(II2cBus i2cBus, byte address = (byte)Addresses.Default) : base(i2cBus, address) - { - } + { } /// /// Raise all change events for subscribers @@ -64,47 +68,44 @@ protected override void RaiseEventsAndNotify(IChangeResult<(Units.Temperature? T /// /// Calculates the compensated pressure and temperature. /// - protected override Task<(Units.Temperature? Temperature, RelativeHumidity? Humidity)> ReadSensor() + protected async override Task<(Units.Temperature? Temperature, RelativeHumidity? Humidity)> ReadSensor() { - return Task.Run(() => + (Units.Temperature? Temperature, RelativeHumidity? Humidity) conditions; + + // Read the humidity + BusComms?.WriteRegister((byte)Registers.Config, MeasureHumidity); + + // Maximum conversion time should be 40ms + while ((BusComms?.ReadRegister((byte)Registers.Status) & 0x01) > 0) { - (Units.Temperature? Temperature, RelativeHumidity? Humidity) conditions; - - // Read the humidity - Peripheral?.WriteRegister((byte)Registers.Config, MeasureHumidity); - - // Maximum conversion time should be 40ms - while ((Peripheral?.ReadRegister((byte)Registers.Status) & 0x01) > 0) - { - Thread.Sleep(40); - } - - byte[] data = new byte[2]; - - Peripheral?.ReadRegister((byte)Registers.DataHigh, data); - int temp = data[0] << 8; - temp |= data[1]; - temp >>= 4; - - conditions.Humidity = new RelativeHumidity(temp / 16.0 - 24); - - // Read the temperature - Peripheral?.WriteRegister((byte)Registers.Config, MeasureTemperature); - - // Maximum conversion time should be 40ms - while ((Peripheral?.ReadRegister((byte)Registers.Status) & 0x01) > 0) - { - Thread.Sleep(40); - } - - Peripheral?.ReadRegister((byte)Registers.DataHigh, data); - temp = data[0] << 8; - temp |= data[1]; - temp >>= 2; //drop the two unused bits (14 bit value) - conditions.Temperature = new Units.Temperature(temp / 32.0 - 50, Units.Temperature.UnitType.Celsius); - - return conditions; - }); + await Task.Delay(40); + } + + byte[] data = new byte[2]; + + BusComms?.ReadRegister((byte)Registers.DataHigh, data); + int temp = data[0] << 8; + temp |= data[1]; + temp >>= 4; + + conditions.Humidity = new RelativeHumidity(temp / 16.0 - 24); + + // Read the temperature + BusComms?.WriteRegister((byte)Registers.Config, MeasureTemperature); + + // Maximum conversion time should be 40ms + while ((BusComms?.ReadRegister((byte)Registers.Status) & 0x01) > 0) + { + Thread.Sleep(40); + } + + BusComms?.ReadRegister((byte)Registers.DataHigh, data); + temp = data[0] << 8; + temp |= data[1]; + temp >>= 2; //drop the two unused bits (14 bit value) + conditions.Temperature = new Units.Temperature(temp / 32.0 - 50, Units.Temperature.UnitType.Celsius); + + return conditions; } async Task ISensor.Read() diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Th02/Samples/Th02_Sample/Th02_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Th02/Samples/Th02_Sample/Th02_Sample.csproj index df7937ed1c..c4398f5377 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Th02/Samples/Th02_Sample/Th02_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Th02/Samples/Th02_Sample/Th02_Sample.csproj @@ -15,7 +15,7 @@ 8.0 - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Camera.Mlx90640/Driver/Mlx90640.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Camera.Mlx90640/Driver/Mlx90640.Enums.cs index 4b8b202e1a..45091d733b 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Camera.Mlx90640/Driver/Mlx90640.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Camera.Mlx90640/Driver/Mlx90640.Enums.cs @@ -3,7 +3,7 @@ public partial class Mlx90640 { /// - /// Valid addresses for the sensor + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Camera.Mlx90640/Driver/Mlx90640.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Camera.Mlx90640/Driver/Mlx90640.cs index 71e0ef23ab..8684713fc8 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Camera.Mlx90640/Driver/Mlx90640.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Camera.Mlx90640/Driver/Mlx90640.cs @@ -1,5 +1,5 @@ -using System; -using Meadow.Hardware; +using Meadow.Hardware; +using System; using System.Threading; namespace Meadow.Foundation.Sensors.Camera @@ -8,7 +8,7 @@ namespace Meadow.Foundation.Sensors.Camera /// Represents the MLX90640 32x24 IR array /// The MLX90640 is a fully calibrated 32x24 pixels thermal IR array /// - public partial class Mlx90640 + public partial class Mlx90640 : II2cPeripheral { /// /// Camera serial number as a string @@ -18,9 +18,9 @@ public partial class Mlx90640 /// /// Emissivity /// - public float Emissivity + public float Emissivity { - get => emissivity; + get => emissivity; set { if (value > 1) @@ -35,13 +35,13 @@ public float Emissivity { emissivity = value; } - } + } } /// /// Reflected temperature /// - public Meadow.Units.Temperature ReflectedTemperature { get; set; } + public Units.Temperature ReflectedTemperature { get; set; } /// /// Camera configuration @@ -53,7 +53,15 @@ public float Emissivity const byte OpenAirTaShift = 8; const short DeviceId1Register = 0x2407; - readonly II2cPeripheral i2CPeripheral; + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + + /// + /// I2C Communication bus used to communicate with the peripheral + /// + protected readonly II2cCommunications i2cComms; float emissivity; @@ -67,7 +75,7 @@ public Mlx90640(II2cBus i2cBus, byte address = (byte)Addresses.Default, float emissivity = 0.95f) { - i2CPeripheral = new I2cPeripheral(i2cBus, address); + i2cComms = new I2cCommunications(i2cBus, address); Emissivity = emissivity; Config = new Mlx90640Config(); @@ -75,7 +83,7 @@ public Mlx90640(II2cBus i2cBus, } /// - /// Initialize the MLX90640. Read the MLX90640 serial number and EEProm + /// Initialize the MLX90640 and read the MLX90640 serial number and EEProm /// void Initialize() { @@ -100,7 +108,7 @@ void Initialize() public float[] ReadRawData() { ushort[] mlx90640Frame = new ushort[834]; - float[] frameBuffer =new float[32 * 24]; + float[] frameBuffer = new float[32 * 24]; for (byte page = 0; page < 2; page++) { @@ -163,12 +171,11 @@ public void SetMode(Mode mode) bool GetFrameData(ref ushort[] frameData) { - ushort dataReady = 1; ushort[] controlRegister1 = new ushort[1]; ushort[] statusRegister = new ushort[1]; byte cnt = 0; - dataReady = 0; + ushort dataReady = 0; while (dataReady == 0) { I2CRead(0x8000, 1, ref statusRegister); @@ -194,7 +201,7 @@ bool GetFrameData(ref ushort[] frameData) if (cnt > 4) return false; - I2CRead(0x800D, 1, ref controlRegister1); + I2CRead(0x800D, 1, ref controlRegister1); frameData[832] = controlRegister1[0]; frameData[833] = (ushort)(statusRegister[0] & 0x0001); @@ -208,9 +215,9 @@ void I2CRead(int startAddress, ushort readLen, ref ushort[] data) while (readLen > 0) { - ushort toRead16 = (int)(MaxBufferSize / 2); + ushort toRead16 = MaxBufferSize / 2; - if (readLen < (int)(MaxBufferSize / 2)) + if (readLen < MaxBufferSize / 2) toRead16 = readLen; cmd[0] = (byte)(startAddress >> 8); @@ -218,13 +225,13 @@ void I2CRead(int startAddress, ushort readLen, ref ushort[] data) Span writeBuffer = new Span(cmd); Span tempBuf = new Span(new byte[toRead16 * 2]); - i2CPeripheral.Exchange(writeBuffer, tempBuf); + i2cComms.Exchange(writeBuffer, tempBuf); // we now have to swap every two bytes int index = 0; for (int i = bufferIndex; i < bufferIndex + toRead16; i++) { - data[i] = (ushort)((ushort)(tempBuf[index] * 256) + (ushort)tempBuf[index + 1]); ; + data[i] = (ushort)((ushort)(tempBuf[index] * 256) + tempBuf[index + 1]); ; index += 2; } @@ -244,7 +251,7 @@ bool I2CWrite(ushort writeAddress, ushort data) cmd[2] = (byte)(data >> 8); cmd[3] = (byte)(data & 0x00FF); - i2CPeripheral.Write(cmd); + i2cComms.Write(cmd); Thread.Sleep(1); @@ -322,7 +329,7 @@ void CalculateTo(ushort[] frameData, Mlx90640Config mlx90640, float emissivity, { if (irDataCP[i] > 32767) irDataCP[i] = irDataCP[i] - 65536; - + irDataCP[i] = irDataCP[i] * gain; } @@ -402,8 +409,8 @@ float GetTa(ushort[] frameData, Mlx90640Config mlx90640) ptatArt = frameData[768]; if (ptatArt > 32767) ptatArt -= 65536; - - ptatArt = (float)((ptat / (ptat * mlx90640.AlphaPTAT + ptatArt)) * Math.Pow(2, (double)18)); + + ptatArt = (float)((ptat / (ptat * mlx90640.AlphaPTAT + ptatArt)) * Math.Pow(2, 18)); ta = (float)((ptatArt / (1 + mlx90640.KvPTAT * (vdd - 3.3)) - mlx90640.VPTAT25)); ta = ta / mlx90640.KtPTAT + 25; @@ -425,7 +432,7 @@ float GetVdd(ushort[] frameData, Mlx90640Config mlx90640) } resolutionRAM = (frameData[832] & 0x0C00) >> 10; - resolutionCorrection = (float)(Math.Pow(2, (double)mlx90640.ResolutionEE) / Math.Pow(2, (double)resolutionRAM)); + resolutionCorrection = (float)(Math.Pow(2, mlx90640.ResolutionEE) / Math.Pow(2, resolutionRAM)); vdd = (float)((resolutionCorrection * vdd - mlx90640.Vdd25) / mlx90640.KVdd + 3.3); return vdd; @@ -480,7 +487,7 @@ void ExtractPTATParameters(ref ushort[] eeData) KvPTAT = (eeData[50] & 0xFC00) >> 10; if (KvPTAT > 31) KvPTAT -= 64; - + KvPTAT /= 4096; KtPTAT = eeData[50] & 0x03FF; @@ -517,7 +524,7 @@ void ExtractTgcParameters(ref ushort[] eeData) tgc = eeData[60] & 0x00FF; if (tgc > 127) tgc -= 256; - + tgc /= 32.0f; Config.Tgc = tgc; @@ -539,7 +546,7 @@ void ExtractKsTaParameters(ref ushort[] eeData) KsTa = (eeData[60] & 0xFF00) >> 8; if (KsTa > 127) KsTa -= 256; - + KsTa /= 8192.0f; Config.KsTa = KsTa; @@ -637,10 +644,10 @@ void ExtractAlphaParameters(ref ushort[] eeData) alphaTemp[p] = (eeData[64 + p] & 0x03F0) >> 4; if (alphaTemp[p] > 31) alphaTemp[p] = alphaTemp[p] - 64; - + alphaTemp[p] = alphaTemp[p] * (1 << accRemScale); alphaTemp[p] = (alphaRef + (accRow[i] << accRowScale) + (accColumn[j] << accColumnScale) + alphaTemp[p]); - alphaTemp[p] = (float)(alphaTemp[p] / Math.Pow(2, (double)alphaScale)); + alphaTemp[p] = (float)(alphaTemp[p] / Math.Pow(2, alphaScale)); alphaTemp[p] = alphaTemp[p] - Config.Tgc * (Config.CpAlpha[0] + Config.CpAlpha[1]) / 2; alphaTemp[p] = ScaleAlpha / alphaTemp[p]; } @@ -651,7 +658,7 @@ void ExtractAlphaParameters(ref ushort[] eeData) { if (alphaTemp[i] > temp) temp = alphaTemp[i]; - + } alphaScale = 0; @@ -670,7 +677,7 @@ void ExtractAlphaParameters(ref ushort[] eeData) for (int i = 0; i < 768; i++) { - temp = (float)(alphaTemp[i] * Math.Pow(2, (double)alphaScale)); + temp = (float)(alphaTemp[i] * Math.Pow(2, alphaScale)); Config.Alpha[i] = (short)(temp + 0.5); } @@ -775,13 +782,13 @@ void ExtractKtaPixelParameters(ref ushort[] eeData) KtaRoCe = (sbyte)((eeData[55] & 0xFF00) >> 8); if (KtaRoCe > 127) KtaRoCe = (sbyte)(KtaRoCe - 256); - + KtaRC[1] = KtaRoCe; KtaReCe = (sbyte)((eeData[55] & 0x00FF)); if (KtaReCe > 127) KtaReCe = (sbyte)(KtaReCe - 256); - + KtaRC[3] = KtaReCe; ktaScale1 = (byte)(((eeData[56] & 0x00F0) >> 4) + 8); @@ -796,10 +803,10 @@ void ExtractKtaPixelParameters(ref ushort[] eeData) ktaTemp[p] = (eeData[64 + p] & 0x000E) >> 1; if (ktaTemp[p] > 3) ktaTemp[p] = ktaTemp[p] - 8; - + ktaTemp[p] = ktaTemp[p] * (1 << ktaScale2); ktaTemp[p] = KtaRC[split] + ktaTemp[p]; - ktaTemp[p] = (float)(ktaTemp[p] / Math.Pow(2, (double)ktaScale1)); + ktaTemp[p] = (float)(ktaTemp[p] / Math.Pow(2, ktaScale1)); } } @@ -808,7 +815,7 @@ void ExtractKtaPixelParameters(ref ushort[] eeData) { if (Math.Abs(ktaTemp[i]) > temp) temp = Math.Abs(ktaTemp[i]); - + } ktaScale1 = 0; @@ -820,7 +827,7 @@ void ExtractKtaPixelParameters(ref ushort[] eeData) for (int i = 0; i < 768; i++) { - temp = (float)(ktaTemp[i] * Math.Pow(2, (double)ktaScale1)); + temp = (float)(ktaTemp[i] * Math.Pow(2, ktaScale1)); if (temp < 0) Config.Kta[i] = (sbyte)(temp - 0.5); else @@ -846,25 +853,25 @@ void ExtractKvPixelParameters(ref ushort[] eeData) KvRoCo = (sbyte)((eeData[52] & 0xF000) >> 12); if (KvRoCo > 7) KvRoCo = (sbyte)(KvRoCo - 16); - + KvT[0] = KvRoCo; KvReCo = (sbyte)((eeData[52] & 0x0F00) >> 8); if (KvReCo > 7) KvReCo = (sbyte)(KvReCo - 16); - + KvT[2] = KvReCo; KvRoCe = (sbyte)((eeData[52] & 0x00F0) >> 4); if (KvRoCe > 7) KvRoCe = (sbyte)(KvRoCe - 16); - + KvT[1] = KvRoCe; KvReCe = (sbyte)((eeData[52] & 0x000F)); if (KvReCe > 7) KvReCe = (sbyte)(KvReCe - 16); - + KvT[3] = KvReCe; kvScale = (byte)((eeData[56] & 0x0F00) >> 8); @@ -876,7 +883,7 @@ void ExtractKvPixelParameters(ref ushort[] eeData) int p = 32 * i + j; split = (byte)(2 * (p / 32 - (p / 64) * 2) + p % 2); kvTemp[p] = KvT[split]; - kvTemp[p] = (float)(kvTemp[p] / Math.Pow(2, (double)kvScale)); + kvTemp[p] = (float)(kvTemp[p] / Math.Pow(2, kvScale)); } } @@ -885,7 +892,7 @@ void ExtractKvPixelParameters(ref ushort[] eeData) { if (Math.Abs(kvTemp[i]) > temp) temp = Math.Abs(kvTemp[i]); - + } kvScale = 0; @@ -897,7 +904,7 @@ void ExtractKvPixelParameters(ref ushort[] eeData) for (int i = 0; i < 768; i++) { - temp = (float)(kvTemp[i] * Math.Pow(2, (double)kvScale)); + temp = (float)(kvTemp[i] * Math.Pow(2, kvScale)); if (temp < 0) Config.Kv[i] = (sbyte)(temp - 0.5); else @@ -929,7 +936,7 @@ void ExtractCILCParameters(ref ushort[] eeData) { ilChessC[1] = ilChessC[1] - 32; } - + ilChessC[1] = ilChessC[1] / 2.0f; ilChessC[2] = (eeData[53] & 0xF800) >> 11; @@ -937,7 +944,7 @@ void ExtractCILCParameters(ref ushort[] eeData) { ilChessC[2] = ilChessC[2] - 32; } - + ilChessC[2] = ilChessC[2] / 8.0f; Config.CalibrationModeEE = calibrationModeEE; @@ -996,16 +1003,16 @@ void ExtractCPParameters(ref ushort[] eeData) } ktaScale1 = (byte)(((eeData[56] & 0x00F0) >> 4) + 8); - Config.CpKta = (float)(cpKta / Math.Pow(2, (double)ktaScale1)); + Config.CpKta = (float)(cpKta / Math.Pow(2, ktaScale1)); cpKv = (eeData[59] & 0xFF00) >> 8; if (cpKv > 127) { cpKv -= 256; } - + kvScale = (byte)((eeData[56] & 0x0F00) >> 8); - Config.CpKv = (float)(cpKv / Math.Pow(2, (double)kvScale)); + Config.CpKv = (float)(cpKv / Math.Pow(2, kvScale)); Config.CpAlpha[0] = alphaSP[0]; Config.CpAlpha[1] = alphaSP[1]; @@ -1033,7 +1040,7 @@ void ExtractDeviatingPixels(ref ushort[] eeData) } - if(Config.BrokenPixels.Count > 1 ) + if (Config.BrokenPixels.Count > 1) { for (pixCnt = 0; pixCnt < Config.BrokenPixels.Count; pixCnt++) { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Camera.Mlx90640/Driver/Sensors.Camera.Mlx90640.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Camera.Mlx90640/Driver/Sensors.Camera.Mlx90640.csproj index 1852bc1f84..04cb4004b2 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Camera.Mlx90640/Driver/Sensors.Camera.Mlx90640.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Camera.Mlx90640/Driver/Sensors.Camera.Mlx90640.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Camera.Mlx90640/Samples/Mlx90640_Sample/Mlx90640_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Camera.Mlx90640/Samples/Mlx90640_Sample/Mlx90640_Sample.csproj index 902cd346e8..9fe420dbde 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Camera.Mlx90640/Samples/Mlx90640_Sample/Mlx90640_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Camera.Mlx90640/Samples/Mlx90640_Sample/Mlx90640_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Camera.Vc0706/Driver/Sensors.Camera.Vc0706.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Camera.Vc0706/Driver/Sensors.Camera.Vc0706.csproj index 11c0c96579..05c688529a 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Camera.Vc0706/Driver/Sensors.Camera.Vc0706.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Camera.Vc0706/Driver/Sensors.Camera.Vc0706.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Camera.Vc0706/Samples/Vc0706_Sample/Vc0706_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Camera.Vc0706/Samples/Vc0706_Sample/Vc0706_Sample.csproj index 9fba944813..76f5a7cfb2 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Camera.Vc0706/Samples/Vc0706_Sample/Vc0706_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Camera.Vc0706/Samples/Vc0706_Sample/Vc0706_Sample.csproj @@ -16,7 +16,7 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Hcsr04/Driver/Sensors.Distance.Hcsr04.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Hcsr04/Driver/Sensors.Distance.Hcsr04.csproj index 01afc7693d..0072bb0676 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Hcsr04/Driver/Sensors.Distance.Hcsr04.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Hcsr04/Driver/Sensors.Distance.Hcsr04.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Hcsr04/Samples/Hcsr04_Sample/Hcsr04_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Hcsr04/Samples/Hcsr04_Sample/Hcsr04_Sample.csproj index 8acdbb04e8..7d32d67f2f 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Hcsr04/Samples/Hcsr04_Sample/Hcsr04_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Hcsr04/Samples/Hcsr04_Sample/Hcsr04_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Distance.MaxBotix/Driver/MaxBotix.I2c.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Distance.MaxBotix/Driver/MaxBotix.I2c.cs index 9880fcb62c..a120826d69 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Distance.MaxBotix/Driver/MaxBotix.I2c.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Distance.MaxBotix/Driver/MaxBotix.I2c.cs @@ -1,11 +1,16 @@ -using System.Threading; -using Meadow.Hardware; +using Meadow.Hardware; using Meadow.Units; +using System.Threading; namespace Meadow.Foundation.Sensors.Distance { - public partial class MaxBotix + public partial class MaxBotix : II2cPeripheral { + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + /// /// Creates a new MaxBotix object communicating over I2C /// @@ -13,7 +18,7 @@ public partial class MaxBotix /// The distance sensor type /// The I2C address public MaxBotix(II2cBus i2cBus, SensorType sensor, byte address = (byte)Addresses.Default) - :base(i2cBus, address) + : base(i2cBus, address) { sensorType = sensor; communication = CommunicationType.I2C; @@ -23,13 +28,13 @@ public MaxBotix(II2cBus i2cBus, SensorType sensor, byte address = (byte)Addresse void StartI2cSensor(byte address) { - Peripheral.ReadRegister(address); + BusComms.ReadRegister(address); Thread.Sleep(100); } Length ReadSensorI2c() { - return new Length(Peripheral.ReadRegisterAsUShort(0x51), GetUnitsForSensor(sensorType)); + return new Length(BusComms.ReadRegisterAsUShort(0x51), GetUnitsForSensor(sensorType)); } } } \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Distance.MaxBotix/Driver/MaxBotix.enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Distance.MaxBotix/Driver/MaxBotix.enums.cs index 8b31aa0a42..1bc972d847 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Distance.MaxBotix/Driver/MaxBotix.enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Distance.MaxBotix/Driver/MaxBotix.enums.cs @@ -3,7 +3,7 @@ public partial class MaxBotix { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Distance.MaxBotix/Driver/Sensors.Distance.MaxBotix.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Distance.MaxBotix/Driver/Sensors.Distance.MaxBotix.csproj index 6f9cbeaa26..233efc917e 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Distance.MaxBotix/Driver/Sensors.Distance.MaxBotix.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Distance.MaxBotix/Driver/Sensors.Distance.MaxBotix.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Distance.MaxBotix/Samples/MaxBotix_Sample/MaxBotix_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Distance.MaxBotix/Samples/MaxBotix_Sample/MaxBotix_Sample.csproj index f45e574b78..442e13c818 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Distance.MaxBotix/Samples/MaxBotix_Sample/MaxBotix_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Distance.MaxBotix/Samples/MaxBotix_Sample/MaxBotix_Sample.csproj @@ -6,7 +6,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Vl53l0x/Driver/Sensors.Distance.Vl53l0x.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Vl53l0x/Driver/Sensors.Distance.Vl53l0x.csproj index 72fa456699..683357de86 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Vl53l0x/Driver/Sensors.Distance.Vl53l0x.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Vl53l0x/Driver/Sensors.Distance.Vl53l0x.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Vl53l0x/Driver/Vl53l0x.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Vl53l0x/Driver/Vl53l0x.Enums.cs index bc308765ce..00eba29ad0 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Vl53l0x/Driver/Vl53l0x.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Vl53l0x/Driver/Vl53l0x.Enums.cs @@ -6,7 +6,7 @@ public partial class Vl53l0x { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Vl53l0x/Driver/Vl53l0x.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Vl53l0x/Driver/Vl53l0x.cs index 0a02e4f120..73e5772ada 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Vl53l0x/Driver/Vl53l0x.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Vl53l0x/Driver/Vl53l0x.cs @@ -10,7 +10,7 @@ namespace Meadow.Foundation.Sensors.Distance /// /// Represents the Vl53l0x distance sensor /// - public partial class Vl53l0x : ByteCommsSensorBase, IRangeFinder + public partial class Vl53l0x : ByteCommsSensorBase, IRangeFinder, II2cPeripheral { /// /// Distance updated event @@ -36,20 +36,25 @@ public bool IsShutdown } /// - /// The distance to the measured object. + /// The distance to the measured object /// public Length? Distance { get; protected set; } = new Length(0); /// - /// Minimum valid distance in mm. + /// Minimum valid distance /// public Length MinimumDistance => new Length(30, Length.UnitType.Millimeters); /// - /// Maximum valid distance in mm (CurrentDistance returns -1 if above). + /// Maximum valid distance (CurrentDistance returns -1 if above) /// public Length MaximumDistance => new Length(2000, Length.UnitType.Millimeters); + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + readonly IDigitalOutputPort shutdownPort; byte stopVariable; @@ -61,8 +66,7 @@ public bool IsShutdown /// I2C address public Vl53l0x(II2cBus i2cBus, byte address = (byte)Addresses.Default) : this(i2cBus, null, address) - { - } + { } /// /// Creates a new Vl53l0x object @@ -106,18 +110,18 @@ protected async Task Initialize() throw new Exception("Failed to find expected ID register values"); } - Peripheral.WriteRegister(0x88, 0x00); - Peripheral.WriteRegister(0x80, 0x01); - Peripheral.WriteRegister(0xFF, 0x01); - Peripheral.WriteRegister(0x00, 0x00); + BusComms.WriteRegister(0x88, 0x00); + BusComms.WriteRegister(0x80, 0x01); + BusComms.WriteRegister(0xFF, 0x01); + BusComms.WriteRegister(0x00, 0x00); stopVariable = Read(0x91); - Peripheral.WriteRegister(0x00, 0x01); - Peripheral.WriteRegister(0xFF, 0x00); - Peripheral.WriteRegister(0x80, 0x00); + BusComms.WriteRegister(0x00, 0x01); + BusComms.WriteRegister(0xFF, 0x00); + BusComms.WriteRegister(0x80, 0x00); - Peripheral.WriteRegister((byte)Register.SystemSequenceConfig, 0xFF); + BusComms.WriteRegister((byte)Register.SystemSequenceConfig, 0xFF); var spadInfo = GetSpadInfo(); int spadCount = spadInfo.Item1; bool spad_is_aperture = spadInfo.Item2; @@ -125,11 +129,11 @@ protected async Task Initialize() byte[] ref_spad_map = new byte[7]; ref_spad_map[0] = (byte)Register.GlobalConfigSpadEnablesRef0; - Peripheral.WriteRegister(0xFF, 0x01); - Peripheral.WriteRegister((byte)Register.DynamicSpadRefEnStartOffset, 0x00); - Peripheral.WriteRegister((byte)Register.DynamicSpadNumRequestedRefSpad, 0x2C); - Peripheral.WriteRegister(0xFF, 0x00); - Peripheral.WriteRegister((byte)Register.GlobalConfigRefEnStartSelect, 0xB4); + BusComms.WriteRegister(0xFF, 0x01); + BusComms.WriteRegister((byte)Register.DynamicSpadRefEnStartOffset, 0x00); + BusComms.WriteRegister((byte)Register.DynamicSpadNumRequestedRefSpad, 0x2C); + BusComms.WriteRegister(0xFF, 0x00); + BusComms.WriteRegister((byte)Register.GlobalConfigRefEnStartSelect, 0xB4); var first_spad_to_enable = (spad_is_aperture) ? 12 : 0; var spads_enabled = 0; @@ -146,100 +150,100 @@ protected async Task Initialize() } } - Peripheral.WriteRegister(0xFF, 0x01); - Peripheral.WriteRegister(0x00, 0x00); - Peripheral.WriteRegister(0xFF, 0x00); - Peripheral.WriteRegister(0x09, 0x00); - Peripheral.WriteRegister(0x10, 0x00); - Peripheral.WriteRegister(0x11, 0x00); - Peripheral.WriteRegister(0x24, 0x01); - Peripheral.WriteRegister(0x25, 0xFF); - Peripheral.WriteRegister(0x75, 0x00); - Peripheral.WriteRegister(0xFF, 0x01); - Peripheral.WriteRegister(0x4E, 0x2C); - Peripheral.WriteRegister(0x48, 0x00); - Peripheral.WriteRegister(0x30, 0x20); - Peripheral.WriteRegister(0xFF, 0x00); - Peripheral.WriteRegister(0x30, 0x09); - Peripheral.WriteRegister(0x54, 0x00); - Peripheral.WriteRegister(0x31, 0x04); - Peripheral.WriteRegister(0x32, 0x03); - Peripheral.WriteRegister(0x40, 0x83); - Peripheral.WriteRegister(0x46, 0x25); - Peripheral.WriteRegister(0x60, 0x00); - Peripheral.WriteRegister(0x27, 0x00); - Peripheral.WriteRegister(0x50, 0x06); - Peripheral.WriteRegister(0x51, 0x00); - Peripheral.WriteRegister(0x52, 0x96); - Peripheral.WriteRegister(0x56, 0x08); - Peripheral.WriteRegister(0x57, 0x30); - Peripheral.WriteRegister(0x61, 0x00); - Peripheral.WriteRegister(0x62, 0x00); - Peripheral.WriteRegister(0x64, 0x00); - Peripheral.WriteRegister(0x65, 0x00); - Peripheral.WriteRegister(0x66, 0xA0); - Peripheral.WriteRegister(0xFF, 0x01); - Peripheral.WriteRegister(0x22, 0x32); - Peripheral.WriteRegister(0x47, 0x14); - Peripheral.WriteRegister(0x49, 0xFF); - Peripheral.WriteRegister(0x4A, 0x00); - Peripheral.WriteRegister(0xFF, 0x00); - Peripheral.WriteRegister(0x7A, 0x0A); - Peripheral.WriteRegister(0x7B, 0x00); - Peripheral.WriteRegister(0x78, 0x21); - Peripheral.WriteRegister(0xFF, 0x01); - Peripheral.WriteRegister(0x23, 0x34); - Peripheral.WriteRegister(0x42, 0x00); - Peripheral.WriteRegister(0x44, 0xFF); - Peripheral.WriteRegister(0x45, 0x26); - Peripheral.WriteRegister(0x46, 0x05); - Peripheral.WriteRegister(0x40, 0x40); - Peripheral.WriteRegister(0x0E, 0x06); - Peripheral.WriteRegister(0x20, 0x1A); - Peripheral.WriteRegister(0x43, 0x40); - Peripheral.WriteRegister(0xFF, 0x00); - Peripheral.WriteRegister(0x34, 0x03); - Peripheral.WriteRegister(0x35, 0x44); - Peripheral.WriteRegister(0xFF, 0x01); - Peripheral.WriteRegister(0x31, 0x04); - Peripheral.WriteRegister(0x4B, 0x09); - Peripheral.WriteRegister(0x4C, 0x05); - Peripheral.WriteRegister(0x4D, 0x04); - Peripheral.WriteRegister(0xFF, 0x00); - Peripheral.WriteRegister(0x44, 0x00); - Peripheral.WriteRegister(0x45, 0x20); - Peripheral.WriteRegister(0x47, 0x08); - Peripheral.WriteRegister(0x48, 0x28); - Peripheral.WriteRegister(0x67, 0x00); - Peripheral.WriteRegister(0x70, 0x04); - Peripheral.WriteRegister(0x71, 0x01); - Peripheral.WriteRegister(0x72, 0xFE); - Peripheral.WriteRegister(0x76, 0x00); - Peripheral.WriteRegister(0x77, 0x00); - Peripheral.WriteRegister(0xFF, 0x01); - Peripheral.WriteRegister(0x0D, 0x01); - Peripheral.WriteRegister(0xFF, 0x00); - Peripheral.WriteRegister(0x80, 0x01); - Peripheral.WriteRegister(0x01, 0xF8); - Peripheral.WriteRegister(0xFF, 0x01); - Peripheral.WriteRegister(0x8E, 0x01); - Peripheral.WriteRegister(0x00, 0x01); - Peripheral.WriteRegister(0xFF, 0x00); - Peripheral.WriteRegister(0x80, 0x00); - - Peripheral.WriteRegister((byte)Register.SystemInterruptConfigGpio, 0x04); + BusComms.WriteRegister(0xFF, 0x01); + BusComms.WriteRegister(0x00, 0x00); + BusComms.WriteRegister(0xFF, 0x00); + BusComms.WriteRegister(0x09, 0x00); + BusComms.WriteRegister(0x10, 0x00); + BusComms.WriteRegister(0x11, 0x00); + BusComms.WriteRegister(0x24, 0x01); + BusComms.WriteRegister(0x25, 0xFF); + BusComms.WriteRegister(0x75, 0x00); + BusComms.WriteRegister(0xFF, 0x01); + BusComms.WriteRegister(0x4E, 0x2C); + BusComms.WriteRegister(0x48, 0x00); + BusComms.WriteRegister(0x30, 0x20); + BusComms.WriteRegister(0xFF, 0x00); + BusComms.WriteRegister(0x30, 0x09); + BusComms.WriteRegister(0x54, 0x00); + BusComms.WriteRegister(0x31, 0x04); + BusComms.WriteRegister(0x32, 0x03); + BusComms.WriteRegister(0x40, 0x83); + BusComms.WriteRegister(0x46, 0x25); + BusComms.WriteRegister(0x60, 0x00); + BusComms.WriteRegister(0x27, 0x00); + BusComms.WriteRegister(0x50, 0x06); + BusComms.WriteRegister(0x51, 0x00); + BusComms.WriteRegister(0x52, 0x96); + BusComms.WriteRegister(0x56, 0x08); + BusComms.WriteRegister(0x57, 0x30); + BusComms.WriteRegister(0x61, 0x00); + BusComms.WriteRegister(0x62, 0x00); + BusComms.WriteRegister(0x64, 0x00); + BusComms.WriteRegister(0x65, 0x00); + BusComms.WriteRegister(0x66, 0xA0); + BusComms.WriteRegister(0xFF, 0x01); + BusComms.WriteRegister(0x22, 0x32); + BusComms.WriteRegister(0x47, 0x14); + BusComms.WriteRegister(0x49, 0xFF); + BusComms.WriteRegister(0x4A, 0x00); + BusComms.WriteRegister(0xFF, 0x00); + BusComms.WriteRegister(0x7A, 0x0A); + BusComms.WriteRegister(0x7B, 0x00); + BusComms.WriteRegister(0x78, 0x21); + BusComms.WriteRegister(0xFF, 0x01); + BusComms.WriteRegister(0x23, 0x34); + BusComms.WriteRegister(0x42, 0x00); + BusComms.WriteRegister(0x44, 0xFF); + BusComms.WriteRegister(0x45, 0x26); + BusComms.WriteRegister(0x46, 0x05); + BusComms.WriteRegister(0x40, 0x40); + BusComms.WriteRegister(0x0E, 0x06); + BusComms.WriteRegister(0x20, 0x1A); + BusComms.WriteRegister(0x43, 0x40); + BusComms.WriteRegister(0xFF, 0x00); + BusComms.WriteRegister(0x34, 0x03); + BusComms.WriteRegister(0x35, 0x44); + BusComms.WriteRegister(0xFF, 0x01); + BusComms.WriteRegister(0x31, 0x04); + BusComms.WriteRegister(0x4B, 0x09); + BusComms.WriteRegister(0x4C, 0x05); + BusComms.WriteRegister(0x4D, 0x04); + BusComms.WriteRegister(0xFF, 0x00); + BusComms.WriteRegister(0x44, 0x00); + BusComms.WriteRegister(0x45, 0x20); + BusComms.WriteRegister(0x47, 0x08); + BusComms.WriteRegister(0x48, 0x28); + BusComms.WriteRegister(0x67, 0x00); + BusComms.WriteRegister(0x70, 0x04); + BusComms.WriteRegister(0x71, 0x01); + BusComms.WriteRegister(0x72, 0xFE); + BusComms.WriteRegister(0x76, 0x00); + BusComms.WriteRegister(0x77, 0x00); + BusComms.WriteRegister(0xFF, 0x01); + BusComms.WriteRegister(0x0D, 0x01); + BusComms.WriteRegister(0xFF, 0x00); + BusComms.WriteRegister(0x80, 0x01); + BusComms.WriteRegister(0x01, 0xF8); + BusComms.WriteRegister(0xFF, 0x01); + BusComms.WriteRegister(0x8E, 0x01); + BusComms.WriteRegister(0x00, 0x01); + BusComms.WriteRegister(0xFF, 0x00); + BusComms.WriteRegister(0x80, 0x00); + + BusComms.WriteRegister((byte)Register.SystemInterruptConfigGpio, 0x04); var gpio_hv_mux_active_high = Read((byte)Register.GpioHvMuxActiveHigh); - Peripheral.WriteRegister((byte)Register.GpioHvMuxActiveHigh, (byte)(gpio_hv_mux_active_high & ~0x10)); + BusComms.WriteRegister((byte)Register.GpioHvMuxActiveHigh, (byte)(gpio_hv_mux_active_high & ~0x10)); - Peripheral.WriteRegister((byte)Register.GpioHvMuxActiveHigh, 0x01); - Peripheral.WriteRegister((byte)Register.SystemSequenceConfig, 0xE8); + BusComms.WriteRegister((byte)Register.GpioHvMuxActiveHigh, 0x01); + BusComms.WriteRegister((byte)Register.SystemSequenceConfig, 0xE8); - Peripheral.WriteRegister((byte)Register.SystemSequenceConfig, 0x01); + BusComms.WriteRegister((byte)Register.SystemSequenceConfig, 0x01); PerformSingleRefCalibration(0x40); - Peripheral.WriteRegister((byte)Register.SystemSequenceConfig, 0x02); + BusComms.WriteRegister((byte)Register.SystemSequenceConfig, 0x02); PerformSingleRefCalibration(0x00); - Peripheral.WriteRegister((byte)Register.SystemSequenceConfig, 0xE8); + BusComms.WriteRegister((byte)Register.SystemSequenceConfig, 0xE8); } /// @@ -285,7 +289,7 @@ public void SetAddress(byte newAddress) return; byte address = (byte)(newAddress & 0x7F); - Peripheral.WriteRegister((byte)Register.I2CSlaveDeviceAddress, address); + BusComms.WriteRegister((byte)Register.I2CSlaveDeviceAddress, address); } /// @@ -317,19 +321,19 @@ public async Task ShutDown(bool state) /// protected Tuple GetSpadInfo() { - Peripheral.WriteRegister(0x80, 0x01); - Peripheral.WriteRegister(0xFF, 0x01); - Peripheral.WriteRegister(0x00, 0x00); - Peripheral.WriteRegister(0xFF, 0x06); + BusComms.WriteRegister(0x80, 0x01); + BusComms.WriteRegister(0xFF, 0x01); + BusComms.WriteRegister(0x00, 0x00); + BusComms.WriteRegister(0xFF, 0x06); var result = (byte)(Read(0x83) | 0x04); - Peripheral.WriteRegister(0x83, result); + BusComms.WriteRegister(0x83, result); - Peripheral.WriteRegister(0xFF, 0x07); - Peripheral.WriteRegister(0x81, 0x01); - Peripheral.WriteRegister(0x94, 0x6B); + BusComms.WriteRegister(0xFF, 0x07); + BusComms.WriteRegister(0x81, 0x01); + BusComms.WriteRegister(0x94, 0x6B); - Peripheral.WriteRegister(0x83, 0x00); + BusComms.WriteRegister(0x83, 0x00); int tCount = 0; while (Read(0x83) == 0x00) @@ -342,21 +346,21 @@ protected Tuple GetSpadInfo() } } - Peripheral.WriteRegister(0x83, 0x01); + BusComms.WriteRegister(0x83, 0x01); var tmp = Read(0x92); var count = tmp & 0x7F; var is_aperture = ((tmp >> 7) & 0x01) == 1; - Peripheral.WriteRegister(0x81, 0x00); - Peripheral.WriteRegister(0xFF, 0x06); + BusComms.WriteRegister(0x81, 0x00); + BusComms.WriteRegister(0xFF, 0x06); var t = (byte)(Read(0x83) & ~0x04); - Peripheral.WriteRegister(0xFF, t); + BusComms.WriteRegister(0xFF, t); - Peripheral.WriteRegister(0xFF, 0x01); - Peripheral.WriteRegister(0x00, 0x01); - Peripheral.WriteRegister(0xFF, 0x00); - Peripheral.WriteRegister(0x80, 0x00); + BusComms.WriteRegister(0xFF, 0x01); + BusComms.WriteRegister(0x00, 0x01); + BusComms.WriteRegister(0xFF, 0x00); + BusComms.WriteRegister(0x80, 0x00); return new Tuple(count, is_aperture); } @@ -368,7 +372,7 @@ protected Tuple GetSpadInfo() /// protected void PerformSingleRefCalibration(byte vhvInitByte) { - Peripheral.WriteRegister((byte)Register.RangeStart, (byte)(0x01 | vhvInitByte & 0xFF)); + BusComms.WriteRegister((byte)Register.RangeStart, (byte)(0x01 | vhvInitByte & 0xFF)); int tCount = 0; @@ -382,33 +386,33 @@ protected void PerformSingleRefCalibration(byte vhvInitByte) } } - Peripheral.WriteRegister((byte)Register.GpioHvMuxActiveHigh, 0x01); - Peripheral.WriteRegister((byte)Register.RangeStart, 0x00); + BusComms.WriteRegister((byte)Register.GpioHvMuxActiveHigh, 0x01); + BusComms.WriteRegister((byte)Register.RangeStart, 0x00); } byte Read(byte address) { - var result = Peripheral.ReadRegister(address); + var result = BusComms.ReadRegister(address); return result; } int Read16(byte address) { - //var result = Peripheral.ReadRegisters(address, 2); - Peripheral.ReadRegister(address, ReadBuffer.Span[0..2]); + //var result = BusComms.ReadRegisters(address, 2); + BusComms.ReadRegister(address, ReadBuffer.Span[0..2]); return (ReadBuffer.Span[0] << 8) | ReadBuffer.Span[1]; } async Task GetRawRangeData() { - Peripheral.WriteRegister(0x80, 0x01); - Peripheral.WriteRegister(0xFF, 0x01); - Peripheral.WriteRegister(0x00, 0x00); - Peripheral.WriteRegister(0x91, stopVariable); - Peripheral.WriteRegister(0x00, 0x01); - Peripheral.WriteRegister(0xFF, 0x00); - Peripheral.WriteRegister(0x80, 0x00); - Peripheral.WriteRegister((byte)Register.RangeStart, 0x01); + BusComms.WriteRegister(0x80, 0x01); + BusComms.WriteRegister(0xFF, 0x01); + BusComms.WriteRegister(0x00, 0x00); + BusComms.WriteRegister(0x91, stopVariable); + BusComms.WriteRegister(0x00, 0x01); + BusComms.WriteRegister(0xFF, 0x00); + BusComms.WriteRegister(0x80, 0x00); + BusComms.WriteRegister((byte)Register.RangeStart, 0x01); int tCount = 0; while ((byte)(Read((byte)Register.RangeStart) & 0x01) > 0) @@ -435,7 +439,7 @@ async Task GetRawRangeData() } var range_mm = Read16((byte)Register.ResultRangeStatus + 10); - Peripheral.WriteRegister((byte)Register.GpioHvMuxActiveHigh, 0x01); + BusComms.WriteRegister((byte)Register.GpioHvMuxActiveHigh, 0x01); return range_mm; } diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Vl53l0x/Samples/Vl53l0x_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Vl53l0x/Samples/Vl53l0x_Sample/MeadowApp.cs index 65d6be25ea..7bbbed3b6c 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Vl53l0x/Samples/Vl53l0x_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Vl53l0x/Samples/Vl53l0x_Sample/MeadowApp.cs @@ -1,10 +1,10 @@ -using System; -using System.Threading.Tasks; -using Meadow; +using Meadow; using Meadow.Devices; using Meadow.Foundation.Sensors.Distance; using Meadow.Hardware; using Meadow.Units; +using System; +using System.Threading.Tasks; using LU = Meadow.Units.Length.UnitType; namespace Sensors.Distance.Vl53l0x_Sample @@ -20,7 +20,7 @@ public override Task Initialize() Resolver.Log.Info("Initializing hardware..."); var i2cBus = Device.CreateI2cBus(I2cBusSpeed.FastPlus); - sensor = new Vl53l0x(i2cBus, (byte)Vl53l0x.Addresses.Default); + sensor = new Vl53l0x(i2cBus); sensor.DistanceUpdated += Sensor_Updated; @@ -39,10 +39,10 @@ private void Sensor_Updated(object sender, IChangeResult result) if (result.New == null) { return; } if (result.New < new Length(0, LU.Millimeters)) - { + { Resolver.Log.Info("out of range."); } - else + else { Resolver.Log.Info($"{result.New.Millimeters}mm / {result.New.Inches:n3}\""); } diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Vl53l0x/Samples/Vl53l0x_Sample/Vl53l0x_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Vl53l0x/Samples/Vl53l0x_Sample/Vl53l0x_Sample.csproj index 25a856b8d8..85df091c69 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Vl53l0x/Samples/Vl53l0x_Sample/Vl53l0x_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Distance.Vl53l0x/Samples/Vl53l0x_Sample/Vl53l0x_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Ags01Db/Driver/Ags01Db.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Ags01Db/Driver/Ags01Db.Enums.cs index 62da821d61..dd97bda25a 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Ags01Db/Driver/Ags01Db.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Ags01Db/Driver/Ags01Db.Enums.cs @@ -8,7 +8,7 @@ public partial class Ags01Db { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Ags01Db/Driver/Ags01Db.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Ags01Db/Driver/Ags01Db.cs index 933acd97c2..5c5f39cac9 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Ags01Db/Driver/Ags01Db.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Ags01Db/Driver/Ags01Db.cs @@ -1,7 +1,7 @@ -using System; -using System.Threading.Tasks; using Meadow.Hardware; using Meadow.Units; +using System; +using System.Threading.Tasks; namespace Meadow.Foundation.Sensors.Environmental { @@ -10,7 +10,7 @@ namespace Meadow.Foundation.Sensors.Environmental /// Pinout (left to right, label side down): VDD, SDA, GND, SCL /// Note: requires pullup resistors on SDA/SCL /// - public partial class Ags01Db : ByteCommsSensorBase + public partial class Ags01Db : ByteCommsSensorBase, II2cPeripheral { const byte CRC_POLYNOMIAL = 0x31; const byte CRC_INIT = 0xFF; @@ -30,6 +30,11 @@ public partial class Ags01Db : ByteCommsSensorBase /// public Concentration? Concentration { get; private set; } + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + /// /// Create a new Ags01Db object /// @@ -41,26 +46,22 @@ public Ags01Db(II2cBus i2cBus, byte address = (byte)Addresses.Default) } /// - /// Get ASG01DB VOC Gas Concentration and - /// Update the Concentration property. + /// Get ASG01DB VOC Gas Concentration and update the Concentration property /// - protected override Task ReadSensor() + protected override Task ReadSensor() { - return Task.Run(() => - { - WriteBuffer.Span[0] = ASG_DATA_MSB; - WriteBuffer.Span[1] = ASG_DATA_LSB; + WriteBuffer.Span[0] = ASG_DATA_MSB; + WriteBuffer.Span[1] = ASG_DATA_LSB; - Peripheral.Exchange(WriteBuffer.Span[0..1], ReadBuffer.Span); + BusComms.Exchange(WriteBuffer.Span[0..1], ReadBuffer.Span); - var value = ReadBuffer.Span[0] << 8 | ReadBuffer.Span[1]; + var value = ReadBuffer.Span[0] << 8 | ReadBuffer.Span[1]; - var voc = value / 10.0;//should be ppm + var voc = value / 10.0;//ppm - Concentration = new Concentration(voc, Units.Concentration.UnitType.PartsPerMillion); + Concentration = new Concentration(voc, Units.Concentration.UnitType.PartsPerMillion); - return Concentration.Value; - }); + return Task.FromResult(Concentration.Value); } /// @@ -74,10 +75,10 @@ public byte GetVersion() WriteBuffer.Span[0] = ASG_VERSION_MSB; WriteBuffer.Span[1] = ASG_VERSION_LSB; - Peripheral.Exchange(WriteBuffer.Span[0..1], ReadBuffer.Span[0..1]); + BusComms.Exchange(WriteBuffer.Span[0..1], ReadBuffer.Span[0..1]); // CRC check - if (!CheckCrc8(ReadBuffer.Slice(0, 1).ToArray(), 1, ReadBuffer.Span[1])) + if (!CheckCrc8(ReadBuffer[..1].ToArray(), 1, ReadBuffer.Span[1])) { return unchecked((byte)-1); } diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Ags01Db/Driver/Sensors.Environmental.Ags01Db.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Ags01Db/Driver/Sensors.Environmental.Ags01Db.csproj index 3fa445deee..6521e34226 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Ags01Db/Driver/Sensors.Environmental.Ags01Db.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Ags01Db/Driver/Sensors.Environmental.Ags01Db.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Ags01Db/Samples/Ags01Db_Sample/Ags01Db_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Ags01Db/Samples/Ags01Db_Sample/Ags01Db_Sample.csproj index 24305de7ec..23b61a416e 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Ags01Db/Samples/Ags01Db_Sample/Ags01Db_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Ags01Db/Samples/Ags01Db_Sample/Ags01Db_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Ens160/Driver/Ens160.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Ens160/Driver/Ens160.cs index 998cfaa5db..44b8b02b2b 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Ens160/Driver/Ens160.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Ens160/Driver/Ens160.cs @@ -1,21 +1,21 @@ -using System; -using System.Threading.Tasks; using Meadow.Hardware; using Meadow.Peripherals.Sensors; using Meadow.Peripherals.Sensors.Environmental; using Meadow.Units; using Meadow.Utilities; +using System; +using System.Threading.Tasks; namespace Meadow.Foundation.Sensors.Environmental { /// /// Represents an ENS160 Digital Metal-Oxide Multi-Gas Sensor /// - public partial class Ens160 : - ByteCommsSensorBase<(Concentration? CO2Concentration, - Concentration? EthanolConcentration, - Concentration? TVOCConcentration)>, - IConcentrationSensor + public partial class Ens160 : + ByteCommsSensorBase<(Concentration? CO2Concentration, + Concentration? EthanolConcentration, + Concentration? TVOCConcentration)>, + IConcentrationSensor, II2cPeripheral { /// /// Raised when the CO2 concentration changes @@ -62,10 +62,15 @@ public partial class Ens160 : /// public OperatingMode CurrentOperatingMode { - get => (OperatingMode)Peripheral.ReadRegister((byte)Registers.OPMODE); - set => Peripheral.WriteRegister((byte)Registers.OPMODE, (byte)value); + get => (OperatingMode)BusComms.ReadRegister((byte)Registers.OPMODE); + set => BusComms.WriteRegister((byte)Registers.OPMODE, (byte)value); } + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + /// /// Create a new ENS160 object /// @@ -88,8 +93,8 @@ public Ens160(II2cBus i2cBus, byte address = (byte)Addresses.Default) /// protected async Task Initialize() { - Peripheral.WriteRegister((byte)Registers.COMMAND, (byte)Commands.NOP); - Peripheral.WriteRegister((byte)Registers.COMMAND, (byte)Commands.CLRGPR); + BusComms.WriteRegister((byte)Registers.COMMAND, (byte)Commands.NOP); + BusComms.WriteRegister((byte)Registers.COMMAND, (byte)Commands.CLRGPR); await Task.Delay(10); await Reset(); @@ -101,7 +106,7 @@ protected async Task Initialize() /// public Task Reset() { - Peripheral.WriteRegister((byte)Registers.OPMODE, (byte)OperatingMode.Reset); + BusComms.WriteRegister((byte)Registers.OPMODE, (byte)OperatingMode.Reset); return Task.Delay(10); } @@ -112,7 +117,7 @@ public Task Reset() /// ID as a ushort (2 bytes) public ushort GetDeviceID() { - return Peripheral.ReadRegisterAsUShort((byte)Registers.PART_ID); + return BusComms.ReadRegisterAsUShort((byte)Registers.PART_ID); } /// @@ -121,11 +126,11 @@ public ushort GetDeviceID() /// The major, minor, release values as a ttuple of bytes public (byte Major, byte Minor, byte Release) GetFirmwareVersion() { - Peripheral.WriteRegister((byte)Registers.COMMAND, (byte)Commands.GET_APPVER); + BusComms.WriteRegister((byte)Registers.COMMAND, (byte)Commands.GET_APPVER); var version = new byte[3]; - Peripheral.ReadRegister((byte)Registers.GPR_READ_4); + BusComms.ReadRegister((byte)Registers.GPR_READ_4); return (version[0], version[1], version[2]); } @@ -135,7 +140,7 @@ public ushort GetDeviceID() /// void ClearGPRRegisters() { - Peripheral.WriteRegister((byte)Registers.COMMAND, (byte)Commands.CLRGPR); + BusComms.WriteRegister((byte)Registers.COMMAND, (byte)Commands.CLRGPR); } /// @@ -146,7 +151,7 @@ public void SetTemperature(Units.Temperature ambientTemperature) { ushort temp = (ushort)(ambientTemperature.Kelvin * 64); - Peripheral.WriteRegister((byte)Registers.TEMP_IN, temp); + BusComms.WriteRegister((byte)Registers.TEMP_IN, temp); } /// @@ -157,7 +162,7 @@ public void SetHumidity(RelativeHumidity humidity) { ushort hum = (ushort)(humidity.Percent * 64); - Peripheral.WriteRegister((byte)Registers.RH_IN, hum); + BusComms.WriteRegister((byte)Registers.RH_IN, hum); } /// @@ -165,7 +170,7 @@ public void SetHumidity(RelativeHumidity humidity) /// public UBAAirQualityIndex GetAirQualityIndex() { - var value = Peripheral.ReadRegister((byte)Registers.DATA_AQI); + var value = BusComms.ReadRegister((byte)Registers.DATA_AQI); var aqi = value >> 5; @@ -174,33 +179,33 @@ public UBAAirQualityIndex GetAirQualityIndex() bool IsNewDataAvailable() { - var value = Peripheral.ReadRegister((byte)Registers.DATA_STATUS); + var value = BusComms.ReadRegister((byte)Registers.DATA_STATUS); return BitHelpers.GetBitValue(value, 0x02); } bool IsNewGPRAvailable() { - var value = Peripheral.ReadRegister((byte)Registers.DATA_STATUS); + var value = BusComms.ReadRegister((byte)Registers.DATA_STATUS); return BitHelpers.GetBitValue(value, 0x03); } Concentration GetTotalVolotileOrganicCompounds() { - var con = Peripheral.ReadRegisterAsUShort((byte)Registers.DATA_TVOC); + var con = BusComms.ReadRegisterAsUShort((byte)Registers.DATA_TVOC); return new Concentration(con, Units.Concentration.UnitType.PartsPerBillion); } Concentration GetCO2Concentration() { - var con = Peripheral.ReadRegisterAsUShort((byte)Registers.DATA_ECO2); + var con = BusComms.ReadRegisterAsUShort((byte)Registers.DATA_ECO2); return new Concentration(con, Units.Concentration.UnitType.PartsPerMillion); } Concentration GetEthanolConcentration() { - var con = Peripheral.ReadRegisterAsUShort((byte)Registers.DATA_ETOH); + var con = BusComms.ReadRegisterAsUShort((byte)Registers.DATA_ETOH); return new Concentration(con, Units.Concentration.UnitType.PartsPerBillion); } @@ -210,7 +215,7 @@ Concentration GetEthanolConcentration() /// Temperature public Units.Temperature GetTemperature() { - var temp = Peripheral.ReadRegisterAsUShort((byte)Registers.DATA_T); + var temp = BusComms.ReadRegisterAsUShort((byte)Registers.DATA_T); return new Units.Temperature(temp / 64.0, Units.Temperature.UnitType.Kelvin); } @@ -220,7 +225,7 @@ public Units.Temperature GetTemperature() /// public RelativeHumidity GetHumidity() { - var hum = Peripheral.ReadRegisterAsUShort((byte)Registers.DATA_T); + var hum = BusComms.ReadRegisterAsUShort((byte)Registers.DATA_T); return new RelativeHumidity(hum / 512.0); } @@ -246,27 +251,24 @@ public override void StopUpdating() /// Get Scdx40 C02 Gas Concentration and /// Update the Concentration property /// - protected override async Task<(Concentration? CO2Concentration, + protected override Task<(Concentration? CO2Concentration, Concentration? EthanolConcentration, Concentration? TVOCConcentration)> ReadSensor() { - return await Task.Run(() => - { - (Concentration? CO2Concentration, Concentration? EthanolConcentration, Concentration? TVOCConcentration) conditions; + (Concentration? CO2Concentration, Concentration? EthanolConcentration, Concentration? TVOCConcentration) conditions; - conditions.CO2Concentration = GetCO2Concentration(); - conditions.EthanolConcentration = GetEthanolConcentration(); - conditions.TVOCConcentration = GetTotalVolotileOrganicCompounds(); + conditions.CO2Concentration = GetCO2Concentration(); + conditions.EthanolConcentration = GetEthanolConcentration(); + conditions.TVOCConcentration = GetTotalVolotileOrganicCompounds(); - return conditions; - }); + return Task.FromResult(conditions); } /// /// Raise change events for subscribers /// /// The change result with the current sensor data - protected void RaiseChangedAndNotify(IChangeResult<(Concentration? CO2Concentration, Concentration? EthanolConcentration, Concentration? TVOCConcentration)> changeResult) + protected override void RaiseEventsAndNotify(IChangeResult<(Concentration? CO2Concentration, Concentration? EthanolConcentration, Concentration? TVOCConcentration)> changeResult) { if (changeResult.New.CO2Concentration is { } concentration) { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Ens160/Driver/Sensors.Environmental.Ens160.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Ens160/Driver/Sensors.Environmental.Ens160.csproj index 492a80dc04..be41a70ceb 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Ens160/Driver/Sensors.Environmental.Ens160.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Ens160/Driver/Sensors.Environmental.Ens160.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Ens160/Samples/Ens160_Sample/Ens160_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Ens160/Samples/Ens160_Sample/Ens160_Sample.csproj index a0633d896f..8c07ca3633 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Ens160/Samples/Ens160_Sample/Ens160_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Ens160/Samples/Ens160_Sample/Ens160_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Ens160/Samples/Ens160_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Ens160/Samples/Ens160_Sample/MeadowApp.cs index 3f34254395..4e22b203a1 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Ens160/Samples/Ens160_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Ens160/Samples/Ens160_Sample/MeadowApp.cs @@ -1,8 +1,8 @@ -using System; -using System.Threading.Tasks; -using Meadow; +using Meadow; using Meadow.Devices; using Meadow.Foundation.Sensors.Environmental; +using System; +using System.Threading.Tasks; namespace Sensors.Environmental.Ens160_Sample { @@ -17,10 +17,10 @@ public override Task Initialize() Resolver.Log.Info("Initializing..."); var i2cBus = Device.CreateI2cBus(Meadow.Hardware.I2cBusSpeed.Standard); - + sensor = new Ens160(i2cBus, (byte)Ens160.Addresses.Address_0x53); - + var consumer = Ens160.CreateObserver( handler: result => { @@ -46,7 +46,7 @@ public override Task Initialize() Resolver.Log.Info($" CO2 Concentration: {result.New.CO2Concentration?.PartsPerMillion:N0}ppm"); Resolver.Log.Info($" Ethanol Concentraion: {result.New.EthanolConcentration?.PartsPerBillion:N0}ppb"); Resolver.Log.Info($" TVOC Concentraion: {result.New.TVOCConcentration?.PartsPerBillion:N0}ppb"); - Resolver.Log.Info($" AQI: {sensor.GetAirQualityIndex()}"); + Resolver.Log.Info($" AQI: {sensor.GetAirQualityIndex()}"); }; } diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.MiniPID2/Datasheet/23-minipid2-manual-3-pin-v1.4-final-version.pdf b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.MiniPID2/Datasheet/23-minipid2-manual-3-pin-v1.4-final-version.pdf new file mode 100644 index 0000000000..487783c6be Binary files /dev/null and b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.MiniPID2/Datasheet/23-minipid2-manual-3-pin-v1.4-final-version.pdf differ diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.MiniPID2/Driver/MiniPID2.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.MiniPID2/Driver/MiniPID2.Enums.cs new file mode 100644 index 0000000000..8ece9f0cd7 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.MiniPID2/Driver/MiniPID2.Enums.cs @@ -0,0 +1,44 @@ +namespace Meadow.Foundation.Sensors.Environmental +{ + partial class MiniPID2 + { + /// + /// The MiniPID 2 Volatile Organic Compounds (VOC) sensor variant + /// + public enum MiniPID2Type : byte + { + /// + /// MiniPID 2 PartsPerMillion VOC Sensor + /// + PPM, + /// + /// MiniPID 2 PartsPerMillion Wide Range VOC Sensor + /// + PPM_WR, + /// + /// MiniPID 2 PartsPerBillion VOC Sensor + /// + PPB, + /// + /// MiniPID 2 PartsPerBillion Wide Range VOC Sensor + /// + PPB_WR, + /// + /// MiniPID 2 High Sensitivity VOC Sensor + /// + HS, + /// + /// MiniPID 2 10.0 eV VOC Sensor + /// + _10ev, + /// + /// MiniPID 2 11.7 eV VOC Sensor + /// + _11_7eV, + /// + /// The number of supported sensors + /// + count + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.MiniPID2/Driver/MiniPID2.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.MiniPID2/Driver/MiniPID2.cs new file mode 100644 index 0000000000..302bef2418 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.MiniPID2/Driver/MiniPID2.cs @@ -0,0 +1,222 @@ +using Meadow.Hardware; +using Meadow.Peripherals.Sensors.Environmental; +using Meadow.Units; +using System; +using System.Threading.Tasks; + +namespace Meadow.Foundation.Sensors.Environmental +{ + /// + /// Represents an IonScience MiniPID2 analog photoionisation (PID) Volatile Organic Compounds (VOC) sensor + /// + public partial class MiniPID2 : SamplingSensorBase, IConcentrationSensor + { + /// + /// Raised when the VOC concentration changes + /// + public event EventHandler> ConcentrationUpdated = delegate { }; + + /// + /// Raised when the VOC concentration changes + /// + public event EventHandler> VOCConcentrationUpdated = delegate { }; + + /// + /// The current VOC concentration value + /// + public Concentration? Concentration { get; protected set; } + + /// + /// The MiniPID2 device type + /// + public MiniPID2Type MiniPID2DeviceType { get; protected set; } + + /// + /// AnalogInputPort connected to temperature sensor + /// + protected IAnalogInputPort AnalogInputPort { get; } + + SensorCalibration[] calibrations; + + /// + /// Create a new MiniPID2 object + /// + /// The analog data pin connected to the sensor + /// The MiniPID sensor type + /// How many samples to take during a given reading. + /// These are automatically averaged to reduce noise + /// The time between sample readings + public MiniPID2(IPin analogPin, + MiniPID2Type pid2Type, + int sampleCount = 5, + TimeSpan? sampleInterval = null) : + this(analogPin.CreateAnalogInputPort(sampleCount, + sampleInterval ?? TimeSpan.FromMilliseconds(40), + new Voltage(3.3, Voltage.UnitType.Volts)), pid2Type) + { + } + + /// + /// Create a new MiniPID2 object + /// + /// The analog port connected to the sensor + /// The MiniPID sensor type + public MiniPID2(IAnalogInputPort analogInputPort, MiniPID2Type pid2Type) + { + MiniPID2DeviceType = pid2Type; + AnalogInputPort = analogInputPort; + Initialize(); + } + + /// + /// Set the sensor voltage offset + /// Useful for compensating for air conditions + /// + /// Offset voltage + /// The sensor to change + public void SetOffsetForSensor(Voltage offset, MiniPID2Type sensorType) + { + calibrations[(int)sensorType].Offset = offset; + } + + /// + /// Get the voltage offset for a sensor + /// + /// The sensor + /// The offset as voltage + public Voltage GetOffsetForSensor(MiniPID2Type sensorType) + => calibrations[(int)sensorType].Offset; + + /// + /// Initialize the sensor + /// + void Initialize() + { + static SensorCalibration GetCalibration(int airOffsetLow, int airOffsetHigh, double sensitivity, double minimumPPB) + { + return new SensorCalibration(new Voltage((airOffsetLow + airOffsetHigh) / 2, Voltage.UnitType.Millivolts), + new Voltage(sensitivity, Voltage.UnitType.Millivolts), + new Concentration(minimumPPB, Units.Concentration.UnitType.PartsPerBillion)); + } + + calibrations = new SensorCalibration[(int)MiniPID2Type.count]; + + calibrations[(int)MiniPID2Type.PPM] = GetCalibration(51, 65, 65, 100); + calibrations[(int)MiniPID2Type.PPM_WR] = GetCalibration(51, 64, 40, 500); + calibrations[(int)MiniPID2Type.PPB] = GetCalibration(51, 80, 30, 1); + calibrations[(int)MiniPID2Type.PPB_WR] = GetCalibration(51, 80, 5, 20); + calibrations[(int)MiniPID2Type.HS] = GetCalibration(100, 200, 600, 0.5); + calibrations[(int)MiniPID2Type._10ev] = GetCalibration(51, 80, 15, 5); + calibrations[(int)MiniPID2Type._11_7eV] = GetCalibration(51, 90, 1, 100); + + AnalogInputPort.Subscribe + ( + IAnalogInputPort.CreateObserver( + result => + { + ChangeResult changeResult = new ChangeResult() + { + New = VoltageToConcentration(result.New), + Old = Concentration + }; + Concentration = changeResult.New; + RaiseEventsAndNotify(changeResult); + } + ) + ); + } + + /// + /// Convenience method to get the current concentration. For frequent reads, use + /// StartSampling() and StopSampling() in conjunction with the SampleBuffer. + /// + /// The concentration averages of the given sample count + protected override async Task ReadSensor() + { + var voltage = await AnalogInputPort.Read(); + var newConcentration = VoltageToConcentration(voltage); + Concentration = newConcentration; + return newConcentration; + } + + /// + /// Starts updating the sensor on the updateInterval frequency specified + /// + public override void StartUpdating(TimeSpan? updateInterval = null) + { + lock (samplingLock) + { + if (IsSampling) { return; } + IsSampling = true; + AnalogInputPort.StartUpdating(updateInterval); + } + } + + /// + /// Stops sampling the concentration + /// + public override void StopUpdating() + { + lock (samplingLock) + { + if (!IsSampling) { return; } + IsSampling = false; + AnalogInputPort.StopUpdating(); + } + } + + /// + /// Method to notify subscribers to ConcentrationUpdated event handler + /// + /// + protected override void RaiseEventsAndNotify(IChangeResult changeResult) + { + ConcentrationUpdated?.Invoke(this, changeResult); + base.RaiseEventsAndNotify(changeResult); + } + + /// + /// Converts voltage to Concentration + /// + /// + /// Concentration + protected Concentration VoltageToConcentration(Voltage voltage) + { + int i = (int)MiniPID2DeviceType; + + var ppm = (voltage.Millivolts - calibrations[i].Offset.Millivolts) / calibrations[i].Sensitivity.Millivolts; + + if (ppm < calibrations[i].MinimumDetectionLimit.PartsPerMillion) + { + return calibrations[i].MinimumDetectionLimit; + } + + return new Concentration(ppm, Units.Concentration.UnitType.PartsPerMillion); + } + + struct SensorCalibration + { + public SensorCalibration(Voltage offset, Voltage sensitivity, Concentration minimumDetectionLimit) + { + Offset = offset; + Sensitivity = sensitivity; + MinimumDetectionLimit = minimumDetectionLimit; + } + + /// + /// The offset to compensate for air quality/conditions + /// + public Voltage Offset { get; set; } + + /// + /// Sensitivity mv/ppm as voltage + /// + public Voltage Sensitivity { get; set; } + + /// + /// The minimum concentration returned by the sensor + /// + public Concentration MinimumDetectionLimit { get; set; } + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.MiniPID2/Driver/Sensors.Environmental.MiniPID2.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.MiniPID2/Driver/Sensors.Environmental.MiniPID2.csproj new file mode 100644 index 0000000000..a69b3481a4 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.MiniPID2/Driver/Sensors.Environmental.MiniPID2.csproj @@ -0,0 +1,22 @@ + + + true + icon.png + Wilderness Labs, Inc + netstandard2.1 + Library + MiniPID2 + Wilderness Labs, Inc + http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ + Meadow.Foundation.Sensors.Environmental.MiniPID2 + https://github.com/WildernessLabs/Meadow.Foundation + Meadow,Meadow.Foundation,Environmental,MiniPID2,VOC,photoionisation,PID,gas,AQI,air,quality + 0.1.0 + true + MiniPID2 analog photoionisation (PID) VOC sensor + + + + + + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.MiniPID2/Samples/MiniPID2_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.MiniPID2/Samples/MiniPID2_Sample/MeadowApp.cs new file mode 100644 index 0000000000..ea59c52d29 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.MiniPID2/Samples/MiniPID2_Sample/MeadowApp.cs @@ -0,0 +1,54 @@ +using Meadow; +using Meadow.Devices; +using Meadow.Foundation.Sensors.Environmental; +using System; +using System.Threading.Tasks; + +namespace Sensors.Environmental.Ens160_Sample +{ + public class MeadowApp : App + { + // + + MiniPID2 sensor; + + public override Task Initialize() + { + Resolver.Log.Info("Initializing..."); + + sensor = new MiniPID2(Device.Pins.A01, MiniPID2.MiniPID2Type.PPB_WR); + + var consumer = MiniPID2.CreateObserver( + handler: result => + { + Resolver.Log.Info($"Observer: VOC concentration changed by threshold; new: {result.New.PartsPerBillion:N1}ppm"); + }, + filter: result => + { + if (result.Old is { } oldCon && + result.New is { } newCon) + { + return Math.Abs((newCon - oldCon).PartsPerMillion) > 10; + } + return false; + } + ); + + sensor?.Subscribe(consumer); + + if (sensor != null) + { + sensor.Updated += (sender, result) => + { + Resolver.Log.Info($" VOC Concentraion: {result.New.PartsPerMillion:N1}ppm"); + }; + } + + sensor?.StartUpdating(TimeSpan.FromSeconds(2)); + + return base.Initialize(); + } + + // + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.MiniPID2/Samples/MiniPID2_Sample/MiniPID2_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.MiniPID2/Samples/MiniPID2_Sample/MiniPID2_Sample.csproj new file mode 100644 index 0000000000..a679cd628b --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.MiniPID2/Samples/MiniPID2_Sample/MiniPID2_Sample.csproj @@ -0,0 +1,20 @@ + + + https://github.com/WildernessLabs/Meadow.Foundation + Wilderness Labs, Inc + Wilderness Labs, Inc + true + netstandard2.1 + Library + App + + + + + + + + Always + + + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.MiniPID2/Samples/MiniPID2_Sample/meadow.config.yaml b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.MiniPID2/Samples/MiniPID2_Sample/meadow.config.yaml new file mode 100644 index 0000000000..32363cb69c --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.MiniPID2/Samples/MiniPID2_Sample/meadow.config.yaml @@ -0,0 +1,2 @@ +MonoControl: + Options: --jit \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Datasheet/NextPM-User-Guide_v3.5.pdf b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Datasheet/NextPM-User-Guide_v3.5.pdf new file mode 100644 index 0000000000..6e73a59c0d Binary files /dev/null and b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Datasheet/NextPM-User-Guide_v3.5.pdf differ diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Datasheet/NextPM_RS485_v2.1.pdf b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Datasheet/NextPM_RS485_v2.1.pdf new file mode 100644 index 0000000000..e2c90b8e1e Binary files /dev/null and b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Datasheet/NextPM_RS485_v2.1.pdf differ diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Driver/CommandManager.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Driver/CommandManager.cs new file mode 100644 index 0000000000..2308911940 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Driver/CommandManager.cs @@ -0,0 +1,54 @@ +using System; +using System.Linq; + +namespace Meadow.Foundation.Sensors.Environmental +{ + internal static class CommandManager + { + public static (int commandLength, int expectedResponseLength) GenerateCommand(NextPm.CommandByte command, byte[] buffer, params byte[] payload) + { + buffer[0] = NextPm.SensorAddress; + buffer[1] = (byte)command; + + var payloadLength = 2; + + if (payload != null && payload.Length > 0) + { + Array.Copy(payload, 0, buffer, 2, payload.Length); + payloadLength += payload.Length; + } + + buffer[payloadLength] = CalculateChecksum(buffer, 0, payloadLength); + + switch (command) + { + case NextPm.CommandByte.ReadFirmware: + return (3, 6); + case NextPm.CommandByte.ReadTempAndHumidity: + return (3, 8); + case NextPm.CommandByte.ReadWriteFanSpeed: + return (payloadLength + 1, 6); + case NextPm.CommandByte.SetPowerMode: + return (payloadLength + 1, 4); + case NextPm.CommandByte.ReadSensorState: + return (3, 4); + case NextPm.CommandByte.Read10sConcentrations: + case NextPm.CommandByte.Read60sConcentrations: + case NextPm.CommandByte.Read900sConcentrations: + return (3, 16); + default: throw new NotImplementedException(); + } + } + + public static byte CalculateChecksum(byte[] data, int start, int length) + { + return (byte)(0x100 - (data.Skip(start).Take(length).Sum(d => d) % 256)); + } + + public static bool ValidateChecksum(byte[] data, int start, int length) + { + var expected = CalculateChecksum(data, start, length - 1); + return expected == data[start + length - 1]; + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Driver/NextPm.Constants.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Driver/NextPm.Constants.cs new file mode 100644 index 0000000000..e29d294d50 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Driver/NextPm.Constants.cs @@ -0,0 +1,7 @@ +namespace Meadow.Foundation.Sensors.Environmental +{ + public partial class NextPm + { + internal const byte SensorAddress = 0x81; // fixed address, per the data sheet + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Driver/NextPm.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Driver/NextPm.Enums.cs new file mode 100644 index 0000000000..f6f8cb06f6 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Driver/NextPm.Enums.cs @@ -0,0 +1,33 @@ +using System; + +namespace Meadow.Foundation.Sensors.Environmental +{ + public partial class NextPm + { + internal enum CommandByte : byte + { + Read10sConcentrations = 0x11, + Read60sConcentrations = 0x12, + Read900sConcentrations = 0x13, + ReadTempAndHumidity = 0x14, + SetPowerMode = 0x15, + ReadSensorState = 0x16, + ReadFirmware = 0x17, + ReadWriteFanSpeed = 0x21, + ReadWriteModbusAddress = 0x22 + } + + [Flags] + internal enum SensorStatus : byte + { + Sleep = 1 << 0, + Degraded = 1 << 1, + NotReady = 1 << 2, + HeaterError = 1 << 3, + TempHumidyError = 1 << 4, + FanError = 1 << 5, + MemoryError = 1 << 6, + LaserError = 1 << 7, + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Driver/NextPm.Serial.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Driver/NextPm.Serial.cs new file mode 100644 index 0000000000..c95578a5c2 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Driver/NextPm.Serial.cs @@ -0,0 +1,83 @@ +using Meadow.Hardware; +using System; +using System.Threading.Tasks; + +namespace Meadow.Foundation.Sensors.Environmental +{ + /// + /// Represents a TERA Sensor NextPM particulate matter sensor + /// + public partial class NextPm + { + private ISerialPort _port; + // dev note: these common buffers are used to minimize heap allocations during serial communications with the sensor + private byte[] _readBuffer = new byte[16]; + private byte[] _writeBuffer = new byte[16]; + + private ISerialPort InitializePort(ISerialPort port) + { + if (port.IsOpen) + { + port.Close(); + } + + port.BaudRate = 115200; + port.DataBits = 8; + port.Parity = Parity.Even; + port.StopBits = StopBits.One; + + return port; + } + + private async Task SendCommand(CommandByte command, params byte[] payload) + { + var parameters = CommandManager.GenerateCommand(command, _writeBuffer, payload); + + if (!_port.IsOpen) + { + _port.Open(); + } + + _port.Write(_writeBuffer, 0, parameters.commandLength); + + var read = 0; + var expected = parameters.expectedResponseLength; + var timeoutMs = 3000; + var readDelay = 500; + + await Task.Delay(100); // initial device response delay + + Array.Clear(_readBuffer, 0, _readBuffer.Length); + + do + { + read += _port.Read(_readBuffer, read, _readBuffer.Length - read); + if (read >= expected) break; + + if (read > 2 && _readBuffer[1] != (byte)command && _readBuffer[1] == 0x16) + { + var status = (SensorStatus)_readBuffer[2]; + // typically a "fail" due to the device being in sleep state + throw new TeraException($"Device status: {status}"); + } + + await Task.Delay(readDelay); + timeoutMs -= readDelay; + } while (timeoutMs > 0); + + if (read < expected) + { + throw new TeraException("Serial timeout"); + } + else + { + var checksumIsValid = CommandManager.ValidateChecksum(_readBuffer, 0, parameters.expectedResponseLength); + + if (!checksumIsValid) + { + throw new TeraException("Invalid response checksum"); + } + } + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Driver/NextPm.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Driver/NextPm.cs new file mode 100644 index 0000000000..88f43e0985 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Driver/NextPm.cs @@ -0,0 +1,284 @@ +using Meadow.Hardware; +using Meadow.Units; +using System; +using System.Threading.Tasks; + +namespace Meadow.Foundation.Sensors.Environmental +{ + /// + /// Represents a TERA Sensor NextPM serial particulate matter sensor + /// + public partial class NextPm : + PollingSensorBase<( + ParticulateReading? reading10s, + ParticulateReading? reading1min, + ParticulateReading? reading15min, + Units.Temperature? temperature, + RelativeHumidity? humidity)>, + IDisposable, IPowerControllablePeripheral + { + /// + /// Raised when a new 10-second average reading is taken + /// + public event EventHandler> Readings10sUpdated = delegate { }; + /// + /// Raised when a new 1-minute average reading is taken + /// + public event EventHandler> Readings1minUpdated = delegate { }; + /// + /// Raised when a new 15-minute average reading is taken + /// + public event EventHandler> Readings15minUpdated = delegate { }; + /// + /// Raised when a new temperature reading is taken + /// + public event EventHandler> TemperatureUpdated = delegate { }; + /// + /// Raised when a new humidity reading is taken + /// + public event EventHandler> HumidityUpdated = delegate { }; + + /// + /// Returns true if the object is disposed, otherwise false + /// + public bool IsDisposed { get; private set; } + + /// + /// Creates a NextPm instance + /// + /// + public NextPm(SerialPortName portName) + : this(portName.CreateSerialPort()) + { + } + + /// + /// Creates a NextPm instance + /// + /// + public NextPm(ISerialPort port) + { + _port = InitializePort(port); + + _port.Open(); + } + + /// + /// Gets the sensor's firmware + /// + /// The sensor's firmware version + public async Task GetFirmwareVersion() + { + await SendCommand(CommandByte.ReadFirmware); + return (short)(_readBuffer[3] << 8 | _readBuffer[4]); + } + + /// + /// Checks to see if the sensor is in Sleep mode + /// + /// True if the sensor is in Sleep mode + public async Task IsAsleep() + { + await SendCommand(CommandByte.ReadSensorState); + return ((SensorStatus)_readBuffer[2] & SensorStatus.Sleep) == SensorStatus.Sleep; + } + + /// + /// Puts the device into Sleep mode + /// + public async Task PowerOff() + { + await SendCommand(CommandByte.SetPowerMode, 0x01); + } + + /// + /// Wakes the device from Sleep mode + /// + public async Task PowerOn() + { + await SendCommand(CommandByte.SetPowerMode, 0x00); + } + + /// + /// Gets the fan speed (in percentage) + /// + public async Task GetFanSpeed() + { + await SendCommand(CommandByte.ReadWriteFanSpeed, 0x00, 0x00); + + // dev note: + // this offset doesn't match the data sheet. The data sheet says there should be 1 byte of response data, but I'm seeing 2 bytes. + // data sheet also says the value range should be 30-100, but with 2 bytes I see a value of 290, so totally guessing on this reponse here + // the data sheet also says it should be 5 bytes, but the sensor requires 6 or it will give an error + return _readBuffer[4]; + } + + /// + /// Sets the sensor fan speed (in percentage) + /// + /// + /// + public async Task SetFanSpeed(int speedPercent) + { + // dev note: + // the sensor seems to accept the command, but I can' hear any difference in fan speed from 30 to 100% + if (speedPercent < 30 || speedPercent > 100) + { + throw new ArgumentOutOfRangeException(nameof(speedPercent), "Valid range is 30-100"); + } + + await SendCommand(CommandByte.ReadWriteFanSpeed, 0x00, (byte)speedPercent); + } + + /// + /// Gets the sensor's current Temperature and Humidity readings + /// + public async Task<(Units.Temperature temperature, RelativeHumidity humidity)> GetTemperatureAndHumidity() + { + await SendCommand(CommandByte.ReadTempAndHumidity); + + var rawTemp = (_readBuffer[3] << 8 | _readBuffer[4]) / 100d; + var realTemp = 0.9754 * rawTemp - 4.2488; // math from data sheet + var rawHumidity = (_readBuffer[5] << 8 | _readBuffer[6]) / 100d; + var realHumidity = 1.1768 * rawHumidity - 4.727; // math from data sheet + + return (new Units.Temperature(realTemp, Units.Temperature.UnitType.Celsius), + new RelativeHumidity(realHumidity)); + } + + /// + /// Gets the average particulate reading for the past 10 seconds + /// + public async Task Get10SecondAverageReading() + { + await SendCommand(CommandByte.Read10sConcentrations); + return new ParticulateReading(_readBuffer, 3); + } + + /// + /// Gets the average particulate reading for the past 60 seconds + /// + public async Task Get1MinuteAverageReading() + { + await SendCommand(CommandByte.Read60sConcentrations); + return new ParticulateReading(_readBuffer, 3); + } + + /// + /// Gets the average particulate reading for the past 15 minutes + /// + public async Task Get15MinuteAverageReading() + { + await SendCommand(CommandByte.Read900sConcentrations); + return new ParticulateReading(_readBuffer, 3); + } + + /// + protected override void RaiseEventsAndNotify(IChangeResult<( + ParticulateReading? reading10s, + ParticulateReading? reading1min, + ParticulateReading? reading15min, + Units.Temperature? temperature, + RelativeHumidity? humidity)> changeResult) + { + if (changeResult.New.reading10s is { } r10) + { + Readings10sUpdated?.Invoke(this, new ChangeResult(r10, changeResult.Old?.reading10s)); + } + if (changeResult.New.reading1min is { } r1) + { + Readings1minUpdated?.Invoke(this, new ChangeResult(r1, changeResult.Old?.reading10s)); + } + if (changeResult.New.reading15min is { } r15) + { + Readings15minUpdated?.Invoke(this, new ChangeResult(r15, changeResult.Old?.reading10s)); + } + if (changeResult.New.temperature is { } temperature) + { + TemperatureUpdated?.Invoke(this, new ChangeResult(temperature, changeResult.Old?.temperature)); + } + if (changeResult.New.humidity is { } humidity) + { + HumidityUpdated?.Invoke(this._port, new ChangeResult(humidity, changeResult.Old?.humidity)); + } + base.RaiseEventsAndNotify(changeResult); + } + + /// + protected override async Task<( + ParticulateReading? reading10s, + ParticulateReading? reading1min, + ParticulateReading? reading15min, + Units.Temperature? temperature, + RelativeHumidity? humidity)> ReadSensor() + { + (ParticulateReading? reading10s, ParticulateReading? reading1min, ParticulateReading? reading15min, Units.Temperature? temperature, RelativeHumidity? humidity) conditions; + + // data sheet indicates you should always read all 4 bytes, in order, for valid data + try + { + conditions.reading10s = await Get10SecondAverageReading(); + } + catch (TeraException) + { + // data likely not ready, or device is asleep + conditions.reading10s = null; + } + + try + { + conditions.reading1min = await Get1MinuteAverageReading(); + } + catch (TeraException) + { + // data likely not ready, or device is asleep + conditions.reading1min = null; + } + + try + { + conditions.reading15min = await Get15MinuteAverageReading(); + } + catch (TeraException) + { + // data likely not ready, or device is asleep + conditions.reading15min = null; + } + + try + { + var th = await GetTemperatureAndHumidity(); + conditions.temperature = th.temperature; + conditions.humidity = th.humidity; + } + catch (TeraException) + { + // data likely not ready, or device is asleep + conditions.temperature = null; + conditions.humidity = null; + } + + return conditions; + } + + /// + protected virtual void Dispose(bool disposing) + { + if (!IsDisposed) + { + if (disposing) + { + _port?.Dispose(); + } + IsDisposed = true; + } + } + + /// + public void Dispose() + { + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Driver/ParticulateReading.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Driver/ParticulateReading.cs new file mode 100644 index 0000000000..fa98e3bd74 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Driver/ParticulateReading.cs @@ -0,0 +1,44 @@ +using Meadow.Units; +using System; + +namespace Meadow.Foundation.Sensors.Environmental +{ + /// + /// A collection of particulate density readings + /// + public struct ParticulateReading + { + private byte[] _data; + + internal ParticulateReading(byte[] rawData, int offset) + { + _data = new byte[12]; + Array.Copy(rawData, offset, _data, 0, 12); + } + + /// + /// Count of 1-micron particles + /// + public ParticleDensity CountOf1micronParticles => new ParticleDensity(_data[0] << 8 | _data[1], ParticleDensity.UnitType.ParticlesPerLiter); + /// + /// Count of 2.5 micron particles + /// + public ParticleDensity CountOf2_5micronParticles => new ParticleDensity(_data[2] << 8 | _data[3], ParticleDensity.UnitType.ParticlesPerLiter); + /// + /// Count of 10 micron particles + /// + public ParticleDensity CountOf10micronParticles => new ParticleDensity(_data[4] << 8 | _data[5], ParticleDensity.UnitType.ParticlesPerLiter); + /// + /// Density of 1 micron particles + /// + public Density EnvironmentalPM_1micron => new Density((_data[6] << 8 | _data[7]) / 10d, Density.UnitType.MicroGramsPerMetersCubed); + /// + /// Density of 2.5 micron particles + /// + public Density EnvironmentalPM_2_5micron => new Density((_data[8] << 8 | _data[9]) / 10d, Density.UnitType.MicroGramsPerMetersCubed); + /// + /// Density of 10 micron particles + /// + public Density EnvironmentalPM_10micron => new Density((_data[10] << 8 | _data[11]) / 10d, Density.UnitType.MicroGramsPerMetersCubed); + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Driver/Sensors.Environmental.NextPm.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Driver/Sensors.Environmental.NextPm.csproj new file mode 100644 index 0000000000..adb8b0141f --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Driver/Sensors.Environmental.NextPm.csproj @@ -0,0 +1,25 @@ + + + true + icon.png + Wilderness Labs, Inc + netstandard2.1 + Library + NextPm + Wilderness Labs, Inc + http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ + Meadow.Foundation.Sensors.Environmental.NextPm + https://github.com/WildernessLabs/Meadow.Foundation + Meadow,Meadow.Foundation,Environmental,NextPM,tera,gas,particle,particulate,matter,AQI,air,quality + 0.1.0 + enable + true + TERA Sensor NextPM serial particulate matter sensor + + + + + + + + \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Driver/TeraException.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Driver/TeraException.cs new file mode 100644 index 0000000000..16e47dc703 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Driver/TeraException.cs @@ -0,0 +1,12 @@ +using System; + +namespace Meadow.Foundation.Sensors.Environmental +{ + /// + /// Exception thrown by a TERA NextPM sensor + /// + public sealed class TeraException : Exception + { + internal TeraException(string message) : base(message) { } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Samples/NextPm_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Samples/NextPm_Sample/MeadowApp.cs new file mode 100644 index 0000000000..500d4cd702 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Samples/NextPm_Sample/MeadowApp.cs @@ -0,0 +1,56 @@ +using Meadow; +using Meadow.Devices; +using Meadow.Foundation.Sensors.Environmental; +using System.Threading.Tasks; + +namespace NextPm_Sample +{ + // Change F7FeatherV2 to F7FeatherV1 for V1.x boards + public class MeadowApp : App + { + // + + NextPm nextPm; + + public override Task Initialize() + { + var port = Device + .PlatformOS + .GetSerialPortName("COM1") + .CreateSerialPort(); + + nextPm = new NextPm(port); + + nextPm.Readings10sUpdated += NextPm_Readings10sUpdated; + + return Task.CompletedTask; + } + + private void NextPm_Readings10sUpdated(object sender, IChangeResult e) + { + Resolver.Log.Info($"Past 10 seconds"); + Resolver.Log.Info($" {e.New.CountOf1micronParticles.ParticlesPerLiter:0} 1 micron particles per liter"); + Resolver.Log.Info($" {e.New.CountOf2_5micronParticles.ParticlesPerLiter:0} 2.5 micron particles per liter"); + Resolver.Log.Info($" {e.New.CountOf10micronParticles.ParticlesPerLiter:0} 10 micron particles per liter"); + Resolver.Log.Info($" {e.New.EnvironmentalPM_1micron.MicroGramsPerMetersCubed:0} ug/L^3 1 micron particles"); + Resolver.Log.Info($" {e.New.EnvironmentalPM_2_5micron.MicroGramsPerMetersCubed:0} ug/L^3 1 micron particles"); + Resolver.Log.Info($" {e.New.EnvironmentalPM_10micron.MicroGramsPerMetersCubed:0} ug/L^3 1 micron particles"); + } + + public override async Task Run() + { + Resolver.Log.Info("Run..."); + + var firmware = await nextPm.GetFirmwareVersion(); + Resolver.Log.Info($"Firmware: 0x{firmware:X4}"); + + var tempAndHumidity = await nextPm.GetTemperatureAndHumidity(); + Resolver.Log.Info($"Temp: {tempAndHumidity.temperature:0.0}C Humidity: {tempAndHumidity.humidity}%"); + + nextPm.StartUpdating(); + } + + + // + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Samples/NextPm_Sample/NextPm_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Samples/NextPm_Sample/NextPm_Sample.csproj new file mode 100644 index 0000000000..0eaafa71c7 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Samples/NextPm_Sample/NextPm_Sample.csproj @@ -0,0 +1,17 @@ + + + netstandard2.1 + true + Library + App + + + + + + + + Always + + + \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Samples/NextPm_Sample/meadow.config.yaml b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Samples/NextPm_Sample/meadow.config.yaml new file mode 100644 index 0000000000..32363cb69c --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.NextPm/Samples/NextPm_Sample/meadow.config.yaml @@ -0,0 +1,2 @@ +MonoControl: + Options: --jit \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Pmsa003I/Datasheet/4505_PMSA003I_series_data_manual_English_V2.6.pdf b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Pmsa003I/Datasheet/4505_PMSA003I_series_data_manual_English_V2.6.pdf new file mode 100644 index 0000000000..204bb5e244 Binary files /dev/null and b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Pmsa003I/Datasheet/4505_PMSA003I_series_data_manual_English_V2.6.pdf differ diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Pmsa003I/Driver/Pmsa003i.Constants.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Pmsa003I/Driver/Pmsa003i.Constants.cs new file mode 100644 index 0000000000..53aaead995 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Pmsa003I/Driver/Pmsa003i.Constants.cs @@ -0,0 +1,7 @@ +namespace Meadow.Foundation.Sensors.Environmental +{ + public partial class Pmsa003i + { // This is reversed because we reverse the whole message because it is big-endian and it makes converting values easier + private static readonly byte[] Preamble = { 0x4d, 0x42 }; + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Pmsa003I/Driver/Pmsa003i.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Pmsa003I/Driver/Pmsa003i.Enums.cs new file mode 100644 index 0000000000..82cb2a69cb --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Pmsa003I/Driver/Pmsa003i.Enums.cs @@ -0,0 +1,21 @@ +namespace Meadow.Foundation.Sensors.Environmental +{ + public partial class Pmsa003i + { + /// + /// Valid I2C addresses for the sensor + /// + internal enum Addresses : byte + { + /// + /// Bus address 0x52 + /// ADDR is low + /// + Address_0x12 = 0x12, + /// + /// Default bus address + /// + Default = Address_0x12 + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Pmsa003I/Driver/Pmsa003i.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Pmsa003I/Driver/Pmsa003i.cs new file mode 100644 index 0000000000..fa653f2606 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Pmsa003I/Driver/Pmsa003i.cs @@ -0,0 +1,299 @@ +using Meadow.Hardware; +using Meadow.Units; +using System; +using System.Linq; +using System.Threading.Tasks; + +namespace Meadow.Foundation.Sensors.Environmental +{ + /// + /// Represents a Pmsa003i AQI particulate matter sensor + /// + public partial class Pmsa003i : + ByteCommsSensorBase<( + Density? StandardParticulateMatter_1micron, //Particulate Matter 1 micron or less + Density? StandardParticulateMatter_2_5micron, //Particulate Matter 2.5 micron or less + Density? StandardParticulateMatter_10micron, //Particulate Matter 10 micron or less + Density? EnvironmentalParticulateMatter_1micron, + Density? EnvironmentalParticulateMatter_2_5micron, + Density? EnvironmentalParticulateMatter_10micron, + ParticleDensity? ParticleDensity_0_3microns, + ParticleDensity? ParticleDensity_0_5microns, + ParticleDensity? ParticleDensity_10microns, + ParticleDensity? ParticleDensity_25microns, + ParticleDensity? ParticleDensity_50microns, + ParticleDensity? ParticleDensity_100microns)>, + II2cPeripheral + { + /// + /// Raised when the Standard particulate matter PM1.0 density changes + /// + public event EventHandler> StandardPM_1micronUpdated = delegate { }; + + /// + /// Raised when the Standard particulate matter PM2.5 density changes + /// + public event EventHandler> StandardPM_2_5micronUpdated = delegate { }; + + /// + /// Raised when the Standard particulate matter PM10.0 density changes + /// + public event EventHandler> StandardPM_10micronUpdated = delegate { }; + + /// + /// Raised when the Environment particulate matter PM1.0 density changes + /// + public event EventHandler> EnvironmentalPM_1micronUpdated = delegate { }; + + /// + /// Raised when the Environment particulate matter PM2.5 density changes + /// + public event EventHandler> EnvironmentalPM_2_5micronUpdated = delegate { }; + + /// + /// Raised when the Environment particulate matter PM10.0 density changes + /// + public event EventHandler> EnvironmentalPM_10micronUpdated = delegate { }; + + /// + /// Raised when the number of of 0-0.3 micron particles (in 0.1 liters of air) changes + /// + public event EventHandler> CountOf0_3micronParticlesUpdated = delegate { }; + + /// + /// Raised when the number of of 0.3-0.5 micron particles (in 0.1 liters of air) changes + /// + public event EventHandler> CountOf0_5micronParticlesUpdated = delegate { }; + + /// + /// Raised when the number of of 0.5-10 micron particles changes + /// + public event EventHandler> CountOf10micronParticlesUpdated = delegate { }; + + /// + /// Raised when the number of of 10-25 micron particles (in 0.1 liters of air) changes + /// + public event EventHandler> CountOf25micronParticlesUpdated = delegate { }; + + /// + /// Raised when the number of of 25-50 micron particles (in 0.1 liters of air) changes + /// + public event EventHandler> CountOf50micronParticlesUpdated = delegate { }; + + /// + /// Raised when the number of 50-100 micron particles (in 0.1 liters of air) changes + /// + public event EventHandler> CountOf100micronParticlesUpdated = delegate { }; + + /// + /// Standard particulate matter PM1.0 density + /// + public Density? PM1_0Std => Conditions.StandardParticulateMatter_1micron; + + /// + /// Standard particulate matter PM2.5 density + /// + public Density? PM2_5Std => Conditions.StandardParticulateMatter_2_5micron; + + /// + /// Standard particulate matter PM10 density + /// + public Density? PM10_0Std => Conditions.StandardParticulateMatter_10micron; + + /// + /// Standard particulate matter PM1.0 density + /// + public Density? PM1_0Env => Conditions.EnvironmentalParticulateMatter_1micron; + + /// + /// Standard particulate matter PM2.5 density + /// + public Density? PM2_5Env => Conditions.EnvironmentalParticulateMatter_2_5micron; + + /// + /// Standard particulate matter PM10 density + /// + public Density? PM10_0Env => Conditions.EnvironmentalParticulateMatter_10micron; + + /// + /// Particle density of 0 - 0.3 micron particles inair + /// + public ParticleDensity? CountOf0_3micronParticles => Conditions.ParticleDensity_0_3microns; + /// + /// Particle density of of 0.3 - 0.5 micron particles in air + /// + public ParticleDensity? CountOf0_5micronParticles => Conditions.ParticleDensity_0_5microns; + /// + /// Particle density of of 0.5 - 10 micron particles in air + /// + public ParticleDensity? CountOf10micronParticles => Conditions.ParticleDensity_10microns; + /// + /// Particle density of of 0.5 - 10 micron particles in air + /// + public ParticleDensity? CountOf25micronParticles => Conditions.ParticleDensity_25microns; + /// + /// Particle density of of 10 - 50 micron particles in air + /// + public ParticleDensity? CountOf50micronParticles => Conditions.ParticleDensity_50microns; + /// + /// Particle density of of 50 - 100 micron particles in air + /// + public ParticleDensity? CountOf100micronParticles => Conditions.ParticleDensity_100microns; + + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + + /// + /// Create a new PMSA003I sensor object + /// + /// + /// The I2C bus + public Pmsa003i(II2cBus i2cBus) + : base(i2cBus, (byte)Addresses.Default) + { } + + /// + /// Starts updating the sensor on the updateInterval frequency specified + /// + public override void StartUpdating(TimeSpan? updateInterval = null) + { + base.StartUpdating(updateInterval); + } + + /// + /// Stop updating the sensor + /// The sensor will not respond to commands for 500ms + /// The call will delay the calling thread for 500ms + /// + public override void StopUpdating() + { + base.StopUpdating(); + } + + /// + /// Read data from the sensor + /// + /// + /// + protected override Task<( + Density? StandardParticulateMatter_1micron, + Density? StandardParticulateMatter_2_5micron, + Density? StandardParticulateMatter_10micron, + Density? EnvironmentalParticulateMatter_1micron, + Density? EnvironmentalParticulateMatter_2_5micron, + Density? EnvironmentalParticulateMatter_10micron, + ParticleDensity? ParticleDensity_0_3microns, + ParticleDensity? ParticleDensity_0_5microns, + ParticleDensity? ParticleDensity_10microns, + ParticleDensity? ParticleDensity_25microns, + ParticleDensity? ParticleDensity_50microns, + ParticleDensity? ParticleDensity_100microns)> ReadSensor() + { + var buffer = new byte[32]; + BusComms.Read(buffer); + var span = buffer.AsSpan(); + span.Reverse(); + if (buffer[30..32].SequenceEqual(Preamble) == false) + { + throw new Exception("Preamble mismatch!"); + } + var messageLength = BitConverter.ToUInt16(span[28..30]); + if (messageLength != 28) + { + throw new Exception("Message is corrupt or has invalid length"); + } + + // this is in big-endian format, so we need to reverse things... + var pm10Standard = new Density(BitConverter.ToUInt16(span[26..28]), Density.UnitType.MicroGramsPerMetersCubed); + var pm25Standard = new Density(BitConverter.ToUInt16(span[24..26]), Density.UnitType.MicroGramsPerMetersCubed); + var pm100Standard = new Density(BitConverter.ToUInt16(span[22..24]), Density.UnitType.MicroGramsPerMetersCubed); + var pm10Environmental = new Density(BitConverter.ToUInt16(span[20..22]), Density.UnitType.MicroGramsPerMetersCubed); + var pm25Environmental = new Density(BitConverter.ToUInt16(span[18..20]), Density.UnitType.MicroGramsPerMetersCubed); + var pm100Environmental = new Density(BitConverter.ToUInt16(span[16..18]), Density.UnitType.MicroGramsPerMetersCubed); + var p03um = new ParticleDensity(BitConverter.ToUInt16(span[14..16]), ParticleDensity.UnitType.ParticlesPerCentiliter); + var p05um = new ParticleDensity(BitConverter.ToUInt16(span[12..14]), ParticleDensity.UnitType.ParticlesPerCentiliter); + var p10um = new ParticleDensity(BitConverter.ToUInt16(span[10..12]), ParticleDensity.UnitType.ParticlesPerCentiliter); + var p25um = new ParticleDensity(BitConverter.ToUInt16(span[8..10]), ParticleDensity.UnitType.ParticlesPerCentiliter); + var p50um = new ParticleDensity(BitConverter.ToUInt16(span[6..8]), ParticleDensity.UnitType.ParticlesPerCentiliter); + var p100um = new ParticleDensity(BitConverter.ToUInt16(span[4..6]), ParticleDensity.UnitType.ParticlesPerCentiliter); + + Conditions = (pm10Standard, pm25Standard, pm100Standard, pm10Environmental, pm25Environmental, + pm100Environmental, p03um, p05um, p10um, p25um, p50um, p100um); + + return Task.FromResult(Conditions); + } + + /// + /// Raise change events for subscribers + /// + /// The change result with the current sensor data + protected override void RaiseEventsAndNotify( + IChangeResult<(Density? StandardParticulateMatter_1micron, + Density? StandardParticulateMatter_2_5micron, + Density? StandardParticulateMatter_10micron, + Density? EnvironmentalParticulateMatter_1micron, + Density? EnvironmentalParticulateMatter_2_5micron, + Density? EnvironmentalParticulateMatter_10micron, + ParticleDensity? ParticleDensity_0_3microns, + ParticleDensity? ParticleDensity_0_5microns, + ParticleDensity? ParticleDensity_10microns, + ParticleDensity? ParticleDensity_25microns, + ParticleDensity? ParticleDensity_50microns, + ParticleDensity? ParticleDensity_100microns)> changeResult) + { + if (changeResult.New.StandardParticulateMatter_1micron is { } SPM0_1) + { + StandardPM_1micronUpdated?.Invoke(this, new ChangeResult(SPM0_1, changeResult.Old.Value.StandardParticulateMatter_1micron)); + } + if (changeResult.New.StandardParticulateMatter_2_5micron is { } SPM0_2_5) + { + StandardPM_1micronUpdated?.Invoke(this, new ChangeResult(SPM0_2_5, changeResult.Old.Value.StandardParticulateMatter_2_5micron)); + } + if (changeResult.New.StandardParticulateMatter_10micron is { } SPM0_10) + { + StandardPM_1micronUpdated?.Invoke(this, new ChangeResult(SPM0_10, changeResult.Old.Value.StandardParticulateMatter_10micron)); + } + if (changeResult.New.EnvironmentalParticulateMatter_1micron is { } EM0_1) + { + StandardPM_1micronUpdated?.Invoke(this, new ChangeResult(EM0_1, changeResult.Old.Value.EnvironmentalParticulateMatter_1micron)); + } + if (changeResult.New.EnvironmentalParticulateMatter_2_5micron is { } EM0_2_5) + { + StandardPM_1micronUpdated?.Invoke(this, new ChangeResult(EM0_2_5, changeResult.Old.Value.EnvironmentalParticulateMatter_2_5micron)); + } + if (changeResult.New.EnvironmentalParticulateMatter_10micron is { } EM0_10) + { + StandardPM_1micronUpdated?.Invoke(this, new ChangeResult(EM0_10, changeResult.Old.Value.EnvironmentalParticulateMatter_10micron)); + } + + if (changeResult.New.ParticleDensity_0_3microns is { } P_0_3) + { + CountOf0_3micronParticlesUpdated?.Invoke(this, new ChangeResult(P_0_3, changeResult.Old.Value.ParticleDensity_0_3microns)); + } + if (changeResult.New.ParticleDensity_0_5microns is { } P_0_5) + { + CountOf0_5micronParticlesUpdated?.Invoke(this, new ChangeResult(P_0_5, changeResult.Old.Value.ParticleDensity_0_5microns)); + } + if (changeResult.New.ParticleDensity_10microns is { } P_10) + { + CountOf10micronParticlesUpdated?.Invoke(this, new ChangeResult(P_10, changeResult.Old.Value.ParticleDensity_10microns)); + } + if (changeResult.New.ParticleDensity_25microns is { } P_25) + { + CountOf25micronParticlesUpdated?.Invoke(this, new ChangeResult(P_25, changeResult.Old.Value.ParticleDensity_25microns)); + } + if (changeResult.New.ParticleDensity_50microns is { } P_50) + { + CountOf50micronParticlesUpdated?.Invoke(this, new ChangeResult(P_50, changeResult.Old.Value.ParticleDensity_50microns)); + } + if (changeResult.New.ParticleDensity_100microns is { } P_100) + { + CountOf100micronParticlesUpdated?.Invoke(this, new ChangeResult(P_100, changeResult.Old.Value.ParticleDensity_100microns)); + } + + base.RaiseEventsAndNotify(changeResult); + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Pmsa003I/Driver/Sensors.Environmental.Pmsa003i.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Pmsa003I/Driver/Sensors.Environmental.Pmsa003i.csproj new file mode 100644 index 0000000000..338879f461 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Pmsa003I/Driver/Sensors.Environmental.Pmsa003i.csproj @@ -0,0 +1,22 @@ + + + true + icon.png + Wilderness Labs, Inc + netstandard2.1 + Library + Pmsa300i + Wilderness Labs, Inc + http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ + Meadow.Foundation.Sensors.Environmental.Pmsa300i + https://github.com/WildernessLabs/Meadow.Foundation + Meadow,Meadow.Foundation,Environmental,Pmsa300i,gas,particle,particulate,matter,AQI,air,quality + 0.1.0 + true + PMSA300I I2C particulate matter AQI sensor + + + + + + \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Pmsa003I/Samples/Pmsa003I_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Pmsa003I/Samples/Pmsa003I_Sample/MeadowApp.cs new file mode 100644 index 0000000000..fcf2829ff1 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Pmsa003I/Samples/Pmsa003I_Sample/MeadowApp.cs @@ -0,0 +1,68 @@ +using Meadow; +using Meadow.Devices; +using Meadow.Foundation.Sensors.Environmental; +using Meadow.Hardware; +using Meadow.Units; +using System; +using System.Threading.Tasks; + +namespace Pmsa003i_Sample +{ + // Change F7FeatherV2 to F7FeatherV1 for V1.x boards + public class MeadowApp : App + { + // + + Pmsa003i pmsa003i; + + public override Task Initialize() + { + var bus = Device.CreateI2cBus(I2cBusSpeed.Standard); + pmsa003i = new Pmsa003i(bus); + + pmsa003i.Updated += Pmsa003i_Updated; + + return base.Initialize(); + } + + public override Task Run() + { + Resolver.Log.Info("Run..."); + + pmsa003i.StartUpdating(TimeSpan.FromSeconds(2)); + + return base.Run(); + } + + private void Pmsa003i_Updated(object sender, IChangeResult<( + Density? StandardParticulateMatter_1micron, + Density? StandardParticulateMatter_2_5micron, + Density? StandardParticulateMatter_10micron, + Density? EnvironmentalParticulateMatter_1micron, + Density? EnvironmentalParticulateMatter_2_5micron, + Density? EnvironmentalParticulateMatter_10micron, + ParticleDensity? ParticleDensity_0_3microns, + ParticleDensity? ParticleDensity_0_5microns, + ParticleDensity? ParticleDensity_10microns, + ParticleDensity? ParticleDensity_25microns, + ParticleDensity? ParticleDensity_50microns, + ParticleDensity? ParticleDensity_100microns)> e) + { + Resolver.Log.Info($"Standard Particulate Matter 1 micron: {e.New.StandardParticulateMatter_1micron.Value.MicroGramsPerMetersCubed} micrograms per m^3"); + Resolver.Log.Info($"Standard Particulate Matter 2_5micron: {e.New.StandardParticulateMatter_2_5micron.Value.MicroGramsPerMetersCubed} micrograms per m^3"); + Resolver.Log.Info($"Standard Particulate Matter 10 micron: {e.New.StandardParticulateMatter_10micron.Value.MicroGramsPerMetersCubed} micrograms per m^3"); + Resolver.Log.Info($"Environmental Particulate Matter 1 micron: {e.New.EnvironmentalParticulateMatter_1micron.Value.MicroGramsPerMetersCubed} micrograms per m^3"); + Resolver.Log.Info($"Environmental Particulate Matter 2.5 micron: {e.New.EnvironmentalParticulateMatter_2_5micron.Value.MicroGramsPerMetersCubed} micrograms per m^3"); + Resolver.Log.Info($"Environmental Particulate Matter 10 micron: {e.New.EnvironmentalParticulateMatter_10micron.Value.MicroGramsPerMetersCubed} micrograms per m^3"); ; + + Resolver.Log.Info($"Count of particles - 0.3 microns: {e.New.ParticleDensity_0_3microns.Value.ParticlesPerCentiliter} in 0.1 liters of air"); + Resolver.Log.Info($"Count of particles - 0.5 microns: {e.New.ParticleDensity_0_5microns.Value.ParticlesPerCentiliter} in 0.1 liters of air"); + Resolver.Log.Info($"Count of particles - 10 microns: {e.New.ParticleDensity_10microns.Value.ParticlesPerCentiliter} in 0.1 liters of air"); + Resolver.Log.Info($"Count of particles - 25 microns: {e.New.ParticleDensity_25microns.Value.ParticlesPerCentiliter} in 0.1 liters of air"); + Resolver.Log.Info($"Count of particles - 50 microns: {e.New.ParticleDensity_50microns.Value.ParticlesPerCentiliter} in 0.1 liters of air"); + Resolver.Log.Info($"Count of particles - 100 microns: {e.New.ParticleDensity_100microns.Value.ParticlesPerCentiliter} in 0.1 liters of air"); + } + + // + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Pmsa003I/Samples/Pmsa003I_Sample/Pmsa003I_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Pmsa003I/Samples/Pmsa003I_Sample/Pmsa003I_Sample.csproj new file mode 100644 index 0000000000..a5797baf3f --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Pmsa003I/Samples/Pmsa003I_Sample/Pmsa003I_Sample.csproj @@ -0,0 +1,17 @@ + + + netstandard2.1 + true + Library + App + + + + + + + + Always + + + \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Pmsa003I/Samples/Pmsa003I_Sample/meadow.config.yaml b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Pmsa003I/Samples/Pmsa003I_Sample/meadow.config.yaml new file mode 100644 index 0000000000..32363cb69c --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Pmsa003I/Samples/Pmsa003I_Sample/meadow.config.yaml @@ -0,0 +1,2 @@ +MonoControl: + Options: --jit \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Scd4x/Driver/Scd4xBase.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Scd4x/Driver/Scd4xBase.cs index ab7d5a5ebb..e7aa52e88e 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Scd4x/Driver/Scd4xBase.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Scd4x/Driver/Scd4xBase.cs @@ -1,10 +1,10 @@ -using System; -using System.Threading; -using System.Threading.Tasks; using Meadow.Hardware; using Meadow.Peripherals.Sensors; using Meadow.Peripherals.Sensors.Environmental; using Meadow.Units; +using System; +using System.Threading; +using System.Threading.Tasks; namespace Meadow.Foundation.Sensors.Environmental { @@ -12,10 +12,10 @@ namespace Meadow.Foundation.Sensors.Environmental /// Base class for SCD4x series of C02 sensors /// public abstract partial class Scd4xBase - : ByteCommsSensorBase<(Concentration? Concentration, + : ByteCommsSensorBase<(Concentration? Concentration, Units.Temperature? Temperature, RelativeHumidity? Humidity)>, - ITemperatureSensor, IHumiditySensor, IConcentrationSensor + ITemperatureSensor, IHumiditySensor, IConcentrationSensor, II2cPeripheral { /// /// Raised when the concentration changes @@ -47,6 +47,11 @@ public abstract partial class Scd4xBase /// public RelativeHumidity? Humidity => Conditions.Humidity; + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + /// /// Create a new Scd4xBase object /// @@ -106,7 +111,7 @@ public byte[] GetSerialNumber() Thread.Sleep(1); var data = new byte[9]; - Peripheral.Read(data); + BusComms.Read(data); var ret = new byte[6]; @@ -119,7 +124,7 @@ public byte[] GetSerialNumber() return ret; } - + /// /// Is there sensor measurement data ready /// Sensor returns data ~5 seconds in normal operation and ~30 seconds in low power mode @@ -130,7 +135,7 @@ protected bool IsDataReady() SendCommand(Commands.GetDataReadyStatus); Thread.Sleep(1); var data = new byte[3]; - Peripheral.Read(data); + BusComms.Read(data); if (data[1] == 0 && (data[0] & 0x07) == 0) { @@ -184,7 +189,7 @@ void SendCommand(Commands command) data[0] = (byte)((ushort)command >> 8); data[1] = (byte)(ushort)command; - Peripheral.Write(data); + BusComms.Write(data); } /// @@ -193,30 +198,27 @@ void SendCommand(Commands command) /// protected override async Task<(Concentration? Concentration, Units.Temperature? Temperature, RelativeHumidity? Humidity)> ReadSensor() { - return await Task.Run(() => - { - while(IsDataReady() == false) - { - Thread.Sleep(500); - } + while (IsDataReady() == false) + { + await Task.Delay(500); + } - (Concentration Concentration, Units.Temperature Temperature, RelativeHumidity Humidity) conditions; + (Concentration Concentration, Units.Temperature Temperature, RelativeHumidity Humidity) conditions; - SendCommand(Commands.ReadMeasurement); - Thread.Sleep(1); - Peripheral.Read(ReadBuffer.Span[0..9]); + SendCommand(Commands.ReadMeasurement); + Thread.Sleep(1); + BusComms.Read(ReadBuffer.Span[0..9]); - int value = ReadBuffer.Span[0] << 8 | ReadBuffer.Span[1]; - conditions.Concentration = new Concentration(value, Units.Concentration.UnitType.PartsPerMillion); + int value = ReadBuffer.Span[0] << 8 | ReadBuffer.Span[1]; + conditions.Concentration = new Concentration(value, Units.Concentration.UnitType.PartsPerMillion); - conditions.Temperature = CalcTemperature(ReadBuffer.Span[3], ReadBuffer.Span[4]); + conditions.Temperature = CalcTemperature(ReadBuffer.Span[3], ReadBuffer.Span[4]); - value = ReadBuffer.Span[6] << 8 | ReadBuffer.Span[8]; - double humidiy = 100 * value / 65536.0; - conditions.Humidity = new RelativeHumidity(humidiy, RelativeHumidity.UnitType.Percent); + value = ReadBuffer.Span[6] << 8 | ReadBuffer.Span[8]; + double humidiy = 100 * value / 65536.0; + conditions.Humidity = new RelativeHumidity(humidiy, RelativeHumidity.UnitType.Percent); - return conditions; - }); + return conditions; } Units.Temperature CalcTemperature(byte valueHigh, byte valueLow) @@ -247,28 +249,6 @@ protected void RaiseChangedAndNotify(IChangeResult<(Concentration? Concentration base.RaiseEventsAndNotify(changeResult); } - byte GetCrc(byte value1, byte value2) - { - static byte CrcCalc(byte crc, byte value) - { - crc ^= value; - for (byte crcBit = 8; crcBit > 0; --crcBit) - { - if ((crc & 0x80) > 0) - { - crc = (byte)((crc << 1) ^ 0x31); - } - else - { - crc <<= 1; - } - } - return crc; - } - - return CrcCalc(CrcCalc(0xFF, value1), value2); - } - async Task ISensor.Read() => (await Read()).Temperature.Value; diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Scd4x/Driver/Sensors.Environmental.Scd4x.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Scd4x/Driver/Sensors.Environmental.Scd4x.csproj index f9ce7628f3..0d940068b8 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Scd4x/Driver/Sensors.Environmental.Scd4x.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Scd4x/Driver/Sensors.Environmental.Scd4x.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Scd4x/Samples/Scd40_Sample/Scd40_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Scd4x/Samples/Scd40_Sample/Scd40_Sample.csproj index 19f4ff98c4..9e1e521dba 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Scd4x/Samples/Scd40_Sample/Scd40_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Scd4x/Samples/Scd40_Sample/Scd40_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Scd4x/Samples/Scd41_Sample/Scd41_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Scd4x/Samples/Scd41_Sample/Scd41_Sample.csproj index 19f4ff98c4..9e1e521dba 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Scd4x/Samples/Scd41_Sample/Scd41_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Scd4x/Samples/Scd41_Sample/Scd41_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Y4000/Driver/Sensors.Environmental.Y4000.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Y4000/Driver/Sensors.Environmental.Y4000.csproj index 7d05d9d64a..e9cd7c0efe 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Y4000/Driver/Sensors.Environmental.Y4000.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Y4000/Driver/Sensors.Environmental.Y4000.csproj @@ -17,7 +17,7 @@ - - + + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Y4000/Driver/Y4000.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Y4000/Driver/Y4000.cs index 7148411993..856d8ead64 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Y4000/Driver/Y4000.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Y4000/Driver/Y4000.cs @@ -1,9 +1,8 @@ using Meadow.Hardware; using Meadow.Modbus; using Meadow.Units; -using System.Threading.Tasks; using System; -using System.Net; +using System.Threading.Tasks; namespace Meadow.Foundation.Sensors.Environmental { @@ -253,7 +252,7 @@ public async Task GetErrorFlag() /* * Get and Set time work but Get returns bad values * Leaving code here for future investigation - */ + */ /// /// Set the time on the device /// Stores: year, month, day, hour, minute and second @@ -295,14 +294,14 @@ async Task GetTime() /// Reads data from the sensor /// /// The latest sensor reading - protected override async Task<(ConcentrationInWater? DisolvedOxygen, - ConcentrationInWater? Chlorophyl, - ConcentrationInWater? BlueGreenAlgae, - Conductivity? ElectricalConductivity, - PotentialHydrogen? PH, - Turbidity? Turbidity, - Units.Temperature? Temperature, - Voltage? OxidationReductionPotential)> + protected override async Task<(ConcentrationInWater? DisolvedOxygen, + ConcentrationInWater? Chlorophyl, + ConcentrationInWater? BlueGreenAlgae, + Conductivity? ElectricalConductivity, + PotentialHydrogen? PH, + Turbidity? Turbidity, + Units.Temperature? Temperature, + Voltage? OxidationReductionPotential)> ReadSensor() { (ConcentrationInWater? DisolvedOxygen, @@ -377,7 +376,7 @@ protected override void RaiseEventsAndNotify( { OxidationReductionPotentialUpdated?.Invoke(this, new ChangeResult(Redux, changeResult.Old?.OxidationReductionPotential)); } - + base.RaiseEventsAndNotify(changeResult); } } diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Y4000/Samples/Y4000_Sample/Y4000_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Y4000/Samples/Y4000_Sample/Y4000_Sample.csproj index d593369f05..e2b6c815c0 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Y4000/Samples/Y4000_Sample/Y4000_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Environmental.Y4000/Samples/Y4000_Sample/Y4000_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Gnss.Mt3339/Driver/Sensors.Gnss.Mt3339.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Gnss.Mt3339/Driver/Sensors.Gnss.Mt3339.csproj index 97358fcb5c..71e76c0cfb 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Gnss.Mt3339/Driver/Sensors.Gnss.Mt3339.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Gnss.Mt3339/Driver/Sensors.Gnss.Mt3339.csproj @@ -16,14 +16,11 @@ MediaTek MT3339 serial GNSS / GPS controller enable - - 8.0 - - - 8.0 + + 10.0 - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Gnss.Mt3339/Samples/Mt3339_Sample/Mt3339_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Gnss.Mt3339/Samples/Mt3339_Sample/Mt3339_Sample.csproj index b9d40e4f9a..fd8ede7b83 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Gnss.Mt3339/Samples/Mt3339_Sample/Mt3339_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Gnss.Mt3339/Samples/Mt3339_Sample/Mt3339_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Gnss.NeoM8/Driver/NeoM8.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Gnss.NeoM8/Driver/NeoM8.Enums.cs index fa30c6be10..aaef4ee3c0 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Gnss.NeoM8/Driver/NeoM8.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Gnss.NeoM8/Driver/NeoM8.Enums.cs @@ -3,7 +3,7 @@ public partial class NeoM8 { /// - /// Valid addresses for the sensor + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Gnss.NeoM8/Driver/NeoM8.I2c.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Gnss.NeoM8/Driver/NeoM8.I2c.cs index 7aead6f425..b8583c35d6 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Gnss.NeoM8/Driver/NeoM8.I2c.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Gnss.NeoM8/Driver/NeoM8.I2c.cs @@ -6,26 +6,33 @@ namespace Meadow.Foundation.Sensors.Gnss { - public partial class NeoM8 + public partial class NeoM8 : II2cPeripheral { - I2cPeripheral i2CPeripheral; + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; - readonly Memory i2cBuffer = new byte[BUFFER_SIZE]; + /// + /// I2C Communication bus used to communicate with the peripheral + /// + protected II2cCommunications i2cComms; - IDigitalOutputPort resetPort; - IDigitalInputPort ppsPort; + readonly Memory i2cBuffer = new byte[BUFFER_SIZE]; + readonly IDigitalOutputPort resetPort; + readonly IDigitalInputPort ppsPort; /// /// Create a new NeoM8 object using I2C /// - public NeoM8(II2cBus i2cBus, byte address = (byte)Addresses.Default, IPin resetPin = null, IPin ppsPin = null) + public NeoM8(II2cBus i2cBus, byte address = (byte)Addresses.Default, IPin resetPin = null, IPin ppsPin = null) { - if(resetPin != null) + if (resetPin != null) { resetPort = resetPin.CreateDigitalOutputPort(true); } - if(ppsPin != null) + if (ppsPin != null) { ppsPort = ppsPin.CreateDigitalInputPort(InterruptMode.EdgeRising, ResistorMode.InternalPullDown); } @@ -46,7 +53,7 @@ public NeoM8(II2cBus i2cBus, byte address = (byte)Addresses.Default, IDigitalOut async Task InitializeI2c(II2cBus i2cBus, byte address) { - i2CPeripheral = new I2cPeripheral(i2cBus, address, 128); + i2cComms = new I2cCommunications(i2cBus, address, 128); messageProcessor = new SerialMessageProcessor(suffixDelimiter: Encoding.ASCII.GetBytes("\r\n"), preserveDelimiter: true, @@ -62,27 +69,29 @@ async Task InitializeI2c(II2cBus i2cBus, byte address) async Task StartUpdatingI2c() { - await Task.Run(() => + var t = new Task(() => { int len; while (true) { - len = i2CPeripheral.ReadRegisterAsUShort(0xFD, ByteOrder.BigEndian); + len = i2cComms.ReadRegisterAsUShort(0xFD, ByteOrder.BigEndian); - if(len > 0) + if (len > 0) { - if(len > 0) + if (len > 0) { var data = i2cBuffer.Slice(0, Math.Min(len, BUFFER_SIZE)).Span; - i2CPeripheral.ReadRegister(0xFF, data); + i2cComms.ReadRegister(0xFF, data); messageProcessor.Process(data.ToArray()); } } Thread.Sleep(COMMS_SLEEP_MS); } - }); + }, TaskCreationOptions.LongRunning); + t.Start(); + await t; } } } \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Gnss.NeoM8/Driver/NeoM8.Serial.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Gnss.NeoM8/Driver/NeoM8.Serial.cs index 401e075517..e2f9659008 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Gnss.NeoM8/Driver/NeoM8.Serial.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Gnss.NeoM8/Driver/NeoM8.Serial.cs @@ -34,8 +34,8 @@ public NeoM8(IMeadowDevice device, SerialPortName serialPortName, IPin resetPin, suffixDelimiter: Encoding.ASCII.GetBytes("\r\n"), preserveDelimiter: true, readBufferSize: 512), - device.CreateDigitalOutputPort(resetPin, true), - device.CreateDigitalInputPort(ppsPin, InterruptMode.EdgeRising, ResistorMode.InternalPullDown)) + (resetPin != null) ? device.CreateDigitalOutputPort(resetPin, true) : null, + (ppsPin != null) ? device.CreateDigitalInputPort(ppsPin, InterruptMode.EdgeRising, ResistorMode.InternalPullDown) : null) { } void InitializeSerial() diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Gnss.NeoM8/Driver/NeoM8.Spi.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Gnss.NeoM8/Driver/NeoM8.Spi.cs index c2fc82dce6..be59cb134d 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Gnss.NeoM8/Driver/NeoM8.Spi.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Gnss.NeoM8/Driver/NeoM8.Spi.cs @@ -1,28 +1,60 @@ using Meadow.Hardware; +using Meadow.Units; using System.Text; using System.Threading; using System.Threading.Tasks; namespace Meadow.Foundation.Sensors.Gnss { - public partial class NeoM8 + public partial class NeoM8 : ISpiPeripheral { - readonly ISpiPeripheral spiPeripheral; + /// + /// The default SPI bus speed for the device + /// + public Frequency DefaultSpiBusSpeed => new Frequency(375, Frequency.UnitType.Kilohertz); + + /// + /// The SPI bus speed for the device + /// + public Frequency SpiBusSpeed + { + get => spiComms.BusSpeed; + set => spiComms.BusSpeed = value; + } + + /// + /// The default SPI bus mode for the device + /// + public SpiClockConfiguration.Mode DefaultSpiBusMode => SpiClockConfiguration.Mode.Mode0; + + /// + /// The SPI bus mode for the device + /// + public SpiClockConfiguration.Mode SpiBusMode + { + get => spiComms.BusMode; + set => spiComms.BusMode = value; + } + + /// + /// SPI Communication bus used to communicate with the peripheral + /// + protected ISpiCommunications spiComms; const byte NULL_VALUE = 0xFF; /// /// Create a new NEOM8 object using SPI /// - public NeoM8(ISpiBus spiBus, - IDigitalOutputPort chipSelectPort, - IDigitalOutputPort resetPort = null, + public NeoM8(ISpiBus spiBus, + IDigitalOutputPort chipSelectPort, + IDigitalOutputPort resetPort = null, IDigitalInputPort ppsPort = null) { ResetPort = resetPort; PulsePerSecondPort = ppsPort; - spiPeripheral = new SpiPeripheral(spiBus, chipSelectPort); + spiComms = new SpiCommunications(spiBus, chipSelectPort, DefaultSpiBusSpeed, DefaultSpiBusMode); _ = InitializeSpi(); } @@ -34,17 +66,11 @@ public NeoM8(ISpiBus spiBus, IPin chipSelectPin = null, IPin resetPin = null, IP { var chipSelectPort = chipSelectPin.CreateDigitalOutputPort(); - spiPeripheral = new SpiPeripheral(spiBus, chipSelectPort); + spiComms = new SpiCommunications(spiBus, chipSelectPort, DefaultSpiBusSpeed, DefaultSpiBusMode); - if (resetPin != null) - { - resetPin.CreateDigitalOutputPort(true); - } + resetPin?.CreateDigitalOutputPort(true); - if (ppsPin != null) - { - ppsPin.CreateDigitalInputPort(InterruptMode.EdgeRising, ResistorMode.InternalPullDown); - } + ppsPin?.CreateDigitalInputPort(InterruptMode.EdgeRising, ResistorMode.InternalPullDown); _ = InitializeSpi(); } @@ -65,13 +91,13 @@ async Task InitializeSpi() } async Task StartUpdatingSpi() - { + { byte[] data = new byte[BUFFER_SIZE]; static bool HasMoreData(byte[] data) { bool hasNullValue = false; - for(int i = 1; i < data.Length; i++) + for (int i = 1; i < data.Length; i++) { if (data[i] == NULL_VALUE) { hasNullValue = true; } if (data[i - 1] == NULL_VALUE && data[i] != NULL_VALUE) @@ -82,19 +108,20 @@ static bool HasMoreData(byte[] data) return !hasNullValue; } - await Task.Run(() => + var t = new Task(() => { while (true) { - spiPeripheral.Read(data); + spiComms.Read(data); messageProcessor.Process(data); - if(HasMoreData(data) == false) + if (HasMoreData(data) == false) { Thread.Sleep(COMMS_SLEEP_MS); } } - }); + }, TaskCreationOptions.LongRunning); + await t; } } } \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Gnss.NeoM8/Driver/Sensors.Gnss.NeoM8.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Gnss.NeoM8/Driver/Sensors.Gnss.NeoM8.csproj index eb535f6559..50cbfe7e1a 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Gnss.NeoM8/Driver/Sensors.Gnss.NeoM8.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Gnss.NeoM8/Driver/Sensors.Gnss.NeoM8.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Gnss.NeoM8/Samples/NeoM8_Sample/NeoM8_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Gnss.NeoM8/Samples/NeoM8_Sample/NeoM8_Sample.csproj index 7c21e5118d..e2881bb3ec 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Gnss.NeoM8/Samples/NeoM8_Sample/NeoM8_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Gnss.NeoM8/Samples/NeoM8_Sample/NeoM8_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.ANONavigationEncoder/Driver/ANONavigationEncoder.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.ANONavigationEncoder/Driver/ANONavigationEncoder.cs new file mode 100644 index 0000000000..160fe6285c --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.ANONavigationEncoder/Driver/ANONavigationEncoder.cs @@ -0,0 +1,80 @@ +using Meadow.Foundation.Sensors.Buttons; +using Meadow.Foundation.Sensors.Rotary; +using Meadow.Hardware; +using Meadow.Peripherals.Sensors.Hid; + +namespace Meadow.Foundation.Sensors.Hid +{ + /// + /// Represents a ANO Directional Navigation and Scroll Wheel Rotary Encoder + /// + public class ANONavigationEncoder + { + /// + /// The directional pad + /// + public IDigitalJoystick DirectionalPad { get; protected set; } + + /// + /// The center button + /// + public PushButton ButtonCenter { get; protected set; } + + /// + /// The rotary wheel + /// + public RotaryEncoder RotaryEncoder { get; protected set; } + + /// + /// Create a new ANONavigationEncoder object + /// + /// The pin connected to switch 1 (left) + /// The pin connected to switch 2 (down) + /// The pin connected to switch 3 (right) + /// The pin connected to switch 4 (up) + /// The pin connected to switch 5 (center button) + /// Are the switches connected to ground (true) or VCC (false) + /// The pin connected to rotary encoder A + /// The pin connected to rotary encoder B + /// Is the rotary encoder connected to ground (true) or VCC (false)> + public ANONavigationEncoder(IPin pinSwitch1, IPin pinSwitch2, IPin pinSwitch3, IPin pinSwitch4, IPin pinSwitch5, + bool isSwitchCommonGround, IPin pinEncoderA, IPin pinEncoderB, bool isEncoderCommonGround) + { + var buttonResistorMode = isSwitchCommonGround ? ResistorMode.InternalPullUp : ResistorMode.InternalPullDown; + + DirectionalPad = new DigitalJoystick( + pinSwitch4, + pinSwitch2, + pinSwitch3, + pinSwitch1, + buttonResistorMode); + + ButtonCenter = new PushButton(pinSwitch5, buttonResistorMode); + + RotaryEncoder = new RotaryEncoder(pinEncoderA, pinEncoderB, isEncoderCommonGround); + } + + /// + /// Create a new ANONavigationEncoder object + /// + /// The port for switch 1 (left) + /// The port for switch 2 (down) + /// The port for switch 3 (right) + /// The port for switch 4 (up) + /// The port for switch 5 (center buttons) + /// The port for rotary encoder A + /// The port for rotary encoder A + public ANONavigationEncoder(IDigitalInputPort portSwitch1, + IDigitalInputPort portSwitch2, + IDigitalInputPort portSwitch3, + IDigitalInputPort portSwitch4, + IDigitalInputPort portSwitch5, + IDigitalInputPort portEncoderA, + IDigitalInputPort portEncoderB) + { + DirectionalPad = new DigitalJoystick(portSwitch1, portSwitch2, portSwitch3, portSwitch4); + ButtonCenter = new PushButton(portSwitch5); + RotaryEncoder = new RotaryEncoder(portEncoderA, portEncoderB); + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.ANONavigationEncoder/Driver/Sensors.Hid.ANONavigationEncoder.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.ANONavigationEncoder/Driver/Sensors.Hid.ANONavigationEncoder.csproj new file mode 100644 index 0000000000..8ca0460119 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.ANONavigationEncoder/Driver/Sensors.Hid.ANONavigationEncoder.csproj @@ -0,0 +1,22 @@ + + + true + icon.png + Wilderness Labs, Inc + netstandard2.1 + Library + ANONavigationEncoder + Wilderness Labs, Inc + http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ + Meadow.Foundation.Sensors.Hid.ANONavigationEncoder + https://github.com/WildernessLabs/Meadow.Foundation + Meadow.Foundation,ANONavigationEncoder,direction,directional,navigation,rotary,encoder + 0.1.9 + true + GPIO ANO Directional Navigation and Scroll Wheel Rotary Encoder + + + + + + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.ANONavigationEncoder/Samples/ANONavigationEncoder_Sample/ANONavigationEncoder_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.ANONavigationEncoder/Samples/ANONavigationEncoder_Sample/ANONavigationEncoder_Sample.csproj new file mode 100644 index 0000000000..e743065dfd --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.ANONavigationEncoder/Samples/ANONavigationEncoder_Sample/ANONavigationEncoder_Sample.csproj @@ -0,0 +1,17 @@ + + + netstandard2.1 + true + Library + App + + + + + + + + Always + + + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.ANONavigationEncoder/Samples/ANONavigationEncoder_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.ANONavigationEncoder/Samples/ANONavigationEncoder_Sample/MeadowApp.cs new file mode 100644 index 0000000000..5411443e5b --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.ANONavigationEncoder/Samples/ANONavigationEncoder_Sample/MeadowApp.cs @@ -0,0 +1,41 @@ +using Meadow; +using Meadow.Devices; +using Meadow.Foundation.Sensors.Hid; +using System.Threading.Tasks; + +namespace ANONavigationEncoder_Sample +{ + public class MeadowApp : App + { + ANONavigationEncoder encoder; + + public override Task Initialize() + { + Resolver.Log.Info("Initialize..."); + + encoder = new ANONavigationEncoder(Device.Pins.A01, Device.Pins.A02, Device.Pins.A03, Device.Pins.A04, + Device.Pins.A05, true, Device.Pins.D02, Device.Pins.D03, true); + + encoder.ButtonCenter.Clicked += ButtonCenter_Clicked; + encoder.DirectionalPad.Updated += DirectionalPad_Updated; + encoder.RotaryEncoder.Rotated += RotaryEncoder_Rotated; + + return Task.CompletedTask; + } + + private void RotaryEncoder_Rotated(object sender, Meadow.Peripherals.Sensors.Rotary.RotaryChangeResult e) + { + Resolver.Log.Info($"Rotary dial moved: {e.New}"); + } + + private void DirectionalPad_Updated(object sender, ChangeResult e) + { + Resolver.Log.Info($"DPad state updated: {e.New}"); + } + + private void ButtonCenter_Clicked(object sender, System.EventArgs e) + { + Resolver.Log.Info("Center button clicked"); + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.ANONavigationEncoder/Samples/ANONavigationEncoder_Sample/meadow.config.yaml b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.ANONavigationEncoder/Samples/ANONavigationEncoder_Sample/meadow.config.yaml new file mode 100644 index 0000000000..32363cb69c --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.ANONavigationEncoder/Samples/ANONavigationEncoder_Sample/meadow.config.yaml @@ -0,0 +1,2 @@ +MonoControl: + Options: --jit \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.As5013/Driver/As5013.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.As5013/Driver/As5013.Enums.cs index a6e76f9534..ae7fd7c148 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.As5013/Driver/As5013.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.As5013/Driver/As5013.Enums.cs @@ -3,7 +3,7 @@ public partial class As5013 { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.As5013/Driver/As5013.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.As5013/Driver/As5013.cs index 4e900dba3c..f30497119d 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.As5013/Driver/As5013.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.As5013/Driver/As5013.cs @@ -10,8 +10,8 @@ namespace Meadow.Foundation.Sensors.Hid /// Represents an AS5013 Hall navigation sensor /// for analog joysticks /// - public partial class As5013 - : SamplingSensorBase, IAnalogJoystick + public partial class As5013 + : SamplingSensorBase, IAnalogJoystick, II2cPeripheral { /// /// Event if interrupt port is provided for interrupt pin @@ -50,15 +50,23 @@ public DigitalJoystickPosition? DigitalPosition { get { - if(IsSampling == false) + if (IsSampling == false) { Update(); } return GetDigitalJoystickPosition(); } - } + } + + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; - readonly II2cPeripheral i2CPeripheral; + /// + /// I2C Communication bus used to communicate with the peripheral + /// + protected readonly II2cCommunications i2cComms; /// /// Create a new As5013 object @@ -68,9 +76,9 @@ public DigitalJoystickPosition? DigitalPosition /// port connected to the interrupt pin public As5013(II2cBus i2cBus, byte address = (byte)Addresses.Default, IDigitalInterruptPort interruptPort = null) { - i2CPeripheral = new I2cPeripheral(i2cBus, address); + i2cComms = new I2cCommunications(i2cBus, address); - if(interruptPort != null) + if (interruptPort != null) { interruptPort.Changed += (s, e) => Interrupt?.Invoke(s, EventArgs.Empty); } @@ -106,14 +114,15 @@ public override void StartUpdating(TimeSpan? updateInterval) SamplingTokenSource = new CancellationTokenSource(); - Task.Run(() => + var t = new Task(() => { while (!SamplingTokenSource.IsCancellationRequested) { Update(); Thread.Sleep((int)UpdateInterval.TotalMilliseconds); } - }, SamplingTokenSource.Token); + }, SamplingTokenSource.Token, TaskCreationOptions.LongRunning); + t.Start(); } } @@ -140,11 +149,11 @@ public void SetLowPowerMode(byte timing) { timing %= 8; - byte value = (byte)(i2CPeripheral.ReadRegister((byte)Register.JOYSTICK_CONTROL1) & 0x7F); + byte value = (byte)(i2cComms.ReadRegister((byte)Register.JOYSTICK_CONTROL1) & 0x7F); value |= (byte)(timing << 4); - i2CPeripheral.WriteRegister((byte)Register.JOYSTICK_CONTROL1, value); + i2cComms.WriteRegister((byte)Register.JOYSTICK_CONTROL1, value); } /// @@ -155,11 +164,11 @@ public void SetScalingFactor(byte scalingFactor) { if (scalingFactor > 32) { - i2CPeripheral.WriteRegister((byte)Register.JOYSTICK_T_CTRL, scalingFactor); + i2cComms.WriteRegister((byte)Register.JOYSTICK_T_CTRL, scalingFactor); } else { - i2CPeripheral.WriteRegister((byte)Register.JOYSTICK_T_CTRL, (byte)Command.JOYSTICK_T_CTRL_SCALING_100_CMD); + i2cComms.WriteRegister((byte)Register.JOYSTICK_T_CTRL, (byte)Command.JOYSTICK_T_CTRL_SCALING_100_CMD); } } @@ -168,7 +177,7 @@ public void SetScalingFactor(byte scalingFactor) /// public void InvertSpinning() { - i2CPeripheral.WriteRegister((byte)Register.JOYSTICK_CONTROL2, (byte)Command.JOYSTICK_INVERT_SPINING_CMD); + i2cComms.WriteRegister((byte)Register.JOYSTICK_CONTROL2, (byte)Command.JOYSTICK_INVERT_SPINING_CMD); } /// @@ -176,16 +185,16 @@ public void InvertSpinning() /// public void SoftReset() { - var value = (byte)(i2CPeripheral.ReadRegister((byte)Register.JOYSTICK_CONTROL1) & 0x01); + var value = (byte)(i2cComms.ReadRegister((byte)Register.JOYSTICK_CONTROL1) & 0x01); - i2CPeripheral.WriteRegister((byte)Register.JOYSTICK_CONTROL1, (byte)((byte)Command.JOYSTICK_CONTROL1_RESET_CMD | value)); + i2cComms.WriteRegister((byte)Register.JOYSTICK_CONTROL1, (byte)((byte)Command.JOYSTICK_CONTROL1_RESET_CMD | value)); } void Update() { - sbyte xValue = (sbyte)i2CPeripheral.ReadRegister((byte)Register.JOYSTICK_X); + sbyte xValue = (sbyte)i2cComms.ReadRegister((byte)Register.JOYSTICK_X); Thread.Sleep(1); - sbyte yValue = (sbyte)i2CPeripheral.ReadRegister((byte)Register.JOYSTICK_Y_RES_INT); + sbyte yValue = (sbyte)i2cComms.ReadRegister((byte)Register.JOYSTICK_Y_RES_INT); Thread.Sleep(1); float newX = xValue / 128.0f * (IsHorizontalInverted ? -1 : 1); @@ -193,9 +202,7 @@ void Update() if (IsVerticalHorizonalSwapped) { - float temp = newX; - newX = newY; - newY = temp; + (newY, newX) = (newX, newY); } var oldPosition = Position; @@ -212,9 +219,9 @@ void Update() /// public void DisableInterrupt() { - var value = (byte)(i2CPeripheral.ReadRegister((byte)Register.JOYSTICK_CONTROL1) & 0x04); + var value = (byte)(i2cComms.ReadRegister((byte)Register.JOYSTICK_CONTROL1) & 0x04); - i2CPeripheral.WriteRegister((byte)Register.JOYSTICK_CONTROL1, (byte)((byte)Command.JOYSTICK_CONTROL1_RESET_CMD | value)); + i2cComms.WriteRegister((byte)Register.JOYSTICK_CONTROL1, (byte)((byte)Command.JOYSTICK_CONTROL1_RESET_CMD | value)); } /// @@ -222,9 +229,9 @@ public void DisableInterrupt() /// public void EnableInterrupt() { - var value = (byte)(i2CPeripheral.ReadRegister((byte)Register.JOYSTICK_CONTROL1) | 0x04); + var value = (byte)(i2cComms.ReadRegister((byte)Register.JOYSTICK_CONTROL1) | 0x04); - i2CPeripheral.WriteRegister((byte)Register.JOYSTICK_CONTROL1, (byte)((byte)Command.JOYSTICK_CONTROL1_RESET_CMD | value)); + i2cComms.WriteRegister((byte)Register.JOYSTICK_CONTROL1, (byte)((byte)Command.JOYSTICK_CONTROL1_RESET_CMD | value)); } /// @@ -232,13 +239,13 @@ public void EnableInterrupt() /// public void SetDefaultConfiguration() { - i2CPeripheral.WriteRegister((byte)Register.JOYSTICK_CONTROL2, (byte)Command.JOYSTICK_CONTROL2_TEST_CMD); - i2CPeripheral.WriteRegister((byte)Register.JOYSTICK_AGC, (byte)Command.JOYSTICK_AGC_MAX_SENSITIVITY_CMD); - i2CPeripheral.WriteRegister((byte)Register.JOYSTICK_T_CTRL, (byte)Command.JOYSTICK_T_CTRL_SCALING_90_8_CMD); + i2cComms.WriteRegister((byte)Register.JOYSTICK_CONTROL2, (byte)Command.JOYSTICK_CONTROL2_TEST_CMD); + i2cComms.WriteRegister((byte)Register.JOYSTICK_AGC, (byte)Command.JOYSTICK_AGC_MAX_SENSITIVITY_CMD); + i2cComms.WriteRegister((byte)Register.JOYSTICK_T_CTRL, (byte)Command.JOYSTICK_T_CTRL_SCALING_90_8_CMD); - byte value = (byte)(i2CPeripheral.ReadRegister((byte)Register.JOYSTICK_CONTROL1) & 0x01); + byte value = (byte)(i2cComms.ReadRegister((byte)Register.JOYSTICK_CONTROL1) & 0x01); - i2CPeripheral.WriteRegister((byte)Register.JOYSTICK_CONTROL1, (byte)((byte)Command.JOYSTICK_CONTROL1_RESET_CMD | value)); + i2cComms.WriteRegister((byte)Register.JOYSTICK_CONTROL1, (byte)((byte)Command.JOYSTICK_CONTROL1_RESET_CMD | value)); } DigitalJoystickPosition GetDigitalJoystickPosition() diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.As5013/Driver/Sensors.Hid.As5013.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.As5013/Driver/Sensors.Hid.As5013.csproj index 99bad67c10..1399c27934 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.As5013/Driver/Sensors.Hid.As5013.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.As5013/Driver/Sensors.Hid.As5013.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.As5013/Samples/As5013_Sample/As5013_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.As5013/Samples/As5013_Sample/As5013_Sample.csproj index b5056d2ae1..7435f00b05 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.As5013/Samples/As5013_Sample/As5013_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.As5013/Samples/As5013_Sample/As5013_Sample.csproj @@ -7,7 +7,7 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.BBQ10Keyboard/Driver/BBQ10Keyboard.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.BBQ10Keyboard/Driver/BBQ10Keyboard.Enums.cs index d530562192..efa6240eea 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.BBQ10Keyboard/Driver/BBQ10Keyboard.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.BBQ10Keyboard/Driver/BBQ10Keyboard.Enums.cs @@ -26,7 +26,7 @@ public enum KeyState } /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.BBQ10Keyboard/Driver/BBQ10Keyboard.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.BBQ10Keyboard/Driver/BBQ10Keyboard.cs index 199c6c259d..a9f1326fd3 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.BBQ10Keyboard/Driver/BBQ10Keyboard.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.BBQ10Keyboard/Driver/BBQ10Keyboard.cs @@ -7,9 +7,17 @@ namespace Meadow.Foundation.Sensors.Hid /// /// Represents a BBQ10Keyboard Featherwing /// - public partial class BBQ10Keyboard + public partial class BBQ10Keyboard : II2cPeripheral { - readonly I2cPeripheral i2CPeripheral; + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + + /// + /// I2C Communication bus used to communicate with the peripheral + /// + protected readonly II2cCommunications i2cComms; readonly IDigitalInterruptPort interruptPort; @@ -18,17 +26,17 @@ public partial class BBQ10Keyboard /// public event EventHandler OnKeyEvent = delegate { }; - byte Status => i2CPeripheral.ReadRegister((byte)Registers.KEY); + byte Status => i2cComms.ReadRegister((byte)Registers.KEY); - byte KeyCount => (byte)(i2CPeripheral.ReadRegister(KEY_COUNT_MASK) & Status); + byte KeyCount => (byte)(i2cComms.ReadRegister(KEY_COUNT_MASK) & Status); /// /// Get or set the backlight /// public byte BackLight { - get => i2CPeripheral.ReadRegister((byte)Registers.BKL); - set => i2CPeripheral.WriteRegister((byte)Registers.BKL, value); + get => i2cComms.ReadRegister((byte)Registers.BKL); + set => i2cComms.WriteRegister((byte)Registers.BKL, value); } /// @@ -36,8 +44,8 @@ public byte BackLight /// public byte BackLight2 { - get => i2CPeripheral.ReadRegister((byte)Registers.BK2); - set => i2CPeripheral.WriteRegister((byte)Registers.BK2, value); + get => i2cComms.ReadRegister((byte)Registers.BK2); + set => i2cComms.WriteRegister((byte)Registers.BK2, value); } /// @@ -48,7 +56,7 @@ public byte BackLight2 /// The I2C address public BBQ10Keyboard(II2cBus i2cBus, IPin interruptPin = null, byte address = (byte)Addresses.Default) { - i2CPeripheral = new I2cPeripheral(i2cBus, address); + i2cComms = new I2cCommunications(i2cBus, address); if (interruptPin != null) { @@ -70,7 +78,7 @@ public KeyEvent GetLastKeyEvent() return new KeyEvent('\0', KeyState.StateIdle); } - var keyData = i2CPeripheral.ReadRegisterAsUShort((byte)Registers.FIF); + var keyData = i2cComms.ReadRegisterAsUShort((byte)Registers.FIF); return new KeyEvent((char)(keyData >> 8), (KeyState)(keyData & 0xFF)); } @@ -80,7 +88,7 @@ public KeyEvent GetLastKeyEvent() /// public void Reset() { - i2CPeripheral?.Write((byte)Registers.RST); + i2cComms?.Write((byte)Registers.RST); Thread.Sleep(100); } @@ -89,7 +97,7 @@ public void Reset() /// protected void ClearInerruptStatus() { - i2CPeripheral.WriteRegister((byte)Registers.INT, 0x00); + i2cComms.WriteRegister((byte)Registers.INT, 0x00); } private void InterruptPort_Changed(object sender, DigitalPortResult e) diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.BBQ10Keyboard/Driver/Sensors.Hid.Bbq10Keyboard.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.BBQ10Keyboard/Driver/Sensors.Hid.Bbq10Keyboard.csproj index ffb135d4d8..f8c4af596e 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.BBQ10Keyboard/Driver/Sensors.Hid.Bbq10Keyboard.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.BBQ10Keyboard/Driver/Sensors.Hid.Bbq10Keyboard.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.BBQ10Keyboard/Samples/Bbq10Keyboard_Sample/Bbq10Keyboard_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.BBQ10Keyboard/Samples/Bbq10Keyboard_Sample/Bbq10Keyboard_Sample.csproj index 2ec7fa5c03..2373c5a1e8 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.BBQ10Keyboard/Samples/Bbq10Keyboard_Sample/Bbq10Keyboard_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.BBQ10Keyboard/Samples/Bbq10Keyboard_Sample/Bbq10Keyboard_Sample.csproj @@ -6,7 +6,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Keyboard/Driver/Sensors.Hid.Keyboard.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Keyboard/Driver/Sensors.Hid.Keyboard.csproj index 91a789a95e..feda6693c1 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Keyboard/Driver/Sensors.Hid.Keyboard.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Keyboard/Driver/Sensors.Hid.Keyboard.csproj @@ -18,6 +18,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Mpr121/Driver/Mpr121.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Mpr121/Driver/Mpr121.cs index 3bab6e67f5..8149a08cfc 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Mpr121/Driver/Mpr121.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Mpr121/Driver/Mpr121.cs @@ -9,15 +9,23 @@ namespace Meadow.Foundation.Sensors.Hid /// /// Represents the MPR121 12-Key Capacitive Touch Sensor /// - public partial class Mpr121 + public partial class Mpr121 : II2cPeripheral { - private readonly II2cPeripheral i2cPeripheral; + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + + /// + /// I2C Communication bus used to communicate with the peripheral + /// + protected readonly II2cCommunications i2cComms; private int refreshPeriod; - private Timer timer; + private readonly Timer timer; - private Dictionary channelStatus; + private readonly Dictionary channelStatus; /// /// Notifies about a the channel statuses have been changed. @@ -36,7 +44,7 @@ public partial class Mpr121 public int RefreshPeriod { get => refreshPeriod; - + set { refreshPeriod = value; @@ -60,7 +68,7 @@ public Mpr121(II2cBus i2cBus, byte address = (byte)Addresses.Default, int refres { this.refreshPeriod = refreshPeriod; - i2cPeripheral = new I2cPeripheral(i2cBus, address); + i2cComms = new I2cCommunications(i2cBus, address); channelStatus = new Dictionary(); @@ -69,15 +77,15 @@ public Mpr121(II2cBus i2cBus, byte address = (byte)Addresses.Default, int refres channelStatus.Add(channel, false); } - configuration = configuration ?? GetDefaultConfiguration(); + configuration ??= GetDefaultConfiguration(); InitializeController(configuration); - if(refreshPeriod < 1) + if (refreshPeriod < 1) { refreshPeriod = Timeout.Infinite; } - + timer = new Timer(RefreshChannelStatus, this, refreshPeriod, refreshPeriod); } @@ -165,7 +173,7 @@ private void InitializeController(Mpr121Configuration configuration) private void SetRegister(Registers register, byte value) { - i2cPeripheral.WriteRegister((byte)register, value); + i2cComms.WriteRegister((byte)register, value); } private void RefreshChannelStatus(object value) @@ -182,7 +190,7 @@ private void RefreshChannelStatus() var period = RefreshPeriod; RefreshPeriod = 0; - var rawStatus = i2cPeripheral.ReadRegisterAsUShort(0x00, ByteOrder.LittleEndian); + var rawStatus = i2cComms.ReadRegisterAsUShort(0x00, ByteOrder.LittleEndian); bool isStatusChanged = false; diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Mpr121/Driver/Mpr121.enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Mpr121/Driver/Mpr121.enums.cs index bde1a53b5a..abbc2e9a43 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Mpr121/Driver/Mpr121.enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Mpr121/Driver/Mpr121.enums.cs @@ -4,7 +4,7 @@ namespace Meadow.Foundation.Sensors.Hid public partial class Mpr121 { /// - /// Valid addresses for the sensor + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Mpr121/Driver/Sensors.Hid.Mpr121.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Mpr121/Driver/Sensors.Hid.Mpr121.csproj index 0086502009..d483b94a5a 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Mpr121/Driver/Sensors.Hid.Mpr121.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Mpr121/Driver/Sensors.Hid.Mpr121.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Mpr121/Samples/Mpr121_Sample/Mpr121_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Mpr121/Samples/Mpr121_Sample/Mpr121_Sample.csproj index 414fe67e97..b1acabddd1 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Mpr121/Samples/Mpr121_Sample/Mpr121_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Mpr121/Samples/Mpr121_Sample/Mpr121_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Tsc2004/Driver/Sensors.Hid.Tsc2004.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Tsc2004/Driver/Sensors.Hid.Tsc2004.csproj index d1e054065c..87e2465458 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Tsc2004/Driver/Sensors.Hid.Tsc2004.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Tsc2004/Driver/Sensors.Hid.Tsc2004.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Tsc2004/Driver/Tsc2004.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Tsc2004/Driver/Tsc2004.Enums.cs index a39c63e9dd..db84f79085 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Tsc2004/Driver/Tsc2004.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Tsc2004/Driver/Tsc2004.Enums.cs @@ -3,7 +3,7 @@ public partial class Tsc2004 { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Tsc2004/Driver/Tsc2004.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Tsc2004/Driver/Tsc2004.cs index 6f0c34cd41..d7ad9639ba 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Tsc2004/Driver/Tsc2004.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Tsc2004/Driver/Tsc2004.cs @@ -8,29 +8,35 @@ namespace Meadow.Foundation.Sensors.Hid /// /// Represents a TSC2004 4-wire touch screen controller /// - public partial class Tsc2004 + public partial class Tsc2004 : II2cPeripheral { - readonly I2cPeripheral i2CPeripheral; + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + + /// + /// I2C Communication bus used to communicate with the peripheral + /// + protected readonly II2cCommunications i2cComms; - //default values from arturo182 - /// - /// Minimum X value of touchscreen + /// Minimum X value of touchscreen (defaults to 366) /// public int XMin { get; set; } = 366; /// - /// Maximum X value of touchscreen + /// Maximum X value of touchscreen (defaults to 3567) /// public int XMax { get; set; } = 3567; /// - /// Minimum Y value of touchscreen + /// Minimum Y value of touchscreen (defaults to 334) /// public int YMin { get; set; } = 334; /// - /// Maximum Y value of touchscreen + /// Maximum Y value of touchscreen (defaults to 3787) /// public int YMax { get; set; } = 3787; @@ -56,7 +62,7 @@ public partial class Tsc2004 /// The I2C address public Tsc2004(II2cBus i2cBus, byte address = (byte)Addresses.Default) { - i2CPeripheral = new I2cPeripheral(i2cBus, address); + i2cComms = new I2cCommunications(i2cBus, address); Initialize(); } @@ -106,8 +112,8 @@ public Point3d GetPoint() /// public Point3d GetPointRaw() { - while((ReadRegister16((byte)Registers.STATUS) & STATUS_DAV_MASK) == 0) - { + while ((ReadRegister16((byte)Registers.STATUS) & STATUS_DAV_MASK) == 0) + { return new Point3d(); } @@ -118,10 +124,10 @@ public Point3d GetPointRaw() ushort z1 = ReadRegister16((byte)Registers.Z1); ushort z2 = ReadRegister16((byte)Registers.Z2); - if( x > _MAX_12BIT || - y > _MAX_12BIT || - z1 == 0 || - z2 > _MAX_12BIT || + if (x > _MAX_12BIT || + y > _MAX_12BIT || + z1 == 0 || + z2 > _MAX_12BIT || z1 >= z2) { x = 0; @@ -132,7 +138,7 @@ public Point3d GetPointRaw() { var val = (x * (z2 - z1) / z1); val *= _RESISTOR_VAL; - z = (ushort)(val/4096); + z = (ushort)(val / 4096); } return new Point3d(x, y, z); @@ -144,8 +150,8 @@ public Point3d GetPointRaw() /// True if touched public bool IsTouched() => (ReadRegister16((byte)Registers.STATUS) & STATUS_DAV_MASK) != 0; - - + + /// /// Is the touch buffer empty /// @@ -156,8 +162,8 @@ ushort ReadRegister16(byte address) { Span data = new byte[2]; - i2CPeripheral.ReadRegister((byte)(address | (byte)Registers.READ), data); - + i2cComms.ReadRegister((byte)(address | (byte)Registers.READ), data); + return (ushort)(data[0] << 8 | data[1]); } @@ -168,12 +174,12 @@ void WriteRegister16(byte register, ushort value) data[1] = (byte)((value >> 8) & 0xFF); data[2] = (byte)((value >> 0) & 0xFF); - i2CPeripheral.Write(data); + i2cComms.Write(data); } void SendCommand(byte command) { - i2CPeripheral.Write((byte)(CMD | CMD_12BIT | command)); + i2cComms.Write((byte)(CMD | CMD_12BIT | command)); } int GetXForRotation(int x, int y) diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Tsc2004/Samples/Tsc2004_Sample/Tsc2004_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Tsc2004/Samples/Tsc2004_Sample/Tsc2004_Sample.csproj index 452d91a5d5..60c6a684d5 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Tsc2004/Samples/Tsc2004_Sample/Tsc2004_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.Tsc2004/Samples/Tsc2004_Sample/Tsc2004_Sample.csproj @@ -6,7 +6,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Driver/Controls/WiiExtensionDPad.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Driver/Controls/WiiExtensionDPad.cs index bc70b6129a..bdee20cebb 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Driver/Controls/WiiExtensionDPad.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Driver/Controls/WiiExtensionDPad.cs @@ -1,5 +1,4 @@ -using Meadow; -using Meadow.Peripherals.Sensors.Hid; +using Meadow.Peripherals.Sensors.Hid; using System; namespace Meadow.Foundation.Sensors.Hid @@ -14,11 +13,10 @@ public void Update(bool isLeftPressed, bool isRightPressed, bool isUpPressed, bo { var newPosition = GetDigitalPosition(isLeftPressed, isRightPressed, isUpPressed, isDownPressed); - if(newPosition != Position) + if (newPosition != Position) { - Updated?.Invoke(this, new ChangeResult(newPosition, Position)); - Position = newPosition; + Position = newPosition; } } diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Driver/Drivers/WiiClassicController.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Driver/Drivers/WiiClassicController.cs index 356245b4f7..3863f6b89d 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Driver/Drivers/WiiClassicController.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Driver/Drivers/WiiClassicController.cs @@ -102,8 +102,8 @@ public override void Update() { if(useHighResolutionMode) { - i2cPeripheral.WriteRegister(0, 0); - i2cPeripheral.Read(readBuffer[..8]); + i2cComms.WriteRegister(0, 0); + i2cComms.Read(readBuffer[..8]); } else { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Driver/Drivers/WiiClassicControllerPro.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Driver/Drivers/WiiClassicControllerPro.cs index a6ac62bb25..f013b4d680 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Driver/Drivers/WiiClassicControllerPro.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Driver/Drivers/WiiClassicControllerPro.cs @@ -91,8 +91,8 @@ public override void Update() { if (useHighResolutionMode) { - i2cPeripheral.WriteRegister(0, 0); - i2cPeripheral.Read(readBuffer[..8]); + i2cComms.WriteRegister(0, 0); + i2cComms.Read(readBuffer[..8]); } else { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Driver/Sensors.Hid.WiiExtensionControllers.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Driver/Sensors.Hid.WiiExtensionControllers.csproj index f497a4971d..fc5e6d7ebd 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Driver/Sensors.Hid.WiiExtensionControllers.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Driver/Sensors.Hid.WiiExtensionControllers.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Driver/WiiClassicControllerBase.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Driver/WiiClassicControllerBase.cs index 60e8d1eee4..40a9a2d26e 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Driver/WiiClassicControllerBase.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Driver/WiiClassicControllerBase.cs @@ -131,11 +131,11 @@ protected override void Initialize() base.Initialize(); if (useHighResolutionMode) { - i2cPeripheral.WriteRegister(0xFE, 0x03); + i2cComms.WriteRegister(0xFE, 0x03); } else { - i2cPeripheral.WriteRegister(0xFE, 0x00); + i2cComms.WriteRegister(0xFE, 0x00); } } } diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Driver/WiiExtensionControllerBase.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Driver/WiiExtensionControllerBase.Enums.cs index b099a6feb2..efcd5b09a9 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Driver/WiiExtensionControllerBase.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Driver/WiiExtensionControllerBase.Enums.cs @@ -3,7 +3,7 @@ public abstract partial class WiiExtensionControllerBase { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Driver/WiiExtensionControllerBase.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Driver/WiiExtensionControllerBase.cs index d01bcc8d26..d07dd462c4 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Driver/WiiExtensionControllerBase.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Driver/WiiExtensionControllerBase.cs @@ -1,5 +1,4 @@ using Meadow.Hardware; -using Meadow.Peripherals.Sensors; using System; using System.Threading; using System.Threading.Tasks; @@ -10,17 +9,22 @@ namespace Meadow.Foundation.Sensors.Hid /// Abstract base class that represents /// Nintendo Wiimote I2C extension controllers /// - public abstract partial class WiiExtensionControllerBase + public abstract partial class WiiExtensionControllerBase : II2cPeripheral { + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + /// /// Default I2C bus speed (400kHz) /// - public static I2cBusSpeed DefaultSpeed => I2cBusSpeed.Fast; + public static I2cBusSpeed DefaultI2cSpeed => I2cBusSpeed.Fast; /// - /// The I2C peripheral object for the extension + /// I2C Communication bus used to communicate with the peripheral /// - protected readonly II2cPeripheral i2cPeripheral; + protected readonly II2cCommunications i2cComms; /// /// Data buffer returned by the controller @@ -50,7 +54,7 @@ public abstract partial class WiiExtensionControllerBase /// The extension controller address public WiiExtensionControllerBase(II2cBus i2cBus, byte address) { - i2cPeripheral = new I2cPeripheral(i2cBus, address); + i2cComms = new I2cCommunications(i2cBus, address); Initialize(); } @@ -60,8 +64,8 @@ public WiiExtensionControllerBase(II2cBus i2cBus, byte address) /// protected virtual void Initialize() { - i2cPeripheral.WriteRegister(0xF0, 0x55); - i2cPeripheral.WriteRegister(0xFB, 0x00); + i2cComms.WriteRegister(0xF0, 0x55); + i2cComms.WriteRegister(0xFB, 0x00); Thread.Sleep(100); } @@ -70,9 +74,9 @@ protected virtual void Initialize() /// public virtual void Update() { - i2cPeripheral.Write(0); + i2cComms.Write(0); - i2cPeripheral.Read(readBuffer[..6]); + i2cComms.Read(readBuffer[..6]); } /// @@ -81,8 +85,8 @@ public virtual void Update() /// The ID as a byte public byte[] GetIdentification() { - i2cPeripheral.Write(0xFA); - i2cPeripheral.Read(readBuffer[..6]); + i2cComms.Write(0xFA); + i2cComms.Read(readBuffer[..6]); Resolver.Log.Info(BitConverter.ToString(readBuffer[..6].ToArray())); @@ -103,14 +107,15 @@ public void StartUpdating(TimeSpan? updateInterval) SamplingTokenSource = new CancellationTokenSource(); CancellationToken ct = SamplingTokenSource.Token; - Task.Run(() => + var t = new Task(() => { - while(ct.IsCancellationRequested == false) + while (ct.IsCancellationRequested == false) { Update(); Thread.Sleep(updateInterval.Value); } - }); + }, ct, TaskCreationOptions.LongRunning); + t.Start(); } } diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/NesClassicController_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/NesClassicController_Sample/MeadowApp.cs index 9e9ab08195..a37c010cb7 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/NesClassicController_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/NesClassicController_Sample/MeadowApp.cs @@ -16,7 +16,7 @@ public override Task Initialize() { Resolver.Log.Info("Initialize..."); - var i2cBus = Device.CreateI2cBus(NesClassicController.DefaultSpeed); + var i2cBus = Device.CreateI2cBus(NesClassicController.DefaultI2cSpeed); nesController = new NesClassicController(i2cBus: i2cBus); diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/NesClassicController_Sample/NesClassicController_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/NesClassicController_Sample/NesClassicController_Sample.csproj index efc7f9f6cf..cbea010873 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/NesClassicController_Sample/NesClassicController_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/NesClassicController_Sample/NesClassicController_Sample.csproj @@ -6,7 +6,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/SnesClassicController_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/SnesClassicController_Sample/MeadowApp.cs index ed1100f6c2..d158164c6e 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/SnesClassicController_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/SnesClassicController_Sample/MeadowApp.cs @@ -16,7 +16,7 @@ public override Task Initialize() { Resolver.Log.Info("Initialize..."); - var i2cBus = Device.CreateI2cBus(SnesClassicController.DefaultSpeed); + var i2cBus = Device.CreateI2cBus(SnesClassicController.DefaultI2cSpeed); snesController = new SnesClassicController(i2cBus: i2cBus); diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/SnesClassicController_Sample/SnesClassicController_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/SnesClassicController_Sample/SnesClassicController_Sample.csproj index efc7f9f6cf..cbea010873 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/SnesClassicController_Sample/SnesClassicController_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/SnesClassicController_Sample/SnesClassicController_Sample.csproj @@ -6,7 +6,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/WiiClassicControllerPro_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/WiiClassicControllerPro_Sample/MeadowApp.cs index f0e0a61685..cc2b434b0e 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/WiiClassicControllerPro_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/WiiClassicControllerPro_Sample/MeadowApp.cs @@ -16,7 +16,7 @@ public override Task Initialize() { Resolver.Log.Info("Initialize..."); - var i2cBus = Device.CreateI2cBus(WiiClassicControllerPro.DefaultSpeed); + var i2cBus = Device.CreateI2cBus(WiiClassicControllerPro.DefaultI2cSpeed); classicControllerPro = new WiiClassicControllerPro(i2cBus: i2cBus, useHighResolutionMode: true); diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/WiiClassicControllerPro_Sample/WiiClassicControllerPro_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/WiiClassicControllerPro_Sample/WiiClassicControllerPro_Sample.csproj index efc7f9f6cf..cbea010873 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/WiiClassicControllerPro_Sample/WiiClassicControllerPro_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/WiiClassicControllerPro_Sample/WiiClassicControllerPro_Sample.csproj @@ -6,7 +6,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/WiiClassicController_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/WiiClassicController_Sample/MeadowApp.cs index af3b7699b8..66ec80bb77 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/WiiClassicController_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/WiiClassicController_Sample/MeadowApp.cs @@ -16,7 +16,7 @@ public override Task Initialize() { Resolver.Log.Info("Initialize..."); - var i2cBus = Device.CreateI2cBus(WiiClassicController.DefaultSpeed); + var i2cBus = Device.CreateI2cBus(WiiClassicController.DefaultI2cSpeed); classicController = new WiiClassicController(i2cBus: i2cBus, useHighResolutionMode: true); diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/WiiClassicController_Sample/WiiClassicController_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/WiiClassicController_Sample/WiiClassicController_Sample.csproj index efc7f9f6cf..cbea010873 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/WiiClassicController_Sample/WiiClassicController_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/WiiClassicController_Sample/WiiClassicController_Sample.csproj @@ -6,7 +6,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/WiiNunchuck_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/WiiNunchuck_Sample/MeadowApp.cs index d477cb2c06..d09c3d81eb 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/WiiNunchuck_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/WiiNunchuck_Sample/MeadowApp.cs @@ -16,7 +16,7 @@ public override Task Initialize() { Resolver.Log.Info("Initialize..."); - nunchuck = new WiiNunchuck(Device.CreateI2cBus(WiiNunchuck.DefaultSpeed)); + nunchuck = new WiiNunchuck(Device.CreateI2cBus(WiiNunchuck.DefaultI2cSpeed)); nunchuck.GetIdentification(); diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/WiiNunchuck_Sample/WiiNunchuck_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/WiiNunchuck_Sample/WiiNunchuck_Sample.csproj index efc7f9f6cf..cbea010873 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/WiiNunchuck_Sample/WiiNunchuck_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Hid.WiiExtensionControllers/Samples/WiiNunchuck_Sample/WiiNunchuck_Sample.csproj @@ -6,7 +6,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Alspt19315C/Driver/Sensors.Light.Alspt19315C.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Alspt19315C/Driver/Sensors.Light.Alspt19315C.csproj index 388d18ee63..3ade17edd0 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Alspt19315C/Driver/Sensors.Light.Alspt19315C.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Alspt19315C/Driver/Sensors.Light.Alspt19315C.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Alspt19315C/Samples/Alspt19315C_Sample/Alspt19315C_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Alspt19315C/Samples/Alspt19315C_Sample/Alspt19315C_Sample.csproj index a517a04a0c..d162dbda33 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Alspt19315C/Samples/Alspt19315C_Sample/Alspt19315C_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Alspt19315C/Samples/Alspt19315C_Sample/Alspt19315C_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Light.AnalogSolarIntensityGauge/Driver/Sensors.Light.AnalogSolarIntensityGauge.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Light.AnalogSolarIntensityGauge/Driver/Sensors.Light.AnalogSolarIntensityGauge.csproj index ec8c453c20..6eaea9900d 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Light.AnalogSolarIntensityGauge/Driver/Sensors.Light.AnalogSolarIntensityGauge.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Light.AnalogSolarIntensityGauge/Driver/Sensors.Light.AnalogSolarIntensityGauge.csproj @@ -22,6 +22,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Light.AnalogSolarIntensityGauge/Samples/AnalogSolarIntensityGauge_Sample/AnalogSolarIntensityGauge_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Light.AnalogSolarIntensityGauge/Samples/AnalogSolarIntensityGauge_Sample/AnalogSolarIntensityGauge_Sample.csproj index 35befbcb29..b613283f31 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Light.AnalogSolarIntensityGauge/Samples/AnalogSolarIntensityGauge_Sample/AnalogSolarIntensityGauge_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Light.AnalogSolarIntensityGauge/Samples/AnalogSolarIntensityGauge_Sample/AnalogSolarIntensityGauge_Sample.csproj @@ -6,7 +6,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Bh1745/Driver/Bh1745.Addresses.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Bh1745/Driver/Bh1745.Addresses.cs index f9031af29d..e5fa769eff 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Bh1745/Driver/Bh1745.Addresses.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Bh1745/Driver/Bh1745.Addresses.cs @@ -3,7 +3,7 @@ public partial class Bh1745 { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Bh1745/Driver/Bh1745.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Bh1745/Driver/Bh1745.cs index a4ea3346f3..952ec019b7 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Bh1745/Driver/Bh1745.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Bh1745/Driver/Bh1745.cs @@ -7,25 +7,12 @@ namespace Meadow.Foundation.Sensors.Light { - // TODO: The chip can drive LEDs which will help to identify colors more - // accurately by lighting them up. I found this documentation from the - // pimoroni site (https://shop.pimoroni.com/products/bh1745-luminance-and-colour-sensor-breakout) - // which makes a breakout that has LEDs: - // - // The LEDs are connected to the BH1745 Interrupt line. This is activated by - // a threshold mechanism that is fully documented in the BH1745 chip manual. - // You can select which of the four light sensor channels to use and you can - // set a high and a low threshold. The Interrupt is enabled when the light - // is above the high level or below the low level. Write 0x1D to register - // 0x60 to enable Interrupts and select the unfiltered light sensor. Write - // 0xFF to the four registers starting at 0x62 to force the LEDs on. With - // the default settings in these registers, the LEDS will be off. - /// /// Represents a BH1745 Luminance and Colour Sensor /// public partial class Bh1745 - : ByteCommsSensorBase<(Illuminance? AmbientLight, Color? Color, bool Valid)>, ILightSensor + : ByteCommsSensorBase<(Illuminance? AmbientLight, Color? Color, bool Valid)>, + ILightSensor, II2cPeripheral { /// /// Raised when the luminosity changes @@ -36,7 +23,7 @@ public partial class Bh1745 /// The current Illuminance value /// public Illuminance? Illuminance => Conditions.AmbientLight; - + /// /// Interrupt reset status /// @@ -44,7 +31,7 @@ public InterruptStatus InterruptReset { get { - var intReset = Peripheral.ReadRegister(Registers.SYSTEM_CONTROL); + var intReset = BusComms.ReadRegister(Registers.SYSTEM_CONTROL); intReset = (byte)((intReset & MaskValues.INT_RESET) >> 6); return (InterruptStatus)intReset; } @@ -54,9 +41,9 @@ public InterruptStatus InterruptReset { throw new ArgumentOutOfRangeException(); } - var intReset = Peripheral.ReadRegister(Registers.SYSTEM_CONTROL); + var intReset = BusComms.ReadRegister(Registers.SYSTEM_CONTROL); intReset = (byte)((intReset & ~MaskValues.INT_RESET) | (byte)value << 6); - Peripheral?.WriteRegister(Registers.SYSTEM_CONTROL, intReset); + BusComms?.WriteRegister(Registers.SYSTEM_CONTROL, intReset); } } @@ -72,9 +59,9 @@ public MeasurementTimeType MeasurementTime { throw new ArgumentOutOfRangeException(); } - var time = Peripheral.ReadRegister(Registers.MODE_CONTROL1); + var time = BusComms.ReadRegister(Registers.MODE_CONTROL1); time = (byte)((time & ~MaskValues.MEASUREMENT_TIME) | (byte)value); - Peripheral?.WriteRegister(Registers.MODE_CONTROL1, time); + BusComms?.WriteRegister(Registers.MODE_CONTROL1, time); measurementTime = value; } } @@ -88,9 +75,9 @@ public bool IsMeasurementActive get => isMeasurementActive; set { - var active = Peripheral.ReadRegister(Registers.MODE_CONTROL2); + var active = BusComms.ReadRegister(Registers.MODE_CONTROL2); active = (byte)((active & ~MaskValues.RGBC_EN) | Convert.ToByte(value) << 4); - Peripheral?.WriteRegister(Registers.MODE_CONTROL2, active); + BusComms?.WriteRegister(Registers.MODE_CONTROL2, active); isMeasurementActive = value; } } @@ -108,9 +95,9 @@ public AdcGainTypes AdcGain { throw new ArgumentOutOfRangeException(); } - var adcGain = Peripheral.ReadRegister(Registers.MODE_CONTROL2); + var adcGain = BusComms.ReadRegister(Registers.MODE_CONTROL2); adcGain = (byte)((adcGain & ~MaskValues.ADC_GAIN) | (byte)value); - Peripheral?.WriteRegister(Registers.MODE_CONTROL2, adcGain); + BusComms?.WriteRegister(Registers.MODE_CONTROL2, adcGain); this.adcGain = value; } } @@ -123,7 +110,7 @@ public bool InterruptSignalIsActive { get { - var intStatus = Peripheral.ReadRegister(Registers.INTERRUPT); + var intStatus = BusComms.ReadRegister(Registers.INTERRUPT); intStatus = (byte)((intStatus & MaskValues.INT_STATUS) >> 7); return Convert.ToBoolean(intStatus); } @@ -141,9 +128,9 @@ public LatchBehaviorTypes LatchBehavior { throw new ArgumentOutOfRangeException(); } - var intLatch = Peripheral.ReadRegister(Registers.INTERRUPT); + var intLatch = BusComms.ReadRegister(Registers.INTERRUPT); intLatch = (byte)((intLatch & ~MaskValues.INT_LATCH) | (byte)value << 4); - Peripheral?.WriteRegister(Registers.INTERRUPT, intLatch); + BusComms?.WriteRegister(Registers.INTERRUPT, intLatch); latchBehavior = value; } } @@ -158,9 +145,9 @@ public InterruptChannels InterruptSource set { if (!Enum.IsDefined(typeof(InterruptChannels), value)) { throw new ArgumentOutOfRangeException(); } - var intSource = Peripheral.ReadRegister(Registers.INTERRUPT); + var intSource = BusComms.ReadRegister(Registers.INTERRUPT); intSource = (byte)((intSource & ~MaskValues.INT_SOURCE) | (byte)value << 2); - Peripheral?.WriteRegister(Registers.INTERRUPT, intSource); + BusComms?.WriteRegister(Registers.INTERRUPT, intSource); interruptSource = value; } } @@ -174,9 +161,9 @@ public bool InterruptIsEnabled get => isInterruptEnabled; set { - var intPin = Peripheral.ReadRegister(Registers.INTERRUPT); + var intPin = BusComms.ReadRegister(Registers.INTERRUPT); intPin = (byte)((intPin & ~MaskValues.INT_ENABLE) | Convert.ToByte(value)); - Peripheral?.WriteRegister(Registers.INTERRUPT, intPin); + BusComms?.WriteRegister(Registers.INTERRUPT, intPin); isInterruptEnabled = value; } } @@ -194,9 +181,9 @@ public InterruptTypes InterruptPersistence { throw new ArgumentOutOfRangeException(); } - var intPersistence = Peripheral.ReadRegister(Registers.PERSISTENCE); + var intPersistence = BusComms.ReadRegister(Registers.PERSISTENCE); intPersistence = (byte)((intPersistence & ~MaskValues.PERSISTENCE_MASK) | (byte)value); - Peripheral?.WriteRegister(Registers.PERSISTENCE, intPersistence); + BusComms?.WriteRegister(Registers.PERSISTENCE, intPersistence); interruptPersistence = value; } } @@ -210,7 +197,7 @@ public ushort LowerInterruptThreshold get => lowerInterruptThreshold; set { - Peripheral.WriteRegister(Registers.TL, value); + BusComms.WriteRegister(Registers.TL, value); lowerInterruptThreshold = value; } } @@ -224,7 +211,7 @@ public ushort UpperInterruptThreshold get => upperInterruptThreshold; set { - Peripheral.WriteRegister(Registers.TH, value); + BusComms.WriteRegister(Registers.TH, value); upperInterruptThreshold = value; } } @@ -235,6 +222,11 @@ public ushort UpperInterruptThreshold /// public ChannelMultipliers CompensationMultipliers { get; set; } + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + /// /// Create a new BH17545 color sensor object /// @@ -258,38 +250,31 @@ public Bh1745(II2cBus i2cBus, byte address = (byte)Addresses.Default) /// The latest sensor reading protected override Task<(Illuminance? AmbientLight, Color? Color, bool Valid)> ReadSensor() { - return Task.Run(() => - { - (Illuminance? AmbientLight, Color? Color, bool Valid) conditions; + (Illuminance? AmbientLight, Color? Color, bool Valid) conditions; - // get the ambient light - var clearData = ReadClearDataRegister(); + // get the ambient light + var clearData = ReadClearDataRegister(); - if (clearData == 0) { conditions.Color = Color.Black; } + if (clearData == 0) { conditions.Color = Color.Black; } - // apply channel multipliers and normalize - double compensatedRed = ReadRedDataRegister() * CompensationMultipliers.Red / (int)MeasurementTime * 360; - double compensatedGreen = ReadGreenDataRegister() * CompensationMultipliers.Green / (int)MeasurementTime * 360; - double compensatedBlue = ReadBlueDataRegister() * CompensationMultipliers.Blue / (int)MeasurementTime * 360; - double compensatedClear = clearData * CompensationMultipliers.Clear / (int)MeasurementTime * 360; + // apply channel multipliers and normalize + double compensatedRed = ReadRedDataRegister() * CompensationMultipliers.Red / (int)MeasurementTime * 360; + double compensatedGreen = ReadGreenDataRegister() * CompensationMultipliers.Green / (int)MeasurementTime * 360; + double compensatedBlue = ReadBlueDataRegister() * CompensationMultipliers.Blue / (int)MeasurementTime * 360; + double compensatedClear = clearData * CompensationMultipliers.Clear / (int)MeasurementTime * 360; - // scale relative to clear - int red = (int)Math.Min(255, compensatedRed / compensatedClear * 255); - int green = (int)Math.Min(255, compensatedGreen / compensatedClear * 255); - int blue = (int)Math.Min(255, compensatedBlue / compensatedClear * 255); + // scale relative to clear + int red = (int)Math.Min(255, compensatedRed / compensatedClear * 255); + int green = (int)Math.Min(255, compensatedGreen / compensatedClear * 255); + int blue = (int)Math.Min(255, compensatedBlue / compensatedClear * 255); - conditions.Color = Color.FromRgb(red, green, blue); + conditions.Color = Color.FromRgb(red, green, blue); - // TODO: honestly, no idea what this comes back as - // need to test when i get a sensor and compare to other light - // sensors - conditions.AmbientLight = new Illuminance(compensatedClear, Units.Illuminance.UnitType.Lux); + conditions.AmbientLight = new Illuminance(compensatedClear, Units.Illuminance.UnitType.Lux); - // WTH - conditions.Valid = ReadMeasurementIsValid(); + conditions.Valid = ReadMeasurementIsValid(); - return conditions; - }); + return Task.FromResult(conditions); } /// @@ -313,10 +298,10 @@ protected void Reset() { Resolver.Log.Info("Reset"); - var status = Peripheral.ReadRegister(Registers.SYSTEM_CONTROL); + var status = BusComms.ReadRegister(Registers.SYSTEM_CONTROL); status = (byte)((status & ~MaskValues.SW_RESET) | 0x01 << 7); - Peripheral.WriteRegister(Registers.SYSTEM_CONTROL, status); + BusComms.WriteRegister(Registers.SYSTEM_CONTROL, status); // set default measurement configuration MeasurementTime = MeasurementTimeType.Ms160; @@ -333,7 +318,7 @@ protected void Reset() upperInterruptThreshold = 0xFFFF; // write default value to Mode_Control3 - Peripheral.WriteRegister(Registers.MODE_CONTROL3, 0x02); + BusComms.WriteRegister(Registers.MODE_CONTROL3, 0x02); } /// @@ -341,7 +326,7 @@ protected void Reset() /// protected bool ReadMeasurementIsValid() { - var valid = Peripheral.ReadRegister(Registers.MODE_CONTROL2); + var valid = BusComms.ReadRegister(Registers.MODE_CONTROL2); valid = (byte)(valid & MaskValues.VALID); return Convert.ToBoolean(valid); } @@ -350,25 +335,25 @@ protected bool ReadMeasurementIsValid() /// Reads the red data register of the sensor /// /// - protected ushort ReadRedDataRegister() => Peripheral.ReadRegisterAsUShort(Registers.RED_DATA); + protected ushort ReadRedDataRegister() => BusComms.ReadRegisterAsUShort(Registers.RED_DATA); /// /// Reads the green data register of the sensor /// /// - protected ushort ReadGreenDataRegister() => Peripheral.ReadRegisterAsUShort(Registers.GREEN_DATA); + protected ushort ReadGreenDataRegister() => BusComms.ReadRegisterAsUShort(Registers.GREEN_DATA); /// /// Reads the blue data register of the sensor /// /// - protected ushort ReadBlueDataRegister() => Peripheral.ReadRegisterAsUShort(Registers.BLUE_DATA); + protected ushort ReadBlueDataRegister() => BusComms.ReadRegisterAsUShort(Registers.BLUE_DATA); /// /// Reads the clear data register of the sensor /// /// - protected ushort ReadClearDataRegister() => Peripheral.ReadRegisterAsUShort(Registers.CLEAR_DATA); + protected ushort ReadClearDataRegister() => BusComms.ReadRegisterAsUShort(Registers.CLEAR_DATA); async Task ISensor.Read() => (await Read()).AmbientLight.Value; diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Bh1745/Driver/Sensors.Light.Bh1745.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Bh1745/Driver/Sensors.Light.Bh1745.csproj index 6c362b60f5..8c1b9c21e0 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Bh1745/Driver/Sensors.Light.Bh1745.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Bh1745/Driver/Sensors.Light.Bh1745.csproj @@ -18,6 +18,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Bh1745/Samples/Bh1745_Sample/Bh1745_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Bh1745/Samples/Bh1745_Sample/Bh1745_Sample.csproj index 0071a85cc1..42892b5830 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Bh1745/Samples/Bh1745_Sample/Bh1745_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Bh1745/Samples/Bh1745_Sample/Bh1745_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Bh1750/Driver/Bh1750.Addresses.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Bh1750/Driver/Bh1750.Addresses.cs index 78d55511fc..e48257343f 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Bh1750/Driver/Bh1750.Addresses.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Bh1750/Driver/Bh1750.Addresses.cs @@ -3,7 +3,7 @@ public partial class Bh1750 { /// - /// Valid addresses for the sensor + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Bh1750/Driver/Bh1750.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Bh1750/Driver/Bh1750.cs index a5e68f32e3..673bdbe61a 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Bh1750/Driver/Bh1750.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Bh1750/Driver/Bh1750.cs @@ -1,18 +1,17 @@ using Meadow.Hardware; using Meadow.Peripherals.Sensors.Light; using Meadow.Units; -using IU = Meadow.Units.Illuminance.UnitType; using System; using System.Buffers.Binary; using System.Threading.Tasks; -using System.Threading; +using IU = Meadow.Units.Illuminance.UnitType; namespace Meadow.Foundation.Sensors.Light { /// /// Represents a BH1750 ambient light sensor /// - public partial class Bh1750 : ByteCommsSensorBase, ILightSensor + public partial class Bh1750 : ByteCommsSensorBase, ILightSensor, II2cPeripheral { /// /// Raised when a new Illuminance value is read by the sensor @@ -43,6 +42,11 @@ public double LightTransmittance private const float MaxTransmittance = 2.225f; private const float MinTransmittance = 0.272f; + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + /// /// Create a new BH1750 light sensor object using a static reference voltage. /// @@ -60,44 +64,41 @@ public Bh1750( private void Initialize() { - Peripheral.Write((byte)Commands.PowerOn); - Peripheral.Write((byte)Commands.Reset); + BusComms.Write((byte)Commands.PowerOn); + BusComms.Write((byte)Commands.Reset); } /// /// Read the current luminocity /// /// The current Illuminance value - protected override Task ReadSensor() + protected async override Task ReadSensor() { - return Task.Run(() => + if (MeasuringMode == MeasuringModes.OneTimeHighResolutionMode || + MeasuringMode == MeasuringModes.OneTimeHighResolutionMode2 || + MeasuringMode == MeasuringModes.OneTimeLowResolutionMode) { - if (MeasuringMode == MeasuringModes.OneTimeHighResolutionMode || - MeasuringMode == MeasuringModes.OneTimeHighResolutionMode2 || - MeasuringMode == MeasuringModes.OneTimeLowResolutionMode) - { - Peripheral.Write((byte)Commands.PowerOn); - } + BusComms.Write((byte)Commands.PowerOn); + } - Peripheral.Write((byte)MeasuringMode); + BusComms.Write((byte)MeasuringMode); - //wait for the measurement to complete before reading - Thread.Sleep(GetMeasurementTime(MeasuringMode)); + //wait for the measurement to complete before reading + await Task.Delay(GetMeasurementTime(MeasuringMode)); - Peripheral.Read(ReadBuffer.Span[0..2]); + BusComms.Read(ReadBuffer.Span[0..2]); - ushort raw = BinaryPrimitives.ReadUInt16BigEndian(ReadBuffer.Span[0..2]); + ushort raw = BinaryPrimitives.ReadUInt16BigEndian(ReadBuffer.Span[0..2]); - double result = raw / (1.2 * lightTransmittance); + double result = raw / (1.2 * lightTransmittance); - if (MeasuringMode == MeasuringModes.ContinuouslyHighResolutionMode2 || - MeasuringMode == MeasuringModes.OneTimeHighResolutionMode2) - { - result *= 2; - } + if (MeasuringMode == MeasuringModes.ContinuouslyHighResolutionMode2 || + MeasuringMode == MeasuringModes.OneTimeHighResolutionMode2) + { + result *= 2; + } - return new Illuminance(result, IU.Lux); - }); + return new Illuminance(result, IU.Lux); } TimeSpan GetMeasurementTime(MeasuringModes mode) @@ -127,8 +128,8 @@ private void SetLightTransmittance(double transmittance) byte val = (byte)(DefaultLightTransmittance / transmittance); - Peripheral.Write((byte)((byte)Commands.MeasurementTimeHigh | (val >> 5))); - Peripheral.Write((byte)((byte)Commands.MeasurementTimeLow | (val & 0b_0001_1111))); + BusComms.Write((byte)((byte)Commands.MeasurementTimeHigh | (val >> 5))); + BusComms.Write((byte)((byte)Commands.MeasurementTimeLow | (val & 0b_0001_1111))); } /// diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Bh1750/Driver/Sensors.Light.Bh1750.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Bh1750/Driver/Sensors.Light.Bh1750.csproj index f73b1c5a83..b995205fe0 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Bh1750/Driver/Sensors.Light.Bh1750.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Bh1750/Driver/Sensors.Light.Bh1750.csproj @@ -10,7 +10,7 @@ http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ Meadow.Foundation.Sensors.Light.Bh1750 https://github.com/WildernessLabs/Meadow.Foundation - Meadow.Foundation, Light, Bh1750 + Meadow.Foundation,luminance,color,Light,Bh1750 0.1.52 true Bh1750 I2C luminance and color light sensor @@ -19,6 +19,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Bh1750/Samples/Bh1750_Sample/Bh1750_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Bh1750/Samples/Bh1750_Sample/Bh1750_Sample.csproj index e4dfd96e39..7a7b6b7a4a 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Bh1750/Samples/Bh1750_Sample/Bh1750_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Bh1750/Samples/Bh1750_Sample/Bh1750_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Max44009/Driver/Max44009.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Max44009/Driver/Max44009.Enums.cs index 25cc2579c8..533dac2185 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Max44009/Driver/Max44009.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Max44009/Driver/Max44009.Enums.cs @@ -3,7 +3,7 @@ public partial class Max44009 { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Max44009/Driver/Max44009.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Max44009/Driver/Max44009.cs index 27adaebccc..812cf7d8c0 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Max44009/Driver/Max44009.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Max44009/Driver/Max44009.cs @@ -1,22 +1,27 @@ -using System; -using System.Threading.Tasks; -using Meadow.Hardware; +using Meadow.Hardware; using Meadow.Units; +using System; +using System.Threading.Tasks; namespace Meadow.Foundation.Sensors.Light { /// /// Driver for the Max44009 light-to-digital converter /// - public partial class Max44009 : ByteCommsSensorBase + public partial class Max44009 : ByteCommsSensorBase, II2cPeripheral { + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + /// /// Create a new Max44009 object /// /// The I2C bus /// The I2C address public Max44009(II2cBus i2cBus, byte address = (byte)Addresses.Default) - : base (i2cBus, address) + : base(i2cBus, address) { Initialize(); } @@ -26,7 +31,7 @@ public Max44009(II2cBus i2cBus, byte address = (byte)Addresses.Default) /// protected void Initialize() { - Peripheral.WriteRegister(0x02, 0x00); + BusComms.WriteRegister(0x02, 0x00); } /// @@ -35,19 +40,16 @@ protected void Initialize() /// The latest sensor reading protected override Task ReadSensor() { - return Task.Run(() => { - - Peripheral.ReadRegister(0x03, ReadBuffer.Span[0..2]); + BusComms.ReadRegister(0x03, ReadBuffer.Span[0..2]); - var exponent = (ReadBuffer.Span[0] >> 4); - if (exponent == 0x0f) throw new Exception("Out of range"); + var exponent = (ReadBuffer.Span[0] >> 4); + if (exponent == 0x0f) throw new Exception("Out of range"); - int mantissa = ((ReadBuffer.Span[0] & 0x0F) >> 4) | (ReadBuffer.Span[1] & 0x0F); + int mantissa = ((ReadBuffer.Span[0] & 0x0F) >> 4) | (ReadBuffer.Span[1] & 0x0F); - var luminance = Math.Pow(2, exponent) * mantissa * 0.72; + var luminance = Math.Pow(2, exponent) * mantissa * 0.72; - return new Illuminance(luminance, Illuminance.UnitType.Lux); - }); + return Task.FromResult(new Illuminance(luminance, Illuminance.UnitType.Lux)); } } } \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Max44009/Driver/Sensors.Light.Max44009.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Max44009/Driver/Sensors.Light.Max44009.csproj index 9d5fbc6fd7..43bf0de40c 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Max44009/Driver/Sensors.Light.Max44009.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Max44009/Driver/Sensors.Light.Max44009.csproj @@ -10,7 +10,7 @@ http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ Meadow.Foundation.Sensors.Light.Max44009 https://github.com/WildernessLabs/Meadow.Foundation - Meadow.Foundation, Max44009, Light + Meadow.Foundation,Max44009,Light,ultraviolet 0.1.49 true Max44009 I2C ultraviolet and ambient light sensor @@ -18,6 +18,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Max44009/Samples/Max44009_Sample/Max44009_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Max44009/Samples/Max44009_Sample/Max44009_Sample.csproj index 79fe294729..e23cf0ef63 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Max44009/Samples/Max44009_Sample/Max44009_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Max44009/Samples/Max44009_Sample/Max44009_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Si1145/Driver/Sensors.Light.Si1145.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Si1145/Driver/Sensors.Light.Si1145.csproj index d86ef87ab4..9e4bd488fe 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Si1145/Driver/Sensors.Light.Si1145.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Si1145/Driver/Sensors.Light.Si1145.csproj @@ -18,6 +18,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Si1145/Driver/Si1145.Addresses.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Si1145/Driver/Si1145.Addresses.cs index 88727407c3..433da494b6 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Si1145/Driver/Si1145.Addresses.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Si1145/Driver/Si1145.Addresses.cs @@ -3,7 +3,7 @@ public partial class Si1145 { /// - /// Valid addresses for the sensor + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Si1145/Driver/Si1145.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Si1145/Driver/Si1145.cs index 218a9f04c8..c3762c0b9a 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Si1145/Driver/Si1145.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Si1145/Driver/Si1145.cs @@ -1,29 +1,30 @@ -using System; +using Meadow.Hardware; +using Meadow.Units; +using System; using System.Threading; using System.Threading.Tasks; -using Meadow.Hardware; -using Meadow.Units; namespace Meadow.Foundation.Sensors.Light { - // TODO: the proximity stuff isn't exposed. exposing it needs some more - // thought. you need to hook up an infrared LED to the LED pin. this will - // cause that pin to fire, then the sensor measures the time of flight. - // it's basically a completely different sensor. - /// /// Represents a SiLabs Proximity, UV, and ambient light sensor /// public partial class Si1145 - : ByteCommsSensorBase<(Illuminance? VisibleLight, double? UltravioletIndex, Illuminance? Infrared)> + : ByteCommsSensorBase<(Illuminance? VisibleLight, double? UltravioletIndex, Illuminance? Infrared)>, + II2cPeripheral { + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + /// /// Create a new SI1145 sensor object /// /// I2cBus (default to 400 KHz) public Si1145(II2cBus i2cBus) : base(i2cBus, (byte)Addresses.Default) { - if (Peripheral.ReadRegister(Registers.REG_PARTID) != 0x45) + if (BusComms.ReadRegister(Registers.REG_PARTID) != 0x45) { throw new Exception("Invalid part ID"); } @@ -34,47 +35,37 @@ public Si1145(II2cBus i2cBus) : base(i2cBus, (byte)Addresses.Default) /// Read data from the sensor /// /// Returns visible, ultraviolet index and ifrared data - protected async override Task<(Illuminance? VisibleLight, double? UltravioletIndex, Illuminance? Infrared)> ReadSensor() + protected override Task<(Illuminance? VisibleLight, double? UltravioletIndex, Illuminance? Infrared)> ReadSensor() { - return await Task.Run(() => - { - (Illuminance? VisibleLight, double? UltravioletIndex, Illuminance? Infrared) conditions; + (Illuminance? VisibleLight, double? UltravioletIndex, Illuminance? Infrared) conditions; - // ultraviolet (UV) index - Peripheral.ReadRegister(0x2C, ReadBuffer.Span[0..2]); - int rawUVIndex = (ReadBuffer.Span[1] << 8) | ReadBuffer.Span[0]; - conditions.UltravioletIndex = rawUVIndex / 100.0; + // ultraviolet (UV) index + BusComms.ReadRegister(0x2C, ReadBuffer.Span[0..2]); + int rawUVIndex = (ReadBuffer.Span[1] << 8) | ReadBuffer.Span[0]; + conditions.UltravioletIndex = rawUVIndex / 100.0; - // Infrared - Peripheral.ReadRegister(0x22, ReadBuffer.Span[0..2]); - int rawInfrared = (ReadBuffer.Span[1] << 8) | ReadBuffer.Span[0]; - conditions.Infrared = new Illuminance(rawInfrared, Illuminance.UnitType.Lux); + // Infrared + BusComms.ReadRegister(0x22, ReadBuffer.Span[0..2]); + int rawInfrared = (ReadBuffer.Span[1] << 8) | ReadBuffer.Span[0]; + conditions.Infrared = new Illuminance(rawInfrared, Illuminance.UnitType.Lux); - // Visible - Peripheral.ReadRegister(0x24, ReadBuffer.Span[0..2]); - int rawVisible = (ReadBuffer.Span[1] << 8) | ReadBuffer.Span[0]; - conditions.VisibleLight = new Illuminance(rawVisible, Illuminance.UnitType.Lux); + // Visible + BusComms.ReadRegister(0x24, ReadBuffer.Span[0..2]); + int rawVisible = (ReadBuffer.Span[1] << 8) | ReadBuffer.Span[0]; + conditions.VisibleLight = new Illuminance(rawVisible, Illuminance.UnitType.Lux); - return conditions; - }); + return Task.FromResult(conditions); } - //public double GetProximity() - //{ - // byte[] data = Peripheral.ReadRegisters(0x26, 2); - // int result = (data[1] << 8) | data[0]; - // return result; - //} - private void Initialize() { Reset(); // enable UVindex measurement coefficients! - Peripheral.WriteRegister(Registers.REG_UCOEFF0, 0x29); - Peripheral.WriteRegister(Registers.REG_UCOEFF1, 0x89); - Peripheral.WriteRegister(Registers.REG_UCOEFF2, 0x02); - Peripheral.WriteRegister(Registers.REG_UCOEFF3, 0x00); + BusComms.WriteRegister(Registers.REG_UCOEFF0, 0x29); + BusComms.WriteRegister(Registers.REG_UCOEFF1, 0x89); + BusComms.WriteRegister(Registers.REG_UCOEFF2, 0x02); + BusComms.WriteRegister(Registers.REG_UCOEFF3, 0x00); // enable UV sensor WriteParam(Parameters.PARAM_CHLIST, Parameters.PARAM_CHLIST_ENUV | @@ -82,11 +73,11 @@ private void Initialize() Parameters.PARAM_CHLIST_ENPS1); // enable interrupt on every sample - Peripheral.WriteRegister(Registers.REG_INTCFG, Registers.REG_INTCFG_INTOE); - Peripheral.WriteRegister(Registers.REG_IRQEN, Registers.REG_IRQEN_ALSEVERYSAMPLE); + BusComms.WriteRegister(Registers.REG_INTCFG, Registers.REG_INTCFG_INTOE); + BusComms.WriteRegister(Registers.REG_IRQEN, Registers.REG_IRQEN_ALSEVERYSAMPLE); // program LED current - Peripheral.WriteRegister(Registers.REG_PSLED21, 0x03); // 20mA for LED 1 only + BusComms.WriteRegister(Registers.REG_PSLED21, 0x03); // 20mA for LED 1 only WriteParam(Parameters.PARAM_PS1ADCMUX, Parameters.PARAM_ADCMUX_LARGEIR); // prox sensor #1 uses LED #1 WriteParam(Parameters.PARAM_PSLED12SEL, Parameters.PARAM_PSLED12SEL_PS1LED1); @@ -113,41 +104,41 @@ private void Initialize() WriteParam(Parameters.PARAM_ALSVISADCMISC, Parameters.PARAM_ALSVISADCMISC_VISRANGE); // measurement rate for auto - Peripheral.WriteRegister(Registers.REG_MEASRATE0, 0xFF); // 255 * 31.25uS = 8ms + BusComms.WriteRegister(Registers.REG_MEASRATE0, 0xFF); // 255 * 31.25uS = 8ms // auto run - Peripheral.WriteRegister(Registers.REG_COMMAND, Commands.PSALS_AUTO); + BusComms.WriteRegister(Registers.REG_COMMAND, Commands.PSALS_AUTO); } private byte WriteParam(byte param, int value) { - Peripheral.WriteRegister(Registers.REG_PARAMWR, (byte)value); - Peripheral.WriteRegister(Registers.REG_COMMAND, (byte)(param | Commands.PARAM_SET)); + BusComms.WriteRegister(Registers.REG_PARAMWR, (byte)value); + BusComms.WriteRegister(Registers.REG_COMMAND, (byte)(param | Commands.PARAM_SET)); - return Peripheral.ReadRegister(Registers.REG_PARAMRD); + return BusComms.ReadRegister(Registers.REG_PARAMRD); } private byte ReadParam(byte param) { - Peripheral.WriteRegister(Registers.REG_COMMAND, (byte)(param | Commands.PARAM_QUERY)); - return Peripheral.ReadRegister(Registers.REG_PARAMRD); + BusComms.WriteRegister(Registers.REG_COMMAND, (byte)(param | Commands.PARAM_QUERY)); + return BusComms.ReadRegister(Registers.REG_PARAMRD); } private void Reset() { - Peripheral.WriteRegister(Registers.REG_MEASRATE0, 0); - Peripheral.WriteRegister(Registers.REG_MEASRATE1, 0); - Peripheral.WriteRegister(Registers.REG_IRQEN, 0); - Peripheral.WriteRegister(Registers.REG_IRQMODE1, 0); - Peripheral.WriteRegister(Registers.REG_IRQMODE2, 0); - Peripheral.WriteRegister(Registers.REG_INTCFG, 0); - Peripheral.WriteRegister(Registers.REG_IRQSTAT, 0xFF); + BusComms.WriteRegister(Registers.REG_MEASRATE0, 0); + BusComms.WriteRegister(Registers.REG_MEASRATE1, 0); + BusComms.WriteRegister(Registers.REG_IRQEN, 0); + BusComms.WriteRegister(Registers.REG_IRQMODE1, 0); + BusComms.WriteRegister(Registers.REG_IRQMODE2, 0); + BusComms.WriteRegister(Registers.REG_INTCFG, 0); + BusComms.WriteRegister(Registers.REG_IRQSTAT, 0xFF); - Peripheral.WriteRegister(Registers.REG_COMMAND, Commands.RESET); + BusComms.WriteRegister(Registers.REG_COMMAND, Commands.RESET); Thread.Sleep(10); - Peripheral.WriteRegister(Registers.REG_HWKEY, 0x17); + BusComms.WriteRegister(Registers.REG_HWKEY, 0x17); Thread.Sleep(10); } diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Si1145/Samples/Si1145_Sample/Si1145_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Si1145/Samples/Si1145_Sample/Si1145_Sample.csproj index 133342a340..3062050e54 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Si1145/Samples/Si1145_Sample/Si1145_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Si1145/Samples/Si1145_Sample/Si1145_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Temt6000/Driver/Sensors.Light.Temt6000.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Temt6000/Driver/Sensors.Light.Temt6000.csproj index 990b556f93..3044a6f20f 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Temt6000/Driver/Sensors.Light.Temt6000.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Temt6000/Driver/Sensors.Light.Temt6000.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Temt6000/Samples/Temt6000_Sample/Temt6000_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Temt6000/Samples/Temt6000_Sample/Temt6000_Sample.csproj index 54f0dcbdbc..6bb3f30dc0 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Temt6000/Samples/Temt6000_Sample/Temt6000_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Temt6000/Samples/Temt6000_Sample/Temt6000_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Tsl2591/Driver/Sensors.Light.Tsl2591.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Tsl2591/Driver/Sensors.Light.Tsl2591.csproj index daa0ca04f5..59d9e39b0b 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Tsl2591/Driver/Sensors.Light.Tsl2591.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Tsl2591/Driver/Sensors.Light.Tsl2591.csproj @@ -17,6 +17,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Tsl2591/Driver/Tsl2591.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Tsl2591/Driver/Tsl2591.Enums.cs index 84a32bb9cb..cab3cd875f 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Tsl2591/Driver/Tsl2591.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Tsl2591/Driver/Tsl2591.Enums.cs @@ -14,7 +14,7 @@ namespace Meadow.Foundation.Sensors.Light public partial class Tsl2591 { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Tsl2591/Driver/Tsl2591.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Tsl2591/Driver/Tsl2591.cs index 841ddfc5bb..db2875d788 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Tsl2591/Driver/Tsl2591.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Tsl2591/Driver/Tsl2591.cs @@ -1,9 +1,9 @@ -using System; -using System.Threading.Tasks; -using Meadow.Hardware; +using Meadow.Hardware; using Meadow.Peripherals.Sensors; using Meadow.Peripherals.Sensors.Light; using Meadow.Units; +using System; +using System.Threading.Tasks; using IU = Meadow.Units.Illuminance.UnitType; namespace Meadow.Foundation.Sensors.Light @@ -15,7 +15,7 @@ namespace Meadow.Foundation.Sensors.Light /// public partial class Tsl2591 : ByteCommsSensorBase<(Illuminance? FullSpectrum, Illuminance? Infrared, Illuminance? VisibleLight, Illuminance? Integrated)>, - ILightSensor, IDisposable + ILightSensor, IDisposable, IPowerControllablePeripheral { /// /// Raised when Full Spectrum Illuminance value changes @@ -41,12 +41,12 @@ public partial class Tsl2591 : /// /// Sensor package ID /// - public int PackageID => Peripheral.ReadRegister((byte)(Register.PackageID | Register.Command)); + public int PackageID => BusComms.ReadRegister((byte)(Register.PackageID | Register.Command)); /// /// Sensor device ID /// - public int DeviceID => Peripheral.ReadRegister((byte)(Register.DeviceID | Register.Command)); + public int DeviceID => BusComms.ReadRegister((byte)(Register.DeviceID | Register.Command)); /// /// Gain of the sensor @@ -58,7 +58,7 @@ public GainFactor Gain { PowerOff(); gainFactor = value; - Peripheral.WriteRegister((byte)(Register.Command | Register.Config), (byte)((byte)integrationTime | (byte)gainFactor)); + BusComms.WriteRegister((byte)(Register.Command | Register.Config), (byte)((byte)integrationTime | (byte)gainFactor)); PowerOn(); } } @@ -73,7 +73,7 @@ public IntegrationTimes IntegrationTime { PowerOff(); integrationTime = value; - Peripheral.WriteRegister((byte)(Register.Command | Register.Config), (byte)((byte)integrationTime | (byte)gainFactor)); + BusComms.WriteRegister((byte)(Register.Command | Register.Config), (byte)((byte)integrationTime | (byte)gainFactor)); PowerOn(); } } @@ -119,34 +119,31 @@ public Tsl2591(II2cBus i2cBus, /// Reads data from the sensor /// /// The latest sensor reading - protected override async Task<(Illuminance? FullSpectrum, Illuminance? Infrared, Illuminance? VisibleLight, Illuminance? Integrated)> ReadSensor() + protected override Task<(Illuminance? FullSpectrum, Illuminance? Infrared, Illuminance? VisibleLight, Illuminance? Integrated)> ReadSensor() { - (Illuminance FullSpectrum, Illuminance Infrared, Illuminance VisibleLight, Illuminance Integrated) conditions; + (Illuminance? FullSpectrum, Illuminance? Infrared, Illuminance? VisibleLight, Illuminance? Integrated) conditions; - return await Task.Run(() => - { - // data sheet indicates you should always read all 4 bytes, in order, for valid data - var channel0 = Peripheral.ReadRegisterAsUShort((byte)(Register.CH0DataL | Register.Command)); - var channel1 = Peripheral.ReadRegisterAsUShort((byte)(Register.CH1DataL | Register.Command)); + // data sheet indicates you should always read all 4 bytes, in order, for valid data + var channel0 = BusComms.ReadRegisterAsUShort((byte)(Register.CH0DataL | Register.Command)); + var channel1 = BusComms.ReadRegisterAsUShort((byte)(Register.CH1DataL | Register.Command)); - conditions.FullSpectrum = new Illuminance(channel0, IU.Lux); - conditions.Infrared = new Illuminance(channel1, IU.Lux); - conditions.VisibleLight = new Illuminance(channel0 - channel1, IU.Lux); + conditions.FullSpectrum = new Illuminance(channel0, IU.Lux); + conditions.Infrared = new Illuminance(channel1, IU.Lux); + conditions.VisibleLight = new Illuminance(channel0 - channel1, IU.Lux); - double countsPerLux; + double countsPerLux; - if ((channel0 == 0xffff) || (channel1 == 0xffff)) - { - conditions.Integrated = new Illuminance(-1, IU.Lux); - } - else - { - countsPerLux = (IntegrationTimeInMilliseconds(IntegrationTime) * GainMultiplier(Gain)) / 408.0; - conditions.Integrated = new Illuminance((channel0 - channel1) * (1 - (channel1 / channel0)) / countsPerLux, IU.Lux); - } + if ((channel0 == 0xffff) || (channel1 == 0xffff)) + { + conditions.Integrated = new Illuminance(-1, IU.Lux); + } + else + { + countsPerLux = (IntegrationTimeInMilliseconds(IntegrationTime) * GainMultiplier(Gain)) / 408.0; + conditions.Integrated = new Illuminance((channel0 - channel1) * (1 - (channel1 / channel0)) / countsPerLux, IU.Lux); + } - return conditions; - }); + return Task.FromResult(conditions); } /// @@ -178,17 +175,19 @@ protected override void RaiseEventsAndNotify(IChangeResult<(Illuminance? FullSpe /// /// Power the sensor on /// - public void PowerOn() + public Task PowerOn() { - Peripheral.WriteRegister((byte)(Register.Enable | Register.Command), 3); + BusComms.WriteRegister((byte)(Register.Enable | Register.Command), 3); + return Task.CompletedTask; } /// /// Power the sensor off /// - public void PowerOff() + public Task PowerOff() { - Peripheral.WriteRegister((byte)(Register.Enable | Register.Command), 0); + BusComms.WriteRegister((byte)(Register.Enable | Register.Command), 0); + return Task.CompletedTask; } /// diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Tsl2591/Samples/Tsl2591_Sample/Tsl2591_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Tsl2591/Samples/Tsl2591_Sample/Tsl2591_Sample.csproj index 2dd4e68675..44b469e7a5 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Tsl2591/Samples/Tsl2591_Sample/Tsl2591_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Tsl2591/Samples/Tsl2591_Sample/Tsl2591_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Veml7700/Driver/Sensors.Light.Veml7700.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Veml7700/Driver/Sensors.Light.Veml7700.csproj index 2f9808394d..0cf2ded146 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Veml7700/Driver/Sensors.Light.Veml7700.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Veml7700/Driver/Sensors.Light.Veml7700.csproj @@ -18,6 +18,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Veml7700/Driver/Veml7700.Addresses.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Veml7700/Driver/Veml7700.Addresses.cs index 2f5ecafe4d..cac8db767c 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Veml7700/Driver/Veml7700.Addresses.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Veml7700/Driver/Veml7700.Addresses.cs @@ -3,7 +3,7 @@ public partial class Veml7700 { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Veml7700/Driver/Veml7700.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Veml7700/Driver/Veml7700.cs index b4e6cc7218..35b2085a42 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Veml7700/Driver/Veml7700.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Veml7700/Driver/Veml7700.cs @@ -1,23 +1,22 @@ -using System; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Meadow.Hardware; +using Meadow.Hardware; using Meadow.Peripherals.Sensors.Light; using Meadow.Units; +using System; +using System.Threading.Tasks; namespace Meadow.Foundation.Sensors.Light { /// /// High Accuracy Ambient Light Sensor /// - public partial class Veml7700 : ByteCommsSensorBase, ILightSensor, IDisposable + public partial class Veml7700 : ByteCommsSensorBase, + ILightSensor, II2cPeripheral, IDisposable { /// /// Raised when the luminosity value changes /// public event EventHandler> LuminosityUpdated = delegate { }; - + /// /// Raised when the high range is exceeded /// @@ -43,6 +42,11 @@ public partial class Veml7700 : ByteCommsSensorBase, ILightSensor, private const ushort DATA_FLOOR = 100; private const ushort DATA_CEILING = 10000; + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + /// /// Create a new Veml7700 object with the default address /// @@ -52,10 +56,10 @@ public Veml7700(II2cBus i2cBus) { } - int _gain = 3; - int _integrationTime = 0; - bool _firstRead = true; - bool _outOfRange = false; + int gain = 3; + int integrationTime = 0; + bool firstRead = true; + bool outOfRange = false; /// /// Reads data from the sensor @@ -63,103 +67,91 @@ public Veml7700(II2cBus i2cBus) /// The latest sensor reading protected async override Task ReadSensor() { - return await Task.Run(async () => - { - Illuminance illuminance = new Illuminance(0); + Illuminance illuminance = new Illuminance(0); - if (_firstRead) - { - WriteRegister(Registers.AlsConf0, 0); - //--//--// - await Task.Delay(5); - _firstRead = false; - } + if (firstRead) + { + WriteRegister(Registers.AlsConf0, 0); + await Task.Delay(5); + firstRead = false; + } - // priming read - var data = ReadRegister(DataSource == SensorTypes.Ambient ? Registers.Als : Registers.White); + // priming read + var data = ReadRegister(DataSource == SensorTypes.Ambient ? Registers.Als : Registers.White); - while (true) - { - _outOfRange = false; + while (true) + { + outOfRange = false; - // Resolver.Log.Info($"{DataSource} DATA A: 0x{data:x4}"); + // Resolver.Log.Info($"{DataSource} DATA A: 0x{data:x4}"); - if (data > DATA_CEILING) - { // Too bright! - if (_gain > 1) + if (data > DATA_CEILING) + { // Too bright! + if (gain > 1) + { + await SetGain(--gain); + } + else if (data > DATA_CEILING) + { + // we're at min gain, have to speed integration time + if (++integrationTime >= 4) { - await SetGain(--_gain); + // everything is maxed out + RangeExceededHigh?.Invoke(this, EventArgs.Empty); + outOfRange = true; } - else if (data > DATA_CEILING) + else { - // we're at min gain, have to speed integration time - if (++_integrationTime >= 4) - { - // everything is maxed out - RangeExceededHigh?.Invoke(this, EventArgs.Empty); - _outOfRange = true; - } - else - { - await SetIntegrationTime(_integrationTime); - } + await SetIntegrationTime(integrationTime); } } + } + else if (data < DATA_FLOOR) + { + // Too dim! + if (gain < 4) + { + await SetGain(++gain); + } else if (data < DATA_FLOOR) { - // Too dim! - if (_gain < 4) + // we're at max gain, have to slow integration time + if (--integrationTime <= -2) { - await SetGain(++_gain); + RangeExceededLow?.Invoke(this, EventArgs.Empty); + outOfRange = true; } - else if (data < DATA_FLOOR) + else { - // we're at max gain, have to slow integration time - if (--_integrationTime <= -2) - { - RangeExceededLow?.Invoke(this, EventArgs.Empty); - _outOfRange = true; - } - else - { - await SetIntegrationTime(_integrationTime); - } + await SetIntegrationTime(integrationTime); } } + } - if ((data >= DATA_FLOOR && data <= DATA_CEILING) || _outOfRange) - { - return ScaleDataToIluminance(data, _gain, _integrationTime); - } - - await DelayForIntegrationTime(_integrationTime); - - data = ReadRegister(DataSource == SensorTypes.Ambient ? Registers.Als : Registers.White); + if ((data >= DATA_FLOOR && data <= DATA_CEILING) || outOfRange) + { + return ScaleDataToIluminance(data, gain, integrationTime); } - }); + await DelayForIntegrationTime(integrationTime); + + data = ReadRegister(DataSource == SensorTypes.Ambient ? Registers.Als : Registers.White); + } } private Illuminance ScaleDataToIluminance(ushort data, int gain, int integrationTime) { - int scale; - - switch (gain) + var scale = gain switch { - case 1: // 1/8 - scale = 8; - break; - case 2: // 1/4 - scale = 4; - break; - case 4: // 2 - scale = 2; - break; - case 3: // 1 - default: - scale = 1; - break; - } + // 1/8 + 1 => 8, + // 1/4 + 2 => 4, + // 2 + 4 => 2, + // 1 + _ => 1, + }; switch (integrationTime) { @@ -202,8 +194,11 @@ private Illuminance CalculateCorrectedLux(double lux) return new Illuminance(6.0135E-13 * Math.Pow(lux, 4) - 9.3924E-09 * Math.Pow(lux, 3) + 8.1488E-05 * Math.Pow(lux, 2) + 1.0023E+00 * lux); } - - private void SetPower(bool on) + /// + /// Set power mode + /// + /// + public void SetPower(bool on) { ushort cfg; @@ -318,13 +313,13 @@ private async Task DelayForIntegrationTime(int integrationTime) private ushort ReadRegister(Registers register) { - return Peripheral.ReadRegisterAsUShort((byte)register, ByteOrder.LittleEndian); + return BusComms.ReadRegisterAsUShort((byte)register, ByteOrder.LittleEndian); } private void WriteRegister(Registers register, ushort value) { - Peripheral.WriteRegister((byte)register, value, ByteOrder.LittleEndian); - } + BusComms.WriteRegister((byte)register, value, ByteOrder.LittleEndian); + } } } \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Veml7700/Samples/Veml7700_Sample/Veml7700_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Veml7700/Samples/Veml7700_Sample/Veml7700_Sample.csproj index 56262f8ec4..ba4822da3f 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Light.Veml7700/Samples/Veml7700_Sample/Veml7700_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Light.Veml7700/Samples/Veml7700_Sample/Veml7700_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.LoadCell.Hx711/Driver/Hx711.cs b/Source/Meadow.Foundation.Peripherals/Sensors.LoadCell.Hx711/Driver/Hx711.cs index 2225b695ec..92610519ff 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.LoadCell.Hx711/Driver/Hx711.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.LoadCell.Hx711/Driver/Hx711.cs @@ -15,16 +15,16 @@ public partial class Hx711 : PollingSensorBase, IMassSensor, IDisposable private const uint GPIO_BASE = 0x40020000; private const uint IDR_OFFSET = 0x10; private const uint BSSR_OFFSET = 0x18; - private const int timing_iterations = 3; + private const int timingIterations = 3; - private uint _sck_address; - private int _sck_pin; - private uint _dout_address; - private uint _sck_set; - private uint _sck_clear; - private uint _dout_mask; - private double _gramsPerAdcUnit; - private bool _createdPorts = false; + private uint sckAddress; + private int sckPin; + private uint doutAddress; + private uint sckSet; + private uint sckClear; + private uint doutMask; + private double gramsPerAdcUnit; + private readonly bool createdPorts = false; private IDigitalOutputPort SCK { get; } private IDigitalInputPort DOUT { get; } @@ -74,7 +74,7 @@ public Hx711(IPin sck, IPin dout, uint? tareValue = null) { SCK = sck.CreateDigitalOutputPort(); DOUT = dout.CreateDigitalInputPort(); - _createdPorts = true; // we need to dispose what we create + createdPorts = true; // we need to dispose what we create CalculateRegisterValues(sck, dout); Start(); @@ -185,7 +185,7 @@ public int CalculateCalibrationFactor() /// public void SetCalibrationFactor(int factor, Mass knownValue) { - _gramsPerAdcUnit = (knownValue.Grams / factor); + gramsPerAdcUnit = (knownValue.Grams / factor); } /// @@ -194,32 +194,36 @@ public void SetCalibrationFactor(int factor, Mass knownValue) /// protected override Task ReadSensor() { - if (_gramsPerAdcUnit == 0) + //ReadADC() call may block so wrap the logic in a Task + return Task.Run(() => { - throw new Exception("Calibration factor has not been set"); - } + if (gramsPerAdcUnit == 0) + { + throw new Exception("Calibration factor has not been set"); + } - // get an ADC conversion - var raw = ReadADC(); - // subtract the tare - var adc = raw - TareValue; + // get an ADC conversion + var raw = ReadADC(); + // subtract the tare + var adc = raw - TareValue; - // two's complement - int value; - if ((raw & 0x800000) != 0) - { - value = (int)(~adc + 1) * -1; - } - else - { - value = (int)adc; - } + // two's complement + int value; + if ((raw & 0x800000) != 0) + { + value = (int)(~adc + 1) * -1; + } + else + { + value = (int)adc; + } - // convert to grams - var grams = value * _gramsPerAdcUnit; + // convert to grams + var grams = value * gramsPerAdcUnit; - // convert to desired units - return Task.FromResult(new Mass(grams, Units.Mass.UnitType.Grams)); + // convert to desired units + return new Mass(grams, Units.Mass.UnitType.Grams); + }); } private void CalculateRegisterValues(IPin sck, IPin dout) @@ -230,15 +234,15 @@ private void CalculateRegisterValues(IPin sck, IPin dout) // Bits 15:0 set // Port offset = 0x0400 * index (with A being index 0) int gpio_port = sck.Key.ToString()[1] - 'A'; - _sck_pin = int.Parse(sck.Key.ToString().Substring(2)); - _sck_address = GPIO_BASE | (0x400u * (uint)gpio_port) | BSSR_OFFSET; - _sck_set = 1u << _sck_pin; - _sck_clear = 1u << (16 + _sck_pin); + sckPin = int.Parse(sck.Key.ToString().Substring(2)); + sckAddress = GPIO_BASE | (0x400u * (uint)gpio_port) | BSSR_OFFSET; + sckSet = 1u << sckPin; + sckClear = 1u << (16 + sckPin); gpio_port = dout.Key.ToString()[1] - 'A'; var gpio_pin = int.Parse(dout.Key.ToString().Substring(2)); - _dout_address = GPIO_BASE | (0x400u * (uint)gpio_port) | IDR_OFFSET; - _dout_mask = 1u << gpio_pin; + doutAddress = GPIO_BASE | (0x400u * (uint)gpio_port) | IDR_OFFSET; + doutMask = 1u << gpio_pin; } private unsafe void ClockLow() @@ -246,19 +250,19 @@ private unsafe void ClockLow() // this seems convoluted, but it is intentionally so to keep the compiler from optimizing out out timing. // A single call takes roughly 0.2us, but the part requires a minimum of 0.25us for the ADC to settle. // We don't have a simple micro-sleep, so we simply make multiple calls to assert state to suck up the required timing - for (int i = 0; i < timing_iterations; i++) + for (int i = 0; i < timingIterations; i++) { - var val = 1u << (16 + _sck_pin); // low - *(uint*)_sck_address = val; + var val = 1u << (16 + sckPin); // low + *(uint*)sckAddress = val; } } private unsafe void ClockHigh() { - for (int i = 0; i < timing_iterations; i++) + for (int i = 0; i < timingIterations; i++) { - var val = 1u << _sck_pin; // high - *(uint*)_sck_address = val; + var val = 1u << sckPin; // high + *(uint*)sckAddress = val; } } @@ -269,7 +273,7 @@ private unsafe uint ReadADC() lock (samplingLock) { // data line low indicates ready - while ((*(uint*)_dout_address & _dout_mask) != 0) + while ((*(uint*)doutAddress & doutMask) != 0) { Thread.Sleep(0); } @@ -277,10 +281,10 @@ private unsafe uint ReadADC() for (int i = 0; i < 24; i++) // 24 bits of data { ClockHigh(); - count = count << 1; + count <<= 1; ClockLow(); - if ((*(uint*)_dout_address & _dout_mask) != 0) // read DOUT state + if ((*(uint*)doutAddress & doutMask) != 0) // read DOUT state { count++; } @@ -322,7 +326,7 @@ protected override void RaiseEventsAndNotify(IChangeResult changeResult) /// Is disposing protected virtual void Dispose(bool disposing) { - if (_createdPorts) + if (createdPorts) { SCK.Dispose(); DOUT.Dispose(); diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.LoadCell.Hx711/Driver/Sensors.LoadCell.Hx711.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.LoadCell.Hx711/Driver/Sensors.LoadCell.Hx711.csproj index cbdbe73fc4..855bd45fbd 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.LoadCell.Hx711/Driver/Sensors.LoadCell.Hx711.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.LoadCell.Hx711/Driver/Sensors.LoadCell.Hx711.csproj @@ -10,7 +10,7 @@ http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ Meadow.Foundation.Sensors.LoadCell.Hx711 https://github.com/WildernessLabs/Meadow.Foundation - Meadow.Foundation, LoadCell, Hx711 + Meadow.Foundation,LoadCell,Hx711 0.1.49 true Hx711 digital load cell amplifier @@ -25,6 +25,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.LoadCell.Hx711/Samples/Hx711_Sample/Hx711_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.LoadCell.Hx711/Samples/Hx711_Sample/Hx711_Sample.csproj index 18ed96a0ca..477a7d951c 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.LoadCell.Hx711/Samples/Hx711_Sample/Hx711_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.LoadCell.Hx711/Samples/Hx711_Sample/Hx711_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.LoadCell.Nau7802/Driver/Nau7802.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.LoadCell.Nau7802/Driver/Nau7802.Enums.cs index 051b105d2e..2bb609e3dc 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.LoadCell.Nau7802/Driver/Nau7802.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.LoadCell.Nau7802/Driver/Nau7802.Enums.cs @@ -4,7 +4,7 @@ namespace Meadow.Foundation.Sensors.LoadCell public partial class Nau7802 { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.LoadCell.Nau7802/Driver/Nau7802.cs b/Source/Meadow.Foundation.Peripherals/Sensors.LoadCell.Nau7802/Driver/Nau7802.cs index 7e57421183..d9fe3041ef 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.LoadCell.Nau7802/Driver/Nau7802.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.LoadCell.Nau7802/Driver/Nau7802.cs @@ -1,26 +1,26 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using Meadow.Hardware; +using Meadow.Hardware; using Meadow.Peripherals.Sensors; using Meadow.Units; +using System; +using System.Threading; +using System.Threading.Tasks; namespace Meadow.Foundation.Sensors.LoadCell { /// /// 24-Bit Dual-Channel ADC For Bridge Sensors /// - public partial class Nau7802 : ByteCommsSensorBase, IMassSensor, IDisposable + public partial class Nau7802 : ByteCommsSensorBase, IMassSensor, II2cPeripheral, IDisposable { /// /// Raised when the mass value changes /// public event EventHandler> MassUpdated = delegate { }; - private byte[] _read = new byte[3]; - private double _gramsPerAdcUnit = 0; - private PU_CTRL_BITS _currentPU_CTRL; - private int _tareValue; + private readonly byte[] readBuffer = new byte[3]; + private double gramsPerAdcUnit = 0; + private PU_CTRL_BITS currentPuCTRL; + private int tareValue; /// /// Default sample period @@ -32,6 +32,11 @@ public partial class Nau7802 : ByteCommsSensorBase, IMassSensor, IDisposab /// public Mass? Mass { get; private set; } + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + /// /// Creates an instance of the NAU7802 Driver class /// @@ -66,8 +71,8 @@ private int ReadADC() Thread.Sleep(1); } - Peripheral?.ReadRegister((byte)Register.ADCO_B2, _read); - return _read[0] << 16 | _read[1] << 8 | _read[2]; + BusComms?.ReadRegister((byte)Register.ADCO_B2, readBuffer); + return readBuffer[0] << 16 | readBuffer[1] << 8 | readBuffer[2]; } /// @@ -80,8 +85,8 @@ public void Tare() Thread.Sleep(1); } - _tareValue = ReadADC(); - Output.WriteLine($"Tare base = {_tareValue:x}"); + tareValue = ReadADC(); + Output.WriteLine($"Tare base = {tareValue:x}"); } private void PowerOn() @@ -89,17 +94,17 @@ private void PowerOn() Output.WriteLine($"Powering up..."); // Set and clear the RR bit in 0x00, to guarantee a reset of all register values - _currentPU_CTRL = PU_CTRL_BITS.RR; - Peripheral?.WriteRegister((byte)Register.PU_CTRL, (byte)_currentPU_CTRL); + currentPuCTRL = PU_CTRL_BITS.RR; + BusComms?.WriteRegister((byte)Register.PU_CTRL, (byte)currentPuCTRL); Thread.Sleep(1); // make sure it has time to do it's thing - _currentPU_CTRL &= ~PU_CTRL_BITS.RR; - - Peripheral?.WriteRegister((byte)Register.PU_CTRL, (byte)_currentPU_CTRL); + currentPuCTRL &= ~PU_CTRL_BITS.RR; + + BusComms?.WriteRegister((byte)Register.PU_CTRL, (byte)currentPuCTRL); // turn on the analog and digital power - _currentPU_CTRL |= (PU_CTRL_BITS.PUD | PU_CTRL_BITS.PUA); - - Peripheral?.WriteRegister((byte)Register.PU_CTRL, (byte)_currentPU_CTRL); + currentPuCTRL |= (PU_CTRL_BITS.PUD | PU_CTRL_BITS.PUA); + + BusComms?.WriteRegister((byte)Register.PU_CTRL, (byte)currentPuCTRL); // wait for power-up ready var timeout = 100; do @@ -110,8 +115,8 @@ private void PowerOn() throw new Exception("Timeout powering up"); } Thread.Sleep(10); - _currentPU_CTRL = (PU_CTRL_BITS)(Peripheral?.ReadRegister((byte)Register.PU_CTRL) ?? 0); - } while ((_currentPU_CTRL & PU_CTRL_BITS.PUR) != PU_CTRL_BITS.PUR); + currentPuCTRL = (PU_CTRL_BITS)(BusComms?.ReadRegister((byte)Register.PU_CTRL) ?? 0); + } while ((currentPuCTRL & PU_CTRL_BITS.PUR) != PU_CTRL_BITS.PUR); Output.WriteLine($"Configuring..."); @@ -119,7 +124,7 @@ private void PowerOn() SetLDO(LdoVoltage.LDO_3V3); SetGain(AdcGain.Gain128); SetConversionRate(ConversionRate.SamplePerSecond80); - Peripheral?.WriteRegister((byte)Register.OTP_ADC, 0x30); // turn off CLK_CHP + BusComms?.WriteRegister((byte)Register.OTP_ADC, 0x30); // turn off CLK_CHP EnableCh2DecouplingCap(); if (!CalibrateAdc()) @@ -128,13 +133,13 @@ private void PowerOn() } // turn on cycle start - _currentPU_CTRL = (PU_CTRL_BITS)(Peripheral?.ReadRegister((byte)Register.PU_CTRL) ?? 0); - _currentPU_CTRL |= PU_CTRL_BITS.CS; - - Peripheral?.WriteRegister((byte)Register.PU_CTRL, (byte)_currentPU_CTRL); + currentPuCTRL = (PU_CTRL_BITS)(BusComms?.ReadRegister((byte)Register.PU_CTRL) ?? 0); + currentPuCTRL |= PU_CTRL_BITS.CS; + + BusComms?.WriteRegister((byte)Register.PU_CTRL, (byte)currentPuCTRL); - Output.WriteLine($"PU_CTRL: {_currentPU_CTRL}"); // 0xBE + Output.WriteLine($"PU_CTRL: {currentPuCTRL}"); // 0xBE // Enter the low power standby condition by setting PUA and PUD bits to 0, in R0x00 // Resume operation by setting PUA and PUD bits to 1, in R0x00.This sequence is the same for powering up from the standby condition, except that from standby all of the information in the configuration and calibration registers will be retained if the power supply is stable.Depending on conditions and the application, it may be desirable to perform calibration again to update the calibration registers for the best possible accuracy. @@ -143,61 +148,61 @@ private void PowerOn() private bool IsConversionComplete() { - var puctrl = (PU_CTRL_BITS)(Peripheral?.ReadRegister((byte)Register.PU_CTRL) ?? 0); + var puctrl = (PU_CTRL_BITS)(BusComms?.ReadRegister((byte)Register.PU_CTRL) ?? 0); return (puctrl & PU_CTRL_BITS.CR) == PU_CTRL_BITS.CR; } private void EnableCh2DecouplingCap() { // app note - enable ch2 decoupling cap - var pga_pwr = Peripheral?.ReadRegister((byte)Register.PGA_PWR) ?? 0; + var pga_pwr = BusComms?.ReadRegister((byte)Register.PGA_PWR) ?? 0; pga_pwr |= 1 << 7; - - Peripheral?.WriteRegister((byte)Register.PGA_PWR, pga_pwr); + + BusComms?.WriteRegister((byte)Register.PGA_PWR, pga_pwr); } private void SetLDO(LdoVoltage value) { - var ctrl1 = Peripheral?.ReadRegister((byte)Register.CTRL1) ?? 0; + var ctrl1 = BusComms?.ReadRegister((byte)Register.CTRL1) ?? 0; ctrl1 &= 0b11000111; // clear LDO ctrl1 |= (byte)((byte)value << 3); - - Peripheral?.WriteRegister((byte)Register.CTRL1, ctrl1); - _currentPU_CTRL |= PU_CTRL_BITS.AVDDS; - - Peripheral?.WriteRegister((byte)Register.PU_CTRL, (byte)_currentPU_CTRL); // enable internal LDO + + BusComms?.WriteRegister((byte)Register.CTRL1, ctrl1); + currentPuCTRL |= PU_CTRL_BITS.AVDDS; + + BusComms?.WriteRegister((byte)Register.PU_CTRL, (byte)currentPuCTRL); // enable internal LDO } private void SetGain(AdcGain value) { - var ctrl1 = Peripheral?.ReadRegister((byte)Register.CTRL1) ?? 0; + var ctrl1 = BusComms?.ReadRegister((byte)Register.CTRL1) ?? 0; ctrl1 &= 0b11111000; // clear gain ctrl1 |= (byte)value; //Bus.WriteRegister((byte)Register.CTRL1, ctrl1); - Peripheral?.WriteRegister((byte)Register.CTRL1, ctrl1); + BusComms?.WriteRegister((byte)Register.CTRL1, ctrl1); } void SetConversionRate(ConversionRate value) { - var ctrl2 = Peripheral?.ReadRegister((byte)Register.CTRL2) ?? 0; + var ctrl2 = BusComms?.ReadRegister((byte)Register.CTRL2) ?? 0; ctrl2 &= 0b10001111; // clear gain ctrl2 |= (byte)((byte)value << 4); - - Peripheral?.WriteRegister((byte)Register.CTRL2, ctrl2); + + BusComms?.WriteRegister((byte)Register.CTRL2, ctrl2); } bool CalibrateAdc() { - var ctrl2 = Peripheral?.ReadRegister((byte)Register.CTRL2) ?? 0; + var ctrl2 = BusComms?.ReadRegister((byte)Register.CTRL2) ?? 0; // turn on the calibration bit ctrl2 |= (byte)CTRL2_BITS.CALS; - - Peripheral?.WriteRegister((byte)Register.CTRL2, ctrl2); + + BusComms?.WriteRegister((byte)Register.CTRL2, ctrl2); do { - ctrl2 = Peripheral?.ReadRegister((byte)Register.CTRL2) ?? 0; + ctrl2 = BusComms?.ReadRegister((byte)Register.CTRL2) ?? 0; if ((ctrl2 & (byte)CTRL2_BITS.CAL_ERROR) != 0) { // calibration error @@ -220,7 +225,7 @@ bool CalibrateAdc() /// /// The calibration factor as an int public int CalculateCalibrationFactor() - { + { var reads = 5; var sum = 0; @@ -239,7 +244,7 @@ public int CalculateCalibrationFactor() public void SetCalibrationFactor(int factor, Mass knownValue) { Resolver.Log.Info($"SetCalibrationFactor: knownValue.Grams: {knownValue.Grams:N1}"); - _gramsPerAdcUnit = knownValue.Grams / (double)factor; + gramsPerAdcUnit = knownValue.Grams / factor; } int DoConversion() @@ -263,24 +268,21 @@ int DoConversion() /// Reads data from the sensor /// /// The latest sensor reading - protected override async Task ReadSensor() + protected override Task ReadSensor() { - return await Task.Run(() => + if (gramsPerAdcUnit == 0) { - if (_gramsPerAdcUnit == 0) - { - throw new Exception("Calibration factor has not been set"); - } + throw new Exception("Calibration factor has not been set"); + } - // get an ADC conversion - var c = DoConversion(); - // subtract the tare - var adc = c - _tareValue; - // convert to grams - var grams = adc * _gramsPerAdcUnit; - // convert to desired units - return new Mass(grams, Units.Mass.UnitType.Grams); - }); + // get an ADC conversion + var c = DoConversion(); + // subtract the tare + var adc = c - tareValue; + // convert to grams + var grams = adc * gramsPerAdcUnit; + // convert to desired units + return Task.FromResult(new Mass(grams, Units.Mass.UnitType.Grams)); } diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.LoadCell.Nau7802/Driver/Sensors.LoadCell.Nau7802.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.LoadCell.Nau7802/Driver/Sensors.LoadCell.Nau7802.csproj index a173858ad5..6f4898b7b0 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.LoadCell.Nau7802/Driver/Sensors.LoadCell.Nau7802.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.LoadCell.Nau7802/Driver/Sensors.LoadCell.Nau7802.csproj @@ -10,20 +10,17 @@ http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ Meadow.Foundation.Sensors.LoadCell.Nau7802 https://github.com/WildernessLabs/Meadow.Foundation - Meadow,Meadow.Foundation,LoadCell, Nau7802 + Meadow,Meadow.Foundation,LoadCell,Nau7802 0.1.17 true NAU7802 I2C 24-Bit dual channel analog to digital converter enable - - 8.0 - - - 8.0 + + 10.0 - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.LoadCell.Nau7802/Samples/Nau7802_Sample/Nau7802_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.LoadCell.Nau7802/Samples/Nau7802_Sample/Nau7802_Sample.csproj index 6ab679f263..4d9e4fd123 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.LoadCell.Nau7802/Samples/Nau7802_Sample/Nau7802_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.LoadCell.Nau7802/Samples/Nau7802_Sample/Nau7802_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Moisture.Capacitive/Driver/Sensors.Moisture.Capacitive.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Moisture.Capacitive/Driver/Sensors.Moisture.Capacitive.csproj index 78cc9fd0b6..b1b7f465a0 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Moisture.Capacitive/Driver/Sensors.Moisture.Capacitive.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Moisture.Capacitive/Driver/Sensors.Moisture.Capacitive.csproj @@ -16,14 +16,11 @@ Analog capacitive soil moisture sensor enable - - 8.0 - - - 8.0 + + 10.0 - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Moisture.Capacitive/Samples/Capacitive_Sample/Capacitive_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Moisture.Capacitive/Samples/Capacitive_Sample/Capacitive_Sample.csproj index bdbf243f0b..42e00caf72 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Moisture.Capacitive/Samples/Capacitive_Sample/Capacitive_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Moisture.Capacitive/Samples/Capacitive_Sample/Capacitive_Sample.csproj @@ -12,7 +12,7 @@ 9.0 - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Moisture.Fc28/Driver/Sensors.Moisture.Fc28.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Moisture.Fc28/Driver/Sensors.Moisture.Fc28.csproj index 8d8ecb3e12..4ce9dbee36 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Moisture.Fc28/Driver/Sensors.Moisture.Fc28.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Moisture.Fc28/Driver/Sensors.Moisture.Fc28.csproj @@ -10,20 +10,17 @@ http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ Meadow.Foundation.Sensors.Moisture.Fc28 https://github.com/WildernessLabs/Meadow.Foundation - Meadow.Foundation, FC28, Soil Moisture + Meadow.Foundation,FC28,Soil,Moisture 0.5.54 true FC28 analog soil moisture sensor enable - - 8.0 - - - 8.0 + + 10.0 - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Moisture.Fc28/Samples/Fc28_Sample/Fc28_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Moisture.Fc28/Samples/Fc28_Sample/Fc28_Sample.csproj index 8111a75075..1cf9bc5372 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Moisture.Fc28/Samples/Fc28_Sample/Fc28_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Moisture.Fc28/Samples/Fc28_Sample/Fc28_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Driver/Adxl3xxBase.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Driver/Adxl3xxBase.cs index ef00703841..e56a97929e 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Driver/Adxl3xxBase.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Driver/Adxl3xxBase.cs @@ -84,16 +84,13 @@ protected override void RaiseEventsAndNotify(IChangeResult chang /// Reads data from the sensor /// /// The latest sensor reading - protected override Task ReadSensor() + protected async override Task ReadSensor() { - return Task.Run(async () => - { - var x = await XAnalogIn.Read(); - var y = await YAnalogIn.Read(); - var z = await ZAnalogIn.Read(); + var x = await XAnalogIn.Read(); + var y = await YAnalogIn.Read(); + var z = await ZAnalogIn.Read(); - return new Acceleration3D(VoltageToGravity(x), VoltageToGravity(y), VoltageToGravity(z)); - }); + return new Acceleration3D(VoltageToGravity(x), VoltageToGravity(y), VoltageToGravity(z)); } /// diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Driver/Drivers/Adxl335.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Driver/Drivers/Adxl335.cs index 8acb3bb8e9..c3c7be4989 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Driver/Drivers/Adxl335.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Driver/Drivers/Adxl335.cs @@ -4,18 +4,18 @@ namespace Meadow.Foundation.Sensors.Motion { /// - /// Driver for the ADXL335 triple axis accelerometer. + /// Driver for the ADXL335 triple axis accelerometer /// +/- 3g /// public class Adxl335 : Adxl3xxBase { /// - /// Create a new ADXL335 sensor object. + /// Create a new ADXL335 sensor object /// - /// Analog pin connected to the X axis output from the ADXL335 sensor. - /// Analog pin connected to the Y axis output from the ADXL335 sensor. - /// Analog pin connected to the Z axis output from the ADXL335 sensor. - /// The voltage supplied to the sensor. Defaults to 3.3V if null. + /// Analog pin connected to the X axis output from the ADXL335 sensor + /// Analog pin connected to the Y axis output from the ADXL335 sensor + /// Analog pin connected to the Z axis output from the ADXL335 sensor + /// The voltage supplied to the sensor. Defaults to 3.3V if null public Adxl335( IPin xPin, IPin yPin, IPin zPin, Voltage? supplyVoltage) : base(xPin, yPin, zPin, 6, supplyVoltage) diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Driver/Drivers/Adxl337.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Driver/Drivers/Adxl337.cs index c6d84adb1a..fd3ff3ff13 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Driver/Drivers/Adxl337.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Driver/Drivers/Adxl337.cs @@ -4,22 +4,21 @@ namespace Meadow.Foundation.Sensors.Motion { /// - /// Driver for the ADXL337 triple axis accelerometer. + /// Driver for the ADXL337 triple axis accelerometer /// +/- 3g /// public class Adxl337 : Adxl3xxBase { /// - /// Create a new ADXL335 sensor object. + /// Create a new ADXL335 sensor object /// - /// Analog pin connected to the X axis output from the ADXL335 sensor. - /// Analog pin connected to the Y axis output from the ADXL335 sensor. - /// Analog pin connected to the Z axis output from the ADXL335 sensor. - /// The voltage supplied to the sensor. Defaults to 3.3V if null. - public Adxl337( - IPin xPin, IPin yPin, IPin zPin, Voltage? supplyVoltage) + /// Analog pin connected to the X axis output from the ADXL335 sensor + /// Analog pin connected to the Y axis output from the ADXL335 sensor + /// Analog pin connected to the Z axis output from the ADXL335 sensor + /// The voltage supplied to the sensor. Defaults to 3.3V if null + public Adxl337(IPin xPin, IPin yPin, IPin zPin, Voltage? supplyVoltage) : base(xPin, yPin, zPin, 6, supplyVoltage) { } } -} +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Driver/Drivers/Adxl345.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Driver/Drivers/Adxl345.cs index 1838f149d4..82d848858d 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Driver/Drivers/Adxl345.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Driver/Drivers/Adxl345.cs @@ -3,17 +3,21 @@ using Meadow.Peripherals.Sensors.Motion; using Meadow.Units; using System; -using System.Threading; using System.Threading.Tasks; namespace Meadow.Foundation.Sensors.Motion { /// - /// Driver for the ADXL345 triple axis accelerometer. + /// Driver for the ADXL345 triple axis accelerometer /// +/- 16g /// - public partial class Adxl345 : ByteCommsSensorBase, IAccelerometer + public partial class Adxl345 : ByteCommsSensorBase, IAccelerometer, II2cPeripheral { + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + /// /// Event raised when acceleration changes /// @@ -23,7 +27,7 @@ public partial class Adxl345 : ByteCommsSensorBase, IAcceleromet /// /// Minimum value that can be used for the update interval when the - /// sensor is being configured to generate interrupts. + /// sensor is being configured to generate interrupts /// public const ushort MinimumPollingPeriod = 100; @@ -33,43 +37,43 @@ public partial class Adxl345 : ByteCommsSensorBase, IAcceleromet public Acceleration3D? Acceleration3D => Conditions; /// - /// Values stored in this register are automatically added to the X reading. + /// Values stored in this register are automatically added to the X reading /// /// - /// Scale factor is 15.6 mg/LSB so 0x7f represents an offset of 2g. + /// Scale factor is 15.6 mg/LSB so 0x7f represents an offset of 2g /// public sbyte OffsetX { - get => (sbyte)ReadRegister(Register.OFFSET_X); - set => WriteRegister(Register.OFFSET_X, (byte)value); + get => (sbyte)ReadRegister(Register.OFFSET_X); + set => WriteRegister(Register.OFFSET_X, (byte)value); } /// - /// Values stored in this register are automatically added to the Y reading. + /// Values stored in this register are automatically added to the Y reading /// /// - /// Scale factor is 15.6 mg/LSB so 0x7f represents an offset of 2g. + /// Scale factor is 15.6 mg/LSB so 0x7f represents an offset of 2g /// public sbyte OffsetY { - get => (sbyte)ReadRegister(Register.OFFSET_Y); - set => WriteRegister(Register.OFFSET_Y, (byte)value); + get => (sbyte)ReadRegister(Register.OFFSET_Y); + set => WriteRegister(Register.OFFSET_Y, (byte)value); } /// - /// Values stored in this register are automatically added to the Z reading. + /// Values stored in this register are automatically added to the Z reading /// /// - /// Scale factor is 15.6 mg/LSB so 0x7f represents an offset of 2g. + /// Scale factor is 15.6 mg/LSB so 0x7f represents an offset of 2g /// public sbyte OffsetZ { - get => (sbyte)ReadRegister(Register.OFFSET_Z); - set => WriteRegister(Register.OFFSET_Z, (byte)value); + get => (sbyte)ReadRegister(Register.OFFSET_Z); + set => WriteRegister(Register.OFFSET_Z, (byte)value); } /// - /// Create a new instance of the ADXL345 communicating over the I2C interface. + /// Create a new instance of the ADXL345 communicating over the I2C interface /// /// Address of the I2C sensor /// I2C bus @@ -79,7 +83,7 @@ public Adxl345(II2cBus i2cBus, Addresses address = Addresses.Default) } /// - /// Create a new instance of the ADXL345 communicating over the I2C interface. + /// Create a new instance of the ADXL345 communicating over the I2C interface /// /// Address of the I2C sensor /// I2C bus @@ -100,17 +104,14 @@ public Adxl345(II2cBus i2cBus, byte address) /// Current acceleration protected override Task ReadSensor() { - return Task.Run(() => - { - // read the data from the sensor starting at the X0 register - Peripheral.ReadRegister((byte)Register.X0, ReadBuffer.Span[0..6]); - - return new Acceleration3D( - new Acceleration(ADXL345_MG2G_MULTIPLIER * (short)(ReadBuffer.Span[0] + (ReadBuffer.Span[1] << 8)), Acceleration.UnitType.Gravity), - new Acceleration(ADXL345_MG2G_MULTIPLIER * (short)(ReadBuffer.Span[2] + (ReadBuffer.Span[3] << 8)), Acceleration.UnitType.Gravity), - new Acceleration(ADXL345_MG2G_MULTIPLIER * (short)(ReadBuffer.Span[4] + (ReadBuffer.Span[5] << 8)), Acceleration.UnitType.Gravity) - ); - }); + BusComms.ReadRegister((byte)Register.X0, ReadBuffer.Span[0..6]); + + var conditions = new Acceleration3D( + new Acceleration(ADXL345_MG2G_MULTIPLIER * (short)(ReadBuffer.Span[0] + (ReadBuffer.Span[1] << 8)), Acceleration.UnitType.Gravity), + new Acceleration(ADXL345_MG2G_MULTIPLIER * (short)(ReadBuffer.Span[2] + (ReadBuffer.Span[3] << 8)), Acceleration.UnitType.Gravity), + new Acceleration(ADXL345_MG2G_MULTIPLIER * (short)(ReadBuffer.Span[4] + (ReadBuffer.Span[5] << 8)), Acceleration.UnitType.Gravity)); + + return Task.FromResult(conditions); } /// @@ -126,11 +127,11 @@ protected override void RaiseEventsAndNotify(IChangeResult chang /// /// Set the PowerControl register (see pages 25 and 26 of the data sheet) /// - /// Link the activity and inactivity events. - /// Enable / disable auto sleep when the activity and inactivity are linked. - /// Enable or disable measurements (turn on or off). - /// Put the part to sleep (true) or run in normal more (false). - /// Frequency of measurements when the part is in sleep mode. + /// Link the activity and inactivity events + /// Enable / disable auto sleep when the activity and inactivity are linked + /// Enable or disable measurements (turn on or off) + /// Put the part to sleep (true) or run in normal more (false) + /// Frequency of measurements when the part is in sleep mode public void SetPowerState(bool linkActivityAndInactivity, bool autoSleep, bool measuring, bool sleep, Frequencies frequency) { byte data = 0; @@ -158,13 +159,13 @@ public void SetPowerState(bool linkActivityAndInactivity, bool autoSleep, bool m /// /// Configure the data format (see pages 26 and 27 of the data sheet). /// - /// Put the device into self test mode when true. - /// Use 3-wire SPI (true) or 4-wire SPI (false). + /// Put the device into self test mode when true + /// Use 3-wire SPI (true) or 4-wire SPI (false) /// /// Set to full resolution (true) or 10-bit mode using the range determined by the range /// parameter (false). /// - /// Left-justified when true, right justified with sign extension when false. + /// Left-justified when true, right justified with sign extension when false /// Set the range of the sensor to 2g, 4g, 8g or 16g /// /// The range of the sensor is determined by the following table: @@ -200,7 +201,7 @@ public void SetDataFormat(bool selfTest, bool spiMode, bool fullResolution, bool /// /// Set the data rate and low power mode for the sensor. /// - /// Data rate for the sensor. + /// Data rate for the sensor /// /// Setting this to true will enter low power mode (note measurement will encounter more noise in /// this mode). @@ -224,12 +225,12 @@ public void SetDataRate(byte dataRate, bool lowPower) private void WriteRegister(Register register, byte value) { - Peripheral.WriteRegister((byte)register, value); + BusComms.WriteRegister((byte)register, value); } private byte ReadRegister(Register register) { - return Peripheral.ReadRegister((byte)register); + return BusComms.ReadRegister((byte)register); } /// @@ -238,7 +239,7 @@ private byte ReadRegister(Register register) public void DisplayRegisters() { byte[] registerData = new byte[29]; - Peripheral.ReadRegister((byte)Register.TAP_THRESHOLD, registerData); + BusComms.ReadRegister((byte)Register.TAP_THRESHOLD, registerData); DebugInformation.DisplayRegisters((byte)Register.TAP_THRESHOLD, registerData); } } diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Driver/Drivers/Adxl345_Extras/Adxl345.Addresses.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Driver/Drivers/Adxl345_Extras/Adxl345.Addresses.cs index aed970095c..b975a00da4 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Driver/Drivers/Adxl345_Extras/Adxl345.Addresses.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Driver/Drivers/Adxl345_Extras/Adxl345.Addresses.cs @@ -3,7 +3,7 @@ public partial class Adxl345 { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Driver/Drivers/Adxl362.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Driver/Drivers/Adxl362.cs index 4b4435cb98..3c2899568d 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Driver/Drivers/Adxl362.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Driver/Drivers/Adxl362.cs @@ -11,20 +11,12 @@ namespace Meadow.Foundation.Sensors.Motion { - // Sample Reading - // Accel: [X:-1.04,Y:-0.29,Z:-9.44 (m/s^2)] - // Temp: 21.10C - - // Todo: right now, the sensor default to +-2G sensitivity. that can be - // changed in software. it would be good to expose that. note that the - // conversion will be different based on sensitivity range. - /// /// Driver for the ADXL362 triple axis accelerometer. /// public partial class Adxl362 : ByteCommsSensorBase<(Acceleration3D? Acceleration3D, Units.Temperature? Temperature)>, - IAccelerometer, ITemperatureSensor + IAccelerometer, ITemperatureSensor, ISpiPeripheral { /// /// Raised when the acceleration value changes @@ -40,12 +32,12 @@ public partial class Adxl362 const double AVERAGE_TEMPERATURE_BIAS = 350; /// - /// Digital input port attached to interrupt pin 1 on the ADXL362. + /// Digital input port attached to interrupt pin 1 on the ADXL362 /// private IDigitalInputPort digitalInputPort1; /// - /// Digital Input port attached to interrupt pin 2 on the ADXL362. + /// Digital Input port attached to interrupt pin 2 on the ADXL362 /// private IDigitalInputPort digitalInputPort2; @@ -59,6 +51,36 @@ public partial class Adxl362 /// public Units.Temperature? Temperature => Conditions.Temperature; + /// + /// The default SPI bus speed for the device + /// + public Frequency DefaultSpiBusSpeed => _defaultSpiBusSpeed; + private static Frequency _defaultSpiBusSpeed = new Frequency(8000, Frequency.UnitType.Kilohertz); + + /// + /// The SPI bus speed for the device + /// + public Frequency SpiBusSpeed + { + get => ((SpiCommunications)BusComms).BusSpeed; + set => ((SpiCommunications)BusComms).BusSpeed = value; + } + + /// + /// The default SPI bus mode for the device + /// + public SpiClockConfiguration.Mode DefaultSpiBusMode => _defaultSpiBusMode; + private static SpiClockConfiguration.Mode _defaultSpiBusMode = SpiClockConfiguration.Mode.Mode0; + + /// + /// The SPI bus mode for the device + /// + public SpiClockConfiguration.Mode SpiBusMode + { + get => ((SpiCommunications)BusComms).BusMode; + set => ((SpiCommunications)BusComms).BusMode = value; + } + /// /// Indicate of data is ready to be read /// @@ -68,7 +90,7 @@ public bool DataReady { WriteBuffer.Span[0] = Commands.READ_REGISTER; WriteBuffer.Span[1] = Registers.DEVICE_ID; - Peripheral.Exchange(WriteBuffer.Span[0..2], ReadBuffer.Span[0..1]); + BusComms.Exchange(WriteBuffer.Span[0..2], ReadBuffer.Span[0..1]); return (ReadBuffer.Span[0] & StatusBitsMasks.DATA_READY) != 0; } } @@ -82,14 +104,13 @@ public bool FIFOReady { WriteBuffer.Span[0] = Commands.READ_REGISTER; WriteBuffer.Span[1] = Registers.DEVICE_ID; - Peripheral.Exchange(WriteBuffer.Span[0..2], ReadBuffer.Span[0..1]); + BusComms.Exchange(WriteBuffer.Span[0..2], ReadBuffer.Span[0..1]); return (ReadBuffer.Span[0] & StatusBitsMasks.FIFO_READY) != 0; } } /// - /// Indicate if there are at least the desired number - /// of samples in the FIFO buffer + /// Indicate if there are at least the desired number of samples in the FIFO buffer /// public bool FIFOWatermark { @@ -97,7 +118,7 @@ public bool FIFOWatermark { WriteBuffer.Span[0] = Commands.READ_REGISTER; WriteBuffer.Span[1] = Registers.DEVICE_ID; - Peripheral.Exchange(WriteBuffer.Span[0..2], ReadBuffer.Span[0..1]); + BusComms.Exchange(WriteBuffer.Span[0..2], ReadBuffer.Span[0..1]); return (ReadBuffer.Span[0] & StatusBitsMasks.FIFO_WATERMARK) != 0; } } @@ -112,14 +133,13 @@ public bool FIFOOverrun { WriteBuffer.Span[0] = Commands.READ_REGISTER; WriteBuffer.Span[1] = Registers.DEVICE_ID; - Peripheral.Exchange(WriteBuffer.Span[0..2], ReadBuffer.Span[0..1]); + BusComms.Exchange(WriteBuffer.Span[0..2], ReadBuffer.Span[0..1]); return (ReadBuffer.Span[0] & StatusBitsMasks.FIFO_OVERRUN) != 0; } } /// - /// Indicate if any activity has been detected over the - /// specified threshold + /// Indicate if any activity has been detected over the specified threshold /// public bool ActivityDetected { @@ -127,14 +147,13 @@ public bool ActivityDetected { WriteBuffer.Span[0] = Commands.READ_REGISTER; WriteBuffer.Span[1] = Registers.DEVICE_ID; - Peripheral.Exchange(WriteBuffer.Span[0..2], ReadBuffer.Span[0..1]); + BusComms.Exchange(WriteBuffer.Span[0..2], ReadBuffer.Span[0..1]); return (ReadBuffer.Span[0] & StatusBitsMasks.ACTIVITY_DETECTED) != 0; } } /// - /// Indicate if the sensor has detected inactivity or a - /// free fall condition + /// Indicate if the sensor has detected inactivity or a free fall condition /// public bool InactivityDetected { @@ -142,7 +161,7 @@ public bool InactivityDetected { WriteBuffer.Span[0] = Commands.READ_REGISTER; WriteBuffer.Span[1] = Registers.DEVICE_ID; - Peripheral.Exchange(WriteBuffer.Span[0..2], ReadBuffer.Span[0..1]); + BusComms.Exchange(WriteBuffer.Span[0..2], ReadBuffer.Span[0..1]); return (ReadBuffer.Span[0] & StatusBitsMasks.INACTIVITY_DETECTED) != 0; } } @@ -156,7 +175,7 @@ public bool IsAwake { WriteBuffer.Span[0] = Commands.READ_REGISTER; WriteBuffer.Span[1] = Registers.DEVICE_ID; - Peripheral.Exchange(WriteBuffer.Span[0..2], ReadBuffer.Span[0..1]); + BusComms.Exchange(WriteBuffer.Span[0..2], ReadBuffer.Span[0..1]); return (ReadBuffer.Span[0] & StatusBitsMasks.AWAKE) != 0; } } @@ -171,7 +190,7 @@ public int DeviceID { WriteBuffer.Span[0] = Commands.READ_REGISTER; WriteBuffer.Span[1] = Registers.DEVICE_ID; - Peripheral.Exchange(WriteBuffer.Span[0..2], ReadBuffer.Span[0..6]); + BusComms.Exchange(WriteBuffer.Span[0..2], ReadBuffer.Span[0..6]); int result = WriteBuffer.Span[0]; result |= WriteBuffer.Span[1] << 8; result |= WriteBuffer.Span[2] << 16; @@ -189,7 +208,7 @@ public byte Status { WriteBuffer.Span[0] = Commands.READ_REGISTER; WriteBuffer.Span[1] = Registers.DEVICE_ID; - Peripheral.Exchange(WriteBuffer.Span[0..2], ReadBuffer.Span[0..1]); + BusComms.Exchange(WriteBuffer.Span[0..2], ReadBuffer.Span[0..1]); return ReadBuffer.Span[0]; } } @@ -203,19 +222,18 @@ public byte ActivityInactivityControl { WriteBuffer.Span[0] = Commands.READ_REGISTER; WriteBuffer.Span[1] = Registers.ACTIVITY_INACTIVITY_CONTROL; - Peripheral.Exchange(WriteBuffer.Span[0..2], ReadBuffer.Span[0..1]); + BusComms.Exchange(WriteBuffer.Span[0..2], ReadBuffer.Span[0..1]); return ReadBuffer.Span[0]; } set { - Peripheral.WriteRegister(Commands.WRITE_REGISTER, value); + BusComms.WriteRegister(Commands.WRITE_REGISTER, value); } } /// - /// Set the value of the self test register. Setting this to true will put - /// the device into self test mode, setting this to false will turn off the - /// self test + /// Set the value of the self test register - setting this to true will put the device into + /// self test mode, setting this to false will turn off the self test /// public bool SelfTest { @@ -226,7 +244,7 @@ public bool SelfTest { selfTest = 1; } - Peripheral.WriteRegister(Commands.WRITE_REGISTER, selfTest); + BusComms.WriteRegister(Commands.WRITE_REGISTER, selfTest); } } @@ -239,12 +257,12 @@ public byte FilterControl { WriteBuffer.Span[0] = Commands.READ_REGISTER; WriteBuffer.Span[1] = Registers.FILTER_CONTROL; - Peripheral.Exchange(WriteBuffer.Span[0..2], ReadBuffer.Span[0..1]); + BusComms.Exchange(WriteBuffer.Span[0..2], ReadBuffer.Span[0..1]); return ReadBuffer.Span[0]; } set { - Peripheral.WriteRegister(Commands.WRITE_REGISTER, value); + BusComms.WriteRegister(Commands.WRITE_REGISTER, value); } } @@ -254,7 +272,7 @@ public byte FilterControl /// Spi Bus object /// Chip select pin public Adxl362(ISpiBus spiBus, IPin chipSelect) - : base(spiBus, chipSelect.CreateDigitalOutputPort()) + : base(spiBus, chipSelect.CreateDigitalOutputPort(), _defaultSpiBusSpeed, _defaultSpiBusMode) { } /// @@ -282,7 +300,7 @@ public void Reset() WriteBuffer.Span[0] = Commands.WRITE_REGISTER; WriteBuffer.Span[1] = Registers.SOFT_RESET; WriteBuffer.Span[2] = 0x52; - Peripheral.Write(WriteBuffer.Span[0..3]); + BusComms.Write(WriteBuffer.Span[0..3]); Thread.Sleep(10); } @@ -294,7 +312,7 @@ public void Start() WriteBuffer.Span[0] = Commands.WRITE_REGISTER; WriteBuffer.Span[1] = Registers.POWER_CONTROL; WriteBuffer.Span[2] = 0x02; - Peripheral.Write(WriteBuffer.Span[0..3]); + BusComms.Write(WriteBuffer.Span[0..3]); } /// @@ -305,10 +323,10 @@ public void Stop() WriteBuffer.Span[0] = Commands.READ_REGISTER; WriteBuffer.Span[1] = Registers.POWER_CONTROL; WriteBuffer.Span[2] = 0x02; - Peripheral.Exchange(WriteBuffer.Span[0..3], ReadBuffer.Span[0..1]); + BusComms.Exchange(WriteBuffer.Span[0..3], ReadBuffer.Span[0..1]); byte power = (byte)((ReadBuffer.Span[0] & (~PowerControlMasks.MEASURE)) & 0xff); WriteBuffer.Span[2] = power; - Peripheral.Write(WriteBuffer.Span[0..3]); + BusComms.Write(WriteBuffer.Span[0..3]); } /// @@ -346,31 +364,26 @@ public override void StopUpdating() /// The latest sensor reading protected override Task<(Acceleration3D? Acceleration3D, Units.Temperature? Temperature)> ReadSensor() { - return Task.Run(() => - { - (Acceleration3D? Acceleration3D, Units.Temperature? Temperature) conditions; + (Acceleration3D? Acceleration3D, Units.Temperature? Temperature) conditions; - // read the XYZ and Temp registers in one go - WriteBuffer.Span[0] = Commands.READ_REGISTER; - WriteBuffer.Span[1] = Registers.X_AXIS_LSB; - Peripheral.Exchange(WriteBuffer.Span[0..2], ReadBuffer.Span[0..8]); - - // milli-gravity (1/1000 G) - conditions.Acceleration3D = new Acceleration3D( - new Acceleration((short)((ReadBuffer.Span[1] << 8) | ReadBuffer.Span[0]) / 1000d, AU.Gravity), - new Acceleration((short)((ReadBuffer.Span[3] << 8) | ReadBuffer.Span[2]) / 1000d, AU.Gravity), - new Acceleration((short)((ReadBuffer.Span[5] << 8) | ReadBuffer.Span[4]) / 1000d, AU.Gravity) - ); - - double rawTemp = (short)((ReadBuffer.Span[7] << 8) | ReadBuffer.Span[6]); - // decimal doesn't come in, so 20.0C comes in as `200`. and also have to remove the bias. - double tempC = (rawTemp - AVERAGE_TEMPERATURE_BIAS) / 10d; - conditions.Temperature = new Units.Temperature(tempC, TU.Celsius); - - return conditions; - }); - } + // read the XYZ and Temp registers in one go + WriteBuffer.Span[0] = Commands.READ_REGISTER; + WriteBuffer.Span[1] = Registers.X_AXIS_LSB; + BusComms.Exchange(WriteBuffer.Span[0..2], ReadBuffer.Span[0..8]); + + // milli-gravity (1/1000 G) + conditions.Acceleration3D = new Acceleration3D( + new Acceleration((short)((ReadBuffer.Span[1] << 8) | ReadBuffer.Span[0]) / 1000d, AU.Gravity), + new Acceleration((short)((ReadBuffer.Span[3] << 8) | ReadBuffer.Span[2]) / 1000d, AU.Gravity), + new Acceleration((short)((ReadBuffer.Span[5] << 8) | ReadBuffer.Span[4]) / 1000d, AU.Gravity)); + double rawTemp = (short)((ReadBuffer.Span[7] << 8) | ReadBuffer.Span[6]); + // decimal doesn't come in, so 20.0C comes in as `200`. and also have to remove the bias. + double tempC = (rawTemp - AVERAGE_TEMPERATURE_BIAS) / 10d; + conditions.Temperature = new Units.Temperature(tempC, TU.Celsius); + + return Task.FromResult(conditions); + } /// /// Configure the activity threshold and activity time. Once configured it will be @@ -402,7 +415,7 @@ public void ConfigureActivityThreshold(ushort threshold, byte numberOfSamples) WriteBuffer.Span[2] = (byte)(threshold & 0xff); WriteBuffer.Span[3] = (byte)((threshold >> 8) & 0xff); WriteBuffer.Span[4] = numberOfSamples; - Peripheral.Write(WriteBuffer.Span[0..5]); + BusComms.Write(WriteBuffer.Span[0..5]); } /// @@ -429,16 +442,14 @@ public void ConfigureInactivityThreshold(ushort threshold, ushort numberOfSample { throw new ArgumentOutOfRangeException(nameof(threshold), "Inactivity threshold should be in the range 0-0x7ff"); } - // // The threshold and number of samples register are in consecutive locations. - // WriteBuffer.Span[0] = Commands.WRITE_REGISTER; WriteBuffer.Span[1] = Registers.INACTIVITY_TIME_COUNT_LSB; WriteBuffer.Span[2] = (byte)(threshold & 0xff); WriteBuffer.Span[3] = (byte)((threshold >> 8) & 0xff); WriteBuffer.Span[4] = (byte)(numberOfSamples & 0xff); WriteBuffer.Span[5] = (byte)((threshold >> 8) & 0xff); - Peripheral.Write(WriteBuffer.Span[0..6]); + BusComms.Write(WriteBuffer.Span[0..6]); } /// @@ -449,14 +460,7 @@ public void ConfigureInactivityThreshold(ushort threshold, ushort numberOfSample /// Resistor mode mapping based upon the active low state. private ResistorMode MapResistorMode(bool activeLow) { - if (activeLow) - { - return (ResistorMode.InternalPullUp); - } - else - { - return (ResistorMode.InternalPullDown); - } + return activeLow ? ResistorMode.InternalPullUp : ResistorMode.InternalPullDown; } /// @@ -467,14 +471,7 @@ private ResistorMode MapResistorMode(bool activeLow) /// Interrupt mode mapping based upon the active low state. private InterruptMode MapInterruptMode(bool activeLow) { - if (activeLow) - { - return (InterruptMode.EdgeFalling); - } - else - { - return (InterruptMode.EdgeRising); - } + return activeLow ? InterruptMode.EdgeFalling : InterruptMode.EdgeRising; } /// @@ -497,7 +494,7 @@ private void ConfigureInterrupts(byte interruptMap1, IPin interruptPin1, byte in WriteBuffer.Span[0] = Commands.WRITE_REGISTER; WriteBuffer.Span[1] = interruptMap1; WriteBuffer.Span[2] = interruptMap2; - Peripheral.Write(WriteBuffer.Span[0..3]); + BusComms.Write(WriteBuffer.Span[0..3]); if (interruptPin1 != null) { @@ -543,13 +540,13 @@ private void DisplayRegisters() WriteBuffer.Span[0] = Commands.READ_REGISTER; WriteBuffer.Span[1] = 0x00; - Peripheral.Exchange(WriteBuffer.Span[0..2], rxBuffer[0..6]); + BusComms.Exchange(WriteBuffer.Span[0..2], rxBuffer[0..6]); DebugInformation.DisplayRegisters(0x00, rxBuffer[2..6].ToArray()); WriteBuffer.Span[1] = Registers.X_AXIS_8BITS; - Peripheral.Exchange(WriteBuffer.Span[0..2], rxBuffer); + BusComms.Exchange(WriteBuffer.Span[0..2], rxBuffer); DebugInformation.DisplayRegisters(Registers.X_AXIS_8BITS, ReadBuffer.Span[2..].ToArray()); } diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Driver/Drivers/Adxl377.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Driver/Drivers/Adxl377.cs index eae3ed0b75..3970034163 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Driver/Drivers/Adxl377.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Driver/Drivers/Adxl377.cs @@ -4,22 +4,20 @@ namespace Meadow.Foundation.Sensors.Motion { /// - /// Driver for the ADXL377 triple axis accelerometer. + /// Driver for the ADXL377 triple axis accelerometer /// +/- 200g /// public class Adxl377 : Adxl3xxBase { /// - /// Create a new ADXL335 sensor object. + /// Create a new ADXL377 sensor object /// - /// Analog pin connected to the X axis output from the ADXL335 sensor. - /// Analog pin connected to the Y axis output from the ADXL335 sensor. - /// Analog pin connected to the Z axis output from the ADXL335 sensor. - /// The voltage supplied to the sensor. Defaults to 3.3V if null. - public Adxl377( - IPin xPin, IPin yPin, IPin zPin, Voltage? supplyVoltage) + /// Analog pin connected to the X axis output from the ADXL335 sensor + /// Analog pin connected to the Y axis output from the ADXL335 sensor + /// Analog pin connected to the Z axis output from the ADXL335 sensor + /// The voltage supplied to the sensor. Defaults to 3.3V if null + public Adxl377(IPin xPin, IPin yPin, IPin zPin, Voltage? supplyVoltage) : base(xPin, yPin, zPin, 400, supplyVoltage) - { - } + { } } -} +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Driver/Sensors.Motion.Adxl3xx.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Driver/Sensors.Motion.Adxl3xx.csproj index ef4c5e6231..29c9fbf424 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Driver/Sensors.Motion.Adxl3xx.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Driver/Sensors.Motion.Adxl3xx.csproj @@ -10,13 +10,13 @@ http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ Meadow.Foundation.Sensors.Motion.Adxl3xx https://github.com/WildernessLabs/Meadow.Foundation - Meadow.Foundation, ADXL335, ADXL345, ADXL337, ADXL362, ADXL377, Accelerometer, Motion + Meadow.Foundation,ADXL335,ADXL345,ADXL337,ADXL362,ADXL377,Accelerometer,Motion,3-axis 0.1.13 true ADXL3xx Analog and I2C 3-axis accelerometers (ADXL335, ADXL345, ADXL337, ADXL362, ADXL377) - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Samples/Adxl335_Sample/Adxl335_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Samples/Adxl335_Sample/Adxl335_Sample.csproj index 13370ea35b..85eef182de 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Samples/Adxl335_Sample/Adxl335_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Samples/Adxl335_Sample/Adxl335_Sample.csproj @@ -10,7 +10,7 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Samples/Adxl337_Sample/Adxl337_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Samples/Adxl337_Sample/Adxl337_Sample.csproj index 13370ea35b..85eef182de 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Samples/Adxl337_Sample/Adxl337_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Samples/Adxl337_Sample/Adxl337_Sample.csproj @@ -10,7 +10,7 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Samples/Adxl345_Sample/Adxl345_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Samples/Adxl345_Sample/Adxl345_Sample.csproj index 60c1a77ce7..6959941263 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Samples/Adxl345_Sample/Adxl345_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Samples/Adxl345_Sample/Adxl345_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Samples/Adxl362_Sample/Adxl362_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Samples/Adxl362_Sample/Adxl362_Sample.csproj index 60c1a77ce7..6959941263 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Samples/Adxl362_Sample/Adxl362_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Samples/Adxl362_Sample/Adxl362_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Samples/Adxl377_Sample/Adxl377_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Samples/Adxl377_Sample/Adxl377_Sample.csproj index 13370ea35b..85eef182de 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Samples/Adxl377_Sample/Adxl377_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Adxl3xx/Samples/Adxl377_Sample/Adxl377_Sample.csproj @@ -10,7 +10,7 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Apds9960/Driver/Apds9960.Addresses.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Apds9960/Driver/Apds9960.Addresses.cs index 1321b7f2ed..21cccf18da 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Apds9960/Driver/Apds9960.Addresses.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Apds9960/Driver/Apds9960.Addresses.cs @@ -3,7 +3,7 @@ public partial class Apds9960 { /// - /// Valid addresses for the sensor + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Apds9960/Driver/Apds9960.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Apds9960/Driver/Apds9960.cs index ebb60674dc..28c7722338 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Apds9960/Driver/Apds9960.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Apds9960/Driver/Apds9960.cs @@ -6,14 +6,11 @@ namespace Meadow.Foundation.Sensors.Motion { - // TODO: the light stuff seems to work. not sure on the RGB conversion though. - // haven't tested any of the gesture stuff. - // need to add distance - /// /// Represents the APDS9960 Proximity, Light, RGB, and Gesture Sensor /// - public partial class Apds9960 : ByteCommsSensorBase<(Color? Color, Illuminance? AmbientLight)> + public partial class Apds9960 : ByteCommsSensorBase<(Color? Color, Illuminance? AmbientLight)>, + II2cPeripheral { /// /// Raised when the ambient light value changes @@ -25,9 +22,13 @@ public partial class Apds9960 : ByteCommsSensorBase<(Color? Color, Illuminance? /// public event EventHandler> ColorUpdated = delegate { }; - readonly IDigitalInputPort interruptPort; + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; - GestureData gestureData; + readonly IDigitalInputPort interruptPort; + readonly GestureData gestureData; int gestureUdDelta; int gestureLrDelta; int gestureUdCount; @@ -90,35 +91,31 @@ public Apds9960(II2cBus i2cBus, IPin interruptPin) /// The latest sensor reading protected override Task<(Color? Color, Illuminance? AmbientLight)> ReadSensor() { - return Task.Run(() => - { - - (Color? Color, Illuminance? AmbientLight) conditions; + (Color? Color, Illuminance? AmbientLight) conditions; - // TODO: before each of these readings, we need to check to see - // if that feature is enabled, and if it's not, skip it and set - // the `conditions.[feature] = null;` + // TODO: before each of these readings, we need to check to see + // if that feature is enabled, and if it's not, skip it and set + // the `conditions.[feature] = null;` - //---- ambient light - // TODO: someone needs to verify this - // have no idea if this conversion is correct. the exten of the datasheet documentation is: - // "RGBC results can be used to calculate ambient light levels (i.e. Lux) and color temperature (i.e. Kelvin)." - // NOTE: looks correct, actually. reading ~600 lux in my office and went to 4k LUX when i moved the sensor to the window - var ambient = ReadAmbientLight(); - conditions.AmbientLight = new Illuminance(ambient, Illuminance.UnitType.Lux); + //---- ambient light + // TODO: someone needs to verify this + // have no idea if this conversion is correct. the exten of the datasheet documentation is: + // "RGBC results can be used to calculate ambient light levels (i.e. Lux) and color temperature (i.e. Kelvin)." + // NOTE: looks correct, actually. reading ~600 lux in my office and went to 4k LUX when i moved the sensor to the window + var ambient = ReadAmbientLight(); + conditions.AmbientLight = new Illuminance(ambient, Illuminance.UnitType.Lux); - //---- color - // TODO: someone needs to verify this. - var rgbDivisor = 65536 / 256; // come back as 16-bit values (ushorts). need to be byte. - var r = (int)(ReadRedLight() / rgbDivisor); - var g = (int)(ReadGreenLight() / rgbDivisor); - var b = (int)(ReadBlueLight() / rgbDivisor); - var a = (int)(ambient / rgbDivisor); + //---- color + // TODO: someone needs to verify this. + var rgbDivisor = 65536 / 256; // come back as 16-bit values (ushorts). need to be byte. + var r = ReadRedLight() / rgbDivisor; + var g = ReadGreenLight() / rgbDivisor; + var b = ReadBlueLight() / rgbDivisor; + var a = ambient / rgbDivisor; - conditions.Color = Foundation.Color.FromRgba(r, g, b, a); + conditions.Color = Foundation.Color.FromRgba(r, g, b, a); - return conditions; - }); + return Task.FromResult(conditions); } /// @@ -145,7 +142,7 @@ private void InterruptPort_Changed(object sender, DigitalPortResult e) void Initialize() { - var id = Peripheral.ReadRegister(Registers.APDS9960_ID); + var id = BusComms.ReadRegister(Registers.APDS9960_ID); // if ((id != APDS9960_ID) && (id != APDS9960_ID_1) && (id != APDS9960_ID_2)) // if(id == 0) @@ -157,12 +154,12 @@ void Initialize() SetMode(OperatingModes.ALL, BooleanValues.OFF); /* Set default values for ambient light and proximity registers */ - Peripheral.WriteRegister(Registers.APDS9960_ATIME, DefaultValues.DEFAULT_ATIME); - Peripheral.WriteRegister(Registers.APDS9960_WTIME, DefaultValues.DEFAULT_WTIME); - Peripheral.WriteRegister(Registers.APDS9960_PPULSE, DefaultValues.DEFAULT_PROX_PPULSE); - Peripheral.WriteRegister(Registers.APDS9960_POFFSET_UR, DefaultValues.DEFAULT_POFFSET_UR); - Peripheral.WriteRegister(Registers.APDS9960_POFFSET_DL, DefaultValues.DEFAULT_POFFSET_DL); - Peripheral.WriteRegister(Registers.APDS9960_CONFIG1, DefaultValues.DEFAULT_CONFIG1); + BusComms.WriteRegister(Registers.APDS9960_ATIME, DefaultValues.DEFAULT_ATIME); + BusComms.WriteRegister(Registers.APDS9960_WTIME, DefaultValues.DEFAULT_WTIME); + BusComms.WriteRegister(Registers.APDS9960_PPULSE, DefaultValues.DEFAULT_PROX_PPULSE); + BusComms.WriteRegister(Registers.APDS9960_POFFSET_UR, DefaultValues.DEFAULT_POFFSET_UR); + BusComms.WriteRegister(Registers.APDS9960_POFFSET_DL, DefaultValues.DEFAULT_POFFSET_DL); + BusComms.WriteRegister(Registers.APDS9960_CONFIG1, DefaultValues.DEFAULT_CONFIG1); SetLEDDrive(DefaultValues.DEFAULT_LDRIVE); Resolver.Log.Info("SetProximityGain"); @@ -175,18 +172,18 @@ void Initialize() SetLightIntHighThreshold(DefaultValues.DEFAULT_AIHT); - Peripheral.WriteRegister(Registers.APDS9960_PERS, DefaultValues.DEFAULT_PERS); + BusComms.WriteRegister(Registers.APDS9960_PERS, DefaultValues.DEFAULT_PERS); - Peripheral.WriteRegister(Registers.APDS9960_CONFIG2, DefaultValues.DEFAULT_CONFIG2); + BusComms.WriteRegister(Registers.APDS9960_CONFIG2, DefaultValues.DEFAULT_CONFIG2); - Peripheral.WriteRegister(Registers.APDS9960_CONFIG3, DefaultValues.DEFAULT_CONFIG3); + BusComms.WriteRegister(Registers.APDS9960_CONFIG3, DefaultValues.DEFAULT_CONFIG3); Resolver.Log.Info("SetGestureEnterThresh"); SetGestureEnterThresh(DefaultValues.DEFAULT_GPENTH); SetGestureExitThresh(DefaultValues.DEFAULT_GEXTH); - Peripheral.WriteRegister(Registers.APDS9960_GCONF1, DefaultValues.DEFAULT_GCONF1); + BusComms.WriteRegister(Registers.APDS9960_GCONF1, DefaultValues.DEFAULT_GCONF1); SetGestureGain(DefaultValues.DEFAULT_GGAIN); @@ -194,12 +191,12 @@ void Initialize() SetGestureWaitTime(DefaultValues.DEFAULT_GWTIME); - Peripheral.WriteRegister(Registers.APDS9960_GOFFSET_U, DefaultValues.DEFAULT_GOFFSET); - Peripheral.WriteRegister(Registers.APDS9960_GOFFSET_D, DefaultValues.DEFAULT_GOFFSET); - Peripheral.WriteRegister(Registers.APDS9960_GOFFSET_L, DefaultValues.DEFAULT_GOFFSET); - Peripheral.WriteRegister(Registers.APDS9960_GOFFSET_R, DefaultValues.DEFAULT_GOFFSET); - Peripheral.WriteRegister(Registers.APDS9960_GPULSE, DefaultValues.DEFAULT_GPULSE); - Peripheral.WriteRegister(Registers.APDS9960_GCONF3, DefaultValues.DEFAULT_GCONF3); + BusComms.WriteRegister(Registers.APDS9960_GOFFSET_U, DefaultValues.DEFAULT_GOFFSET); + BusComms.WriteRegister(Registers.APDS9960_GOFFSET_D, DefaultValues.DEFAULT_GOFFSET); + BusComms.WriteRegister(Registers.APDS9960_GOFFSET_L, DefaultValues.DEFAULT_GOFFSET); + BusComms.WriteRegister(Registers.APDS9960_GOFFSET_R, DefaultValues.DEFAULT_GOFFSET); + BusComms.WriteRegister(Registers.APDS9960_GPULSE, DefaultValues.DEFAULT_GPULSE); + BusComms.WriteRegister(Registers.APDS9960_GCONF3, DefaultValues.DEFAULT_GCONF3); SetGestureIntEnable(DefaultValues.DEFAULT_GIEN); } @@ -210,7 +207,7 @@ void Initialize() */ byte GetMode() { - return Peripheral.ReadRegister(Registers.APDS9960_ENABLE); + return BusComms.ReadRegister(Registers.APDS9960_ENABLE); } /** @@ -258,7 +255,7 @@ void SetMode(byte mode, byte enable) } /* Write value back to ENABLE register */ - Peripheral.WriteRegister(Registers.APDS9960_ENABLE, reg_val); + BusComms.WriteRegister(Registers.APDS9960_ENABLE, reg_val); } /// @@ -330,8 +327,8 @@ Set AUX to LED_BOOST_100 Enable PON, WEN, PEN, GEN in ENABLE */ ResetGestureParameters(); - Peripheral.WriteRegister(Registers.APDS9960_WTIME, 0xFF); - Peripheral.WriteRegister(Registers.APDS9960_PPULSE, DefaultValues.DEFAULT_GESTURE_PPULSE); + BusComms.WriteRegister(Registers.APDS9960_WTIME, 0xFF); + BusComms.WriteRegister(Registers.APDS9960_PPULSE, DefaultValues.DEFAULT_GESTURE_PPULSE); SetLEDBoost(GainValues.LED_BOOST_100); @@ -363,7 +360,7 @@ public void DisableGestureSensor() /// True if available public bool IsGestureAvailable() { - byte val = Peripheral.ReadRegister(Registers.APDS9960_GSTATUS); + byte val = BusComms.ReadRegister(Registers.APDS9960_GSTATUS); /* Shift and mask out GVALID bit */ val &= BitFields.APDS9960_GVALID; @@ -394,19 +391,19 @@ public Direction ReadGesture() /* Wait some time to collect next batch of FIFO data */ Thread.Sleep(FIFO_PAUSE_TIME); - var gstatus = Peripheral.ReadRegister(Registers.APDS9960_GSTATUS); + var gstatus = BusComms.ReadRegister(Registers.APDS9960_GSTATUS); /* If we have valid data, read in FIFO */ if ((gstatus & BitFields.APDS9960_GVALID) == BitFields.APDS9960_GVALID) { - fifo_level = Peripheral.ReadRegister(Registers.APDS9960_GFLVL); + fifo_level = BusComms.ReadRegister(Registers.APDS9960_GFLVL); /* If there's stuff in the FIFO, read it into our data block */ if (fifo_level > 0) { byte len = (byte)(fifo_level * 4); - Peripheral.ReadRegister(Registers.APDS9960_GFIFO_U, readBuffer.Span[0..len]); + BusComms.ReadRegister(Registers.APDS9960_GFIFO_U, readBuffer.Span[0..len]); Resolver.Log.Info(BitConverter.ToString(readBuffer.Span[0..len].ToArray())); @@ -472,9 +469,9 @@ public void EnablePower(bool enable) /// protected ushort ReadAmbientLight() { - byte val = Peripheral.ReadRegister(Registers.APDS9960_CDATAL); + byte val = BusComms.ReadRegister(Registers.APDS9960_CDATAL); - byte val_byte = Peripheral.ReadRegister(Registers.APDS9960_CDATAH); + byte val_byte = BusComms.ReadRegister(Registers.APDS9960_CDATAH); return (ushort)(val + (val_byte << 8)); } @@ -485,9 +482,9 @@ protected ushort ReadAmbientLight() /// protected ushort ReadRedLight() { - byte val = Peripheral.ReadRegister(Registers.APDS9960_RDATAL); + byte val = BusComms.ReadRegister(Registers.APDS9960_RDATAL); - byte val_byte = Peripheral.ReadRegister(Registers.APDS9960_RDATAH); + byte val_byte = BusComms.ReadRegister(Registers.APDS9960_RDATAH); return (ushort)(val + (val_byte << 8)); } @@ -498,9 +495,9 @@ protected ushort ReadRedLight() /// protected ushort ReadGreenLight() { - byte val = Peripheral.ReadRegister(Registers.APDS9960_GDATAL); + byte val = BusComms.ReadRegister(Registers.APDS9960_GDATAL); - byte val_byte = Peripheral.ReadRegister(Registers.APDS9960_GDATAH); + byte val_byte = BusComms.ReadRegister(Registers.APDS9960_GDATAH); return (ushort)(val + (val_byte << 8)); } @@ -511,9 +508,9 @@ protected ushort ReadGreenLight() /// protected ushort ReadBlueLight() { - byte val = Peripheral.ReadRegister(Registers.APDS9960_BDATAL); + byte val = BusComms.ReadRegister(Registers.APDS9960_BDATAL); - byte val_byte = Peripheral.ReadRegister(Registers.APDS9960_BDATAH); + byte val_byte = BusComms.ReadRegister(Registers.APDS9960_BDATAH); return (ushort)(val + (val_byte << 8)); } @@ -524,7 +521,7 @@ protected ushort ReadBlueLight() /// public byte ReadProximity() { - return Peripheral.ReadRegister(Registers.APDS9960_PDATA); + return BusComms.ReadRegister(Registers.APDS9960_PDATA); } /// @@ -815,7 +812,7 @@ bool DecodeGesture() */ public byte GetProxIntLowThresh() { - return Peripheral.ReadRegister(Registers.APDS9960_PILT); + return BusComms.ReadRegister(Registers.APDS9960_PILT); } /** @@ -826,7 +823,7 @@ public byte GetProxIntLowThresh() */ public void SetProxIntLowThresh(byte threshold) { - Peripheral.WriteRegister(Registers.APDS9960_PILT, threshold); + BusComms.WriteRegister(Registers.APDS9960_PILT, threshold); } /** @@ -836,7 +833,7 @@ public void SetProxIntLowThresh(byte threshold) */ public byte GetProxIntHighThresh() { - return Peripheral.ReadRegister(Registers.APDS9960_PIHT); + return BusComms.ReadRegister(Registers.APDS9960_PIHT); } /** @@ -847,7 +844,7 @@ public byte GetProxIntHighThresh() */ public void SetProxIntHighThresh(byte threshold) { - Peripheral.WriteRegister(Registers.APDS9960_PIHT, threshold); + BusComms.WriteRegister(Registers.APDS9960_PIHT, threshold); } /** @@ -863,7 +860,7 @@ public void SetProxIntHighThresh(byte threshold) */ public byte GetLEDDrive() { - byte val = Peripheral.ReadRegister(Registers.APDS9960_CONTROL); + byte val = BusComms.ReadRegister(Registers.APDS9960_CONTROL); /* Shift and mask out LED drive bits */ val = (byte)((val >> 6) & 0b00000011); @@ -885,7 +882,7 @@ public byte GetLEDDrive() */ public bool SetLEDDrive(byte drive) { - byte val = Peripheral.ReadRegister(Registers.APDS9960_CONTROL); + byte val = BusComms.ReadRegister(Registers.APDS9960_CONTROL); /* Set bits in register to given value */ drive &= 0b00000011; @@ -894,7 +891,7 @@ public bool SetLEDDrive(byte drive) val |= drive; /* Write register value back into CONTROL register */ - Peripheral.WriteRegister(Registers.APDS9960_CONTROL, val); + BusComms.WriteRegister(Registers.APDS9960_CONTROL, val); return true; } @@ -912,7 +909,7 @@ public bool SetLEDDrive(byte drive) */ public byte GetProximityGain() { - byte val = Peripheral.ReadRegister(Registers.APDS9960_CONTROL); + byte val = BusComms.ReadRegister(Registers.APDS9960_CONTROL); /* Shift and mask out PDRIVE bits */ val = (byte)((val >> 2) & 0b00000011); @@ -934,7 +931,7 @@ public byte GetProximityGain() */ public void SetProximityGain(byte drive) { - byte val = Peripheral.ReadRegister(Registers.APDS9960_CONTROL); + byte val = BusComms.ReadRegister(Registers.APDS9960_CONTROL); /* Set bits in register to given value */ drive &= 0b00000011; @@ -943,7 +940,7 @@ public void SetProximityGain(byte drive) val |= drive; /* Write register value back into CONTROL register */ - Peripheral.WriteRegister(Registers.APDS9960_CONTROL, val); + BusComms.WriteRegister(Registers.APDS9960_CONTROL, val); } /** @@ -959,7 +956,7 @@ public void SetProximityGain(byte drive) */ byte GetAmbientLightGain() { - byte val = Peripheral.ReadRegister(Registers.APDS9960_CONTROL); + byte val = BusComms.ReadRegister(Registers.APDS9960_CONTROL); /* Shift and mask out ADRIVE bits */ val &= 0b00000011; @@ -981,15 +978,13 @@ byte GetAmbientLightGain() */ void SetAmbientLightGain(byte drive) { - byte val = Peripheral.ReadRegister(Registers.APDS9960_CONTROL); + byte val = BusComms.ReadRegister(Registers.APDS9960_CONTROL); - /* Set bits in register to given value */ drive &= 0b00000011; val &= 0b11111100; val |= drive; - /* Write register value back into CONTROL register */ - Peripheral.WriteRegister(Registers.APDS9960_CONTROL, val); + BusComms.WriteRegister(Registers.APDS9960_CONTROL, val); } /** @@ -1005,7 +1000,7 @@ void SetAmbientLightGain(byte drive) */ byte GetLEDBoost() { - byte val = Peripheral.ReadRegister(Registers.APDS9960_CONTROL); + byte val = BusComms.ReadRegister(Registers.APDS9960_CONTROL); /* Shift and mask out LED_BOOST bits */ val = (byte)((val >> 4) & 0b00000011); @@ -1027,7 +1022,7 @@ byte GetLEDBoost() */ void SetLEDBoost(byte boost) { - byte val = Peripheral.ReadRegister(Registers.APDS9960_CONFIG2); + byte val = BusComms.ReadRegister(Registers.APDS9960_CONFIG2); /* Set bits in register to given value */ boost &= 0b00000011; @@ -1035,7 +1030,7 @@ void SetLEDBoost(byte boost) val &= 0b11001111; val |= boost; - Peripheral.WriteRegister(Registers.APDS9960_CONFIG2, val); + BusComms.WriteRegister(Registers.APDS9960_CONFIG2, val); } /** @@ -1045,7 +1040,7 @@ void SetLEDBoost(byte boost) */ byte GetProxGainCompEnable() { - byte val = Peripheral.ReadRegister(Registers.APDS9960_CONFIG3); + byte val = BusComms.ReadRegister(Registers.APDS9960_CONFIG3); /* Shift and mask out PCMP bits */ val = (byte)((val >> 5) & 0b00000001); @@ -1061,7 +1056,7 @@ byte GetProxGainCompEnable() */ void SetProxGainCompEnable(byte enable) { - byte val = Peripheral.ReadRegister(Registers.APDS9960_CONFIG3); + byte val = BusComms.ReadRegister(Registers.APDS9960_CONFIG3); /* Set bits in register to given value */ enable &= 0b00000001; @@ -1070,7 +1065,7 @@ void SetProxGainCompEnable(byte enable) val |= enable; /* Write register value back into CONFIG3 register */ - Peripheral.WriteRegister(Registers.APDS9960_CONFIG3, val); + BusComms.WriteRegister(Registers.APDS9960_CONFIG3, val); } /** @@ -1087,7 +1082,7 @@ void SetProxGainCompEnable(byte enable) */ byte GetProxPhotoMask() { - byte val = Peripheral.ReadRegister(Registers.APDS9960_CONFIG3); + byte val = BusComms.ReadRegister(Registers.APDS9960_CONFIG3); /* Mask out photodiode enable mask bits */ val &= 0b00001111; @@ -1110,14 +1105,14 @@ byte GetProxPhotoMask() */ void SetProxPhotoMask(byte mask) { - byte val = Peripheral.ReadRegister(Registers.APDS9960_CONFIG3); + byte val = BusComms.ReadRegister(Registers.APDS9960_CONFIG3); /* Set bits in register to given value */ mask &= 0b00001111; val &= 0b11110000; val |= mask; - Peripheral.WriteRegister(Registers.APDS9960_CONFIG3, val); + BusComms.WriteRegister(Registers.APDS9960_CONFIG3, val); } /** @@ -1127,7 +1122,7 @@ void SetProxPhotoMask(byte mask) */ byte GetGestureEnterThresh() { - byte val = Peripheral.ReadRegister(Registers.APDS9960_GPENTH); + byte val = BusComms.ReadRegister(Registers.APDS9960_GPENTH); return val; } @@ -1140,7 +1135,7 @@ byte GetGestureEnterThresh() */ void SetGestureEnterThresh(byte threshold) { - Peripheral.WriteRegister(Registers.APDS9960_GPENTH, threshold); + BusComms.WriteRegister(Registers.APDS9960_GPENTH, threshold); } /** @@ -1150,7 +1145,7 @@ void SetGestureEnterThresh(byte threshold) */ byte GetGestureExitThresh() { - byte val = Peripheral.ReadRegister(Registers.APDS9960_GEXTH); + byte val = BusComms.ReadRegister(Registers.APDS9960_GEXTH); return val; } @@ -1163,7 +1158,7 @@ byte GetGestureExitThresh() */ void SetGestureExitThresh(byte threshold) { - Peripheral.WriteRegister(Registers.APDS9960_GEXTH, threshold); + BusComms.WriteRegister(Registers.APDS9960_GEXTH, threshold); } /** @@ -1179,7 +1174,7 @@ void SetGestureExitThresh(byte threshold) */ byte GetGestureGain() { - byte val = Peripheral.ReadRegister(Registers.APDS9960_GCONF2); + byte val = BusComms.ReadRegister(Registers.APDS9960_GCONF2); /* Shift and mask out GGAIN bits */ val = (byte)((val >> 5) & 0b00000011); @@ -1201,7 +1196,7 @@ byte GetGestureGain() */ void SetGestureGain(byte gain) { - byte val = Peripheral.ReadRegister(Registers.APDS9960_GCONF2); + byte val = BusComms.ReadRegister(Registers.APDS9960_GCONF2); /* Set bits in register to given value */ gain &= 0b00000011; @@ -1210,7 +1205,7 @@ void SetGestureGain(byte gain) val |= gain; /* Write register value back into GCONF2 register */ - Peripheral.WriteRegister(Registers.APDS9960_GCONF2, val); + BusComms.WriteRegister(Registers.APDS9960_GCONF2, val); } /** @@ -1227,7 +1222,7 @@ void SetGestureGain(byte gain) byte GetGestureLEDDrive() { /* Read value from GCONF2 register */ - byte val = Peripheral.ReadRegister(Registers.APDS9960_GCONF2); + byte val = BusComms.ReadRegister(Registers.APDS9960_GCONF2); /* Shift and mask out GLDRIVE bits */ val = (byte)((val >> 3) & 0b00000011); @@ -1249,7 +1244,7 @@ byte GetGestureLEDDrive() */ void SetGestureLEDDrive(byte drive) { - byte val = Peripheral.ReadRegister(Registers.APDS9960_GCONF2); + byte val = BusComms.ReadRegister(Registers.APDS9960_GCONF2); /* Set bits in register to given value */ drive &= 0b00000011; @@ -1257,7 +1252,7 @@ void SetGestureLEDDrive(byte drive) val &= 0b11100111; val |= drive; - Peripheral.WriteRegister(Registers.APDS9960_GCONF2, val); + BusComms.WriteRegister(Registers.APDS9960_GCONF2, val); } /** @@ -1277,7 +1272,7 @@ void SetGestureLEDDrive(byte drive) */ byte GetGestureWaitTime() { - byte val = Peripheral.ReadRegister(Registers.APDS9960_GCONF2); + byte val = BusComms.ReadRegister(Registers.APDS9960_GCONF2); /* Mask out GWTIME bits */ val &= 0b00000111; @@ -1303,14 +1298,14 @@ byte GetGestureWaitTime() */ void SetGestureWaitTime(byte time) { - byte val = Peripheral.ReadRegister(Registers.APDS9960_GCONF2); + byte val = BusComms.ReadRegister(Registers.APDS9960_GCONF2); /* Set bits in register to given value */ time &= 0b00000111; val &= 0b11111000; val |= time; - Peripheral.WriteRegister(Registers.APDS9960_GCONF2, val); + BusComms.WriteRegister(Registers.APDS9960_GCONF2, val); } /** @@ -1321,11 +1316,11 @@ void SetGestureWaitTime(byte time) */ ushort GetLightIntLowThreshold() { - var threshold = Peripheral.ReadRegister(Registers.APDS9960_AILTL); + var threshold = BusComms.ReadRegister(Registers.APDS9960_AILTL); - var val_byte = Peripheral.ReadRegister(Registers.APDS9960_AILTH); + var val_byte = BusComms.ReadRegister(Registers.APDS9960_AILTH); - return (byte)(threshold + ((ushort)val_byte << 8)); + return (byte)(threshold + (val_byte << 8)); } /** @@ -1343,8 +1338,8 @@ void SetLightIntLowThreshold(ushort threshold) val_low = (byte)(threshold & 0x00FF); val_high = (byte)((threshold & 0xFF00) >> 8); - Peripheral.WriteRegister(Registers.APDS9960_AILTL, val_low); - Peripheral.WriteRegister(Registers.APDS9960_AILTL, val_high); + BusComms.WriteRegister(Registers.APDS9960_AILTL, val_low); + BusComms.WriteRegister(Registers.APDS9960_AILTL, val_high); } /** @@ -1355,11 +1350,11 @@ void SetLightIntLowThreshold(ushort threshold) */ ushort GetLightIntHighThreshold() { - var threshold = Peripheral.ReadRegister(Registers.APDS9960_AIHTL); + var threshold = BusComms.ReadRegister(Registers.APDS9960_AIHTL); - var val_byte = Peripheral.ReadRegister(Registers.APDS9960_AIHTH); + var val_byte = BusComms.ReadRegister(Registers.APDS9960_AIHTH); - return (byte)(threshold + ((ushort)val_byte << 8)); + return (byte)(threshold + (val_byte << 8)); } /** @@ -1374,8 +1369,8 @@ void SetLightIntHighThreshold(ushort threshold) byte val_low = (byte)(threshold & 0x00FF); byte val_high = (byte)((threshold & 0xFF00) >> 8); - Peripheral.WriteRegister(Registers.APDS9960_AIHTL, val_low); - Peripheral.WriteRegister(Registers.APDS9960_AIHTH, val_high); + BusComms.WriteRegister(Registers.APDS9960_AIHTL, val_low); + BusComms.WriteRegister(Registers.APDS9960_AIHTH, val_high); } /** @@ -1386,7 +1381,7 @@ void SetLightIntHighThreshold(ushort threshold) */ byte GetProximityIntLowThreshold() { - return Peripheral.ReadRegister(Registers.APDS9960_PILT); + return BusComms.ReadRegister(Registers.APDS9960_PILT); } /** @@ -1397,7 +1392,7 @@ byte GetProximityIntLowThreshold() */ void SetProximityIntLowThreshold(byte threshold) { - Peripheral.WriteRegister(Registers.APDS9960_PILT, threshold); + BusComms.WriteRegister(Registers.APDS9960_PILT, threshold); } /** @@ -1408,7 +1403,7 @@ void SetProximityIntLowThreshold(byte threshold) */ byte GetProximityIntHighThreshold() { - return Peripheral.ReadRegister(Registers.APDS9960_PIHT); + return BusComms.ReadRegister(Registers.APDS9960_PIHT); } /** @@ -1419,7 +1414,7 @@ byte GetProximityIntHighThreshold() */ void SetProximityIntHighThreshold(byte threshold) { - Peripheral.WriteRegister(Registers.APDS9960_PIHT, threshold); + BusComms.WriteRegister(Registers.APDS9960_PIHT, threshold); } /** @@ -1429,7 +1424,7 @@ void SetProximityIntHighThreshold(byte threshold) */ byte GetAmbientLightIntEnable() { - byte val = Peripheral.ReadRegister(Registers.APDS9960_ENABLE); + byte val = BusComms.ReadRegister(Registers.APDS9960_ENABLE); /* Shift and mask out AIEN bit */ val = (byte)((val >> 4) & 0b00000001); @@ -1445,7 +1440,7 @@ byte GetAmbientLightIntEnable() */ void SetAmbientLightIntEnable(bool enable) { - byte val = Peripheral.ReadRegister(Registers.APDS9960_ENABLE); + byte val = BusComms.ReadRegister(Registers.APDS9960_ENABLE); /* Set bits in register to given value */ byte data = (byte)(enable ? 0x1 : 0x0); @@ -1454,7 +1449,7 @@ void SetAmbientLightIntEnable(bool enable) val &= 0b11101111; val |= data; - Peripheral.WriteRegister(Registers.APDS9960_ENABLE, val); + BusComms.WriteRegister(Registers.APDS9960_ENABLE, val); } /** @@ -1464,7 +1459,7 @@ void SetAmbientLightIntEnable(bool enable) */ byte GetProximityIntEnable() { - byte val = Peripheral.ReadRegister(Registers.APDS9960_ENABLE); + byte val = BusComms.ReadRegister(Registers.APDS9960_ENABLE); /* Shift and mask out PIEN bit */ val = (byte)((val >> 5) & 0b00000001); @@ -1480,7 +1475,7 @@ byte GetProximityIntEnable() */ void SetProximityIntEnable(byte enable) { - byte val = Peripheral.ReadRegister(Registers.APDS9960_ENABLE); + byte val = BusComms.ReadRegister(Registers.APDS9960_ENABLE); /* Set bits in register to given value */ enable &= 0b00000001; @@ -1488,7 +1483,7 @@ void SetProximityIntEnable(byte enable) val &= 0b11011111; val |= enable; - Peripheral.WriteRegister(Registers.APDS9960_ENABLE, val); + BusComms.WriteRegister(Registers.APDS9960_ENABLE, val); } /** @@ -1498,7 +1493,7 @@ void SetProximityIntEnable(byte enable) */ byte GetGestureIntEnable() { - byte val = Peripheral.ReadRegister(Registers.APDS9960_GCONF4); + byte val = BusComms.ReadRegister(Registers.APDS9960_GCONF4); /* Shift and mask out GIEN bit */ val = (byte)((val >> 1) & 0b00000001); @@ -1514,7 +1509,7 @@ byte GetGestureIntEnable() */ void SetGestureIntEnable(byte enable) { - byte val = Peripheral.ReadRegister(Registers.APDS9960_GCONF4); + byte val = BusComms.ReadRegister(Registers.APDS9960_GCONF4); /* Set bits in register to given value */ enable &= 0b00000001; @@ -1522,7 +1517,7 @@ void SetGestureIntEnable(byte enable) val &= 0b11111101; val |= enable; - Peripheral.WriteRegister(Registers.APDS9960_GCONF4, val); + BusComms.WriteRegister(Registers.APDS9960_GCONF4, val); } /** @@ -1532,7 +1527,7 @@ void SetGestureIntEnable(byte enable) */ void ClearAmbientLightInt() { - Peripheral.WriteRegister(Registers.APDS9960_AICLEAR, 0); + BusComms.WriteRegister(Registers.APDS9960_AICLEAR, 0); } /** @@ -1542,7 +1537,7 @@ void ClearAmbientLightInt() */ void ClearProximityInt() { - Peripheral.WriteRegister(Registers.APDS9960_PICLEAR, 0); + BusComms.WriteRegister(Registers.APDS9960_PICLEAR, 0); } /** @@ -1552,7 +1547,7 @@ void ClearProximityInt() */ byte GetGestureMode() { - byte val = Peripheral.ReadRegister(Registers.APDS9960_GCONF4); + byte val = BusComms.ReadRegister(Registers.APDS9960_GCONF4); /* Mask out GMODE bit */ val &= 0b00000001; @@ -1568,14 +1563,14 @@ byte GetGestureMode() */ void SetGestureMode(byte mode) { - byte val = Peripheral.ReadRegister(Registers.APDS9960_GCONF4); + byte val = BusComms.ReadRegister(Registers.APDS9960_GCONF4); /* Set bits in register to given value */ mode &= 0b00000001; val &= 0b11111110; val |= mode; - Peripheral.WriteRegister(Registers.APDS9960_GCONF4, val); + BusComms.WriteRegister(Registers.APDS9960_GCONF4, val); } /* Container for gesture data */ diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Apds9960/Driver/Sensors.Motion.Apds9960.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Apds9960/Driver/Sensors.Motion.Apds9960.csproj index 66013fd7c5..d0752d9ff3 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Apds9960/Driver/Sensors.Motion.Apds9960.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Apds9960/Driver/Sensors.Motion.Apds9960.csproj @@ -10,7 +10,7 @@ http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ Meadow.Foundation.Sensors.Motion.Apds9960 https://github.com/WildernessLabs/Meadow.Foundation - Meadow.Foundation, Acceleration, Accelerometer, Apds9960 + Meadow.Foundation,Acceleration,Accelerometer,Apds9960 0.1.20 false APDS9960 I2C proximity, light, color and gesture sensor @@ -18,6 +18,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Apds9960/Samples/Apds9960_Sample/Apds9960_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Apds9960/Samples/Apds9960_Sample/Apds9960_Sample.csproj index 3b004462fb..98eb4777c2 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Apds9960/Samples/Apds9960_Sample/Apds9960_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Apds9960/Samples/Apds9960_Sample/Apds9960_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bmi270/Driver/Bmi270.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bmi270/Driver/Bmi270.Enums.cs index f839858181..4c137f14f6 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bmi270/Driver/Bmi270.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bmi270/Driver/Bmi270.Enums.cs @@ -18,7 +18,7 @@ public enum Addresses : byte /// /// Default bus address 0x68 /// - Address_Default = Address_0x68, + Default = Address_0x68, } /// diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bmi270/Driver/Bmi270.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bmi270/Driver/Bmi270.cs index 8f2c129d7c..6d39352869 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bmi270/Driver/Bmi270.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bmi270/Driver/Bmi270.cs @@ -11,7 +11,8 @@ namespace Meadow.Foundation.Sensors.Accelerometers /// Represents a BMI270 interial measurement unit (IMU) /// public partial class Bmi270 : - ByteCommsSensorBase<(Acceleration3D? Acceleration3D, AngularVelocity3D? AngularVelocity3D, Units.Temperature? Temperature)> + PollingSensorBase<(Acceleration3D? Acceleration3D, AngularVelocity3D? AngularVelocity3D, Units.Temperature? Temperature)>, + II2cPeripheral { /// /// Event raised when linear acceleration changes @@ -53,7 +54,15 @@ public partial class Bmi270 : /// public AngularVelocityRange CurrentAngularVelocityRange { get; private set; } - readonly II2cPeripheral i2cPeripheral; + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + + /// + /// I2C Communication bus used to communicate with the peripheral + /// + protected readonly II2cCommunications i2cComms; /// /// Create a new Bmi270 instance @@ -64,9 +73,9 @@ public Bmi270(II2cBus i2cBus, byte address = (byte)Addresses.Address_0x68) { //Read buffer: 16 (needs at least 13) //Write buffer: 256 bytes for the config data + 1 for the address - i2cPeripheral = new I2cPeripheral(i2cBus, address, 16, 256 + 1); + i2cComms = new I2cCommunications(i2cBus, address, 16, 256 + 1); - var id = i2cPeripheral.ReadRegister(CHIP_ID); + var id = i2cComms.ReadRegister(CHIP_ID); if (id != 36) { @@ -79,7 +88,7 @@ public Bmi270(II2cBus i2cBus, byte address = (byte)Addresses.Address_0x68) void Initialize() { //disable advanced power save mode - i2cPeripheral.WriteRegister(PWR_CONF, 0xB0); + i2cComms.WriteRegister(PWR_CONF, 0xB0); SetAccelerationRange(AccelerationRange._16g); @@ -87,12 +96,12 @@ void Initialize() Thread.Sleep(1); //Write INIT_CTRL 0x00 to prepare config load - i2cPeripheral.WriteRegister(INIT_CTRL, 0); + i2cComms.WriteRegister(INIT_CTRL, 0); //upload a configuration file to register INIT_DATA ushort index = 0; ushort length = 128; - byte[] dmaLocation = new byte[2]; + byte[] dmaLocation = new byte[2]; while (index < bmi270_config_file.Length) //8096 { /* Store 0 to 3 bits of address in first byte */ @@ -103,21 +112,21 @@ void Initialize() Thread.Sleep(1); //probably not needed ... data sheet wants a 2us delay - i2cPeripheral.WriteRegister(INIT_0, dmaLocation); + i2cComms.WriteRegister(INIT_0, dmaLocation); - i2cPeripheral.WriteRegister(INIT_DATA, bmi270_config_file.Skip(index).Take(length).ToArray()); + i2cComms.WriteRegister(INIT_DATA, bmi270_config_file.Skip(index).Take(length).ToArray()); index += length; } //Write INIT_CTRL 0x01 to complete config load - i2cPeripheral.WriteRegister(INIT_CTRL, 1); + i2cComms.WriteRegister(INIT_CTRL, 1); //wait until register INTERNAL_STATUS contains 0b0001 (~20 ms) while (true) { Thread.Sleep(10); - byte status = i2cPeripheral.ReadRegister(INTERNAL_STATUS); + byte status = i2cComms.ReadRegister(INTERNAL_STATUS); if (status == 0x01) { break; } } @@ -131,7 +140,7 @@ void Initialize() /// AccelerationRange public void SetAccelerationRange(AccelerationRange accelRange) { - i2cPeripheral.WriteRegister(ACC_RANGE, (byte)accelRange); + i2cComms.WriteRegister(ACC_RANGE, (byte)accelRange); CurrentAccelerationRange = accelRange; } @@ -141,7 +150,7 @@ public void SetAccelerationRange(AccelerationRange accelRange) /// AngularAccelerationRange public void SetAngularVelocityRange(AngularVelocityRange angRange) { //This register also sets the OIS range but it's not implemented so we can ignore it - i2cPeripheral.WriteRegister(GYR_RANGE, (byte)angRange); + i2cComms.WriteRegister(GYR_RANGE, (byte)angRange); } /// @@ -171,85 +180,82 @@ protected override void RaiseEventsAndNotify(IChangeResult<(Acceleration3D? Acce /// The latest sensor reading protected override Task<(Acceleration3D? Acceleration3D, AngularVelocity3D? AngularVelocity3D, Units.Temperature? Temperature)> ReadSensor() { - return Task.Run(() => + (Acceleration3D? Acceleration3D, AngularVelocity3D? AngularVelocity3D, Units.Temperature? Temperature) conditions; + + //12 bytes - includes accel and gyro + var data = ReadAccelerationData(); + + //likely +/- 2g by default + var accelX = (short)(data[1] << 8 | data[0]); + var accelY = (short)(data[3] << 8 | data[2]); + var accelZ = (short)(data[5] << 8 | data[4]); + + double divisor = CurrentAccelerationRange switch + { + AccelerationRange._2g => 16384, + AccelerationRange._4g => 8192, + AccelerationRange._8g => 4096, + AccelerationRange._16g => 2048, + _ => throw new ArgumentException("CurrentAccelerationRange is out of range") + }; + + var gX = accelX / divisor; + var gY = accelY / divisor; + var gZ = accelZ / divisor; + + divisor = CurrentAngularVelocityRange switch { - (Acceleration3D? Acceleration3D, AngularVelocity3D? AngularVelocity3D, Units.Temperature? Temperature) conditions; - - //12 bytes - includes accel and gyro - var data = ReadAccelerationData(); - - //likely +/- 2g by default - var accelX = (short)(data[1] << 8 | data[0]); - var accelY = (short)(data[3] << 8 | data[2]); - var accelZ = (short)(data[5] << 8 | data[4]); - - double divisor = CurrentAccelerationRange switch - { - AccelerationRange._2g => 16384, - AccelerationRange._4g => 8192, - AccelerationRange._8g => 4096, - AccelerationRange._16g => 2048, - _ => throw new ArgumentException("CurrentAccelerationRange is out of range") - }; - - var gX = accelX / divisor; - var gY = accelY / divisor; - var gZ = accelZ / divisor; - - divisor = CurrentAngularVelocityRange switch - { - AngularVelocityRange._2000dps => 16.4, - AngularVelocityRange._1000dps => 32.8, - AngularVelocityRange._500dps => 65.5, - AngularVelocityRange._250dps => 131, - AngularVelocityRange._125dps => 262, - - _ => throw new ArgumentException("CurrentAngularAccelerationRange is out of range") - }; - - var gyroX = (short)(data[7] << 8 | data[6]); - var gyroY = (short)(data[9] << 8 | data[8]); - var gyroZ = (short)(data[11] << 8 | data[10]); - - var dpsX = gyroX / divisor; - var dpsY = gyroY / divisor; - var dpsZ = gyroZ / divisor; - - conditions.Acceleration3D = new Acceleration3D( - new Acceleration(gX, Acceleration.UnitType.Gravity), - new Acceleration(gY, Acceleration.UnitType.Gravity), - new Acceleration(gZ, Acceleration.UnitType.Gravity)); - - conditions.AngularVelocity3D = new AngularVelocity3D( - new AngularVelocity(dpsX, AngularVelocity.UnitType.DegreesPerSecond), - new AngularVelocity(dpsY, AngularVelocity.UnitType.DegreesPerSecond), - new AngularVelocity(dpsZ, AngularVelocity.UnitType.DegreesPerSecond)); - - //Get the temperature - ushort tempRaw = (ushort)(i2cPeripheral.ReadRegister(TEMPERATURE_1) << 8 | i2cPeripheral.ReadRegister(TEMPERATURE_0)); - double tempC; - - double degreePerByte = 0.001953125; //in celcius - - if (tempRaw < 0x8000) - { - tempC = 23 + tempRaw * degreePerByte; - } - else - { - tempC = -41 + (tempRaw - 0x8000) * degreePerByte; - } - - if(tempRaw == 0x8000) - { //means we have an invalid temperature reading - conditions.Temperature = null; - } - else - { - conditions.Temperature = new Units.Temperature(tempC, Units.Temperature.UnitType.Celsius); - } - return conditions; - }); + AngularVelocityRange._2000dps => 16.4, + AngularVelocityRange._1000dps => 32.8, + AngularVelocityRange._500dps => 65.5, + AngularVelocityRange._250dps => 131, + AngularVelocityRange._125dps => 262, + + _ => throw new ArgumentException("CurrentAngularAccelerationRange is out of range") + }; + + var gyroX = (short)(data[7] << 8 | data[6]); + var gyroY = (short)(data[9] << 8 | data[8]); + var gyroZ = (short)(data[11] << 8 | data[10]); + + var dpsX = gyroX / divisor; + var dpsY = gyroY / divisor; + var dpsZ = gyroZ / divisor; + + conditions.Acceleration3D = new Acceleration3D( + new Acceleration(gX, Acceleration.UnitType.Gravity), + new Acceleration(gY, Acceleration.UnitType.Gravity), + new Acceleration(gZ, Acceleration.UnitType.Gravity)); + + conditions.AngularVelocity3D = new AngularVelocity3D( + new AngularVelocity(dpsX, AngularVelocity.UnitType.DegreesPerSecond), + new AngularVelocity(dpsY, AngularVelocity.UnitType.DegreesPerSecond), + new AngularVelocity(dpsZ, AngularVelocity.UnitType.DegreesPerSecond)); + + //Get the temperature + ushort tempRaw = (ushort)(i2cComms.ReadRegister(TEMPERATURE_1) << 8 | i2cComms.ReadRegister(TEMPERATURE_0)); + double tempC; + + double degreePerByte = 0.001953125; //in celcius + + if (tempRaw < 0x8000) + { + tempC = 23 + tempRaw * degreePerByte; + } + else + { + tempC = -41 + (tempRaw - 0x8000) * degreePerByte; + } + + if (tempRaw == 0x8000) + { //means we have an invalid temperature reading + conditions.Temperature = null; + } + else + { + conditions.Temperature = new Units.Temperature(tempC, Units.Temperature.UnitType.Celsius); + } + return Task.FromResult(conditions); } /// @@ -258,33 +264,33 @@ protected override void RaiseEventsAndNotify(IChangeResult<(Acceleration3D? Acce /// The power mode public void SetPowerMode(PowerMode powerMode) { - switch(powerMode) + switch (powerMode) { case PowerMode.Suspend: - i2cPeripheral.WriteRegister(PWR_CTRL, 0x00); - i2cPeripheral.WriteRegister(PWR_CONF, 0x00); + i2cComms.WriteRegister(PWR_CTRL, 0x00); + i2cComms.WriteRegister(PWR_CONF, 0x00); break; case PowerMode.Configuration: - i2cPeripheral.WriteRegister(PWR_CTRL, 0x00); - i2cPeripheral.WriteRegister(PWR_CONF, 0x00); + i2cComms.WriteRegister(PWR_CTRL, 0x00); + i2cComms.WriteRegister(PWR_CONF, 0x00); break; case PowerMode.LowPower: - i2cPeripheral.WriteRegister(PWR_CTRL, 0x04); - i2cPeripheral.WriteRegister(ACC_CONF, 0x17); - i2cPeripheral.WriteRegister(GYR_CONF, 0xA9); - i2cPeripheral.WriteRegister(PWR_CONF, 0x03); + i2cComms.WriteRegister(PWR_CTRL, 0x04); + i2cComms.WriteRegister(ACC_CONF, 0x17); + i2cComms.WriteRegister(GYR_CONF, 0xA9); + i2cComms.WriteRegister(PWR_CONF, 0x03); break; case PowerMode.Normal: - i2cPeripheral.WriteRegister(PWR_CTRL, 0x0E); - i2cPeripheral.WriteRegister(ACC_CONF, 0xA8); - i2cPeripheral.WriteRegister(GYR_CONF, 0xA9); - i2cPeripheral.WriteRegister(PWR_CONF, 0x02); + i2cComms.WriteRegister(PWR_CTRL, 0x0E); + i2cComms.WriteRegister(ACC_CONF, 0xA8); + i2cComms.WriteRegister(GYR_CONF, 0xA9); + i2cComms.WriteRegister(PWR_CONF, 0x02); break; case PowerMode.Performance: - i2cPeripheral.WriteRegister(PWR_CTRL, 0x0E); - i2cPeripheral.WriteRegister(ACC_CONF, 0xA8); - i2cPeripheral.WriteRegister(GYR_CONF, 0xE9); - i2cPeripheral.WriteRegister(PWR_CONF, 0x02); + i2cComms.WriteRegister(PWR_CTRL, 0x0E); + i2cComms.WriteRegister(ACC_CONF, 0xA8); + i2cComms.WriteRegister(GYR_CONF, 0xE9); + i2cComms.WriteRegister(PWR_CONF, 0x02); break; } } @@ -292,7 +298,7 @@ public void SetPowerMode(PowerMode powerMode) byte[] ReadAccelerationData() { var readBuffer = new byte[12]; - i2cPeripheral.ReadRegister(0x0C, readBuffer); + i2cComms.ReadRegister(0x0C, readBuffer); return readBuffer; } } diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bmi270/Driver/Sensors.Motion.Bmi270.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bmi270/Driver/Sensors.Motion.Bmi270.csproj index 11ee9c7dac..8455ab7d79 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bmi270/Driver/Sensors.Motion.Bmi270.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bmi270/Driver/Sensors.Motion.Bmi270.csproj @@ -18,6 +18,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bmi270/Samples/Bmi270_Sample/Bmi270_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bmi270/Samples/Bmi270_Sample/Bmi270_Sample.csproj index 5ca84cf1a5..eac0b078c1 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bmi270/Samples/Bmi270_Sample/Bmi270_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bmi270/Samples/Bmi270_Sample/Bmi270_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bmi270/Samples/Bmi270_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bmi270/Samples/Bmi270_Sample/MeadowApp.cs index 7f29e7b56b..d25e3f4b69 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bmi270/Samples/Bmi270_Sample/MeadowApp.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bmi270/Samples/Bmi270_Sample/MeadowApp.cs @@ -8,7 +8,7 @@ namespace MeadowApp { // Change F7FeatherV2 to F7FeatherV1 for V1.x boards - public class MeadowApp : App + public class MeadowApp : App { // diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bno055/Driver/Bno055.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bno055/Driver/Bno055.Enums.cs index d695ebd9bd..82c7be7fd1 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bno055/Driver/Bno055.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bno055/Driver/Bno055.Enums.cs @@ -3,7 +3,7 @@ public partial class Bno055 { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { @@ -32,7 +32,7 @@ public enum ErrorCodes : byte NoError = 0x00, /// - /// Peripheral initialization error. + /// BusComms initialization error. /// PeripheralInitializationError = 0x01, @@ -93,7 +93,7 @@ public enum SystemStatusCodes : byte SystemError = 0x01, /// - /// Peripheral initialization in progess. + /// BusComms initialization in progess. /// PeripheralInitializationInProgess = 0x02, diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bno055/Driver/Bno055.Registers.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bno055/Driver/Bno055.Registers.cs index 25f52154fb..76736732e6 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bno055/Driver/Bno055.Registers.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bno055/Driver/Bno055.Registers.cs @@ -532,7 +532,7 @@ private static class Registers /// /// Indicates the type of error (if any) that has occurred. /// 0: No error - /// 1: Peripheral initialization error + /// 1: BusComms initialization error /// 2: System initialization error /// 3: Self test failed /// 4: Register map value out of range diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bno055/Driver/Bno055.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bno055/Driver/Bno055.cs index 60eb5da0ea..dace41b79d 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bno055/Driver/Bno055.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bno055/Driver/Bno055.cs @@ -10,27 +10,6 @@ namespace Meadow.Foundation.Sensors.Motion { - // Sample Reading: - // Accel: [X:0.00,Y:-1.15,Z:10.09 (m/s^2)] - // Gyro: [X:0.00,Y:-0.06,Z:0.06 (degrees/s)] - // Compass: [X:19.38,Y:-36.75,Z:-118.25 (Tesla)] - // Gravity: [X:0.00, Y:-1.12, Z:9.74 (meters/s^2)] - // Quaternion orientation: [X:-0.06, Y:0.00, Z:0.00] - // Euler orientation: [heading: 0.00, Roll: 0.00, Pitch: 0.12] - // Linear Accel: [X:0.00, Y:-0.03, Z:0.35 (meters/s^2)] - // Temp: 33.00C - - //TODO: the sensor works great as is right now, but there's some room for - // improvement. Currently, we basically turn it on full bore and get all - // the readings. - // However, there's an opportunity here to allow users to selectively turn - // on the various features, and then in the `ReadSensor()` method we can - // check before we do the reading to see what the user has turned on. - // if the feature is turned on, we can read and parse the registers and then - // set the `Conditions.[X] = reading`, otherwise set them to `null`, since - // all the conditions are nullable. this would provide folks with an - // opportunity to use the sensor in a low or lower-power configuration. - /// /// Provide methods / properties to allow an application to control a BNO055 /// 9-axis absolute orientation sensor. @@ -48,8 +27,13 @@ public partial class Bno055 : ByteCommsSensorBase<( MagneticField3D? MagneticField3D, Quaternion? QuaternionOrientation, Acceleration3D? LinearAcceleration, Acceleration3D? GravityVector, EulerAngles? EulerOrientation, Units.Temperature? Temperature)>, - IAccelerometer, IGyroscope, ITemperatureSensor + IAccelerometer, IGyroscope, ITemperatureSensor, II2cPeripheral { + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + /// /// Raised when the acceleration value changes /// @@ -137,13 +121,13 @@ public Sensor TemperatureSource { get { - return (Sensor)Peripheral.ReadRegister(Registers.TemperatureSource); + return (Sensor)BusComms.ReadRegister(Registers.TemperatureSource); } set { if ((value == Sensor.Accelerometer) || (value == Sensor.Gyroscope)) { - Peripheral.WriteRegister(Registers.TemperatureSource, (byte)value); + BusComms.WriteRegister(Registers.TemperatureSource, (byte)value); } else { @@ -157,10 +141,10 @@ public Sensor TemperatureSource /// public byte PowerMode { - get => Peripheral.ReadRegister(Registers.PowerMode); + get => BusComms.ReadRegister(Registers.PowerMode); set { - Peripheral.WriteRegister(Registers.PowerMode, value); + BusComms.WriteRegister(Registers.PowerMode, value); Thread.Sleep(15); } } @@ -173,14 +157,14 @@ public byte PowerMode /// public byte OperatingMode { - get => Peripheral.ReadRegister(Registers.OperatingMode); + get => BusComms.ReadRegister(Registers.OperatingMode); set { if (value > OperatingModes.MAXIMUM_VALUE) { throw new ArgumentOutOfRangeException(); } - Peripheral.WriteRegister(Registers.OperatingMode, value); + BusComms.WriteRegister(Registers.OperatingMode, value); Thread.Sleep(20); } } @@ -197,14 +181,14 @@ public byte OperatingMode /// private byte Page { - get => Peripheral.ReadRegister(Registers.PageID); + get => BusComms.ReadRegister(Registers.PageID); set { if ((value != 0) && (value != 1)) { throw new ArgumentOutOfRangeException(); } - Peripheral.WriteRegister(Registers.PageID, value); + BusComms.WriteRegister(Registers.PageID, value); } } @@ -220,22 +204,22 @@ private byte Page /// /// Get the system calibration status. /// - public bool IsSystemCalibrated => ((Peripheral.ReadRegister(Registers.CalibrationStatus) >> 6) & 0x03) != 0; + public bool IsSystemCalibrated => ((BusComms.ReadRegister(Registers.CalibrationStatus) >> 6) & 0x03) != 0; /// /// Get the accelerometer calibration status. /// - public bool IsAccelerometerCalibrated => ((Peripheral.ReadRegister(Registers.CalibrationStatus) >> 2) & 0x03) != 0; + public bool IsAccelerometerCalibrated => ((BusComms.ReadRegister(Registers.CalibrationStatus) >> 2) & 0x03) != 0; /// /// Get the gyroscope calibration status. /// - public bool IsGyroscopeCalibrated => ((Peripheral.ReadRegister(Registers.CalibrationStatus) >> 4) & 0x03) != 0; + public bool IsGyroscopeCalibrated => ((BusComms.ReadRegister(Registers.CalibrationStatus) >> 4) & 0x03) != 0; /// /// Get the magnetometer status. /// - public bool IsMagnetometerCalibrated => (Peripheral.ReadRegister(Registers.CalibrationStatus) & 0x03) != 0; + public bool IsMagnetometerCalibrated => (BusComms.ReadRegister(Registers.CalibrationStatus) & 0x03) != 0; /// /// Is the system fully calibrated? @@ -265,7 +249,7 @@ public Bno055(II2cBus i2cBus, Addresses address = Addresses.Default) public Bno055(II2cBus i2cBus, byte address) : base(i2cBus, address, readBufferSize: 256) { - var id = Peripheral.ReadRegister(Registers.ChipID); + var id = BusComms.ReadRegister(Registers.ChipID); if (id != 0xa0) { @@ -303,78 +287,75 @@ protected override Task< Acceleration3D? LinearAcceleration, Acceleration3D? GravityVector, EulerAngles? EulerOrientation, Units.Temperature? Temperature)> ReadSensor() { - return Task.Run(() => + if (PowerMode != PowerModes.NORMAL) { - if (PowerMode != PowerModes.NORMAL) - { - PowerMode = PowerModes.NORMAL; - } + PowerMode = PowerModes.NORMAL; + } - if (OperatingMode != OperatingModes.NINE_DEGREES_OF_FREEDOM) - { - OperatingMode = OperatingModes.NINE_DEGREES_OF_FREEDOM; - } + if (OperatingMode != OperatingModes.NINE_DEGREES_OF_FREEDOM) + { + OperatingMode = OperatingModes.NINE_DEGREES_OF_FREEDOM; + } - // The amazing Octple! - (Acceleration3D? Acceleration3D, AngularVelocity3D? AngularVelocity3D, - MagneticField3D? MagneticField3D, Quaternion? QuaternionOrientation, - Acceleration3D? LinearAcceleration, Acceleration3D? GravityVector, - EulerAngles? EulerOrientation, Units.Temperature? Temperature) conditions; - - // make all the readings - // This method reads ony the sensor motion / orientation registers. When - // accessing the data from a register it is necessary to subtract the - // access of the start of the sensor registers from the register required - // in order to get the correct offset into the _sensorReadings array. - - int length = Registers.GravityVectorZMSB + 1 - Registers.AccelerometerXLSB; - Peripheral.ReadRegister(Registers.AccelerometerXLSB, ReadBuffer.Span[0..length]); - - // for debugging, you can look at the raw data: - //DebugInformation.DisplayRegisters(0x00, ReadBuffer.Span[0..length].ToArray()); - - //---- Acceleration3D - double accelDivisor = 100.0; //m/s2 - var accelData = GetReadings(Registers.AccelerometerXLSB - Registers.StartOfSensorData, accelDivisor); - conditions.Acceleration3D = new Acceleration3D(accelData.X, accelData.Y, accelData.Z, Acceleration.UnitType.MetersPerSecondSquared); - - //---- AngularAcceleration3D - double angularDivisor = 900.0; //radians - var angularData = GetReadings(Registers.GyroscopeXLSB - Registers.StartOfSensorData, angularDivisor); - conditions.AngularVelocity3D = new AngularVelocity3D(angularData.X, angularData.Y, angularData.Z, AngularVelocity.UnitType.RadiansPerSecond); - - //---- MagneticField3D - var magnetometerData = GetReadings(Registers.MagnetometerXLSB - Registers.StartOfSensorData, 16.0); - conditions.MagneticField3D = new MagneticField3D(magnetometerData.X, magnetometerData.Y, magnetometerData.Z, MagneticField.UnitType.Tesla); - - //---- Quarternion Orientation - int quaternionData = Registers.QuaternionDataWLSB - Registers.StartOfSensorData; - short w = (short)((ReadBuffer.Span[quaternionData + 1] << 8) | ReadBuffer.Span[quaternionData]); - short x = (short)((ReadBuffer.Span[quaternionData + 3] << 8) | ReadBuffer.Span[quaternionData + 2]); - short y = (short)((ReadBuffer.Span[quaternionData + 5] << 8) | ReadBuffer.Span[quaternionData + 4]); - short z = (short)((ReadBuffer.Span[quaternionData + 5] << 8) | ReadBuffer.Span[quaternionData + 4]); - double factor = 1.0 / (1 << 14); - conditions.QuaternionOrientation = new Quaternion(w * factor, x * factor, y * factor, z * factor); - - //---- Linear Acceleration - double linearAccellDivisor = 100.0; //m/s2 - var linearAccelData = GetReadings(Registers.LinearAccelerationXLSB - Registers.StartOfSensorData, linearAccellDivisor); - conditions.LinearAcceleration = new Acceleration3D(linearAccelData.X, linearAccelData.Y, linearAccelData.Z, Acceleration.UnitType.MetersPerSecondSquared); - - //---- Gravity Vector - double gravityVectorDivisor = 100.0; //m/s2 - var gravityVectorData = GetReadings(Registers.GravityVectorXLSB - Registers.StartOfSensorData, gravityVectorDivisor); - conditions.GravityVector = new Acceleration3D(gravityVectorData.X, gravityVectorData.Y, gravityVectorData.Z, Acceleration.UnitType.MetersPerSecondSquared); - - //---- euler - double eulerDivisor = 900.0; //radians - conditions.EulerOrientation = ConvertReadingToEulerAngles(Registers.EulerAngleXLSB - Registers.StartOfSensorData, eulerDivisor); - - //---- temperature - conditions.Temperature = new Units.Temperature(Peripheral.ReadRegister(Registers.Temperature), Units.Temperature.UnitType.Celsius); - - return conditions; - }); + // The amazing Octple! + (Acceleration3D? Acceleration3D, AngularVelocity3D? AngularVelocity3D, + MagneticField3D? MagneticField3D, Quaternion? QuaternionOrientation, + Acceleration3D? LinearAcceleration, Acceleration3D? GravityVector, + EulerAngles? EulerOrientation, Units.Temperature? Temperature) conditions; + + // make all the readings + // This method reads ony the sensor motion / orientation registers. When + // accessing the data from a register it is necessary to subtract the + // access of the start of the sensor registers from the register required + // in order to get the correct offset into the _sensorReadings array. + + int length = Registers.GravityVectorZMSB + 1 - Registers.AccelerometerXLSB; + BusComms.ReadRegister(Registers.AccelerometerXLSB, ReadBuffer.Span[0..length]); + + // for debugging, you can look at the raw data: + //DebugInformation.DisplayRegisters(0x00, ReadBuffer.Span[0..length].ToArray()); + + //---- Acceleration3D + double accelDivisor = 100.0; //m/s2 + var accelData = GetReadings(Registers.AccelerometerXLSB - Registers.StartOfSensorData, accelDivisor); + conditions.Acceleration3D = new Acceleration3D(accelData.X, accelData.Y, accelData.Z, Acceleration.UnitType.MetersPerSecondSquared); + + //---- AngularAcceleration3D + double angularDivisor = 900.0; //radians + var angularData = GetReadings(Registers.GyroscopeXLSB - Registers.StartOfSensorData, angularDivisor); + conditions.AngularVelocity3D = new AngularVelocity3D(angularData.X, angularData.Y, angularData.Z, AngularVelocity.UnitType.RadiansPerSecond); + + //---- MagneticField3D + var magnetometerData = GetReadings(Registers.MagnetometerXLSB - Registers.StartOfSensorData, 16.0); + conditions.MagneticField3D = new MagneticField3D(magnetometerData.X, magnetometerData.Y, magnetometerData.Z, MagneticField.UnitType.Tesla); + + //---- Quarternion Orientation + int quaternionData = Registers.QuaternionDataWLSB - Registers.StartOfSensorData; + short w = (short)((ReadBuffer.Span[quaternionData + 1] << 8) | ReadBuffer.Span[quaternionData]); + short x = (short)((ReadBuffer.Span[quaternionData + 3] << 8) | ReadBuffer.Span[quaternionData + 2]); + short y = (short)((ReadBuffer.Span[quaternionData + 5] << 8) | ReadBuffer.Span[quaternionData + 4]); + short z = (short)((ReadBuffer.Span[quaternionData + 5] << 8) | ReadBuffer.Span[quaternionData + 4]); + double factor = 1.0 / (1 << 14); + conditions.QuaternionOrientation = new Quaternion(w * factor, x * factor, y * factor, z * factor); + + //---- Linear Acceleration + double linearAccellDivisor = 100.0; //m/s2 + var linearAccelData = GetReadings(Registers.LinearAccelerationXLSB - Registers.StartOfSensorData, linearAccellDivisor); + conditions.LinearAcceleration = new Acceleration3D(linearAccelData.X, linearAccelData.Y, linearAccelData.Z, Acceleration.UnitType.MetersPerSecondSquared); + + //---- Gravity Vector + double gravityVectorDivisor = 100.0; //m/s2 + var gravityVectorData = GetReadings(Registers.GravityVectorXLSB - Registers.StartOfSensorData, gravityVectorDivisor); + conditions.GravityVector = new Acceleration3D(gravityVectorData.X, gravityVectorData.Y, gravityVectorData.Z, Acceleration.UnitType.MetersPerSecondSquared); + + //---- euler + double eulerDivisor = 900.0; //radians + conditions.EulerOrientation = ConvertReadingToEulerAngles(Registers.EulerAngleXLSB - Registers.StartOfSensorData, eulerDivisor); + + //---- temperature + conditions.Temperature = new Units.Temperature(BusComms.ReadRegister(Registers.Temperature), Units.Temperature.UnitType.Celsius); + + return Task.FromResult(conditions); } /// @@ -460,7 +441,7 @@ public void DisplayRegisters() int length = 0x6A; byte[] buffer = new byte[length]; - Peripheral.ReadRegister(Registers.ChipID, buffer); + BusComms.ReadRegister(Registers.ChipID, buffer); DebugInformation.DisplayRegisters(0x00, buffer); Resolver.Log.Info("== /REGISTERS ======================================================================="); diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bno055/Driver/Sensors.Motion.Bno055.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bno055/Driver/Sensors.Motion.Bno055.csproj index a84b7c0795..c87e32a6be 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bno055/Driver/Sensors.Motion.Bno055.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bno055/Driver/Sensors.Motion.Bno055.csproj @@ -18,6 +18,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bno055/Samples/Bno055_Sample/Bno055_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bno055/Samples/Bno055_Sample/Bno055_Sample.csproj index 9fa1e3e1a8..118ffe67c3 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bno055/Samples/Bno055_Sample/Bno055_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Bno055/Samples/Bno055_Sample/Bno055_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hcsens0040/Driver/Hcsens0040.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hcsens0040/Driver/Hcsens0040.cs index 60c9f138b2..9c60dcc21b 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hcsens0040/Driver/Hcsens0040.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hcsens0040/Driver/Hcsens0040.cs @@ -4,27 +4,27 @@ namespace Meadow.Foundation.Sensors.Motion { /// - /// Create a new Hscens0040 object. + /// Create a new Hscens0040 object /// public class Hcsens0040 { /// /// Digital input port /// - private readonly IDigitalInputPort _digitalInputPort; + private readonly IDigitalInputPort digitalInputPort; /// - /// Delgate for the motion start and end events. + /// Delgate for the motion start and end events /// public delegate void MotionChange(object sender); /// - /// Event raised when motion is detected. + /// Event raised when motion is detected /// public event MotionChange OnMotionDetected; /// - /// Create a new Parallax PIR object connected to an input pin and IO Device. + /// Create a new Parallax PIR object connected to an input pin and IO Device /// /// The input pin public Hcsens0040(IPin inputPin) : @@ -32,15 +32,15 @@ public Hcsens0040(IPin inputPin) : { } /// - /// Create a new Parallax PIR object connected to a interrupt port. + /// Create a new Parallax PIR object connected to a interrupt port /// /// public Hcsens0040(IDigitalInputPort digitalInputPort) { if (digitalInputPort != null) { - _digitalInputPort = digitalInputPort; - _digitalInputPort.Changed += DigitalInputPortChanged; + this.digitalInputPort = digitalInputPort; + this.digitalInputPort.Changed += DigitalInputPortChanged; } else { @@ -49,11 +49,11 @@ public Hcsens0040(IDigitalInputPort digitalInputPort) } /// - /// Catch the PIR motion change interrupts and work out which interrupt should be raised. + /// Catch the PIR motion change interrupts and work out which interrupt should be raised /// private void DigitalInputPortChanged(object sender, DigitalPortResult e) { - if (_digitalInputPort.State == true) + if (digitalInputPort.State == true) { OnMotionDetected?.Invoke(this); } diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hcsens0040/Driver/Sensors.Motion.Hcsens0040.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hcsens0040/Driver/Sensors.Motion.Hcsens0040.csproj index 1d6d481672..96873bbe2a 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hcsens0040/Driver/Sensors.Motion.Hcsens0040.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hcsens0040/Driver/Sensors.Motion.Hcsens0040.csproj @@ -10,13 +10,13 @@ http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ Meadow.Foundation.Sensors.Motion.Hcsens0040 https://github.com/WildernessLabs/Meadow.Foundation - Meadow, Meadow.Foundation, Motion, HCSENS0040, RCWL-0516 + Meadow,Meadow.Foundation,Motion,microwave,HCSENS0040,RCWL-0516 0.1.52 true HCSENS0040 digital microwave motion sensor - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hcsens0040/Samples/Hcsens0040_Sample/Hcsens0040_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hcsens0040/Samples/Hcsens0040_Sample/Hcsens0040_Sample.csproj index e450603049..5dd325d050 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hcsens0040/Samples/Hcsens0040_Sample/Hcsens0040_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hcsens0040/Samples/Hcsens0040_Sample/Hcsens0040_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hmc5883/Driver/Hmc5883.Addresses.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hmc5883/Driver/Hmc5883.Addresses.cs index f17556a4bf..629dd6c7b1 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hmc5883/Driver/Hmc5883.Addresses.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hmc5883/Driver/Hmc5883.Addresses.cs @@ -3,7 +3,7 @@ public partial class Hmc5883 { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hmc5883/Driver/Hmc5883.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hmc5883/Driver/Hmc5883.cs index 00a064790a..aa48362b74 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hmc5883/Driver/Hmc5883.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hmc5883/Driver/Hmc5883.cs @@ -7,12 +7,17 @@ namespace Meadow.Foundation.Sensors.Motion { /// - /// Driver for the Hmc5883 digital compass. + /// Driver for the Hmc5883 digital compass /// /// This driver is untested /// - public partial class Hmc5883 : ByteCommsSensorBase + public partial class Hmc5883 : ByteCommsSensorBase, II2cPeripheral { + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + /// /// Event to be raised when the compass changes /// @@ -47,21 +52,20 @@ public partial class Hmc5883 : ByteCommsSensorBase /// Gain /// Measuring mode /// Output rate - /// Samples amount + /// Sample amount /// Measurement configuration public Hmc5883(II2cBus i2cBus, byte address = (byte)Addresses.Default, GainLevels gain = GainLevels.Gain1090, MeasuringModes measuringMode = MeasuringModes.Continuous, DataOutputRates outputRate = DataOutputRates.Rate15, - SampleAmounts samplesAmount = SampleAmounts.One, + SampleAmounts sampleAmount = SampleAmounts.One, MeasurementConfigurations measurementConfig = MeasurementConfigurations.Normal) : base(i2cBus, address) { - this.gain = (byte)gain; this.measuringMode = (byte)measuringMode; this.outputRate = (byte)outputRate; - this.sampleAmount = (byte)samplesAmount; + this.sampleAmount = (byte)sampleAmount; this.measurementConfig = (byte)measurementConfig; Initialize(); @@ -75,9 +79,9 @@ protected virtual void Initialize() byte configA = (byte)(sampleAmount | (outputRate << 2) | measurementConfig); byte configB = (byte)(gain << 5); - Peripheral.WriteRegister(Registers.HMC_CONFIG_REG_A_ADDR, configA); - Peripheral.WriteRegister(Registers.HMC_CONFIG_REG_B_ADDR, configB); - Peripheral.WriteRegister(Registers.HMC_MODE_REG_ADDR, measuringMode); + BusComms.WriteRegister(Registers.HMC_CONFIG_REG_A_ADDR, configA); + BusComms.WriteRegister(Registers.HMC_CONFIG_REG_B_ADDR, configB); + BusComms.WriteRegister(Registers.HMC_MODE_REG_ADDR, measuringMode); } /// @@ -86,7 +90,7 @@ protected virtual void Initialize() /// The updated sensor data protected override void RaiseEventsAndNotify(IChangeResult changeResult) { - this.DirectionUpdated?.Invoke(this, changeResult); + DirectionUpdated?.Invoke(this, changeResult); base.RaiseEventsAndNotify(changeResult); } @@ -96,13 +100,10 @@ protected override void RaiseEventsAndNotify(IChangeResult changeResult) /// The latest sensor reading protected override Task ReadSensor() { - return Task.Run(() => - { - ushort x = Peripheral.ReadRegisterAsUShort(Registers.HMC_X_MSB_REG_ADDR, ByteOrder.BigEndian); - ushort y = Peripheral.ReadRegisterAsUShort(Registers.HMC_Y_MSB_REG_ADDR, ByteOrder.BigEndian); - ushort z = Peripheral.ReadRegisterAsUShort(Registers.HMC_Z_MSB_REG_ADDR, ByteOrder.BigEndian); - return new Vector(x, y, z); - }); + ushort x = BusComms.ReadRegisterAsUShort(Registers.HMC_X_MSB_REG_ADDR, ByteOrder.BigEndian); + ushort y = BusComms.ReadRegisterAsUShort(Registers.HMC_Y_MSB_REG_ADDR, ByteOrder.BigEndian); + ushort z = BusComms.ReadRegisterAsUShort(Registers.HMC_Z_MSB_REG_ADDR, ByteOrder.BigEndian); + return Task.FromResult(new Vector(x, y, z)); } /// @@ -127,8 +128,8 @@ public static Azimuth DirectionToHeading(Vector direction) /// private Statuses GetStatus() { - Peripheral.Write(Registers.HMC_STATUS_REG_ADDR); - Peripheral.Read(ReadBuffer.Span[0..1]); + BusComms.Write(Registers.HMC_STATUS_REG_ADDR); + BusComms.Read(ReadBuffer.Span[0..1]); return (Statuses)ReadBuffer.Span[0]; } } diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hmc5883/Driver/Qmc5883.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hmc5883/Driver/Qmc5883.cs index 58e23a7ed9..38414c3217 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hmc5883/Driver/Qmc5883.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hmc5883/Driver/Qmc5883.cs @@ -1,8 +1,7 @@ -using System; +using Meadow.Foundation.Spatial; +using Meadow.Hardware; using System.Threading; using System.Threading.Tasks; -using Meadow.Foundation.Spatial; -using Meadow.Hardware; namespace Meadow.Foundation.Sensors.Motion { @@ -37,16 +36,16 @@ public Qmc5883(II2cBus i2cBus, byte address = (byte)Addresses.Qmc5883, /// override protected void Initialize() { - Peripheral.WriteRegister(0x0B, 0x01); + BusComms.WriteRegister(0x0B, 0x01); Thread.Sleep(50); - Peripheral.WriteRegister(0x20, 0x40); + BusComms.WriteRegister(0x20, 0x40); Thread.Sleep(50); - Peripheral.WriteRegister(0x21, 0x01); + BusComms.WriteRegister(0x21, 0x01); Thread.Sleep(50); - Peripheral.WriteRegister(0x09, 0x0D); + BusComms.WriteRegister(0x09, 0x0D); } /// @@ -55,19 +54,17 @@ override protected void Initialize() /// The latest sensor reading protected override Task ReadSensor() { - return Task.Run(() => { - Peripheral.ReadRegister(0x00, ReadBuffer.Span[0..6]); + BusComms.ReadRegister(0x00, ReadBuffer.Span[0..6]); - ushort X = (ushort)(ReadBuffer.Span[0] | ReadBuffer.Span[1] << 8); - ushort Y = (ushort)(ReadBuffer.Span[2] | ReadBuffer.Span[3] << 8); - ushort Z = (ushort)(ReadBuffer.Span[4] | ReadBuffer.Span[5] << 8); + ushort X = (ushort)(ReadBuffer.Span[0] | ReadBuffer.Span[1] << 8); + ushort Y = (ushort)(ReadBuffer.Span[2] | ReadBuffer.Span[3] << 8); + ushort Z = (ushort)(ReadBuffer.Span[4] | ReadBuffer.Span[5] << 8); - var v = new Vector(X, Y, Z); + var v = new Vector(X, Y, Z); - Resolver.Log.Info($"{X}, {Y}, {Z} : {DirectionToHeading(v)}"); + Resolver.Log.Info($"{X}, {Y}, {Z} : {DirectionToHeading(v)}"); - return v; - }); + return Task.FromResult(v); } } } \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hmc5883/Driver/Sensors.Motion.Hmc5883.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hmc5883/Driver/Sensors.Motion.Hmc5883.csproj index d3434de0e9..d6495bb2f6 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hmc5883/Driver/Sensors.Motion.Hmc5883.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hmc5883/Driver/Sensors.Motion.Hmc5883.csproj @@ -18,6 +18,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hmc5883/Samples/Hmc5883_Sample/Hmc5883_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hmc5883/Samples/Hmc5883_Sample/Hmc5883_Sample.csproj index 9ab89f1ada..79bcba9366 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hmc5883/Samples/Hmc5883_Sample/Hmc5883_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hmc5883/Samples/Hmc5883_Sample/Hmc5883_Sample.csproj @@ -12,7 +12,7 @@ 9.0 - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hmc5883/Samples/Qmc5883_Sample/Qmc5883_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hmc5883/Samples/Qmc5883_Sample/Qmc5883_Sample.csproj index 9ab89f1ada..79bcba9366 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hmc5883/Samples/Qmc5883_Sample/Qmc5883_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Hmc5883/Samples/Qmc5883_Sample/Qmc5883_Sample.csproj @@ -12,7 +12,7 @@ 9.0 - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lis2Mdl/Datasheet/lis2mdl.pdf b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lis2Mdl/Datasheet/lis2mdl.pdf new file mode 100644 index 0000000000..0ebca1a726 Binary files /dev/null and b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lis2Mdl/Datasheet/lis2mdl.pdf differ diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lis2Mdl/Driver/Lis2Mdl.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lis2Mdl/Driver/Lis2Mdl.Enums.cs new file mode 100644 index 0000000000..c30e3f6524 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lis2Mdl/Driver/Lis2Mdl.Enums.cs @@ -0,0 +1,66 @@ +namespace Meadow.Foundation.Sensors.Accelerometers +{ + public partial class Lis2Mdl + { + /// + /// Valid I2C addresses for the sensor + /// + public enum Addresses : byte + { + /// + /// Bus address 0x1E + /// + Address_0x1E = 0x1E, + /// + /// Bus address 0x1C (connect SDO/SA1 pin to the ground) + /// + Address_0x1C = 0x1C, + /// + /// Default I2C address + /// + Default = Address_0x1E, + } + + /// + /// Represents the output data rate (ODR) options for the LIS2MDL magnetometer. + /// + public enum OutputDataRate + { + /// + /// Output Data Rate: 10 Hz. + /// + Odr10Hz = 0x00, + /// + /// Output Data Rate: 20 Hz. + /// + Odr20Hz = 0x04, + /// + /// Output Data Rate: 50 Hz. + /// + Odr50Hz = 0x08, + /// + /// Output Data Rate: 100 Hz. + /// + Odr100Hz = 0x0C, + } + + /// + /// Represents the operating mode options for the LIS2MDL magnetometer. + /// + public enum OperatingMode + { + /// + /// Continuous mode: The sensor continuously measures and updates the output registers. + /// + ContinuousMode = 0x00, + /// + /// Single-conversion mode: The sensor performs one measurement and then enters a low-power state until another single-conversion command is received. + /// + SingleConversionMode = 0x01, + /// + /// Power-down mode: The sensor enters a low-power state and stops measuring. + /// + PowerDownMode = 0x03, + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lis2Mdl/Driver/Lis2Mdl.Registers.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lis2Mdl/Driver/Lis2Mdl.Registers.cs new file mode 100644 index 0000000000..4204db940e --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lis2Mdl/Driver/Lis2Mdl.Registers.cs @@ -0,0 +1,11 @@ +namespace Meadow.Foundation.Sensors.Accelerometers +{ + public partial class Lis2Mdl + { + private const byte WHO_AM_I = 0x4F; + private const byte CTRL_REG1 = 0x60; + private const byte CTRL_REG2 = 0x61; + private const byte CTRL_REG3 = 0x62; + private const byte OUTX_L_REG = 0x68; + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lis2Mdl/Driver/Lis2Mdl.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lis2Mdl/Driver/Lis2Mdl.cs new file mode 100644 index 0000000000..26bf1b7f75 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lis2Mdl/Driver/Lis2Mdl.cs @@ -0,0 +1,228 @@ +using Meadow.Hardware; +using Meadow.Peripherals.Sensors.Motion; +using Meadow.Units; +using System; +using System.Threading.Tasks; + +namespace Meadow.Foundation.Sensors.Accelerometers +{ + /// + /// Represents a LIS2MDL is a low-power, high-performance 3-axis magnetometer from STMicroelectronics + /// with a fixed full range of ±50 gauss and a 16-bit resolution + /// + public partial class Lis2Mdl : PollingSensorBase, IMagnetometer, II2cPeripheral + { + /// + /// Event raised when magnetic field changes + /// + public event EventHandler> MagneticField3DUpdated = delegate { }; + + /// + /// Current Magnetic Field 3D + /// + public MagneticField3D? MagneticField3D => Conditions; + + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + + /// + /// I2C Communication bus used to communicate with the peripheral + /// + protected readonly II2cCommunications i2cComms; + + /// + /// Create a new Lis2Mdl instance + /// + /// The I2C bus connected to the sensor + /// The I2C address + public Lis2Mdl(II2cBus i2cBus, byte address = (byte)Addresses.Default) + { + i2cComms = new I2cCommunications(i2cBus, address); + + Initialize(); + } + + /// + /// Initializes the LSM303AGR sensor + /// + void Initialize() + { + // Configure the device + i2cComms.WriteRegister(CTRL_REG1, 0x10); // Temperature compensation: ON, ODR: 10Hz, Mode: Continuous + i2cComms.WriteRegister(CTRL_REG2, 0x00); // Full-scale: ±50 Gauss + i2cComms.WriteRegister(CTRL_REG3, 0x00); // Continuous mode + } + + /// + /// Raise events for subcribers and notify of value changes + /// + /// The updated sensor data + protected override void RaiseEventsAndNotify(IChangeResult changeResult) + { + if (changeResult.New is { } mag) + { + MagneticField3DUpdated?.Invoke(this, new ChangeResult(mag, changeResult.Old)); + } + base.RaiseEventsAndNotify(changeResult); + } + + /// + /// Reads data from the sensor + /// + /// The latest sensor reading + protected override Task ReadSensor() + { + var (x, y, z) = ReadMagnetometerRaw(); + + var conditions = new MagneticField3D(x / 1500.0, y / 1500.0, z / 1500.0, MagneticField.UnitType.Gauss); + + return Task.FromResult(conditions); + } + + /// + /// Reads raw magnetometer data + /// + /// A tuple containing the X, Y, and Z values of the magnetometer. + (short x, short y, short z) ReadMagnetometerRaw() + { + Span rawData = stackalloc byte[6]; + i2cComms.ReadRegister(OUTX_L_REG, rawData); + + short x = BitConverter.ToInt16(rawData.Slice(0, 2)); + short y = BitConverter.ToInt16(rawData.Slice(2, 2)); + short z = BitConverter.ToInt16(rawData.Slice(4, 2)); + + return (x, y, z); + } + + /// + /// Gets the output data rate (ODR) of the magnetometer. + /// + /// The output data rate as a enum. + public OutputDataRate GetOutputDataRate() + { + byte odrByte = i2cComms.ReadRegister(CTRL_REG1); + return (OutputDataRate)(odrByte & 0x0C); + } + + /// + /// Sets the output data rate (ODR) of the magnetometer. + /// + /// The desired output data rate as a enum. + public void SetOutputDataRate(OutputDataRate odr) + { + byte odrByte = i2cComms.ReadRegister(CTRL_REG1); + odrByte &= 0xF3; // Clear bits 2 and 3 + odrByte |= (byte)odr; + i2cComms.WriteRegister(CTRL_REG1, odrByte); + } + + /// + /// Gets the operating mode of the magnetometer. + /// + /// The operating mode as a enum. + public OperatingMode GetOperatingMode() + { + byte modeByte = i2cComms.ReadRegister(CTRL_REG3); + return (OperatingMode)(modeByte & 0x03); + } + + /// + /// Sets the operating mode of the magnetometer. + /// + /// The desired operating mode as a enum. + public void SetOperatingMode(OperatingMode mode) + { + byte modeByte = i2cComms.ReadRegister(CTRL_REG3); + modeByte &= 0xFC; // Clear bits 0 and 1 + modeByte |= (byte)mode; + i2cComms.WriteRegister(CTRL_REG3, modeByte); + } + + /// + /// Gets the status of the temperature compensation feature. + /// + /// true if temperature compensation is enabled, false otherwise. + public bool GetTemperatureCompensation() + { + byte tempCompByte = i2cComms.ReadRegister(CTRL_REG1); + return (tempCompByte & 0x80) == 0x80; + } + + /// + /// Sets the status of the temperature compensation feature. + /// + /// true to enable temperature compensation, false to disable it. + public void SetTemperatureCompensation(bool enable) + { + byte tempCompByte = i2cComms.ReadRegister(CTRL_REG1); + if (enable) + { + tempCompByte |= 0x80; // Set bit 7 + } + else + { + tempCompByte &= 0x7F; // Clear bit 7 + } + i2cComms.WriteRegister(CTRL_REG1, tempCompByte); + } + + /// + /// Gets the status of the Fast Read feature. + /// + /// true if Fast Read is enabled, false otherwise. + public bool GetFastRead() + { + byte fastReadByte = i2cComms.ReadRegister(CTRL_REG1); + return (fastReadByte & 0x02) == 0x02; + } + + /// + /// Sets the status of the Fast Read feature. + /// + /// true to enable Fast Read, false to disable it. + public void SetFastRead(bool enable) + { + byte fastReadByte = i2cComms.ReadRegister(CTRL_REG1); + if (enable) + { + fastReadByte |= 0x02; // Set bit 1 + } + else + { + fastReadByte &= 0xFD; // Clear bit 1 + } + i2cComms.WriteRegister(CTRL_REG1, fastReadByte); + } + + /// + /// Gets the status of the Block Data Update (BDU) feature. + /// + /// true if BDU is enabled, false otherwise. + public bool GetBlockDataUpdate() + { + byte bduByte = i2cComms.ReadRegister(CTRL_REG1); + return (bduByte & 0x01) == 0x01; + } + + /// + /// Sets the status of the Block Data Update (BDU) feature. + /// + /// true to enable BDU, false to disable it. + public void SetBlockDataUpdate(bool enable) + { + byte bduByte = i2cComms.ReadRegister(CTRL_REG1); + if (enable) + { + bduByte |= 0x01; // Set bit 0 + } + else + { + bduByte &= 0xFE; // Clear bit 0 + } + i2cComms.WriteRegister(CTRL_REG1, bduByte); + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lis2Mdl/Driver/Sensors.Motion.Lis2Mdl.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lis2Mdl/Driver/Sensors.Motion.Lis2Mdl.csproj new file mode 100644 index 0000000000..26ad3bc8cc --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lis2Mdl/Driver/Sensors.Motion.Lis2Mdl.csproj @@ -0,0 +1,23 @@ + + + true + icon.png + Wilderness Labs, Inc + netstandard2.1 + Library + Lis2Mdl + Wilderness Labs, Inc + http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ + Meadow.Foundation.Sensors.Motion.Lis2Mdl + https://github.com/WildernessLabs/Meadow.Foundation + Meadow.Foundation,magnetometer,Lis2Mdl + 0.1.0 + true + LIS2MDL I2C 3-axis magnetometer + Meadow.Foundation.Sensors.Motion + + + + + + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lis2Mdl/Samples/Lis2Mdl_Sample/Lis2Mdl_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lis2Mdl/Samples/Lis2Mdl_Sample/Lis2Mdl_Sample.csproj new file mode 100644 index 0000000000..73a5d6956a --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lis2Mdl/Samples/Lis2Mdl_Sample/Lis2Mdl_Sample.csproj @@ -0,0 +1,20 @@ + + + https://github.com/WildernessLabs/Meadow.Foundation + Wilderness Labs, Inc + Wilderness Labs, Inc + true + netstandard2.1 + Library + App + + + + + + + + Always + + + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lis2Mdl/Samples/Lis2Mdl_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lis2Mdl/Samples/Lis2Mdl_Sample/MeadowApp.cs new file mode 100644 index 0000000000..1adaba0951 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lis2Mdl/Samples/Lis2Mdl_Sample/MeadowApp.cs @@ -0,0 +1,51 @@ +using Meadow; +using Meadow.Devices; +using Meadow.Foundation.Sensors.Accelerometers; +using Meadow.Units; +using System; +using System.Threading.Tasks; + +namespace Lis2Mdl_Sample +{ + // Change F7FeatherV2 to F7FeatherV1 for V1.x boards + public class MeadowApp : App + { + // + + Lis2Mdl sensor; + + public override Task Initialize() + { + Resolver.Log.Info("Initialize hardware..."); + sensor = new Lis2Mdl(Device.CreateI2cBus()); + + // classical .NET events can also be used: + sensor.Updated += HandleResult; + + // Example that uses an IObservable subscription to only be notified when the filter is satisfied + var consumer = Lis2Mdl.CreateObserver(handler: result => HandleResult(this, result), + filter: result => FilterResult(result)); + + sensor.Subscribe(consumer); + + sensor.StartUpdating(TimeSpan.FromMilliseconds(2000)); + + return base.Initialize(); + } + + bool FilterResult(IChangeResult result) + { + return result.New.Z > new MagneticField(0.1, MagneticField.UnitType.Gauss); + } + + void HandleResult(object sender, + IChangeResult result) + { + var mag = result.New; + + Resolver.Log.Info($"MagX={mag.X.Gauss:0.##}gauss, MagY={mag.Y.Gauss:0.##}gauss, GyroZ={mag.Z.Gauss:0.##}gauss"); + } + + // + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lis2Mdl/Samples/Lis2Mdl_Sample/meadow.config.yaml b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lis2Mdl/Samples/Lis2Mdl_Sample/meadow.config.yaml new file mode 100644 index 0000000000..32363cb69c --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lis2Mdl/Samples/Lis2Mdl_Sample/meadow.config.yaml @@ -0,0 +1,2 @@ +MonoControl: + Options: --jit \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lsm303agr/Datasheet/lsm303agr.pdf b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lsm303agr/Datasheet/lsm303agr.pdf new file mode 100644 index 0000000000..4729b35ebf Binary files /dev/null and b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lsm303agr/Datasheet/lsm303agr.pdf differ diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lsm303agr/Driver/Lsm303agr.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lsm303agr/Driver/Lsm303agr.Enums.cs new file mode 100644 index 0000000000..eea6d0b66f --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lsm303agr/Driver/Lsm303agr.Enums.cs @@ -0,0 +1,109 @@ +namespace Meadow.Foundation.Sensors.Accelerometers +{ + public partial class Lsm303agr + { + /// + /// Valid I2C addresses for the sensor + /// + public enum Addresses : byte + { + /// + /// Bus address 0x19 for the accelerometer + /// + AddressAccel_0x19 = 0x19, + /// + /// Bus address 0x1E for the magnetometer + /// + AddressMag_0x1E = 0x1E, + } + + /// + /// Enum representing the sensitivity settings for the accelerometer of the LSM303AGR sensor. + /// + public enum AccSensitivity + { + /// + /// ±2g sensitivity setting for the accelerometer. + /// + G2 = 0x00, + /// + /// ±4g sensitivity setting for the accelerometer. + /// + G4 = 0x10, + /// + /// ±8g sensitivity setting for the accelerometer. + /// + G8 = 0x20, + /// + /// ±16g sensitivity setting for the accelerometer. + /// + G16 = 0x30 + } + + /// + /// Represents the available output data rates for the accelerometer. + /// + public enum AccOutputDataRate + { + /// + /// Output data rate: 1 Hz + /// + Hz1 = 0x10, + /// + /// Output data rate: 10 Hz + /// + Hz10 = 0x20, + /// + /// Output data rate: 25 Hz + /// + Hz25 = 0x30, + /// + /// Output data rate: 50 Hz + /// + Hz50 = 0x40, + /// + /// Output data rate: 100 Hz + /// + Hz100 = 0x50, + /// + /// Output data rate: 200 Hz + /// + Hz200 = 0x60, + /// + /// Output data rate: 400 Hz + /// + Hz400 = 0x70, + /// + /// Output data rate: 1620 Hz + /// + Hz1620 = 0x80, + /// + /// Output data rate: 5376 Hz + /// + Hz5376 = 0x90 + } + + /// + /// Represents the available output data rates for the magnetometer. + /// + public enum MagOutputDataRate + { + /// + /// Output Data Rate: 10 Hz. + /// + Odr10Hz = 0x00, + /// + /// Output Data Rate: 20 Hz. + /// + Odr20Hz = 0x04, + /// + /// Output Data Rate: 50 Hz. + /// + Odr50Hz = 0x08, + /// + /// Output Data Rate: 100 Hz. + /// + Odr100Hz = 0x0C, + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lsm303agr/Driver/Lsm303agr.Registers.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lsm303agr/Driver/Lsm303agr.Registers.cs new file mode 100644 index 0000000000..c329817a8e --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lsm303agr/Driver/Lsm303agr.Registers.cs @@ -0,0 +1,12 @@ +namespace Meadow.Foundation.Sensors.Accelerometers +{ + public partial class Lsm303agr + { + const byte ACC_CTRL_REG1_A = 0x20; + const byte ACC_CTRL_REG4_A = 0x23; + const byte ACC_OUT_X_L_A = 0x28; + const byte MAG_CTRL_REG1_M = 0x20; + const byte MAG_CTRL_REG2_M = 0x21; + const byte MAG_OUTX_L_REG_M = 0x68; + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lsm303agr/Driver/Lsm303agr.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lsm303agr/Driver/Lsm303agr.cs new file mode 100644 index 0000000000..a2f8dcd9a6 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lsm303agr/Driver/Lsm303agr.cs @@ -0,0 +1,250 @@ +using Meadow.Hardware; +using Meadow.Peripherals.Sensors; +using Meadow.Peripherals.Sensors.Motion; +using Meadow.Units; +using System; +using System.Threading.Tasks; + +namespace Meadow.Foundation.Sensors.Accelerometers +{ + /// + /// Represents a LSM303AGR is a system-in-package (SiP) that combines a 3D linear acceleration sensor and a 3D magnetic sensor + /// + public partial class Lsm303agr : + PollingSensorBase<(Acceleration3D? Acceleration3D, MagneticField3D? MagneticField3D)>, + IMagnetometer, IAccelerometer, II2cPeripheral + { + /// + /// Event raised when acceleration changes + /// + public event EventHandler> Acceleration3DUpdated = delegate { }; + + /// + /// Event raised when magnetic field changes + /// + public event EventHandler> MagneticField3DUpdated = delegate { }; + + /// + /// Current Acceleration 3D + /// + public Acceleration3D? Acceleration3D => Conditions.Acceleration3D; + + /// + /// Current Magnetic Field 3D + /// + public MagneticField3D? MagneticField3D => Conditions.MagneticField3D; + + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.AddressAccel_0x19; + + /// + /// I2C Communication bus used to communicate with the accelerometer + /// + readonly II2cCommunications i2cCommsAccel; + + /// + /// I2C Communication bus used to communicate with the magnetometer + /// + readonly II2cCommunications i2cCommsMag; + + /// + /// Create a new Lsm303agr instance + /// + /// The I2C bus connected to the sensor + public Lsm303agr(II2cBus i2cBus) + { + i2cCommsAccel = new I2cCommunications(i2cBus, (byte)Addresses.AddressAccel_0x19); + i2cCommsMag = new I2cCommunications(i2cBus, (byte)Addresses.AddressMag_0x1E); + + Initialize(); + } + + /// + /// Initializes the LSM303AGR sensor + /// + void Initialize() + { + i2cCommsAccel.WriteRegister(ACC_CTRL_REG1_A, 0x57); + i2cCommsMag.WriteRegister(MAG_CTRL_REG1_M, 0x60); + } + + /// + /// Sets the sensitivity of the accelerometer + /// + /// The desired sensitivity setting, specified by the AccSensitivity enum. + public void SetAccelerometerSensitivity(AccSensitivity sensitivity) + { + byte[] writeBuffer = new byte[] { ACC_CTRL_REG4_A, (byte)sensitivity }; + i2cCommsAccel.Write(writeBuffer); + } + + /// + /// Retrieves the current sensitivity setting of the accelerometer + /// + /// The current sensitivity setting, represented by the AccSensitivity enum. + public AccSensitivity GetAccelerometerSensitivity() + { + byte[] readBuffer = new byte[1]; + i2cCommsAccel.ReadRegister(ACC_CTRL_REG4_A, readBuffer); + byte sensitivity = (byte)(readBuffer[0] & 0x30); + return (AccSensitivity)sensitivity; + } + + /// + /// Raise events for subcribers and notify of value changes + /// + /// The updated sensor data + protected override void RaiseEventsAndNotify(IChangeResult<(Acceleration3D? Acceleration3D, MagneticField3D? MagneticField3D)> changeResult) + { + if (changeResult.New.MagneticField3D is { } mag) + { + MagneticField3DUpdated?.Invoke(this, new ChangeResult(mag, changeResult.Old?.MagneticField3D)); + } + if (changeResult.New.Acceleration3D is { } accel) + { + Acceleration3DUpdated?.Invoke(this, new ChangeResult(accel, changeResult.Old?.Acceleration3D)); + } + base.RaiseEventsAndNotify(changeResult); + } + + /// + /// Reads data from the sensor + /// + /// The latest sensor reading + protected override Task<(Acceleration3D? Acceleration3D, MagneticField3D? MagneticField3D)> ReadSensor() + { + (Acceleration3D? Acceleration3D, MagneticField3D? MagneticField3D) conditions; + + var accel = ReadAccelerometerRaw(); + var mag = ReadMagnetometerRaw(); + + conditions.Acceleration3D = GetAcceleration3D(accel.x, accel.y, accel.z, GetAccelerometerSensitivity()); + conditions.MagneticField3D = GetMagneticField3D(mag.x, mag.y, mag.z); + + return Task.FromResult(conditions); + } + + Acceleration3D GetAcceleration3D(short rawX, short rawY, short rawZ, AccSensitivity sensitivity) + { + float lsbPerG = 0; + switch (sensitivity) + { + case AccSensitivity.G2: + lsbPerG = 16384.0f; // 2^16 / (2 * 2) + break; + case AccSensitivity.G4: + lsbPerG = 8192.0f; // 2^16 / (2 * 4) + break; + case AccSensitivity.G8: + lsbPerG = 4096.0f; // 2^16 / (2 * 8) + break; + case AccSensitivity.G16: + lsbPerG = 2048.0f; // 2^16 / (2 * 16) + break; + } + + float x = rawX / lsbPerG; + float y = rawY / lsbPerG; + float z = rawZ / lsbPerG; + + return new Acceleration3D(x, y, z, Acceleration.UnitType.Gravity); + } + + MagneticField3D GetMagneticField3D(short rawX, short rawY, short rawZ) + { + var x = rawX * 1500; + var y = rawY * 1500; + var z = rawZ * 1500; + + return new MagneticField3D(x, y, z, MagneticField.UnitType.Gauss); + } + + /// + /// Reads raw accelerometer data + /// + /// A tuple containing the X, Y, and Z values of the accelerometer. + (short x, short y, short z) ReadAccelerometerRaw() + { + byte[] readBuffer = new byte[6]; + i2cCommsAccel.ReadRegister(ACC_OUT_X_L_A, readBuffer); + + short x = BitConverter.ToInt16(new byte[] { readBuffer[0], readBuffer[1] }, 0); + short y = BitConverter.ToInt16(new byte[] { readBuffer[2], readBuffer[3] }, 0); + short z = BitConverter.ToInt16(new byte[] { readBuffer[4], readBuffer[5] }, 0); + + return (x, y, z); + } + + /// + /// Reads raw magnetometer data + /// + /// A tuple containing the X, Y, and Z values of the magnetometer. + (short x, short y, short z) ReadMagnetometerRaw() + { + byte[] readBuffer = new byte[6]; + i2cCommsMag.ReadRegister(MAG_OUTX_L_REG_M, readBuffer); + + short x = BitConverter.ToInt16(new byte[] { readBuffer[0], readBuffer[1] }, 0); + short y = BitConverter.ToInt16(new byte[] { readBuffer[2], readBuffer[3] }, 0); + short z = BitConverter.ToInt16(new byte[] { readBuffer[4], readBuffer[5] }, 0); + + return (x, y, z); + } + + /// + /// Sets the output data rate for the accelerometer. + /// + /// The desired output data rate setting. + public void SetAccelerometerOutputDataRate(AccOutputDataRate dataRate) + { + byte[] readBuffer = new byte[1]; + i2cCommsAccel.ReadRegister(ACC_CTRL_REG1_A, readBuffer); + + byte newSetting = (byte)((readBuffer[0] & 0x0F) | (byte)dataRate); + i2cCommsAccel.WriteRegister(ACC_CTRL_REG1_A, newSetting); + } + + /// + /// Retrieves the current output data rate setting for the accelerometer. + /// + /// The current output data rate setting. + public AccOutputDataRate GetAccelerometerOutputDataRate() + { + byte[] readBuffer = new byte[1]; + i2cCommsAccel.ReadRegister(ACC_CTRL_REG1_A, readBuffer); + + byte dataRate = (byte)(readBuffer[0] & 0xF0); + return (AccOutputDataRate)dataRate; + } + + /// + /// Sets the output data rate for the magnetometer. + /// + /// The desired output data rate setting. + public void SetMagnetometerOutputDataRate(MagOutputDataRate dataRate) + { + byte odrByte = i2cCommsMag.ReadRegister(MAG_CTRL_REG1_M); + odrByte &= 0xF3; // Clear bits 2 and 3 + odrByte |= (byte)dataRate; + i2cCommsMag.WriteRegister(MAG_CTRL_REG1_M, odrByte); + } + + /// + /// Retrieves the current output data rate setting for the magnetometer. + /// + /// The current output data rate setting. + public MagOutputDataRate GetMagnetometerOutputDataRate() + { + byte odrByte = i2cCommsMag.ReadRegister(MAG_CTRL_REG1_M); + return (MagOutputDataRate)(odrByte & 0x0C); + } + + async Task ISensor.Read() + => (await Read()).Acceleration3D.Value; + + async Task ISensor.Read() + => (await Read()).MagneticField3D.Value; + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lsm303agr/Driver/Sensors.Motion.Lsm303agr.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lsm303agr/Driver/Sensors.Motion.Lsm303agr.csproj new file mode 100644 index 0000000000..e8d8439b05 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lsm303agr/Driver/Sensors.Motion.Lsm303agr.csproj @@ -0,0 +1,23 @@ + + + true + icon.png + Wilderness Labs, Inc + netstandard2.1 + Library + Lsm303agr + Wilderness Labs, Inc + http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ + Meadow.Foundation.Sensors.Motion.Lsm303agr + https://github.com/WildernessLabs/Meadow.Foundation + Meadow.Foundation,Acceleration,Accelerometer,magnetometer,IMU,Lsm303agr + 0.1.0 + true + Lsm303agr I2C 6-axis accelerometer and magnetometer + Meadow.Foundation.Sensors.Motion + + + + + + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lsm303agr/Samples/Lsm303agr_Sample/Lsm303agr_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lsm303agr/Samples/Lsm303agr_Sample/Lsm303agr_Sample.csproj new file mode 100644 index 0000000000..bf0c29aca3 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lsm303agr/Samples/Lsm303agr_Sample/Lsm303agr_Sample.csproj @@ -0,0 +1,20 @@ + + + https://github.com/WildernessLabs/Meadow.Foundation + Wilderness Labs, Inc + Wilderness Labs, Inc + true + netstandard2.1 + Library + App + + + + + + + + Always + + + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lsm303agr/Samples/Lsm303agr_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lsm303agr/Samples/Lsm303agr_Sample/MeadowApp.cs new file mode 100644 index 0000000000..039564d900 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lsm303agr/Samples/Lsm303agr_Sample/MeadowApp.cs @@ -0,0 +1,53 @@ +using Meadow; +using Meadow.Devices; +using Meadow.Foundation.Sensors.Accelerometers; +using Meadow.Units; +using System; +using System.Threading.Tasks; + +namespace Lsm303agr_Sample +{ + // Change F7FeatherV2 to F7FeatherV1 for V1.x boards + public class MeadowApp : App + { + // + + Lsm303agr sensor; + + public override Task Initialize() + { + Resolver.Log.Info("Initialize hardware..."); + sensor = new Lsm303agr(Device.CreateI2cBus()); + + // classical .NET events can also be used: + sensor.Updated += HandleResult; + + // Example that uses an IObservable subscription to only be notified when the filter is satisfied + var consumer = Lsm303agr.CreateObserver(handler: result => HandleResult(this, result), + filter: result => FilterResult(result)); + + sensor.Subscribe(consumer); + + sensor.StartUpdating(TimeSpan.FromMilliseconds(2000)); + + return base.Initialize(); + } + + bool FilterResult(IChangeResult<(Acceleration3D? Acceleration3D, MagneticField3D? MagneticField3D)> result) + { + return result.New.Acceleration3D.Value.Z > new Acceleration(0.1, Acceleration.UnitType.Gravity); + } + + void HandleResult(object sender, + IChangeResult<(Acceleration3D? Acceleration3D, + MagneticField3D? MagneticField3D)> result) + { + var accel = result.New.Acceleration3D.Value; + var mag = result.New.MagneticField3D.Value; + + Resolver.Log.Info($"AccelX={accel.X.Gravity:0.##}g, AccelY={accel.Y.Gravity:0.##}g, AccelZ={accel.Z.Gravity:0.##}g, MagX={mag.X.Gauss:0.##}gauss, MagY={mag.Y.Gauss:0.##}gauss, MagZ={mag.Z.Gauss:0.##}gauss"); + } + + // + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lsm303agr/Samples/Lsm303agr_Sample/meadow.config.yaml b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lsm303agr/Samples/Lsm303agr_Sample/meadow.config.yaml new file mode 100644 index 0000000000..32363cb69c --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Lsm303agr/Samples/Lsm303agr_Sample/meadow.config.yaml @@ -0,0 +1,2 @@ +MonoControl: + Options: --jit \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mag3110/Driver/Mag3110.Addresses.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mag3110/Driver/Mag3110.Addresses.cs index f5f4c42247..648cc07e2e 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mag3110/Driver/Mag3110.Addresses.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mag3110/Driver/Mag3110.Addresses.cs @@ -3,7 +3,7 @@ public partial class Mag3110 { /// - /// Valid addresses for the sensor + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mag3110/Driver/Mag3110.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mag3110/Driver/Mag3110.cs index d7264ccded..d572cfedc1 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mag3110/Driver/Mag3110.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mag3110/Driver/Mag3110.cs @@ -7,23 +7,22 @@ namespace Meadow.Foundation.Sensors.Motion { - // TODO: Sensor is fully converted but data isn't right: - // Accel: [X:429.00,Y:-45.00,Z:-1,682.00 (m/s^2)] - // Temp: 16.00C - - // TODO: Interrupt handling is commented out - /// /// Represents the Xtrinsic MAG3110 Three-Axis, Digital Magnetometer /// public partial class Mag3110 : ByteCommsSensorBase<(MagneticField3D? MagneticField3D, Units.Temperature? Temperature)>, - ITemperatureSensor, IMagnetometer + ITemperatureSensor, IMagnetometer, II2cPeripheral { + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + /// /// Raised when the magnetic field value changes /// - public event EventHandler> MagneticField3dUpdated = delegate { }; + public event EventHandler> MagneticField3DUpdated = delegate { }; /// /// Raised when the temperature value changes @@ -38,7 +37,7 @@ public partial class Mag3110 : /// /// The current magnetic field value /// - public MagneticField3D? MagneticField3d => Conditions.MagneticField3D; + public MagneticField3D? MagneticField3D => Conditions.MagneticField3D; /// /// Current emperature of the die @@ -52,12 +51,12 @@ public bool Standby { get { - var controlRegister = Peripheral.ReadRegister((byte)Registers.CONTROL_1); + var controlRegister = BusComms.ReadRegister(Registers.CONTROL_1); return (controlRegister & 0x03) == 0; } set { - var controlRegister = Peripheral.ReadRegister(Registers.CONTROL_1); + var controlRegister = BusComms.ReadRegister(Registers.CONTROL_1); if (value) { controlRegister &= 0xfc; // ~0x03 @@ -66,7 +65,7 @@ public bool Standby { controlRegister |= 0x01; } - Peripheral.WriteRegister(Registers.CONTROL_1, controlRegister); + BusComms.WriteRegister(Registers.CONTROL_1, controlRegister); } } @@ -76,7 +75,7 @@ public bool Standby /// /// See section 5.1.1 of the datasheet. /// - public bool IsDataReady => (Peripheral.ReadRegister(Registers.DR_STATUS) & 0x08) > 0; + public bool IsDataReady => (BusComms.ReadRegister(Registers.DR_STATUS) & 0x08) > 0; /// @@ -93,7 +92,7 @@ public bool DigitalInputsEnabled set { Standby = true; - var cr2 = Peripheral.ReadRegister(Registers.CONTROL_2); + var cr2 = BusComms.ReadRegister(Registers.CONTROL_2); if (value) { cr2 |= 0x80; @@ -102,7 +101,7 @@ public bool DigitalInputsEnabled { cr2 &= 0x7f; } - Peripheral.WriteRegister(Registers.CONTROL_2, cr2); + BusComms.WriteRegister(Registers.CONTROL_2, cr2); digitalInputsEnabled = value; } } @@ -117,7 +116,7 @@ public bool DigitalInputsEnabled public Mag3110(II2cBus i2cBus, IDigitalInputPort interruptPort = null, byte address = (byte)Addresses.Default) : base(i2cBus, address) { - var deviceID = Peripheral.ReadRegister((byte)Registers.WHO_AM_I); + var deviceID = BusComms.ReadRegister(Registers.WHO_AM_I); if (deviceID != 0xc4) { throw new Exception("Unknown device ID, " + deviceID + " retruend, 0xc4 expected"); @@ -137,13 +136,13 @@ public Mag3110(II2cBus i2cBus, IDigitalInputPort interruptPort = null, byte addr public void Reset() { Standby = true; - Peripheral.WriteRegister(Registers.CONTROL_1, 0x00); - Peripheral.WriteRegister(Registers.CONTROL_2, 0x80); + BusComms.WriteRegister(Registers.CONTROL_1, 0x00); + BusComms.WriteRegister(Registers.CONTROL_2, 0x80); WriteBuffer.Span[0] = Registers.X_OFFSET_MSB; WriteBuffer.Span[1] = WriteBuffer.Span[2] = WriteBuffer.Span[3] = 0; WriteBuffer.Span[4] = WriteBuffer.Span[5] = WriteBuffer.Span[6] = 0; - Peripheral.Write(WriteBuffer.Span[0..7]); + BusComms.Write(WriteBuffer.Span[0..7]); } /// @@ -154,7 +153,7 @@ protected override void RaiseEventsAndNotify(IChangeResult<(MagneticField3D? Mag { if (changeResult.New.MagneticField3D is { } mag) { - MagneticField3dUpdated?.Invoke(this, new ChangeResult(mag, changeResult.Old?.MagneticField3D)); + MagneticField3DUpdated?.Invoke(this, new ChangeResult(mag, changeResult.Old?.MagneticField3D)); } if (changeResult.New.Temperature is { } temp) { @@ -169,26 +168,23 @@ protected override void RaiseEventsAndNotify(IChangeResult<(MagneticField3D? Mag /// The latest sensor reading protected override Task<(MagneticField3D? MagneticField3D, Units.Temperature? Temperature)> ReadSensor() { - return Task.Run(() => - { - (MagneticField3D? MagneticField3D, Units.Temperature? Temperature) conditions; + (MagneticField3D? MagneticField3D, Units.Temperature? Temperature) conditions; - var controlRegister = Peripheral.ReadRegister(Registers.CONTROL_1); - controlRegister |= 0x02; - Peripheral.WriteRegister(Registers.CONTROL_1, controlRegister); + var controlRegister = BusComms.ReadRegister(Registers.CONTROL_1); + controlRegister |= 0x02; + BusComms.WriteRegister(Registers.CONTROL_1, controlRegister); - Peripheral.ReadRegister(Registers.X_MSB, ReadBuffer.Span[0..6]); + BusComms.ReadRegister(Registers.X_MSB, ReadBuffer.Span[0..6]); - conditions.MagneticField3D = new MagneticField3D( - new MagneticField((short)((ReadBuffer.Span[0] << 8) | ReadBuffer.Span[1]), MagneticField.UnitType.MicroTesla), - new MagneticField((short)((ReadBuffer.Span[2] << 8) | ReadBuffer.Span[3]), MagneticField.UnitType.MicroTesla), - new MagneticField((short)((ReadBuffer.Span[4] << 8) | ReadBuffer.Span[5]), MagneticField.UnitType.MicroTesla) - ); + conditions.MagneticField3D = new MagneticField3D( + new MagneticField((short)((ReadBuffer.Span[0] << 8) | ReadBuffer.Span[1]), MagneticField.UnitType.MicroTesla), + new MagneticField((short)((ReadBuffer.Span[2] << 8) | ReadBuffer.Span[3]), MagneticField.UnitType.MicroTesla), + new MagneticField((short)((ReadBuffer.Span[4] << 8) | ReadBuffer.Span[5]), MagneticField.UnitType.MicroTesla) + ); - conditions.Temperature = new Units.Temperature((sbyte)Peripheral.ReadRegister(Registers.TEMPERATURE), Units.Temperature.UnitType.Celsius); + conditions.Temperature = new Units.Temperature((sbyte)BusComms.ReadRegister(Registers.TEMPERATURE), Units.Temperature.UnitType.Celsius); - return conditions; - }); + return Task.FromResult(conditions); } /// diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mag3110/Driver/Sensors.Motion.Mag3110.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mag3110/Driver/Sensors.Motion.Mag3110.csproj index b102549fa1..6b62c7d7e4 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mag3110/Driver/Sensors.Motion.Mag3110.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mag3110/Driver/Sensors.Motion.Mag3110.csproj @@ -10,7 +10,7 @@ http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ Meadow.Foundation.Sensors.Motion.Mag3110 https://github.com/WildernessLabs/Meadow.Foundation - Meadow.Foundation, motion, magnetometer + Meadow.Foundation,motion,magnetometer,MAG3110 0.1.29 true Freescale MAG3110 I2C 3 axis magnetometer @@ -18,6 +18,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mag3110/Samples/Mag3110_Sample/Mag3110_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mag3110/Samples/Mag3110_Sample/Mag3110_Sample.csproj index a19373ce38..62d5cb5495 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mag3110/Samples/Mag3110_Sample/Mag3110_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mag3110/Samples/Mag3110_Sample/Mag3110_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Mma7660fc.Addresses.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Mma7660fc.Addresses.cs index 2e1c1899cd..cbd08ba890 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Mma7660fc.Addresses.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Mma7660fc.Addresses.cs @@ -3,7 +3,7 @@ public partial class Mma7660fc { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Mma7660fc.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Mma7660fc.cs index 985355d6cb..f00567906a 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Mma7660fc.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Mma7660fc.cs @@ -1,16 +1,21 @@ -using System; -using System.Threading.Tasks; -using Meadow.Hardware; +using Meadow.Hardware; using Meadow.Peripherals.Sensors.Motion; using Meadow.Units; +using System; +using System.Threading.Tasks; namespace Meadow.Foundation.Sensors.Motion { /// /// Represents Mma7660fc 3-axis acclerometer /// - public partial class Mma7660fc : ByteCommsSensorBase, IAccelerometer + public partial class Mma7660fc : ByteCommsSensorBase, IAccelerometer, II2cPeripheral { + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + /// /// Raised when new acceleration data is processed /// @@ -38,8 +43,7 @@ public partial class Mma7660fc : ByteCommsSensorBase, IAccelerom /// I2C bus public Mma7660fc(II2cBus i2cBus, Addresses address = Addresses.Default) : this(i2cBus, (byte)address) - { - } + { } /// /// Create a new instance of the Mma7660fc communicating over the I2C interface. @@ -58,10 +62,10 @@ void Initialize() SetSampleRate(SampleRate._32); SetMode(SensorPowerMode.Active); } - + void SetMode(SensorPowerMode mode) { - Peripheral.WriteRegister((byte)Registers.Mode, (byte)mode); + BusComms.WriteRegister((byte)Registers.Mode, (byte)mode); } /// @@ -70,7 +74,7 @@ void SetMode(SensorPowerMode mode) /// sample rate public void SetSampleRate(SampleRate rate) { - Peripheral.WriteRegister((byte)Registers.SleepRate, (byte)rate); + BusComms.WriteRegister((byte)Registers.SleepRate, (byte)rate); } /// @@ -81,21 +85,20 @@ protected override Task ReadSensor() { return Task.Run(() => { - Direction = (DirectionType)(Peripheral.ReadRegister((byte)Registers.TILT) & 0x1C); + Direction = (DirectionType)(BusComms.ReadRegister((byte)Registers.TILT) & 0x1C); - Orientation = (OrientationType)(Peripheral.ReadRegister((byte)Registers.TILT) & 0x03); + Orientation = (OrientationType)(BusComms.ReadRegister((byte)Registers.TILT) & 0x03); int xAccel, yAccel, zAccel; byte x, y, z; //Signed byte 6-bit 2’s complement data with allowable range of +31 to -32 //[5] is 0 if the g direction is positive, 1 if the g direction is negative. + //ensure bit 6 isn't set - if so, it means there was a read/write collision ... try again do { - x = Peripheral.ReadRegister((byte)Registers.XOUT); - } - //ensure bit 6 isn't set - if so, it means there was a read/write collision ... try again - while (x >= 64); + x = BusComms.ReadRegister((byte)Registers.XOUT); + } while (x >= 64); //check bit 5 and flip to negative if ((x & (1 << 5)) != 0) xAccel = x - 64; @@ -103,20 +106,17 @@ protected override Task ReadSensor() do { - y = Peripheral.ReadRegister((byte)Registers.YOUT); - } - //ensure bit 6 isn't set - if so, it means there was a read/write collision ... try again - while (y >= 64); + y = BusComms.ReadRegister((byte)Registers.YOUT); + } while (y >= 64); //ensure bit 6 isn't set - if so, it means there was a read/write collision ... try again if ((y & (1 << 5)) != 0) yAccel = y - 64; else yAccel = y; + //ensure bit 6 isn't set - if so, it means there was a read/write collision ... try again do { - z = Peripheral.ReadRegister((byte)Registers.ZOUT); - } - //ensure bit 6 isn't set - if so, it means there was a read/write collision ... try again - while (y >= 64); + z = BusComms.ReadRegister((byte)Registers.ZOUT); + } while (y >= 64); if ((z & (1 << 5)) != 0) zAccel = z - 64; else zAccel = z; @@ -124,8 +124,7 @@ protected override Task ReadSensor() return new Acceleration3D( new Acceleration(xAccel * 3.0 / 64.0, Acceleration.UnitType.Gravity), new Acceleration(yAccel * 3.0 / 64.0, Acceleration.UnitType.Gravity), - new Acceleration(zAccel * 3.0 / 64.0, Acceleration.UnitType.Gravity) - ); + new Acceleration(zAccel * 3.0 / 64.0, Acceleration.UnitType.Gravity)); }); } diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Sensors.Motion.Mma7660fc.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Sensors.Motion.Mma7660fc.csproj index 73d40ae092..408b1d9ed3 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Sensors.Motion.Mma7660fc.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Driver/Sensors.Motion.Mma7660fc.csproj @@ -10,13 +10,13 @@ http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ Meadow.Foundation.Sensors.Motion.Mma7660fc https://github.com/WildernessLabs/Meadow.Foundation - Meadow.Foundation, Mma7660fc, Accelerometer, Motion + Meadow.Foundation,Mma7660fc,Accelerometer,Motion 0.1.7 true Mma7660fc I2C 3-axis accelerometer - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Samples/Mma7660fc_Sample/Mma7660fc_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Samples/Mma7660fc_Sample/Mma7660fc_Sample.csproj index f9044f50c6..96adca0177 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Samples/Mma7660fc_Sample/Mma7660fc_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mma7660fc/Samples/Mma7660fc_Sample/Mma7660fc_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mmc5603/Driver/Mmc5603.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mmc5603/Driver/Mmc5603.cs index 5293cd8cbd..75cc5a7abd 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mmc5603/Driver/Mmc5603.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mmc5603/Driver/Mmc5603.cs @@ -11,25 +11,30 @@ namespace Meadow.Foundation.Sensors.Motion /// /// Represents the Mmc5603 Three-Axis, Digital Magnetometer /// - public partial class Mmc5603 : - ByteCommsSensorBase, IMagnetometer + public partial class Mmc5603 : ByteCommsSensorBase, + IMagnetometer, II2cPeripheral { + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + /// /// Raised when the magnetic field value changes /// - public event EventHandler> MagneticField3dUpdated = delegate { }; + public event EventHandler> MagneticField3DUpdated = delegate { }; /// /// The current magnetic field value /// - public MagneticField3D? MagneticField3d => Conditions; + public MagneticField3D? MagneticField3D => Conditions; /// /// Get/set continuous sensor reading mode /// public bool ContinuousModeEnabled { - get => (Peripheral.ReadRegister(Registers.CONTROL_2) & 0x10) == 1; + get => (BusComms.ReadRegister(Registers.CONTROL_2) & 0x10) == 1; set => SetContinuousMode(value); } @@ -41,7 +46,7 @@ public bool ContinuousModeEnabled public Mmc5603(II2cBus i2cBus, byte address = (byte)Addresses.Default) : base(i2cBus, address, 10, 8) { - var deviceID = Peripheral.ReadRegister(Registers.WHO_AM_I); + var deviceID = BusComms.ReadRegister(Registers.WHO_AM_I); if (deviceID != 0x10) { @@ -67,18 +72,18 @@ public void Reset() void SetRegisterBit(byte register, byte bitIndex, bool enabled = true) { - var value = Peripheral.ReadRegister(register); + var value = BusComms.ReadRegister(register); value = BitHelpers.SetBit(value, bitIndex, enabled); - Peripheral.WriteRegister(register, value); + BusComms.WriteRegister(register, value); } void SetContinuousMode(bool on) { - if(on == true) + if (on == true) { SetRegisterBit(Registers.CONTROL_0, 7, true); SetRegisterBit(Registers.CONTROL_2, 4, true); - } + } else { SetRegisterBit(Registers.CONTROL_2, 4, false); @@ -93,7 +98,7 @@ protected override void RaiseEventsAndNotify(IChangeResult chan { if (changeResult is { } mag) { - MagneticField3dUpdated?.Invoke(this, new ChangeResult(mag.New, changeResult.Old)); + MagneticField3DUpdated?.Invoke(this, new ChangeResult(mag.New, changeResult.Old)); } base.RaiseEventsAndNotify(changeResult); } @@ -103,18 +108,18 @@ Task TriggerMagneticFieldReading() SetRegisterBit(Registers.CONTROL_0, 0, true); return Task.Delay(10); } - + Task TriggerTemperatureReading() { SetRegisterBit(Registers.CONTROL_0, 1, true); return Task.Delay(10); } - /// - /// Reads data from the sensor - /// - /// The latest sensor reading - protected override Task ReadSensor() + /// + /// Reads data from the sensor + /// + /// The latest sensor reading + protected override Task ReadSensor() { return Task.Run(async () => { @@ -128,7 +133,7 @@ protected override Task ReadSensor() } } - Peripheral.ReadRegister(Registers.OUT_X_L, ReadBuffer.Span[0..9]); //9 bytes + BusComms.ReadRegister(Registers.OUT_X_L, ReadBuffer.Span[0..9]); int x = (int)((uint)(ReadBuffer.Span[0] << 12) | (uint)(ReadBuffer.Span[1] << 4) | (uint)(ReadBuffer.Span[6] >> 4)); int y = (int)((uint)(ReadBuffer.Span[2] << 12) | (uint)(ReadBuffer.Span[3] << 4) | (uint)(ReadBuffer.Span[7] >> 4)); @@ -143,8 +148,7 @@ protected override Task ReadSensor() conditions = new MagneticField3D( new MagneticField(x * 0.00625, MagneticField.UnitType.MicroTesla), new MagneticField(y * 0.00625, MagneticField.UnitType.MicroTesla), - new MagneticField(z * 0.00625, MagneticField.UnitType.MicroTesla) - ); + new MagneticField(z * 0.00625, MagneticField.UnitType.MicroTesla)); return conditions; }); @@ -157,28 +161,28 @@ protected override Task ReadSensor() /// public async Task ReadTemperature() { - if(ContinuousModeEnabled) + if (ContinuousModeEnabled) { throw new Exception("Cannot read temperature while continous sampling mode is enabled"); } - if(IsTemperatureDataReady() == false) + if (IsTemperatureDataReady() == false) { await TriggerTemperatureReading(); } - return new Units.Temperature((sbyte)Peripheral.ReadRegister(Registers.TEMPERATURE) * 0.8 - 75, Units.Temperature.UnitType.Celsius); + return new Units.Temperature((sbyte)BusComms.ReadRegister(Registers.TEMPERATURE) * 0.8 - 75, Units.Temperature.UnitType.Celsius); } bool IsTemperatureDataReady() { - var value = Peripheral.ReadRegister(Registers.STATUS); + var value = BusComms.ReadRegister(Registers.STATUS); return BitHelpers.GetBitValue(value, 7); } bool IsMagneticDataReady() { - var value = Peripheral.ReadRegister(Registers.STATUS); + var value = BusComms.ReadRegister(Registers.STATUS); return BitHelpers.GetBitValue(value, 6); } } diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mmc5603/Driver/Sensors.Motion.Mmc5603.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mmc5603/Driver/Sensors.Motion.Mmc5603.csproj index 6de72f5c57..bed6545694 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mmc5603/Driver/Sensors.Motion.Mmc5603.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mmc5603/Driver/Sensors.Motion.Mmc5603.csproj @@ -18,6 +18,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mmc5603/Samples/Mmc5603_Sample/Mmc5603_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mmc5603/Samples/Mmc5603_Sample/Mmc5603_Sample.csproj index 27c5716ec9..6fbd15eff7 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mmc5603/Samples/Mmc5603_Sample/Mmc5603_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mmc5603/Samples/Mmc5603_Sample/Mmc5603_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mpu6050/Driver/Mpu6050.Addresses.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mpu6050/Driver/Mpu6050.Addresses.cs index 9ca4668d4d..ab7b22ea57 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mpu6050/Driver/Mpu6050.Addresses.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mpu6050/Driver/Mpu6050.Addresses.cs @@ -3,7 +3,7 @@ public partial class Mpu6050 { /// - /// Valid addresses for the sensor + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mpu6050/Driver/Mpu6050.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mpu6050/Driver/Mpu6050.cs index b11abc602e..24ac3f6c24 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mpu6050/Driver/Mpu6050.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mpu6050/Driver/Mpu6050.cs @@ -8,32 +8,28 @@ namespace Meadow.Foundation.Sensors.Motion { - // Sample reading: - // Accel: [X:0.24,Y:-0.74,Z:10.49 (m/s^2)] - // Angular Velocity: [X:-0.90, Y:-1.24, Z:-0.52 (dps)] - // Temp: 33.33C - - // TODO: this sensor has software controlled sensitivity ranges. we should - // expose them. note the `AccelScaleBase` will need to change. Right now it's - // hard coded to +-2G - /// /// Represents an MPU6050 Six-Axis (Gyro + Accelerometer) MEMS MotionTracking device /// public partial class Mpu6050 : ByteCommsSensorBase<(Acceleration3D? Acceleration3D, AngularVelocity3D? AngularVelocity3D, Units.Temperature? Temperature)>, - IAccelerometer, IGyroscope, ITemperatureSensor + IAccelerometer, IGyroscope, ITemperatureSensor, II2cPeripheral { + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + /// /// Raised when the acceration value changes /// public event EventHandler> Acceleration3DUpdated = delegate { }; - + /// /// Raised when the angular acceleration value changes /// public event EventHandler> AngularVelocity3DUpdated = delegate { }; - + /// /// Raised when the temperature value changes /// @@ -85,7 +81,7 @@ public void Wake() { WriteBuffer.Span[0] = Registers.POWER_MANAGEMENT; WriteBuffer.Span[1] = 0x00; - Peripheral?.Write(WriteBuffer.Span[0..2]); + BusComms?.Write(WriteBuffer.Span[0..2]); LoadConfiguration(); } @@ -96,7 +92,7 @@ public void Wake() protected void LoadConfiguration() { // read all 3 config bytes - Peripheral?.ReadRegister(Registers.CONFIG, ReadBuffer.Span[0..3]); + BusComms?.ReadRegister(Registers.CONFIG, ReadBuffer.Span[0..3]); GyroScale = (ReadBuffer.Span[1] & 0b00011000) >> 3; AccelerometerScale = (ReadBuffer.Span[2] & 0b00011000) >> 3; @@ -129,38 +125,29 @@ protected override void RaiseEventsAndNotify(IChangeResult<(Acceleration3D? Acce /// The latest sensor reading protected override Task<(Acceleration3D? Acceleration3D, AngularVelocity3D? AngularVelocity3D, Units.Temperature? Temperature)> ReadSensor() { - return Task.Run(() => - { - (Acceleration3D? Acceleration3D, AngularVelocity3D? AngularVelocity3D, Units.Temperature? Temperature) conditions; - - // we'll just read 14 bytes (7 registers), starting at 0x3b - Peripheral?.ReadRegister(Registers.ACCELEROMETER_X, ReadBuffer.Span); - - //---- acceleration - // get the acceleration 3d - var a_scale = (1 << AccelerometerScale) / AccelScaleBase; - var g_scale = (1 << GyroScale) / GyroScaleBase; - // note that this comes back as mg (1/10 of m/s^2) which is 0.01m/s^2, so we have to multiply by 10 - Acceleration3D newAccel = new Acceleration3D( - new Acceleration(ScaleAndOffset(ReadBuffer.Span, 0, a_scale) * 10, Acceleration.UnitType.MetersPerSecondSquared), - new Acceleration(ScaleAndOffset(ReadBuffer.Span, 2, a_scale) * 10, Acceleration.UnitType.MetersPerSecondSquared), - new Acceleration(ScaleAndOffset(ReadBuffer.Span, 4, a_scale) * 10, Acceleration.UnitType.MetersPerSecondSquared) - ); - conditions.Acceleration3D = newAccel; - - //---- temp - conditions.Temperature = new Units.Temperature(ScaleAndOffset(ReadBuffer.Span, 6, 1 / 340f, 36.53f), TU.Celsius); - - //---- angular acceleration - AngularVelocity3D angularVelocity = new AngularVelocity3D( - new AngularVelocity(ScaleAndOffset(ReadBuffer.Span, 8, g_scale), AngularVelocity.UnitType.DegreesPerSecond), - new AngularVelocity(ScaleAndOffset(ReadBuffer.Span, 10, g_scale), AngularVelocity.UnitType.DegreesPerSecond), - new AngularVelocity(ScaleAndOffset(ReadBuffer.Span, 12, g_scale), AngularVelocity.UnitType.DegreesPerSecond) - ); - conditions.AngularVelocity3D = angularVelocity; - - return conditions; - }); + (Acceleration3D? Acceleration3D, AngularVelocity3D? AngularVelocity3D, Units.Temperature? Temperature) conditions; + + // Read 14 bytes (7 registers), starting at 0x3b + BusComms?.ReadRegister(Registers.ACCELEROMETER_X, ReadBuffer.Span); + + var a_scale = (1 << AccelerometerScale) / AccelScaleBase; + var g_scale = (1 << GyroScale) / GyroScaleBase; + // note that this comes back as mg (1/10 of m/s^2) which is 0.01m/s^2, so we have to multiply by 10 + Acceleration3D newAccel = new Acceleration3D( + new Acceleration(ScaleAndOffset(ReadBuffer.Span, 0, a_scale) * 10, Acceleration.UnitType.MetersPerSecondSquared), + new Acceleration(ScaleAndOffset(ReadBuffer.Span, 2, a_scale) * 10, Acceleration.UnitType.MetersPerSecondSquared), + new Acceleration(ScaleAndOffset(ReadBuffer.Span, 4, a_scale) * 10, Acceleration.UnitType.MetersPerSecondSquared)); + conditions.Acceleration3D = newAccel; + + conditions.Temperature = new Units.Temperature(ScaleAndOffset(ReadBuffer.Span, 6, 1 / 340f, 36.53f), TU.Celsius); + + AngularVelocity3D angularVelocity = new AngularVelocity3D( + new AngularVelocity(ScaleAndOffset(ReadBuffer.Span, 8, g_scale), AngularVelocity.UnitType.DegreesPerSecond), + new AngularVelocity(ScaleAndOffset(ReadBuffer.Span, 10, g_scale), AngularVelocity.UnitType.DegreesPerSecond), + new AngularVelocity(ScaleAndOffset(ReadBuffer.Span, 12, g_scale), AngularVelocity.UnitType.DegreesPerSecond)); + conditions.AngularVelocity3D = angularVelocity; + + return Task.FromResult(conditions); } private float ScaleAndOffset(Span data, int index, float scale, float offset = 0) diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mpu6050/Driver/Sensors.Motion.Mpu6050.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mpu6050/Driver/Sensors.Motion.Mpu6050.csproj index e9e0c5d39c..46217a5c45 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mpu6050/Driver/Sensors.Motion.Mpu6050.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mpu6050/Driver/Sensors.Motion.Mpu6050.csproj @@ -25,6 +25,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mpu6050/Samples/Mpu6050_Sample/Mpu6050_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mpu6050/Samples/Mpu6050_Sample/Mpu6050_Sample.csproj index 14435938aa..77f82e46b7 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mpu6050/Samples/Mpu6050_Sample/Mpu6050_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.Mpu6050/Samples/Mpu6050_Sample/Mpu6050_Sample.csproj @@ -12,7 +12,7 @@ 8.0 - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.ParallaxPir/Driver/Sensors.Motion.ParallaxPir.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.ParallaxPir/Driver/Sensors.Motion.ParallaxPir.csproj index 444ee43356..fb4171f9f6 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.ParallaxPir/Driver/Sensors.Motion.ParallaxPir.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.ParallaxPir/Driver/Sensors.Motion.ParallaxPir.csproj @@ -10,13 +10,13 @@ http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ Meadow.Foundation.Sensors.Motion.ParallaxPir https://github.com/WildernessLabs/Meadow.Foundation - Meadow, Meadow.Foundation, Motion, Parallax, PIR + Meadow,Meadow.Foundation,Motion,Parallax,PIR 0.8.55 true Parallax PIR analog motion sensor - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.ParallaxPir/Samples/ParallaxPir_Sample/ParallaxPir_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.ParallaxPir/Samples/ParallaxPir_Sample/ParallaxPir_Sample.csproj index b33234c529..4b3211b99a 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Motion.ParallaxPir/Samples/ParallaxPir_Sample/ParallaxPir_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Motion.ParallaxPir/Samples/ParallaxPir_Sample/ParallaxPir_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Power.Ina260/Driver/Ina260.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Power.Ina260/Driver/Ina260.Enums.cs index 533261dc27..15ded9391e 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Power.Ina260/Driver/Ina260.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Power.Ina260/Driver/Ina260.Enums.cs @@ -8,7 +8,7 @@ namespace Meadow.Foundation.Sensors.Power public partial class Ina260 { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Power.Ina260/Driver/Ina260.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Power.Ina260/Driver/Ina260.cs index f977dba79a..7f1c161644 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Power.Ina260/Driver/Ina260.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Power.Ina260/Driver/Ina260.cs @@ -9,8 +9,14 @@ namespace Meadow.Foundation.Sensors.Power /// Represents a INA260 Precision Digital Current and Power Monitor /// public partial class Ina260 - : ByteCommsSensorBase<(Units.Power? Power, Units.Voltage? Voltage, Units.Current? Current)> + : ByteCommsSensorBase<(Units.Power? Power, Voltage? Voltage, Current? Current)>, + II2cPeripheral { + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + /// /// Raised when the power value changes /// @@ -19,24 +25,24 @@ public partial class Ina260 /// /// Raised when the voltage value changes /// - public event EventHandler> VoltageUpdated = delegate { }; + public event EventHandler> VoltageUpdated = delegate { }; /// /// Raised when the current value changes /// - public event EventHandler> CurrentUpdated = delegate { }; + public event EventHandler> CurrentUpdated = delegate { }; private const float MeasurementScale = 0.00125f; /// /// The value of the current (in Amps) flowing through the shunt resistor from the last reading /// - public Units.Current? Current => Conditions.Current; + public Current? Current => Conditions.Current; /// /// The voltage from the last reading.. /// - public Units.Voltage? Voltage => Conditions.Voltage; + public Voltage? Voltage => Conditions.Voltage; /// /// The power from the last reading.. @@ -48,9 +54,7 @@ public partial class Ina260 /// /// The I2C bus /// The I2C address - /// - public Ina260(II2cBus i2cBus, - byte address = (byte)Addresses.Default) + public Ina260(II2cBus i2cBus, byte address = (byte)Addresses.Default) : base(i2cBus, address) { switch (address) @@ -68,24 +72,22 @@ public Ina260(II2cBus i2cBus, /// Reads data from the sensor /// /// The latest sensor reading - protected override async Task<(Units.Power? Power, Voltage? Voltage, Current? Current)> ReadSensor() + protected override Task<(Units.Power? Power, Voltage? Voltage, Current? Current)> ReadSensor() { - return await Task.Run(() => - { - (Units.Power? Power, Units.Voltage? Voltage, Units.Current? Current) conditions; - conditions.Voltage = new Units.Voltage(Peripheral.ReadRegister((byte)Register.Voltage) * MeasurementScale, Units.Voltage.UnitType.Volts); - conditions.Current = new Units.Current(Peripheral.ReadRegister((byte)Register.Current) * MeasurementScale, Units.Current.UnitType.Amps); - conditions.Power = new Units.Power(Peripheral.ReadRegister((byte)Register.Power) * 0.01f, Units.Power.UnitType.Watts); + (Units.Power? Power, Voltage? Voltage, Current? Current) conditions; + + conditions.Voltage = new Voltage(BusComms.ReadRegister((byte)Register.Voltage) * MeasurementScale, Units.Voltage.UnitType.Volts); + conditions.Current = new Current(BusComms.ReadRegister((byte)Register.Current) * MeasurementScale, Units.Current.UnitType.Amps); + conditions.Power = new Units.Power(BusComms.ReadRegister((byte)Register.Power) * 0.01f, Units.Power.UnitType.Watts); - return conditions; - }); + return Task.FromResult(conditions); } /// /// Raise events for subcribers and notify of value changes /// /// The updated sensor data - protected override void RaiseEventsAndNotify(IChangeResult<(Units.Power? Power, Units.Voltage? Voltage, Units.Current? Current)> changeResult) + protected override void RaiseEventsAndNotify(IChangeResult<(Units.Power? Power, Voltage? Voltage, Current? Current)> changeResult) { if (changeResult.New.Power is { } power) { @@ -93,11 +95,11 @@ protected override void RaiseEventsAndNotify(IChangeResult<(Units.Power? Power, } if (changeResult.New.Voltage is { } volts) { - VoltageUpdated?.Invoke(this, new ChangeResult(volts, changeResult.Old?.Voltage)); + VoltageUpdated?.Invoke(this, new ChangeResult(volts, changeResult.Old?.Voltage)); } if (changeResult.New.Current is { } amps) { - CurrentUpdated?.Invoke(this, new ChangeResult(amps, changeResult.Old?.Current)); + CurrentUpdated?.Invoke(this, new ChangeResult(amps, changeResult.Old?.Current)); } base.RaiseEventsAndNotify(changeResult); @@ -106,11 +108,11 @@ protected override void RaiseEventsAndNotify(IChangeResult<(Units.Power? Power, /// /// Reads the unique manufacturer identification number /// - public int ManufacturerID => Peripheral.ReadRegister((byte)Register.ManufacturerID); + public int ManufacturerID => BusComms.ReadRegister((byte)Register.ManufacturerID); /// /// Reads the unique die identification number /// - public int DieID => Peripheral.ReadRegister((byte)Register.ManufacturerID); + public int DieID => BusComms.ReadRegister((byte)Register.ManufacturerID); } } \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Power.Ina260/Driver/Sensors.Power.Ina260.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Power.Ina260/Driver/Sensors.Power.Ina260.csproj index 7f5aa69197..63ec7817d2 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Power.Ina260/Driver/Sensors.Power.Ina260.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Power.Ina260/Driver/Sensors.Power.Ina260.csproj @@ -15,14 +15,11 @@ true INA260 I2C current and power monitor - - 8.0 - - - 8.0 + + 10.0 - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Power.Ina260/Samples/Ina260_Sample/Ina260_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Power.Ina260/Samples/Ina260_Sample/Ina260_Sample.csproj index 498e9b6ae9..3933dab743 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Power.Ina260/Samples/Ina260_Sample/Ina260_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Power.Ina260/Samples/Ina260_Sample/Ina260_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Radio.Rfid.IDxxLA/Driver/Sensors.Radio.Rfid.IDxxLA.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Radio.Rfid.IDxxLA/Driver/Sensors.Radio.Rfid.IDxxLA.csproj index 5db0b5833c..04bc9fc1d4 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Radio.Rfid.IDxxLA/Driver/Sensors.Radio.Rfid.IDxxLA.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Radio.Rfid.IDxxLA/Driver/Sensors.Radio.Rfid.IDxxLA.csproj @@ -10,13 +10,13 @@ http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ Meadow.Foundation.Sensors.Radio.Rfid.IDxxLA https://github.com/WildernessLabs/Meadow.Foundation - Meadow, Meadow.Foundation, RFID, ID-2LA, ID-12LA, ID-20LA + Meadow,Meadow.Foundation,RFID,ID-2LA,ID-12LA,ID-20LA 0.1.50 true IDxxLA Serial radio frequency ID readers - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Radio.Rfid.IDxxLA/Samples/IDxxLA_Sample/IDxxLA_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Radio.Rfid.IDxxLA/Samples/IDxxLA_Sample/IDxxLA_Sample.csproj index 88fcc8848f..f01b1f3414 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Radio.Rfid.IDxxLA/Samples/IDxxLA_Sample/IDxxLA_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Radio.Rfid.IDxxLA/Samples/IDxxLA_Sample/IDxxLA_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Sound.Ky038/Driver/Sensors.Sound.Ky038.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Sound.Ky038/Driver/Sensors.Sound.Ky038.csproj index ae14bdc85e..65775ebdcb 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Sound.Ky038/Driver/Sensors.Sound.Ky038.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Sound.Ky038/Driver/Sensors.Sound.Ky038.csproj @@ -10,13 +10,13 @@ http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ Meadow.Foundation.Sensors.Sound.Ky038 https://github.com/WildernessLabs/Meadow.Foundation - Meadow.Foundation, KY-038, Sound, KY038 + Meadow.Foundation,KY-038,Sound,KY038 0.1.49 true KY-038 analog sound sensor - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Sound.Ky038/Samples/Ky038_Sample/Ky038_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Sound.Ky038/Samples/Ky038_Sample/Ky038_Sample.csproj index 76be9d4090..5281294c2d 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Sound.Ky038/Samples/Ky038_Sample/Ky038_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Sound.Ky038/Samples/Ky038_Sample/Ky038_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Lm75/Driver/Lm75.Addresses.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Lm75/Driver/Lm75.Addresses.cs index 0b67a2d964..4f8a4401a3 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Lm75/Driver/Lm75.Addresses.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Lm75/Driver/Lm75.Addresses.cs @@ -3,7 +3,7 @@ public partial class Lm75 { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Lm75/Driver/Lm75.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Lm75/Driver/Lm75.cs index 93ba55e952..f50ddf9f2e 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Lm75/Driver/Lm75.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Lm75/Driver/Lm75.cs @@ -8,8 +8,14 @@ namespace Meadow.Foundation.Sensors.Temperature /// /// TMP102 Temperature sensor object /// - public partial class Lm75 : ByteCommsSensorBase, ITemperatureSensor + public partial class Lm75 : ByteCommsSensorBase, + ITemperatureSensor, II2cPeripheral { + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + /// /// Raised when the value of the reading changes /// @@ -35,32 +41,27 @@ public Lm75(II2cBus i2cBus, byte address = (byte)Addresses.Default) /// protected override Task ReadSensor() { - return Task.Run(() => - { - Peripheral?.Write((byte)Registers.LM_TEMP); + BusComms?.Write((byte)Registers.LM_TEMP); - Peripheral?.ReadRegister((byte)Registers.LM_TEMP, ReadBuffer.Span[0..2]); + BusComms?.ReadRegister((byte)Registers.LM_TEMP, ReadBuffer.Span[0..2]); - // Details in Datasheet P10 - double temp = 0; - ushort raw = (ushort)((ReadBuffer.Span[0] << 3) | (ReadBuffer.Span[1] >> 5)); - if ((ReadBuffer.Span[0] & 0x80) == 0) - { - // temperature >= 0 - temp = raw * 0.125; - } - else - { - raw |= 0xF800; - raw = (ushort)(~raw + 1); - - temp = raw * (-1) * 0.125; - } + // Details in Datasheet P10 + double temp; + ushort raw = (ushort)((ReadBuffer.Span[0] << 3) | (ReadBuffer.Span[1] >> 5)); + if ((ReadBuffer.Span[0] & 0x80) == 0) + { + // temperature >= 0 + temp = raw * 0.125; + } + else + { + raw |= 0xF800; + raw = (ushort)(~raw + 1); - //only accurate to +/- 0.1 degrees - return (new Units.Temperature((float)Math.Round(temp, 1), Units.Temperature.UnitType.Celsius)); + temp = raw * (-1) * 0.125; + } - }); + return Task.FromResult(new Units.Temperature((float)Math.Round(temp, 1), Units.Temperature.UnitType.Celsius)); } /// diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Lm75/Driver/Sensors.Temperature.Lm75.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Lm75/Driver/Sensors.Temperature.Lm75.csproj index 8d592f5407..2f7c3327d3 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Lm75/Driver/Sensors.Temperature.Lm75.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Lm75/Driver/Sensors.Temperature.Lm75.csproj @@ -17,14 +17,11 @@ enable Meadow.Foundation.Sensors.Temperature - - 8.0 - - - 8.0 + + 10.0 - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Lm75/Samples/Lm75_Sample/Lm75_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Lm75/Samples/Lm75_Sample/Lm75_Sample.csproj index 2a06b215b4..5a9abc816a 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Lm75/Samples/Lm75_Sample/Lm75_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Lm75/Samples/Lm75_Sample/Lm75_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Datasheet/MCP960X-L0X-RL0X-Data-Sheet-20005426F.pdf b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Datasheet/MCP960X-L0X-RL0X-Data-Sheet-20005426F.pdf new file mode 100644 index 0000000000..00d3c07d2b Binary files /dev/null and b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Datasheet/MCP960X-L0X-RL0X-Data-Sheet-20005426F.pdf differ diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Driver/Drivers/Mcp9600.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Driver/Drivers/Mcp9600.cs new file mode 100644 index 0000000000..c118755f7d --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Driver/Drivers/Mcp9600.cs @@ -0,0 +1,19 @@ +using Meadow.Hardware; + +namespace Meadow.Foundation.Sensors.Temperature +{ + /// + /// Represents a Mcp9600 Thermocouple sensor object + /// + public partial class Mcp9600 : Mcp960x + { + /// + /// Create a new Mcp9600 object using the default configuration for the sensor + /// + /// The I2C bus + /// I2C address of the sensor + public Mcp9600(II2cBus i2cBus, byte address = (byte)Addresses.Default) : base(i2cBus, address) + { + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Driver/Drivers/Mcp9601.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Driver/Drivers/Mcp9601.cs new file mode 100644 index 0000000000..bdf771d233 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Driver/Drivers/Mcp9601.cs @@ -0,0 +1,19 @@ +using Meadow.Hardware; + +namespace Meadow.Foundation.Sensors.Temperature +{ + /// + /// Represents a Mcp9601 Thermocouple sensor object + /// + public partial class Mcp9601 : Mcp960x + { + /// + /// Create a new Mcp9601 object using the default configuration for the sensor + /// + /// The I2C bus + /// I2C address of the sensor + public Mcp9601(II2cBus i2cBus, byte address = (byte)Addresses.Default) : base(i2cBus, address) + { + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Driver/Mcp960x.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Driver/Mcp960x.Enums.cs new file mode 100644 index 0000000000..b7dbd3f6d1 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Driver/Mcp960x.Enums.cs @@ -0,0 +1,172 @@ +namespace Meadow.Foundation.Sensors.Temperature +{ + public partial class Mcp960x + { + /// + /// Valid I2C addresses for the sensor + /// + public enum Addresses : byte + { + /// + /// Bus address 0x60 + /// + Address_0x60 = 0x60, + /// + /// Bus address 0x61 + /// + Address_0x61 = 0x61, + /// + /// Bus address 0x62 + /// + Address_0x62 = 0x62, + /// + /// Bus address 0x63 + /// + Address_0x63 = 0x63, + /// + /// Bus address 0x64 + /// + Address_0x64 = 0x64, + /// + /// Bus address 0x65 + /// + Address_0x65 = 0x65, + /// + /// Bus address 0x60 + /// + Address_0x66 = 0x66, + /// + /// Bus address 0x66 + /// + Address_0x67 = 0x67, + /// + /// Default bus address 0x67 + /// + Default = Address_0x67 + } + + /// + /// Represents the supported thermocouple types for the MCP960x + /// + public enum ThermocoupleType + { + /// + /// K-type thermocouple (chromel–alumel), widely used due to its broad temperature range and durability + /// + K = 0x00, + /// + /// J-type thermocouple (iron–constantan), commonly used in general-purpose applications + /// + J = 0x01, + /// + /// T-type thermocouple (copper–constantan), suitable for low-temperature measurements + /// + T = 0x02, + /// + /// N-type thermocouple (nicrosil–nisil), known for its stability and resistance to high temperatures + /// + N = 0x03, + /// + /// S-type thermocouple (platinum–rhodium), suitable for high-temperature measurements + /// + S = 0x04, + /// + /// E-type thermocouple (chromel–constantan), featuring a high output signal and excellent stability + /// + E = 0x05, + /// + /// B-type thermocouple (platinum–rhodium), used for very high-temperature measurements + /// + B = 0x06, + /// + /// R-type thermocouple (platinum–rhodium), suitable for high-temperature measurements + /// + R = 0x07 + } + + /// + /// Represents the available ADC resolutions for the MCP960x + /// + public enum AdcResolution + { + /// + /// 18-bit ADC resolution, providing the fastest conversion time + /// + _18Bit = 0x00, + /// + /// 16-bit ADC resolution, providing a balance between conversion time and resolution + /// + _16Bit = 0x01, + /// + /// 14-bit ADC resolution, providing a slower conversion time but higher resolution + /// + _14Bit = 0x02, + /// + /// 12-bit ADC resolution, providing the slowest conversion time but highest resolution + /// + _12Bit = 0x03 + } + + /// + /// Represents the available filter coefficients for the MCP960x + /// + public enum FilterCoefficient + { + /// + /// Filter coefficient value 0 + /// + _0 = 0x00, + /// + /// Filter coefficient value 1 + /// + _1 = 0x01, + /// + /// Filter coefficient value 2 + /// + _2 = 0x02, + /// + /// Filter coefficient value 3 + /// + _3 = 0x03, + /// + /// Filter coefficient value 4 + /// + _4 = 0x04, + /// + /// Filter coefficient value 5 + /// + _5 = 0x05, + /// + /// Filter coefficient value 4 + /// + _6 = 0x06, + /// + /// Filter coefficient value 5 + /// + _7 = 0x07 + } + + /// + /// Represents the alert number for the MCP9600 + /// + public enum AlertNumber + { + /// + /// Alert number 1 + /// + Alert1 = 1, + /// + /// Alert number 2 + /// + Alert2 = 2, + /// + /// Alert number 3 + /// + Alert3 = 3, + /// + /// Alert number 4 + /// + Alert4 = 4 + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Driver/Mcp960x.Registers.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Driver/Mcp960x.Registers.cs new file mode 100644 index 0000000000..2528d1b8e2 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Driver/Mcp960x.Registers.cs @@ -0,0 +1,25 @@ +namespace Meadow.Foundation.Sensors.Temperature +{ + public partial class Mcp960x + { + const byte HOTJUNCTION = 0x00; // Hot junction temperature T_H + const byte JUNCTIONDELTA = 0x01; // Hot/Cold junction delta + const byte COLDJUNCTION = 0x02; // Cold junction temperature T_C + const byte RAWDATAADC = 0x03; // The raw uV reading + const byte STATUS = 0x04; // Current device status + const byte SENSORCONFIG = 0x05; // Configuration for thermocouple type + const byte DEVICECONFIG = 0x06; // Device config like sleep mode + const byte DEVICEID = 0x20; // Device ID/Revision + const byte ALERTCONFIG_1 = 0x08; // The first alert's config + const byte ALERTHYST_1 = 0x0C; // The first alert's hystersis + const byte ALERTLIMIT_1 = 0x10; // the first alert's limitval + + const byte STATUS_ALERT1 = 0x01; // Bit flag for alert 1 status + const byte STATUS_ALERT2 = 0x02; // Bit flag for alert 2 status + const byte STATUS_ALERT3 = 0x04; // Bit flag for alert 3 status + const byte STATUS_ALERT4 = 0x08; // Bit flag for alert 4 status + const byte STATUS_INPUTRANGE = 0x10; // Bit flag for input range + const byte STATUS_THUPDATE = 0x40; // Bit flag for TH update + const byte STATUS_BURST = 0x80; // Bit flag for burst complete + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Driver/Mcp960x.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Driver/Mcp960x.cs new file mode 100644 index 0000000000..5d34d9d606 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Driver/Mcp960x.cs @@ -0,0 +1,301 @@ +using Meadow.Hardware; +using Meadow.Peripherals.Sensors; +using System; +using System.Threading.Tasks; + +namespace Meadow.Foundation.Sensors.Temperature +{ + /// + /// Represents a Mcp960x Thermocouple sensor object + /// + public abstract partial class Mcp960x : + ByteCommsSensorBase<(Units.Temperature? TemperatureHot, Units.Temperature? TemperatureCold)>, + ITemperatureSensor, II2cPeripheral + { + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + + /// + /// Raised when the Hot temperature value changes + /// + public event EventHandler> TemperatureUpdated = delegate { }; + + /// + /// Raised when the Hot temperature value changes + /// + public event EventHandler> TemperatureHotUpdated = delegate { }; + + /// + /// Raised when the Cold / ambient temperature value changes + /// + public event EventHandler> TemperatureColdUpdated = delegate { }; + + /// + /// The Hot Temperature value from the last reading + /// + public Units.Temperature? Temperature => TemperatureHot; + + /// + /// The Hot Temperature value from the last reading + /// + public Units.Temperature? TemperatureHot { get; protected set; } + + /// + /// The Cold Temperature value from the last reading + /// + public Units.Temperature? TemperatureCold { get; protected set; } + + /// + /// Create a new Mcp960x object using the default configuration for the sensor + /// + /// The I2C bus + /// I2C address of the sensor + public Mcp960x(II2cBus i2cBus, byte address) + : base(i2cBus, address) + { + if (BusComms == null) + { + throw new NullReferenceException("Mcp960x peripheral did not initialize"); + } + + BusComms.WriteRegister(DEVICECONFIG, 0x80); + } + + /// + /// Update the Temperature property + /// + protected override Task<(Units.Temperature? TemperatureHot, Units.Temperature? TemperatureCold)> ReadSensor() + { + (Units.Temperature? TemperatureHot, Units.Temperature? TemperatureCold) conditions; + + conditions.TemperatureHot = new Units.Temperature(ReadTemperatureHot(), Units.Temperature.UnitType.Celsius); + conditions.TemperatureCold = new Units.Temperature(ReadTemperatureCold(), Units.Temperature.UnitType.Celsius); + + return Task.FromResult(conditions); + } + + /// + /// Reads the hot junction temperature from the MCP960x + /// + /// The hot junction temperature in degrees Celsius + double ReadTemperatureHot() + { + byte[] readBuffer = new byte[2]; + + BusComms?.ReadRegister(HOTJUNCTION, readBuffer); + + int rawTemp = (readBuffer[0] << 8) | readBuffer[1]; + double temperature = rawTemp * 0.0625; + + return temperature; + } + + /// + /// Reads the cold/ambient temperature from the MCP960x + /// + /// The cold/ambient temperature in degrees Celsius + double ReadTemperatureCold() + { + byte[] readBuffer = new byte[2]; + + BusComms?.ReadRegister(COLDJUNCTION, readBuffer); + + int rawTemp = (readBuffer[0] << 8) | readBuffer[1]; + double temperature = rawTemp * 0.0625; + + return temperature; + } + + /// + /// Sets the thermocouple type for the MCP960x + /// + /// The thermocouple type to set + public void SetThermocoupleType(ThermocoupleType type) + { + byte config = BusComms.ReadRegister(SENSORCONFIG); + + config = (byte)((config & 0xF8) | (byte)type); + + BusComms.WriteRegister(SENSORCONFIG, config); + } + + /// + /// Gets the thermocouple type currently configured for the MCP960x + /// + /// The currently configured thermocouple type + public ThermocoupleType GetThermocoupleType() + { + byte config = BusComms.ReadRegister(SENSORCONFIG); + + return (ThermocoupleType)(config & 0x07); + } + + /// + /// Sets the ADC resolution for the MCP960x + /// + /// The ADC resolution to set + public void SetAdcResolution(AdcResolution resolution) + { + byte config = BusComms.ReadRegister(SENSORCONFIG); + + config = (byte)((config & 0x9F) | ((byte)resolution << 5)); + + BusComms.WriteRegister(SENSORCONFIG, config); + } + + /// + /// Gets the ADC resolution currently configured for the MCP960x + /// + /// The currently configured ADC resolution + public AdcResolution GetAdcResolution() + { + byte config = BusComms.ReadRegister(SENSORCONFIG); + + return (AdcResolution)((config & 0x60) >> 5); + } + + /// + /// Sets the filter coefficient for the MCP960x + /// + /// The filter coefficient to set + public void SetFilterCoefficient(FilterCoefficient coefficient) + { + byte config = BusComms.ReadRegister(SENSORCONFIG); + + config = (byte)((config & 0xF8) | ((byte)coefficient & 0x07)); + + BusComms.WriteRegister(SENSORCONFIG, config); + } + + /// + /// Gets the filter coefficient for the MCP960x + /// + /// The currently configured filter coefficient + public FilterCoefficient GetFilterCoefficient() + { + byte config = BusComms.ReadRegister(SENSORCONFIG); + + return (FilterCoefficient)(config & 0x07); + } + + /// + /// Sets the alert temperature for the specified alert number of the MCP960x + /// + /// The alert number (1-4) to set the temperature for + /// The temperature value + public void SetAlertTemperature(AlertNumber alertNumber, Units.Temperature temperature) + { + if (alertNumber < AlertNumber.Alert1 || alertNumber > AlertNumber.Alert4) + { + throw new ArgumentOutOfRangeException("Alert number must be between Alert1 and Alert4."); + } + + short tempData = (short)(temperature.Celsius / 0.0625); + + BusComms.WriteRegister((byte)(ALERTLIMIT_1 + ((int)alertNumber - 1) * 2), new byte[] { (byte)(tempData >> 8), (byte)(tempData & 0xFF) }); + } + + /// + /// Gets the alert temperature for the specified alert number of the MCP960x + /// + /// The alert number (1-4) to get the temperature for + /// The alert temperature value + public Units.Temperature GetAlertTemperature(AlertNumber alertNumber) + { + if (alertNumber < AlertNumber.Alert1 || alertNumber > AlertNumber.Alert4) + { + throw new ArgumentOutOfRangeException("Alert number must be between Alert1 and Alert4."); + } + + byte[] readBuffer = new byte[2]; + + BusComms.ReadRegister((byte)(ALERTLIMIT_1 + ((int)alertNumber - 1) * 2), readBuffer); + + ushort tempData = (ushort)((readBuffer[0] << 8) | readBuffer[1]); + double temperature = tempData / 16.0; + + return new Units.Temperature(temperature, Units.Temperature.UnitType.Celsius); + } + + /// + /// Configures the alert settings for the MCP960x + /// + /// The alert number (Alert1-Alert4) to configure + /// Whether the alert is enabled + /// Whether the alert triggers on a rising temperature. Set to false for falling temperature + /// Whether the alert triggers on cold junction temperature. Set to false for thermocouple temperature + /// Whether the alert pin is active high. Set to false for active low + /// Whether the alert pin is in interrupt mode. Set to false for comparator mode + public void ConfigureAlert(AlertNumber alertNumber, bool enabled, bool rising, bool alertColdJunction, bool activeHigh, bool interruptMode) + { + if (alertNumber < AlertNumber.Alert1 || alertNumber > AlertNumber.Alert4) + { + throw new ArgumentOutOfRangeException("Alert number must be between Alert1 and Alert4."); + } + + byte configValue = 0; + + if (enabled) configValue |= 0x01; + if (interruptMode) configValue |= 0x02; + if (activeHigh) configValue |= 0x04; + if (rising) configValue |= 0x08; + if (alertColdJunction) configValue |= 0x10; + + BusComms.WriteRegister((byte)(ALERTCONFIG_1 + ((int)alertNumber - 1)), configValue); + } + + /// + /// Enables or disables the MCP960x sensor + /// + /// True to enable the sensor, false to enter sleep mode + public void Enable(bool enable) + { + byte config = BusComms.ReadRegister(DEVICECONFIG); + + config &= 0b1111_1100; // Clear bits 0 and 1 + + if (!enable) // Sleep mode + { + config |= 0x01; + } + + BusComms.WriteRegister(DEVICECONFIG, config); + } + + /// + /// Checks whether the MCP960x sensor is enabled and working or in sleep mode + /// + /// True if in awake mode, false if in sleep mode + public bool IsEnabled() + { + byte config = BusComms.ReadRegister(DEVICECONFIG); + int statusBits = (config & 0b11); + + return statusBits == 0; + } + + /// + /// Raise events for subcribers and notify of value changes + /// + /// The updated sensor data + protected override void RaiseEventsAndNotify(IChangeResult<(Units.Temperature? TemperatureHot, Units.Temperature? TemperatureCold)> changeResult) + { + if (changeResult.New.TemperatureHot is { } hot) + { + TemperatureUpdated?.Invoke(this, new ChangeResult(hot, changeResult.Old?.TemperatureHot)); + TemperatureHotUpdated?.Invoke(this, new ChangeResult(hot, changeResult.Old?.TemperatureHot)); + } + if (changeResult.New.TemperatureCold is { } cold) + { + TemperatureHotUpdated?.Invoke(this, new ChangeResult(cold, changeResult.Old?.TemperatureCold)); + } + + base.RaiseEventsAndNotify(changeResult); + } + + async Task ISensor.Read() + => (await Read()).TemperatureHot ?? throw new Exception("Temperature not available"); + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Driver/Sensors.Temperature.Mcp960x.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Driver/Sensors.Temperature.Mcp960x.csproj new file mode 100644 index 0000000000..1a75acf479 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Driver/Sensors.Temperature.Mcp960x.csproj @@ -0,0 +1,27 @@ + + + true + icon.png + Wilderness Labs, Inc + netstandard2.1 + Library + Mcp960x + Wilderness Labs, Inc + http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ + Meadow.Foundation.Sensors.Temperature.Mcp960x + https://github.com/WildernessLabs/Meadow.Foundation + Meadow.Foundation,Temperature,Thermocouple,Mcp9600,Mcp9601,Mcp960x + 0.1.0 + true + Mcp960x I2C thermocouple temperature sensor + enable + Meadow.Foundation.Sensors.Temperature + + + 10.0 + + + + + + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Samples/Mcp9600_Sample/Mcp9600_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Samples/Mcp9600_Sample/Mcp9600_Sample.csproj new file mode 100644 index 0000000000..d867cb748b --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Samples/Mcp9600_Sample/Mcp9600_Sample.csproj @@ -0,0 +1,20 @@ + + + https://github.com/WildernessLabs/Meadow.Foundation + Wilderness Labs, Inc + Wilderness Labs, Inc + true + netstandard2.1 + Library + App + + + + + + + + Always + + + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Samples/Mcp9600_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Samples/Mcp9600_Sample/MeadowApp.cs new file mode 100644 index 0000000000..1b7b67b244 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Samples/Mcp9600_Sample/MeadowApp.cs @@ -0,0 +1,45 @@ +using Meadow; +using Meadow.Devices; +using Meadow.Foundation.Sensors.Temperature; +using System.Threading.Tasks; + +namespace Sensors.Temperature.MCP9600_Sample +{ + public class MeadowApp : App + { + // + + Mcp9600 sensor; + + public override Task Initialize() + { + Resolver.Log.Info("Initialize..."); + + sensor = new Mcp9600(Device.CreateI2cBus()); + + var consumer = Mcp9600.CreateObserver( + handler: result => + { + Resolver.Log.Info($"Temperature New Value {result.New.TemperatureHot.Value.Celsius}C"); + }, + filter: null + ); + sensor.Subscribe(consumer); + + sensor.Updated += Sensor_Updated; + return Task.CompletedTask; + } + + private void Sensor_Updated(object sender, IChangeResult<(Meadow.Units.Temperature? TemperatureHot, Meadow.Units.Temperature? TemperatureCold)> e) + { + Resolver.Log.Info($"Temperature hot: {e.New.TemperatureHot.Value.Celsius:n2}C, Temperature cold: {e.New.TemperatureCold.Value.Celsius:n2}C"); + } + + public override async Task Run() + { + sensor.StartUpdating(); + } + + // + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Samples/Mcp9600_Sample/meadow.config.yaml b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Samples/Mcp9600_Sample/meadow.config.yaml new file mode 100644 index 0000000000..32363cb69c --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Samples/Mcp9600_Sample/meadow.config.yaml @@ -0,0 +1,2 @@ +MonoControl: + Options: --jit \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Samples/Mcp9601_Sample/Mcp9601_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Samples/Mcp9601_Sample/Mcp9601_Sample.csproj new file mode 100644 index 0000000000..090550a98d --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Samples/Mcp9601_Sample/Mcp9601_Sample.csproj @@ -0,0 +1,20 @@ + + + https://github.com/WildernessLabs/Meadow.Foundation + Wilderness Labs, Inc + Wilderness Labs, Inc + true + netstandard2.1 + Library + App + + + + + + + + Always + + + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Samples/Mcp9601_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Samples/Mcp9601_Sample/MeadowApp.cs new file mode 100644 index 0000000000..a7af3d2982 --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Samples/Mcp9601_Sample/MeadowApp.cs @@ -0,0 +1,45 @@ +using Meadow; +using Meadow.Devices; +using Meadow.Foundation.Sensors.Temperature; +using System.Threading.Tasks; + +namespace Sensors.Temperature.MCP9601_Sample +{ + public class MeadowApp : App + { + // + + Mcp9601 sensor; + + public override Task Initialize() + { + Resolver.Log.Info("Initialize..."); + + sensor = new Mcp9601(Device.CreateI2cBus()); + + var consumer = Mcp9601.CreateObserver( + handler: result => + { + Resolver.Log.Info($"Temperature New Value {result.New.TemperatureHot.Value.Celsius}C"); + }, + filter: null + ); + sensor.Subscribe(consumer); + + sensor.Updated += Sensor_Updated; + return Task.CompletedTask; + } + + private void Sensor_Updated(object sender, IChangeResult<(Meadow.Units.Temperature? TemperatureHot, Meadow.Units.Temperature? TemperatureCold)> e) + { + Resolver.Log.Info($"Temperature hot: {e.New.TemperatureHot.Value.Celsius:n2}C, Temperature cold: {e.New.TemperatureCold.Value.Celsius:n2}C"); + } + + public override async Task Run() + { + sensor.StartUpdating(); + } + + // + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Samples/Mcp9601_Sample/meadow.config.yaml b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Samples/Mcp9601_Sample/meadow.config.yaml new file mode 100644 index 0000000000..32363cb69c --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp960x/Samples/Mcp9601_Sample/meadow.config.yaml @@ -0,0 +1,2 @@ +MonoControl: + Options: --jit \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp9808/Driver/Mcp9808.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp9808/Driver/Mcp9808.Enums.cs index 6384afe74b..8cb7af7277 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp9808/Driver/Mcp9808.Enums.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp9808/Driver/Mcp9808.Enums.cs @@ -3,7 +3,7 @@ public partial class Mcp9808 { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp9808/Driver/Mcp9808.Registers.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp9808/Driver/Mcp9808.Registers.cs new file mode 100644 index 0000000000..0c0c92539e --- /dev/null +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp9808/Driver/Mcp9808.Registers.cs @@ -0,0 +1,27 @@ +namespace Meadow.Foundation.Sensors.Temperature +{ + public partial class Mcp9808 + { + internal class Registers + { + public const ushort CONFIG_SHUTDOWN = 0x0100; // shutdown config + public const ushort CONFIG_CRITLOCKED = 0x0080; // critical trip lock + public const ushort CONFIG_WINLOCKED = 0x0040; // alarm window lock + public const ushort CONFIG_INTCLR = 0x0020; // interrupt clear + public const ushort CONFIG_ALERTSTAT = 0x0010; // alert output status + public const ushort CONFIG_ALERTCTRL = 0x0008; // alert output control + public const ushort CONFIG_ALERTSEL = 0x0004; // alert output select + public const ushort CONFIG_ALERTPOL = 0x0002; // alert output polarity + public const ushort CONFIG_ALERTMODE = 0x0001; // alert output mode + + public const byte REG_CONFIG = 0x01; // config + public const byte UPPER_TEMP = 0x02; // upper alert boundary + public const byte LOWER_TEMP = 0x03; // lower alert boundery + public const byte CRIT_TEMP = 0x04; // critical temperature + public const byte AMBIENT_TEMP = 0x05; // ambient temperature + public const byte MANUFACTURER_ID = 0x06; // manufacturer ID + public const byte DEVICE_ID = 0x07; // device ID + public const byte RESOLUTION = 0x08; // resolution + } + } +} \ No newline at end of file diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp9808/Driver/Mcp9808.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp9808/Driver/Mcp9808.cs index f4b6011e74..4394a4b9b0 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp9808/Driver/Mcp9808.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp9808/Driver/Mcp9808.cs @@ -8,32 +8,19 @@ namespace Meadow.Foundation.Sensors.Temperature /// /// Represents a Mcp9808 temperature sensor /// - public partial class Mcp9808 : ByteCommsSensorBase, ITemperatureSensor + public partial class Mcp9808 : ByteCommsSensorBase, + ITemperatureSensor, II2cPeripheral { + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + /// /// Raised when the temeperature value changes /// public event EventHandler> TemperatureUpdated = delegate { }; - const ushort MCP_CONFIG_SHUTDOWN = 0x0100; // shutdown config - const ushort MCP_CONFIG_CRITLOCKED = 0x0080; // critical trip lock - const ushort MCP_CONFIG_WINLOCKED = 0x0040; // alarm window lock - const ushort MCP_CONFIG_INTCLR = 0x0020; // interrupt clear - const ushort MCP_CONFIG_ALERTSTAT = 0x0010; // alert output status - const ushort MCP_CONFIG_ALERTCTRL = 0x0008; // alert output control - const ushort MCP_CONFIG_ALERTSEL = 0x0004; // alert output select - const ushort MCP_CONFIG_ALERTPOL = 0x0002; // alert output polarity - const ushort MCP_CONFIG_ALERTMODE = 0x0001; // alert output mode - - const byte MCP_REG_CONFIG = 0x01; // config - const byte MCP_UPPER_TEMP = 0x02; // upper alert boundary - const byte MCP_LOWER_TEMP = 0x03; // lower alert boundery - const byte MCP_CRIT_TEMP = 0x04; // critical temperature - const byte MCP_AMBIENT_TEMP = 0x05; // ambient temperature - const byte MCP_MANUFACTURER_ID = 0x06; // manufacturer ID - const byte MCP_DEVICE_ID = 0x07; // device ID - const byte MCP_RESOLUTION = 0x08; // resolution - /// /// The temperature, in degrees celsius (°C), from the last reading. /// @@ -47,7 +34,7 @@ public partial class Mcp9808 : ByteCommsSensorBase, ITemperat public Mcp9808(II2cBus i2CBus, byte address = (byte)Addresses.Default) : base(i2CBus, address, readBufferSize: 8, writeBufferSize: 8) { - Peripheral?.WriteRegister(MCP_REG_CONFIG, (ushort)0x0); + BusComms?.WriteRegister(Registers.REG_CONFIG, (ushort)0x0); } /// @@ -55,11 +42,11 @@ public Mcp9808(II2cBus i2CBus, byte address = (byte)Addresses.Default) /// public void Wake() { - ushort config = Peripheral?.ReadRegisterAsUShort(MCP_REG_CONFIG, ByteOrder.BigEndian) ?? 0; + ushort config = BusComms?.ReadRegisterAsUShort(Registers.REG_CONFIG, ByteOrder.BigEndian) ?? 0; - config = (ushort)(config & (~MCP_CONFIG_SHUTDOWN)); + config = (ushort)(config & (~Registers.CONFIG_SHUTDOWN)); - Peripheral?.WriteRegister(MCP_REG_CONFIG, config); + BusComms?.WriteRegister(Registers.REG_CONFIG, config); } /// @@ -67,17 +54,17 @@ public void Wake() /// public void Sleep() { - ushort config = Peripheral?.ReadRegisterAsUShort(MCP_REG_CONFIG, ByteOrder.BigEndian) ?? 0; + ushort config = BusComms?.ReadRegisterAsUShort(Registers.REG_CONFIG, ByteOrder.BigEndian) ?? 0; - Peripheral?.WriteRegister(MCP_REG_CONFIG, (ushort)(config | MCP_CONFIG_SHUTDOWN)); - } + BusComms?.WriteRegister(Registers.REG_CONFIG, (ushort)(config | Registers.CONFIG_SHUTDOWN)); + } /// /// Read the device ID /// public ushort GetDeviceId() { - return Peripheral?.ReadRegisterAsUShort(MCP_DEVICE_ID, ByteOrder.BigEndian) ?? 0; + return BusComms?.ReadRegisterAsUShort(Registers.DEVICE_ID, ByteOrder.BigEndian) ?? 0; } /// @@ -85,7 +72,7 @@ public ushort GetDeviceId() /// public ushort GetManufactureId() { - return Peripheral?.ReadRegisterAsUShort(MCP_MANUFACTURER_ID, ByteOrder.BigEndian) ?? 0; + return BusComms?.ReadRegisterAsUShort(Registers.MANUFACTURER_ID, ByteOrder.BigEndian) ?? 0; } /// @@ -93,7 +80,7 @@ public ushort GetManufactureId() /// public byte GetResolution() { - return Peripheral?.ReadRegister(MCP_RESOLUTION) ?? 0; + return BusComms?.ReadRegister(Registers.RESOLUTION) ?? 0; } /// @@ -101,32 +88,26 @@ public byte GetResolution() /// public void SetResolution(byte resolution) { - Peripheral?.WriteRegister(MCP_RESOLUTION, resolution); + BusComms?.WriteRegister(Registers.RESOLUTION, resolution); } /// /// Reads data from the sensor /// /// The latest sensor reading - protected override async Task ReadSensor() + protected override Task ReadSensor() { - return await Task.Run(() => - { - ushort value = Peripheral?.ReadRegisterAsUShort(MCP_AMBIENT_TEMP, ByteOrder.BigEndian) ?? 0; - double temp = value & 0x0FFF; + ushort value = BusComms?.ReadRegisterAsUShort(Registers.AMBIENT_TEMP, ByteOrder.BigEndian) ?? 0; + double temp = value & 0x0FFF; - temp /= 16.0; + temp /= 16.0; - if ((value & 0x1000) != 0) - { - temp -= 256; - } - - var newTemp = new Units.Temperature(temp); - Temperature = newTemp; + if ((value & 0x1000) != 0) + { + temp -= 256; + } - return newTemp; - }); + return Task.FromResult(new Units.Temperature(temp, Units.Temperature.UnitType.Celsius)); } /// diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp9808/Driver/Sensors.Temperature.Mcp9808.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp9808/Driver/Sensors.Temperature.Mcp9808.csproj index aef79ce92b..2e09e8c875 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp9808/Driver/Sensors.Temperature.Mcp9808.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp9808/Driver/Sensors.Temperature.Mcp9808.csproj @@ -24,6 +24,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp9808/Samples/Mcp9808_Sample/Mcp9808_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp9808/Samples/Mcp9808_Sample/Mcp9808_Sample.csproj index eadf3f382e..19bcd5127b 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp9808/Samples/Mcp9808_Sample/Mcp9808_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Mcp9808/Samples/Mcp9808_Sample/Mcp9808_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Thermistor/Driver/Sensors.Temperature.Thermistor.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Thermistor/Driver/Sensors.Temperature.Thermistor.csproj index 99d889d591..e662310348 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Thermistor/Driver/Sensors.Temperature.Thermistor.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Thermistor/Driver/Sensors.Temperature.Thermistor.csproj @@ -10,21 +10,18 @@ http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ Meadow.Foundation.Sensors.Temperature.Thermistor https://github.com/WildernessLabs/Meadow.Foundation - Meadow.Foundation, Temperature, Thermistor + Meadow.Foundation,Temperature,Thermistor 0.1.0 true - Thermistor temperature sensor + Thermistor analog temperature sensor enable Meadow.Foundation.Sensors.Temperature - - 8.0 - - - 8.0 + + 10.0 - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Thermistor/Driver/Thermistor.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Thermistor/Driver/Thermistor.cs index bd11eb6b93..3de0868fee 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Thermistor/Driver/Thermistor.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Thermistor/Driver/Thermistor.cs @@ -15,10 +15,11 @@ namespace Meadow.Foundation.Sensors.Temperature /// | /// +---[ TM ]--- < GND /// - public abstract class Thermistor : PollingSensorBase, ITemperatureSensor + public abstract class Thermistor : PollingSensorBase, + ITemperatureSensor { /// - /// The analog input eing used to determine output voltage of the voltage divider circuit + /// The analog input port used to determine output voltage of the voltage divider circuit /// protected IAnalogInputPort AnalogInput { get; } /// @@ -36,10 +37,10 @@ public abstract class Thermistor : PollingSensorBase, ITemper /// The analog input reading the thermistor voltage divider output protected Thermistor(IAnalogInputPort analogInput) { - this.AnalogInput = analogInput; - this.AnalogInput.StartUpdating(); + AnalogInput = analogInput; + AnalogInput.StartUpdating(); - base.Updated += (s, e) => TemperatureUpdated?.Invoke(this, e); + Updated += (s, e) => TemperatureUpdated?.Invoke(this, e); } /// diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Thermistor/Samples/Thermistor_Sample/Thermistor_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Thermistor/Samples/Thermistor_Sample/Thermistor_Sample.csproj index 37b63cf91b..01f779defc 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Thermistor/Samples/Thermistor_Sample/Thermistor_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Thermistor/Samples/Thermistor_Sample/Thermistor_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Tmp102/Driver/Sensors.Temperature.Tmp102.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Tmp102/Driver/Sensors.Temperature.Tmp102.csproj index deebe7d429..8712d8c202 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Tmp102/Driver/Sensors.Temperature.Tmp102.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Tmp102/Driver/Sensors.Temperature.Tmp102.csproj @@ -10,21 +10,18 @@ http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ Meadow.Foundation.Sensors.Temperature.Tmp102 https://github.com/WildernessLabs/Meadow.Foundation - Meadow.Foundation, Temperature, TMP102 + Meadow.Foundation,Temperature,TMP102 0.1.53 true TMP102 I2C temperature sensor enable Meadow.Foundation.Sensors.Temperature - - 8.0 - - - 8.0 + + 10.0 - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Tmp102/Driver/Tmp102.Addresses.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Tmp102/Driver/Tmp102.Addresses.cs index d8404e746a..75909355aa 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Tmp102/Driver/Tmp102.Addresses.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Tmp102/Driver/Tmp102.Addresses.cs @@ -3,7 +3,7 @@ public partial class Tmp102 { /// - /// Valid addresses for the sensor. + /// Valid I2C addresses for the sensor /// public enum Addresses : byte { diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Tmp102/Driver/Tmp102.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Tmp102/Driver/Tmp102.cs index a4b49b323c..525fd49664 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Tmp102/Driver/Tmp102.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Tmp102/Driver/Tmp102.cs @@ -1,34 +1,40 @@ -using System; -using System.Threading.Tasks; -using Meadow.Hardware; +using Meadow.Hardware; using Meadow.Peripherals.Sensors; +using System; +using System.Threading.Tasks; namespace Meadow.Foundation.Sensors.Temperature { /// /// TMP102 Temperature sensor object /// - public partial class Tmp102 : ByteCommsSensorBase, ITemperatureSensor + public partial class Tmp102 : ByteCommsSensorBase, + ITemperatureSensor, II2cPeripheral { + /// + /// The default I2C address for the peripheral + /// + public byte DefaultI2cAddress => (byte)Addresses.Default; + /// /// Raised when the temperature value changes /// public event EventHandler> TemperatureUpdated = delegate { }; /// - /// Backing variable for the SensorResolution property. + /// Backing variable for the SensorResolution property /// private Resolution _sensorResolution; /// - /// Get / set the resolution of the sensor. + /// Get / set the resolution of the sensor /// public Resolution SensorResolution { get => _sensorResolution; set { - Peripheral?.ReadRegister(0x01, ReadBuffer.Span); + BusComms?.ReadRegister(0x01, ReadBuffer.Span); if (value == Resolution.Resolution12Bits) { @@ -39,25 +45,25 @@ public Resolution SensorResolution ReadBuffer.Span[1] |= 0x10; } - Peripheral?.WriteRegister(0x01, ReadBuffer.Span); + BusComms?.WriteRegister(0x01, ReadBuffer.Span); _sensorResolution = value; } } /// - /// The temperature from the last reading. + /// The temperature from the last reading /// public Units.Temperature? Temperature { get; protected set; } /// - /// Create a new TMP102 object using the default configuration for the sensor. + /// Create a new TMP102 object using the default configuration for the sensor /// /// The I2CBus - /// I2C address of the sensor. + /// I2C address of the sensor public Tmp102(II2cBus i2cBus, byte address = (byte)Addresses.Default) : base(i2cBus, address, readBufferSize: 2, writeBufferSize: 2) { - Peripheral?.ReadRegister(0x01, ReadBuffer.Span); + BusComms?.ReadRegister(0x01, ReadBuffer.Span); _sensorResolution = (ReadBuffer.Span[1] & 0x10) > 0 ? Resolution.Resolution13Bits : Resolution.Resolution12Bits; } @@ -67,7 +73,7 @@ public Tmp102(II2cBus i2cBus, byte address = (byte)Addresses.Default) /// protected override Task ReadSensor() { - Peripheral?.ReadRegister(0x00, ReadBuffer.Span); + BusComms?.ReadRegister(0x00, ReadBuffer.Span); int sensorReading; if (SensorResolution == Resolution.Resolution12Bits) diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Tmp102/Samples/Tmp102_Sample/Tmp102_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Tmp102/Samples/Tmp102_Sample/Tmp102_Sample.csproj index f9016499d5..009bf3e218 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Tmp102/Samples/Tmp102_Sample/Tmp102_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Temperature.Tmp102/Samples/Tmp102_Sample/Tmp102_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Weather.SwitchingAnemometer/Driver/Sensors.Weather.SwitchingAnemometer.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Weather.SwitchingAnemometer/Driver/Sensors.Weather.SwitchingAnemometer.csproj index e04b882c26..fcddfa92cc 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Weather.SwitchingAnemometer/Driver/Sensors.Weather.SwitchingAnemometer.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Weather.SwitchingAnemometer/Driver/Sensors.Weather.SwitchingAnemometer.csproj @@ -8,7 +8,7 @@ http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ Meadow.Foundation.Sensors.Weather.SwitchingAnemometer https://github.com/WildernessLabs/Meadow.Foundation - Meadow.Foundation, Weather, Wind, Switching, Anemometer + Meadow.Foundation,Weather,Wind,Switching,Anemometer 0.1.17 true Digital Switching Anemometer wind speed sensor @@ -17,10 +17,10 @@ true icon.png - 8.0 + 10.0 - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Weather.SwitchingAnemometer/Driver/SwitchingAnemometer.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Weather.SwitchingAnemometer/Driver/SwitchingAnemometer.cs index 41237f3fc3..d5cb42cd1c 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Weather.SwitchingAnemometer/Driver/SwitchingAnemometer.cs +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Weather.SwitchingAnemometer/Driver/SwitchingAnemometer.cs @@ -67,8 +67,8 @@ public int SampleCount /// public SwitchingAnemometer(IPin digitalInputPin) : this(digitalInputPin.CreateDigitalInputPort(InterruptMode.EdgeFalling, - ResistorMode.InternalPullUp, - TimeSpan.FromMilliseconds(2), + ResistorMode.InternalPullUp, + TimeSpan.FromMilliseconds(2), TimeSpan.FromMilliseconds(0))) { } @@ -93,8 +93,8 @@ void HandleInputPortChange(object sender, DigitalPortResult result) samples?.Enqueue(result); - if(samples?.Count > sampleCount) - { + if (samples?.Count > sampleCount) + { samples.Dequeue(); } } @@ -133,12 +133,12 @@ public override void StartUpdating(TimeSpan? updateInterval = null) public override void StopUpdating() { base.StopUpdating(); - + if (running) { UnsubscribeToInputPortEvents(); } - + running = false; } @@ -148,14 +148,14 @@ public override void StopUpdating() /// The latest sensor reading protected override async Task ReadSensor() { - if(IsSampling == false) + if (IsSampling == false) { StartUpdating(); await Task.Delay(OneTimeReadDuration); StopUpdating(); } - if(samples?.Count > 0 && (DateTime.Now - samples?.Peek().New.Time > NoWindTimeout)) + if (samples?.Count > 0 && (DateTime.Now - samples?.Peek().New.Time > NoWindTimeout)) { //we've exceeded the no wind interval time samples?.Clear(); //will force a zero reading } @@ -174,7 +174,7 @@ protected override async Task ReadSensor() } // average the speeds - float oversampledSpeed = speedSum / (samples.Count -1); + float oversampledSpeed = speedSum / (samples.Count - 1); return new Speed(oversampledSpeed, SU.KilometersPerHour); } diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Weather.SwitchingAnemometer/Samples/SwitchingAnemometer_Sample/SwitchingAnemometer_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Weather.SwitchingAnemometer/Samples/SwitchingAnemometer_Sample/SwitchingAnemometer_Sample.csproj index f5223cd8d0..7b2ada9419 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Weather.SwitchingAnemometer/Samples/SwitchingAnemometer_Sample/SwitchingAnemometer_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Weather.SwitchingAnemometer/Samples/SwitchingAnemometer_Sample/SwitchingAnemometer_Sample.csproj @@ -11,7 +11,7 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Weather.SwitchingRainGauge/Driver/Sensors.Weather.SwitchingRainGauge.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Weather.SwitchingRainGauge/Driver/Sensors.Weather.SwitchingRainGauge.csproj index 84dc305a36..9879c31c31 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Weather.SwitchingRainGauge/Driver/Sensors.Weather.SwitchingRainGauge.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Weather.SwitchingRainGauge/Driver/Sensors.Weather.SwitchingRainGauge.csproj @@ -10,13 +10,13 @@ http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ Meadow.Foundation.Sensors.Weather.SwitchingRainGauge https://github.com/WildernessLabs/Meadow.Foundation - Meadow, Meadow.Foundation, Rain, RainGauge + Meadow,Meadow.Foundation,Rain,RainGauge 0.1.7 true GPIO rain gauge sensor - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Weather.SwitchingRainGauge/Samples/SwitchingRainGauge_Sample/SwitchingRainGauge_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Weather.SwitchingRainGauge/Samples/SwitchingRainGauge_Sample/SwitchingRainGauge_Sample.csproj index 869c2e8bda..5cc4dff47a 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Weather.SwitchingRainGauge/Samples/SwitchingRainGauge_Sample/SwitchingRainGauge_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Weather.SwitchingRainGauge/Samples/SwitchingRainGauge_Sample/SwitchingRainGauge_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Weather.WindVane/Driver/Sensors.Weather.WindVane.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Weather.WindVane/Driver/Sensors.Weather.WindVane.csproj index ff67d45818..a7e91aa793 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Weather.WindVane/Driver/Sensors.Weather.WindVane.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Weather.WindVane/Driver/Sensors.Weather.WindVane.csproj @@ -10,13 +10,13 @@ http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ Meadow.Foundation.Sensors.Weather.WindVane https://github.com/WildernessLabs/Meadow.Foundation - Meadow, Meadow.Foundation, Wind, WindVane + Meadow,Meadow.Foundation,Wind,WindVane 0.1.22 true WindVane analog wind direction sensor - + diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Weather.WindVane/Samples/WindVane_Sample/WindVane_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Weather.WindVane/Samples/WindVane_Sample/WindVane_Sample.csproj index 3e2b53ebd5..c83295c445 100644 --- a/Source/Meadow.Foundation.Peripherals/Sensors.Weather.WindVane/Samples/WindVane_Sample/WindVane_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Sensors.Weather.WindVane/Samples/WindVane_Sample/WindVane_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.Peripherals/Servos.ServoCore/Driver/Servos.ServoCore.csproj b/Source/Meadow.Foundation.Peripherals/Servos.ServoCore/Driver/Servos.ServoCore.csproj index 94ef80a171..05d9d8c047 100644 --- a/Source/Meadow.Foundation.Peripherals/Servos.ServoCore/Driver/Servos.ServoCore.csproj +++ b/Source/Meadow.Foundation.Peripherals/Servos.ServoCore/Driver/Servos.ServoCore.csproj @@ -9,7 +9,7 @@ http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/ Meadow.Foundation.Servos.ServoCore https://github.com/WildernessLabs/Meadow.Foundation - Meadow, Meadow.Foundation, Servo, Meadow.Foundation.Servo + Meadow,Meadow.Foundation,Servo,Meadow.Foundation.Servo 0.8.49 true PWM generic servo controller @@ -21,6 +21,6 @@ - + diff --git a/Source/Meadow.Foundation.Peripherals/Servos.ServoCore/Samples/ServoCore_Sample/ServoCore_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Servos.ServoCore/Samples/ServoCore_Sample/ServoCore_Sample.csproj index 2de53d3c43..eb96644510 100644 --- a/Source/Meadow.Foundation.Peripherals/Servos.ServoCore/Samples/ServoCore_Sample/ServoCore_Sample.csproj +++ b/Source/Meadow.Foundation.Peripherals/Servos.ServoCore/Samples/ServoCore_Sample/ServoCore_Sample.csproj @@ -9,7 +9,7 @@ App - + diff --git a/Source/Meadow.Foundation.sln b/Source/Meadow.Foundation.sln index ef3ac0c122..23523effbb 100644 --- a/Source/Meadow.Foundation.sln +++ b/Source/Meadow.Foundation.sln @@ -1139,6 +1139,108 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Displays.Gtk", "Meadow.Foun EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Epd5in65f_Sample", "Meadow.Foundation.Peripherals\Displays.ePaperWaveShare\Samples\Epd5in65f_Sample\Epd5in65f_Sample.csproj", "{16A387A9-80AA-4080-85F6-10F53D6EC99E}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Pmsa003i", "Pmsa003i", "{AD6DD7B6-B896-44B9-904E-9330C2C842C7}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{A3F37EFB-9686-4074-9962-5F731C52D919}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Ch1115", "Ch1115", "{753F764D-EA21-43A0-B761-6E9B43D8C90B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Displays.Ch1115", "Meadow.Foundation.Peripherals\Displays.Ch1115\Driver\Displays.Ch1115.csproj", "{C182D69A-FE45-46BF-8522-76E0BC962FFB}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{D46CA94B-9A0C-4188-9EE8-8A51E1499B73}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ch1115_Sample", "Meadow.Foundation.Peripherals\Displays.Ch1115\Samples\Ch1115_Sample\Ch1115_Sample.csproj", "{1F6AF0D5-CF64-4DBA-B920-F86EAB108F2B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sh110x", "Sh110x", "{8D0C58C8-B325-48A1-A500-7E8FDC28C272}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{F288D725-B26F-4E32-B870-F391AF4211EB}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Displays.Sh110x", "Meadow.Foundation.Peripherals\Displays.Sh110x\Driver\Displays.Sh110x.csproj", "{BCF66E00-2BFE-4B8B-829F-2D8088CBCFEB}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sh1106_Sample", "Meadow.Foundation.Peripherals\Displays.Sh110x\Samples\Sh1106_Sample\Sh1106_Sample.csproj", "{F3CFF38B-8F9D-4BE0-8017-FBA5687E15E2}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Led.FourteenSegment", "Led.FourteenSegment", "{1D0D2EEC-2637-489F-83C3-7F7CB36E5512}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{4A7E3CDC-2141-4D74-A8CB-480ED78251B1}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Displays.Led.FourteenSegment", "Meadow.Foundation.Peripherals\Displays.Led.FourteenSegment\Driver\Displays.Led.FourteenSegment.csproj", "{2E207B06-0C55-44FA-8334-62D791DB6105}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FourteenSegment_Sample", "Meadow.Foundation.Peripherals\Displays.Led.FourteenSegment\Samples\FourteenSegment_Sample\FourteenSegment_Sample.csproj", "{B41D00C4-35F9-4E11-BF1A-EAD43F5B8CA6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ht16k33_Character_Sample", "Meadow.Foundation.Peripherals\ICs.IOExpanders.Ht16k33\Samples\Ht16k33_Character_Sample\Ht16k33_Character_Sample.csproj", "{85EA8B09-1C8D-4E67-9770-C1AD0A550DED}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Led.SixteenSegment", "Led.SixteenSegment", "{C6AB70DF-B943-41F7-8DFC-2A89CFDD2C8D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{13D97CCB-2CFF-4AB8-A170-701525DA740B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Displays.Led.SixteenSegment", "Meadow.Foundation.Peripherals\Displays.Led.SixteenSegment\Driver\Displays.Led.SixteenSegment.csproj", "{70A3BC90-AB6A-4498-BFDE-07AA25823036}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SixteenSegment_Sample", "Meadow.Foundation.Peripherals\Displays.Led.SixteenSegment\Samples\SixteenSegment_Sample\SixteenSegment_Sample.csproj", "{A470E563-7ADD-4A76-91AE-C1190134D3FA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sensors.Environmental.Pmsa003i", "Meadow.Foundation.Peripherals\Sensors.Environmental.Pmsa003I\Driver\Sensors.Environmental.Pmsa003i.csproj", "{B935965C-0FFC-4D7B-BDBC-B17C46C785F0}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MiniPID2", "MiniPID2", "{38944011-FA3C-4557-9049-B41B6168F6C0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sensors.Environmental.MiniPID2", "Meadow.Foundation.Peripherals\Sensors.Environmental.MiniPID2\Driver\Sensors.Environmental.MiniPID2.csproj", "{00085539-EB03-49CE-8518-13544FD480BB}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{59445EBB-78B8-4E83-B05D-C597D0C9AEC0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MiniPID2_Sample", "Meadow.Foundation.Peripherals\Sensors.Environmental.MiniPID2\Samples\MiniPID2_Sample\MiniPID2_Sample.csproj", "{95670172-AB31-4239-8805-346DDD57983F}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ANONavigationEncoder", "ANONavigationEncoder", "{E2A8BDCC-626E-450D-918F-785E3777793E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sensors.Hid.ANONavigationEncoder", "Meadow.Foundation.Peripherals\Sensors.Hid.ANONavigationEncoder\Driver\Sensors.Hid.ANONavigationEncoder.csproj", "{D737283C-DDC2-4B77-B4A9-88F5BD6E31F4}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{113D71B4-AE9A-402A-95A0-4D46C28F1EA0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ANONavigationEncoder_Sample", "Meadow.Foundation.Peripherals\Sensors.Hid.ANONavigationEncoder\Samples\ANONavigationEncoder_Sample\ANONavigationEncoder_Sample.csproj", "{3885F704-2844-4EDD-9706-BD1B0C85A29B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sh1107_Sample", "Meadow.Foundation.Peripherals\Displays.Sh110x\Samples\Sh1107_Sample\Sh1107_Sample.csproj", "{EB1F7A63-223D-4DD6-96EA-B04CEAE2292D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Lsm303agr", "Lsm303agr", "{CEA88FA7-1201-440B-9869-362932802FE6}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{257256A8-EAA1-4E7E-87B9-E8A34B5D2CFF}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sensors.Motion.Lsm303agr", "Meadow.Foundation.Peripherals\Sensors.Motion.Lsm303agr\Driver\Sensors.Motion.Lsm303agr.csproj", "{F8FEA194-F417-4141-9025-7F16C4FAA782}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lsm303agr_Sample", "Meadow.Foundation.Peripherals\Sensors.Motion.Lsm303agr\Samples\Lsm303agr_Sample\Lsm303agr_Sample.csproj", "{1B54CA69-FD1F-46FF-9F0C-2AFB00AAB2E1}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Lis2Mdl", "Lis2Mdl", "{698A96DD-692F-4ABE-9B4D-9BDA300C8B84}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{385CB50B-4D17-4FFF-BCCE-C8BF9D280A52}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sensors.Motion.Lis2Mdl", "Meadow.Foundation.Peripherals\Sensors.Motion.Lis2Mdl\Driver\Sensors.Motion.Lis2Mdl.csproj", "{09E368FA-1ACA-4F96-9153-B4959A7EE390}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lis2Mdl_Sample", "Meadow.Foundation.Peripherals\Sensors.Motion.Lis2Mdl\Samples\Lis2Mdl_Sample\Lis2Mdl_Sample.csproj", "{6923DB1E-CDDC-4A84-AAEF-6F6F7D9DC406}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Mcp960x", "Mcp960x", "{CBF95E20-6021-4E5B-807A-E099DBC98764}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{573A2A08-CB36-480E-9C5D-56F851847045}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sensors.Temperature.Mcp960x", "Meadow.Foundation.Peripherals\Sensors.Temperature.Mcp960x\Driver\Sensors.Temperature.Mcp960x.csproj", "{754AFC87-A98F-4BD6-A934-61DB69C0B643}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mcp9600_Sample", "Meadow.Foundation.Peripherals\Sensors.Temperature.Mcp960x\Samples\Mcp9600_Sample\Mcp9600_Sample.csproj", "{3AC34973-19FC-453A-A90E-4406EB355F72}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mcp9601_Sample", "Meadow.Foundation.Peripherals\Sensors.Temperature.Mcp960x\Samples\Mcp9601_Sample\Mcp9601_Sample.csproj", "{41A4E1A7-0BC4-474F-910F-F140EEA1A4BE}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Audio.MicroAudio", "Audio.MicroAudio", "{0236BB4E-B417-4549-B69E-79AC81FC3056}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Audio.MicroAudio", "Meadow.Foundation.Libraries_and_Frameworks\Audio.MicroAudio\Driver\Audio.MicroAudio.csproj", "{F3F3966C-E416-41EF-889B-518FFECFC780}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{99AABDF6-1EE4-4099-B61C-E49CA6F5CA0F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Audio.MicroAudio_Sample", "Meadow.Foundation.Libraries_and_Frameworks\Audio.MicroAudio\Samples\Audio.MicroAudio_Sample\Audio.MicroAudio_Sample.csproj", "{CDC8B582-C7F8-4578-8F1A-0B4B817D2632}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NextPm", "NextPm", "{4F21565E-E855-479E-87D1-7F5F3BC96543}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sensors.Environmental.NextPm", "Meadow.Foundation.Peripherals\Sensors.Environmental.NextPm\Driver\Sensors.Environmental.NextPm.csproj", "{EDDED57B-FCCC-4F76-B94C-C5F793678E36}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{8A37E554-5E29-4E3A-A4EF-6E360FBA359B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NextPm_Sample", "Meadow.Foundation.Peripherals\Sensors.Environmental.NextPm\Samples\NextPm_Sample\NextPm_Sample.csproj", "{0F63B848-5397-41F5-A6A9-4837ED647E1A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Pmsa003I_Sample", "Meadow.Foundation.Peripherals\Sensors.Environmental.Pmsa003I\Samples\Pmsa003I_Sample\Pmsa003I_Sample.csproj", "{31D80302-FD83-4958-B379-DAC2BC91ABDA}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -2691,6 +2793,168 @@ Global {16A387A9-80AA-4080-85F6-10F53D6EC99E}.Release|Any CPU.ActiveCfg = Release|Any CPU {16A387A9-80AA-4080-85F6-10F53D6EC99E}.Release|Any CPU.Build.0 = Release|Any CPU {16A387A9-80AA-4080-85F6-10F53D6EC99E}.Release|Any CPU.Deploy.0 = Release|Any CPU + {C182D69A-FE45-46BF-8522-76E0BC962FFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C182D69A-FE45-46BF-8522-76E0BC962FFB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C182D69A-FE45-46BF-8522-76E0BC962FFB}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {C182D69A-FE45-46BF-8522-76E0BC962FFB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C182D69A-FE45-46BF-8522-76E0BC962FFB}.Release|Any CPU.Build.0 = Release|Any CPU + {C182D69A-FE45-46BF-8522-76E0BC962FFB}.Release|Any CPU.Deploy.0 = Release|Any CPU + {1F6AF0D5-CF64-4DBA-B920-F86EAB108F2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1F6AF0D5-CF64-4DBA-B920-F86EAB108F2B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1F6AF0D5-CF64-4DBA-B920-F86EAB108F2B}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {1F6AF0D5-CF64-4DBA-B920-F86EAB108F2B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1F6AF0D5-CF64-4DBA-B920-F86EAB108F2B}.Release|Any CPU.Build.0 = Release|Any CPU + {1F6AF0D5-CF64-4DBA-B920-F86EAB108F2B}.Release|Any CPU.Deploy.0 = Release|Any CPU + {BCF66E00-2BFE-4B8B-829F-2D8088CBCFEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BCF66E00-2BFE-4B8B-829F-2D8088CBCFEB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BCF66E00-2BFE-4B8B-829F-2D8088CBCFEB}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {BCF66E00-2BFE-4B8B-829F-2D8088CBCFEB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BCF66E00-2BFE-4B8B-829F-2D8088CBCFEB}.Release|Any CPU.Build.0 = Release|Any CPU + {BCF66E00-2BFE-4B8B-829F-2D8088CBCFEB}.Release|Any CPU.Deploy.0 = Release|Any CPU + {F3CFF38B-8F9D-4BE0-8017-FBA5687E15E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F3CFF38B-8F9D-4BE0-8017-FBA5687E15E2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F3CFF38B-8F9D-4BE0-8017-FBA5687E15E2}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {F3CFF38B-8F9D-4BE0-8017-FBA5687E15E2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F3CFF38B-8F9D-4BE0-8017-FBA5687E15E2}.Release|Any CPU.Build.0 = Release|Any CPU + {F3CFF38B-8F9D-4BE0-8017-FBA5687E15E2}.Release|Any CPU.Deploy.0 = Release|Any CPU + {2E207B06-0C55-44FA-8334-62D791DB6105}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2E207B06-0C55-44FA-8334-62D791DB6105}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2E207B06-0C55-44FA-8334-62D791DB6105}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {2E207B06-0C55-44FA-8334-62D791DB6105}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2E207B06-0C55-44FA-8334-62D791DB6105}.Release|Any CPU.Build.0 = Release|Any CPU + {2E207B06-0C55-44FA-8334-62D791DB6105}.Release|Any CPU.Deploy.0 = Release|Any CPU + {B41D00C4-35F9-4E11-BF1A-EAD43F5B8CA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B41D00C4-35F9-4E11-BF1A-EAD43F5B8CA6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B41D00C4-35F9-4E11-BF1A-EAD43F5B8CA6}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {B41D00C4-35F9-4E11-BF1A-EAD43F5B8CA6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B41D00C4-35F9-4E11-BF1A-EAD43F5B8CA6}.Release|Any CPU.Build.0 = Release|Any CPU + {B41D00C4-35F9-4E11-BF1A-EAD43F5B8CA6}.Release|Any CPU.Deploy.0 = Release|Any CPU + {85EA8B09-1C8D-4E67-9770-C1AD0A550DED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {85EA8B09-1C8D-4E67-9770-C1AD0A550DED}.Debug|Any CPU.Build.0 = Debug|Any CPU + {85EA8B09-1C8D-4E67-9770-C1AD0A550DED}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {85EA8B09-1C8D-4E67-9770-C1AD0A550DED}.Release|Any CPU.ActiveCfg = Release|Any CPU + {85EA8B09-1C8D-4E67-9770-C1AD0A550DED}.Release|Any CPU.Build.0 = Release|Any CPU + {85EA8B09-1C8D-4E67-9770-C1AD0A550DED}.Release|Any CPU.Deploy.0 = Release|Any CPU + {70A3BC90-AB6A-4498-BFDE-07AA25823036}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {70A3BC90-AB6A-4498-BFDE-07AA25823036}.Debug|Any CPU.Build.0 = Debug|Any CPU + {70A3BC90-AB6A-4498-BFDE-07AA25823036}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {70A3BC90-AB6A-4498-BFDE-07AA25823036}.Release|Any CPU.ActiveCfg = Release|Any CPU + {70A3BC90-AB6A-4498-BFDE-07AA25823036}.Release|Any CPU.Build.0 = Release|Any CPU + {70A3BC90-AB6A-4498-BFDE-07AA25823036}.Release|Any CPU.Deploy.0 = Release|Any CPU + {A470E563-7ADD-4A76-91AE-C1190134D3FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A470E563-7ADD-4A76-91AE-C1190134D3FA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A470E563-7ADD-4A76-91AE-C1190134D3FA}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {A470E563-7ADD-4A76-91AE-C1190134D3FA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A470E563-7ADD-4A76-91AE-C1190134D3FA}.Release|Any CPU.Build.0 = Release|Any CPU + {A470E563-7ADD-4A76-91AE-C1190134D3FA}.Release|Any CPU.Deploy.0 = Release|Any CPU + {B935965C-0FFC-4D7B-BDBC-B17C46C785F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B935965C-0FFC-4D7B-BDBC-B17C46C785F0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B935965C-0FFC-4D7B-BDBC-B17C46C785F0}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {B935965C-0FFC-4D7B-BDBC-B17C46C785F0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B935965C-0FFC-4D7B-BDBC-B17C46C785F0}.Release|Any CPU.Build.0 = Release|Any CPU + {B935965C-0FFC-4D7B-BDBC-B17C46C785F0}.Release|Any CPU.Deploy.0 = Release|Any CPU + {00085539-EB03-49CE-8518-13544FD480BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {00085539-EB03-49CE-8518-13544FD480BB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {00085539-EB03-49CE-8518-13544FD480BB}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {00085539-EB03-49CE-8518-13544FD480BB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {00085539-EB03-49CE-8518-13544FD480BB}.Release|Any CPU.Build.0 = Release|Any CPU + {00085539-EB03-49CE-8518-13544FD480BB}.Release|Any CPU.Deploy.0 = Release|Any CPU + {95670172-AB31-4239-8805-346DDD57983F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {95670172-AB31-4239-8805-346DDD57983F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {95670172-AB31-4239-8805-346DDD57983F}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {95670172-AB31-4239-8805-346DDD57983F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {95670172-AB31-4239-8805-346DDD57983F}.Release|Any CPU.Build.0 = Release|Any CPU + {95670172-AB31-4239-8805-346DDD57983F}.Release|Any CPU.Deploy.0 = Release|Any CPU + {D737283C-DDC2-4B77-B4A9-88F5BD6E31F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D737283C-DDC2-4B77-B4A9-88F5BD6E31F4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D737283C-DDC2-4B77-B4A9-88F5BD6E31F4}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {D737283C-DDC2-4B77-B4A9-88F5BD6E31F4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D737283C-DDC2-4B77-B4A9-88F5BD6E31F4}.Release|Any CPU.Build.0 = Release|Any CPU + {D737283C-DDC2-4B77-B4A9-88F5BD6E31F4}.Release|Any CPU.Deploy.0 = Release|Any CPU + {3885F704-2844-4EDD-9706-BD1B0C85A29B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3885F704-2844-4EDD-9706-BD1B0C85A29B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3885F704-2844-4EDD-9706-BD1B0C85A29B}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {3885F704-2844-4EDD-9706-BD1B0C85A29B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3885F704-2844-4EDD-9706-BD1B0C85A29B}.Release|Any CPU.Build.0 = Release|Any CPU + {3885F704-2844-4EDD-9706-BD1B0C85A29B}.Release|Any CPU.Deploy.0 = Release|Any CPU + {EB1F7A63-223D-4DD6-96EA-B04CEAE2292D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EB1F7A63-223D-4DD6-96EA-B04CEAE2292D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EB1F7A63-223D-4DD6-96EA-B04CEAE2292D}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {EB1F7A63-223D-4DD6-96EA-B04CEAE2292D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EB1F7A63-223D-4DD6-96EA-B04CEAE2292D}.Release|Any CPU.Build.0 = Release|Any CPU + {EB1F7A63-223D-4DD6-96EA-B04CEAE2292D}.Release|Any CPU.Deploy.0 = Release|Any CPU + {F8FEA194-F417-4141-9025-7F16C4FAA782}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F8FEA194-F417-4141-9025-7F16C4FAA782}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F8FEA194-F417-4141-9025-7F16C4FAA782}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {F8FEA194-F417-4141-9025-7F16C4FAA782}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F8FEA194-F417-4141-9025-7F16C4FAA782}.Release|Any CPU.Build.0 = Release|Any CPU + {F8FEA194-F417-4141-9025-7F16C4FAA782}.Release|Any CPU.Deploy.0 = Release|Any CPU + {1B54CA69-FD1F-46FF-9F0C-2AFB00AAB2E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1B54CA69-FD1F-46FF-9F0C-2AFB00AAB2E1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1B54CA69-FD1F-46FF-9F0C-2AFB00AAB2E1}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {1B54CA69-FD1F-46FF-9F0C-2AFB00AAB2E1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1B54CA69-FD1F-46FF-9F0C-2AFB00AAB2E1}.Release|Any CPU.Build.0 = Release|Any CPU + {1B54CA69-FD1F-46FF-9F0C-2AFB00AAB2E1}.Release|Any CPU.Deploy.0 = Release|Any CPU + {09E368FA-1ACA-4F96-9153-B4959A7EE390}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {09E368FA-1ACA-4F96-9153-B4959A7EE390}.Debug|Any CPU.Build.0 = Debug|Any CPU + {09E368FA-1ACA-4F96-9153-B4959A7EE390}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {09E368FA-1ACA-4F96-9153-B4959A7EE390}.Release|Any CPU.ActiveCfg = Release|Any CPU + {09E368FA-1ACA-4F96-9153-B4959A7EE390}.Release|Any CPU.Build.0 = Release|Any CPU + {09E368FA-1ACA-4F96-9153-B4959A7EE390}.Release|Any CPU.Deploy.0 = Release|Any CPU + {6923DB1E-CDDC-4A84-AAEF-6F6F7D9DC406}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6923DB1E-CDDC-4A84-AAEF-6F6F7D9DC406}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6923DB1E-CDDC-4A84-AAEF-6F6F7D9DC406}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {6923DB1E-CDDC-4A84-AAEF-6F6F7D9DC406}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6923DB1E-CDDC-4A84-AAEF-6F6F7D9DC406}.Release|Any CPU.Build.0 = Release|Any CPU + {6923DB1E-CDDC-4A84-AAEF-6F6F7D9DC406}.Release|Any CPU.Deploy.0 = Release|Any CPU + {754AFC87-A98F-4BD6-A934-61DB69C0B643}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {754AFC87-A98F-4BD6-A934-61DB69C0B643}.Debug|Any CPU.Build.0 = Debug|Any CPU + {754AFC87-A98F-4BD6-A934-61DB69C0B643}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {754AFC87-A98F-4BD6-A934-61DB69C0B643}.Release|Any CPU.ActiveCfg = Release|Any CPU + {754AFC87-A98F-4BD6-A934-61DB69C0B643}.Release|Any CPU.Build.0 = Release|Any CPU + {754AFC87-A98F-4BD6-A934-61DB69C0B643}.Release|Any CPU.Deploy.0 = Release|Any CPU + {3AC34973-19FC-453A-A90E-4406EB355F72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3AC34973-19FC-453A-A90E-4406EB355F72}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3AC34973-19FC-453A-A90E-4406EB355F72}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {3AC34973-19FC-453A-A90E-4406EB355F72}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3AC34973-19FC-453A-A90E-4406EB355F72}.Release|Any CPU.Build.0 = Release|Any CPU + {3AC34973-19FC-453A-A90E-4406EB355F72}.Release|Any CPU.Deploy.0 = Release|Any CPU + {41A4E1A7-0BC4-474F-910F-F140EEA1A4BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {41A4E1A7-0BC4-474F-910F-F140EEA1A4BE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {41A4E1A7-0BC4-474F-910F-F140EEA1A4BE}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {41A4E1A7-0BC4-474F-910F-F140EEA1A4BE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {41A4E1A7-0BC4-474F-910F-F140EEA1A4BE}.Release|Any CPU.Build.0 = Release|Any CPU + {41A4E1A7-0BC4-474F-910F-F140EEA1A4BE}.Release|Any CPU.Deploy.0 = Release|Any CPU + {F3F3966C-E416-41EF-889B-518FFECFC780}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F3F3966C-E416-41EF-889B-518FFECFC780}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F3F3966C-E416-41EF-889B-518FFECFC780}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {F3F3966C-E416-41EF-889B-518FFECFC780}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F3F3966C-E416-41EF-889B-518FFECFC780}.Release|Any CPU.Build.0 = Release|Any CPU + {F3F3966C-E416-41EF-889B-518FFECFC780}.Release|Any CPU.Deploy.0 = Release|Any CPU + {CDC8B582-C7F8-4578-8F1A-0B4B817D2632}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CDC8B582-C7F8-4578-8F1A-0B4B817D2632}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CDC8B582-C7F8-4578-8F1A-0B4B817D2632}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {CDC8B582-C7F8-4578-8F1A-0B4B817D2632}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CDC8B582-C7F8-4578-8F1A-0B4B817D2632}.Release|Any CPU.Build.0 = Release|Any CPU + {CDC8B582-C7F8-4578-8F1A-0B4B817D2632}.Release|Any CPU.Deploy.0 = Release|Any CPU + {EDDED57B-FCCC-4F76-B94C-C5F793678E36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EDDED57B-FCCC-4F76-B94C-C5F793678E36}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EDDED57B-FCCC-4F76-B94C-C5F793678E36}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {EDDED57B-FCCC-4F76-B94C-C5F793678E36}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EDDED57B-FCCC-4F76-B94C-C5F793678E36}.Release|Any CPU.Build.0 = Release|Any CPU + {EDDED57B-FCCC-4F76-B94C-C5F793678E36}.Release|Any CPU.Deploy.0 = Release|Any CPU + {0F63B848-5397-41F5-A6A9-4837ED647E1A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0F63B848-5397-41F5-A6A9-4837ED647E1A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0F63B848-5397-41F5-A6A9-4837ED647E1A}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {0F63B848-5397-41F5-A6A9-4837ED647E1A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0F63B848-5397-41F5-A6A9-4837ED647E1A}.Release|Any CPU.Build.0 = Release|Any CPU + {0F63B848-5397-41F5-A6A9-4837ED647E1A}.Release|Any CPU.Deploy.0 = Release|Any CPU + {31D80302-FD83-4958-B379-DAC2BC91ABDA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {31D80302-FD83-4958-B379-DAC2BC91ABDA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {31D80302-FD83-4958-B379-DAC2BC91ABDA}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {31D80302-FD83-4958-B379-DAC2BC91ABDA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {31D80302-FD83-4958-B379-DAC2BC91ABDA}.Release|Any CPU.Build.0 = Release|Any CPU + {31D80302-FD83-4958-B379-DAC2BC91ABDA}.Release|Any CPU.Deploy.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -3259,6 +3523,57 @@ Global {14ACE12B-5B23-4FF3-B3C2-BFECB21064A6} = {2B794146-DFEE-475A-B919-7D3ED48587B8} {768E2B04-FBE8-4464-B5DE-F5AA010E9D33} = {14ACE12B-5B23-4FF3-B3C2-BFECB21064A6} {16A387A9-80AA-4080-85F6-10F53D6EC99E} = {7311794D-7D2F-47E8-A5B0-C216CBD64A13} + {AD6DD7B6-B896-44B9-904E-9330C2C842C7} = {78E463DA-0FA1-4AAE-A281-D3297C9388C9} + {A3F37EFB-9686-4074-9962-5F731C52D919} = {AD6DD7B6-B896-44B9-904E-9330C2C842C7} + {753F764D-EA21-43A0-B761-6E9B43D8C90B} = {2B794146-DFEE-475A-B919-7D3ED48587B8} + {C182D69A-FE45-46BF-8522-76E0BC962FFB} = {753F764D-EA21-43A0-B761-6E9B43D8C90B} + {D46CA94B-9A0C-4188-9EE8-8A51E1499B73} = {753F764D-EA21-43A0-B761-6E9B43D8C90B} + {1F6AF0D5-CF64-4DBA-B920-F86EAB108F2B} = {D46CA94B-9A0C-4188-9EE8-8A51E1499B73} + {8D0C58C8-B325-48A1-A500-7E8FDC28C272} = {2B794146-DFEE-475A-B919-7D3ED48587B8} + {F288D725-B26F-4E32-B870-F391AF4211EB} = {8D0C58C8-B325-48A1-A500-7E8FDC28C272} + {BCF66E00-2BFE-4B8B-829F-2D8088CBCFEB} = {8D0C58C8-B325-48A1-A500-7E8FDC28C272} + {F3CFF38B-8F9D-4BE0-8017-FBA5687E15E2} = {F288D725-B26F-4E32-B870-F391AF4211EB} + {1D0D2EEC-2637-489F-83C3-7F7CB36E5512} = {2B794146-DFEE-475A-B919-7D3ED48587B8} + {4A7E3CDC-2141-4D74-A8CB-480ED78251B1} = {1D0D2EEC-2637-489F-83C3-7F7CB36E5512} + {2E207B06-0C55-44FA-8334-62D791DB6105} = {1D0D2EEC-2637-489F-83C3-7F7CB36E5512} + {B41D00C4-35F9-4E11-BF1A-EAD43F5B8CA6} = {4A7E3CDC-2141-4D74-A8CB-480ED78251B1} + {85EA8B09-1C8D-4E67-9770-C1AD0A550DED} = {1EB7CD8B-7293-4C4A-9C58-160456BCCB1E} + {C6AB70DF-B943-41F7-8DFC-2A89CFDD2C8D} = {2B794146-DFEE-475A-B919-7D3ED48587B8} + {13D97CCB-2CFF-4AB8-A170-701525DA740B} = {C6AB70DF-B943-41F7-8DFC-2A89CFDD2C8D} + {70A3BC90-AB6A-4498-BFDE-07AA25823036} = {C6AB70DF-B943-41F7-8DFC-2A89CFDD2C8D} + {A470E563-7ADD-4A76-91AE-C1190134D3FA} = {13D97CCB-2CFF-4AB8-A170-701525DA740B} + {B935965C-0FFC-4D7B-BDBC-B17C46C785F0} = {AD6DD7B6-B896-44B9-904E-9330C2C842C7} + {38944011-FA3C-4557-9049-B41B6168F6C0} = {78E463DA-0FA1-4AAE-A281-D3297C9388C9} + {00085539-EB03-49CE-8518-13544FD480BB} = {38944011-FA3C-4557-9049-B41B6168F6C0} + {59445EBB-78B8-4E83-B05D-C597D0C9AEC0} = {38944011-FA3C-4557-9049-B41B6168F6C0} + {95670172-AB31-4239-8805-346DDD57983F} = {59445EBB-78B8-4E83-B05D-C597D0C9AEC0} + {E2A8BDCC-626E-450D-918F-785E3777793E} = {818BF624-10A7-45B2-9BEE-4C411CD9CA06} + {D737283C-DDC2-4B77-B4A9-88F5BD6E31F4} = {E2A8BDCC-626E-450D-918F-785E3777793E} + {113D71B4-AE9A-402A-95A0-4D46C28F1EA0} = {E2A8BDCC-626E-450D-918F-785E3777793E} + {3885F704-2844-4EDD-9706-BD1B0C85A29B} = {113D71B4-AE9A-402A-95A0-4D46C28F1EA0} + {EB1F7A63-223D-4DD6-96EA-B04CEAE2292D} = {F288D725-B26F-4E32-B870-F391AF4211EB} + {CEA88FA7-1201-440B-9869-362932802FE6} = {283E2851-C603-4F0D-A10B-4CDC8CBBE06D} + {257256A8-EAA1-4E7E-87B9-E8A34B5D2CFF} = {CEA88FA7-1201-440B-9869-362932802FE6} + {F8FEA194-F417-4141-9025-7F16C4FAA782} = {CEA88FA7-1201-440B-9869-362932802FE6} + {1B54CA69-FD1F-46FF-9F0C-2AFB00AAB2E1} = {257256A8-EAA1-4E7E-87B9-E8A34B5D2CFF} + {698A96DD-692F-4ABE-9B4D-9BDA300C8B84} = {283E2851-C603-4F0D-A10B-4CDC8CBBE06D} + {385CB50B-4D17-4FFF-BCCE-C8BF9D280A52} = {698A96DD-692F-4ABE-9B4D-9BDA300C8B84} + {09E368FA-1ACA-4F96-9153-B4959A7EE390} = {698A96DD-692F-4ABE-9B4D-9BDA300C8B84} + {6923DB1E-CDDC-4A84-AAEF-6F6F7D9DC406} = {385CB50B-4D17-4FFF-BCCE-C8BF9D280A52} + {CBF95E20-6021-4E5B-807A-E099DBC98764} = {DBC6C89D-A932-4F99-9382-7405A0045988} + {573A2A08-CB36-480E-9C5D-56F851847045} = {CBF95E20-6021-4E5B-807A-E099DBC98764} + {754AFC87-A98F-4BD6-A934-61DB69C0B643} = {CBF95E20-6021-4E5B-807A-E099DBC98764} + {3AC34973-19FC-453A-A90E-4406EB355F72} = {573A2A08-CB36-480E-9C5D-56F851847045} + {41A4E1A7-0BC4-474F-910F-F140EEA1A4BE} = {573A2A08-CB36-480E-9C5D-56F851847045} + {0236BB4E-B417-4549-B69E-79AC81FC3056} = {E0384B86-37FC-403C-B1F7-AA5D1B869EB1} + {F3F3966C-E416-41EF-889B-518FFECFC780} = {0236BB4E-B417-4549-B69E-79AC81FC3056} + {99AABDF6-1EE4-4099-B61C-E49CA6F5CA0F} = {0236BB4E-B417-4549-B69E-79AC81FC3056} + {CDC8B582-C7F8-4578-8F1A-0B4B817D2632} = {99AABDF6-1EE4-4099-B61C-E49CA6F5CA0F} + {4F21565E-E855-479E-87D1-7F5F3BC96543} = {78E463DA-0FA1-4AAE-A281-D3297C9388C9} + {EDDED57B-FCCC-4F76-B94C-C5F793678E36} = {4F21565E-E855-479E-87D1-7F5F3BC96543} + {8A37E554-5E29-4E3A-A4EF-6E360FBA359B} = {4F21565E-E855-479E-87D1-7F5F3BC96543} + {0F63B848-5397-41F5-A6A9-4837ED647E1A} = {8A37E554-5E29-4E3A-A4EF-6E360FBA359B} + {31D80302-FD83-4958-B379-DAC2BC91ABDA} = {A3F37EFB-9686-4074-9962-5F731C52D919} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {AF7CA16F-8C38-4546-87A2-5DAAF58A1520}