Last active
November 26, 2018 15:38
-
-
Save ncarandini/3406a13fee19dc0a11f1542360c9ed24 to your computer and use it in GitHub Desktop.
[Meadow mocked pseudocode] Cycle hue on onboardLed
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Copyright(c) 2018 Nicolò Carandini (aka TPCWare) | |
// Content | |
// ====================================================================================================== | |
// This "not for production code" is just an example on how to run an async task that can be cancelled. | |
// Moreover, in this example there is an implementation of HSL to RGB color conversion. | |
// Build and test | |
// ========================================================================================================= | |
// Run it on LinqPad (https://www.linqpad.net/) or use the code to create a Console app on Visual Studio. | |
// MIT License | |
// ====================================================================================================== | |
// Permission is hereby granted, free of charge, to any person obtaining a copy | |
// of this software and associated documentation files(the "Software"), to deal | |
// in the Software without restriction, including without limitation the rights | |
// to use, copy, modify, merge, publish, distribute, sublicense, and/ or sell | |
// copies of the Software, and to permit persons to whom the Software is | |
// furnished to do so, subject to the following conditions: | |
// | |
// The above copyright notice and this permission notice shall be included in all | |
// copies or substantial portions of the Software. | |
// | |
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE | |
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
// SOFTWARE. | |
async Task Main() // C# 7.1 and up | |
{ | |
var app = new RGBApp(); | |
await app.RunAsync(); | |
} | |
public class RGBApp : AppBase<F7Micro, RGBApp> | |
{ | |
protected bool _running; | |
protected RgbPwmLed onboardLed; | |
private CancellationTokenSource cts; | |
public RGBApp() | |
{ | |
onboardLed = new RgbPwmLed(Pins.OnBoardLEDRed, Pins.OnBoardLEDGreen, Pins.OnBoardLEDBlue); | |
} | |
public async override Task RunAsync() | |
{ | |
// Instantiate the CancellationTokenSource. | |
cts = new CancellationTokenSource(); | |
// We can cancel immediately with this code, put inside a method that has subsribed an event that is triggered by something (a sensor, a button, ...): | |
// cts.Cancel(); | |
// Because we don't have such an event, we will set automatic cancellation after some time (5 seconds) | |
cts.CancelAfter(5000); | |
await CycleHueOnOnboardLed(cts); | |
} | |
private async Task CycleHueOnOnboardLed(CancellationTokenSource cts) | |
{ | |
int pauseMilliseconds = 18; | |
// Note that because we are using HSL, | |
// with lightness = 1 all color will be white regardless of the hue, | |
// with lightness = 0 all colors will be black. | |
double lightness = 0.5; | |
double saturation = 1.0; | |
try | |
{ | |
while (true) | |
{ | |
for (int hue = 0; hue < 360; hue++) | |
{ | |
cts.Token.ThrowIfCancellationRequested(); | |
onboardLed.SetColorFromHSL(hue, saturation, lightness); | |
await Task.Delay(pauseMilliseconds); | |
} | |
} | |
} | |
catch (OperationCanceledException) | |
{ | |
// Don't throw any exception | |
// we are here because the task was cancelled | |
} | |
catch (Exception e) | |
{ | |
throw new Exception($"An error occurred: {e.Message}"); | |
} | |
} | |
} | |
// ***************************** | |
// Extension methods | |
// ***************************** | |
public static class ExtendRgbPwmLed | |
{ | |
public static void SetColorFromHSL(this RgbPwmLed RgbPwmLed, int hue, double sat, double lum) | |
{ | |
RgbPwmLed.SetColor(ColorConversion.FromHSL(hue, sat, lum)); | |
} | |
} | |
// ***************************** | |
// Utils methods | |
// ***************************** | |
public static class ColorConversion | |
{ | |
public static Color FromHSL(int hue, double sat, double lum) | |
{ | |
Color result; | |
// Check parameters for value range | |
if (hue < 0 || hue > 360) | |
{ | |
throw new ArgumentOutOfRangeException(nameof(hue)); | |
} | |
if (sat < 0 || sat > 1) | |
{ | |
throw new ArgumentOutOfRangeException(nameof(sat)); | |
} | |
if (lum < 0 || lum > 1) | |
{ | |
throw new ArgumentOutOfRangeException(nameof(lum)); | |
} | |
// Convert HSL to RGB | |
double r1, g1, b1; | |
double m; | |
try | |
{ | |
double h1 = hue / 60.0; | |
double c = (1 - Math.Abs(2 * lum - 1)) * sat; | |
double x = c * (1 - Math.Abs(h1 % 2 - 1)); | |
m = lum - 0.5 * c; | |
if (h1 <= 1) | |
{ | |
r1 = c; | |
g1 = x; | |
b1 = 0; | |
} | |
else if (h1 <= 2) | |
{ | |
r1 = x; | |
g1 = c; | |
b1 = 0; | |
} | |
else if (h1 <= 3) | |
{ | |
r1 = 0; | |
g1 = c; | |
b1 = x; | |
} | |
else if (h1 <= 4) | |
{ | |
r1 = 0; | |
g1 = x; | |
b1 = c; | |
} | |
else if (h1 <= 5) | |
{ | |
r1 = x; | |
g1 = 0; | |
b1 = c; | |
} | |
else | |
{ | |
r1 = c; | |
g1 = 0; | |
b1 = x; | |
} | |
result = Color.FromArgb(255, Convert.ToInt32(255 * (r1 + m)), Convert.ToInt32(255 * (g1 + m)), Convert.ToInt32(255 * (b1 + m))); | |
} | |
catch (Exception ex) | |
{ | |
throw new Exception("Convert from HSL to RGB failed", ex); | |
} | |
return result; | |
} | |
} | |
// ***************************** | |
// Mocked classes | |
// ***************************** | |
public class AppBase<TDevice, TApp> where TApp : AppBase<TDevice, TApp> | |
{ | |
public static TApp Current { get; private set; } | |
public AppBase() | |
{ | |
Current = (TApp)this; | |
} | |
public virtual Task RunAsync() | |
{ | |
return Task.Delay(1); | |
} | |
} | |
public class RgbPwmLed | |
{ | |
private Pins redPin; | |
private Pins greenPin; | |
private Pins bluePin; | |
public RgbPwmLed(Pins redPin, Pins greenPin, Pins bluePin) | |
{ | |
this.redPin = redPin; | |
this.greenPin = greenPin; | |
this.bluePin = bluePin; | |
} | |
public void SetColor(Color color) | |
{ | |
// For test pourpose | |
Console.WriteLine(color.ToString()); | |
} | |
} | |
public class F7Micro | |
{ } | |
public enum Pins | |
{ | |
OnBoardLEDRed = 4, | |
OnBoardLEDGreen = 7, | |
OnBoardLEDBlue = 12 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment