Skip to content

Commit

Permalink
Merge pull request #21 from WildernessLabs/feature/chromatek
Browse files Browse the repository at this point in the history
Added ChromaTek momentary button
  • Loading branch information
adrianstevens authored Oct 8, 2024
2 parents a16a3f4 + 5b7cf1e commit e68773e
Show file tree
Hide file tree
Showing 9 changed files with 370 additions and 0 deletions.
35 changes: 35 additions & 0 deletions Source/CompositeDevices.sln
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TinyCodeReader_Sample", "Se
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet", "..\..\MQTTnet\Source\MQTTnet\MQTTnet.csproj", "{6DD7AFF8-CDE5-436F-ACA5-835DFF5F1752}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Switches", "Switches", "{D507F2A6-DD68-4A6A-A96A-10DEEC6AFDE4}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ChromaTek", "ChromaTek", "{DA79C3C0-E26D-4921-A4F1-FEAF4BE5EF75}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Switches.ChromaTek", "Switches.ChromaTek\Driver\Switches.ChromaTek.csproj", "{0E68CE3B-5E3A-4E82-83B1-EEB73122686B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Leds.Ws2812", "..\..\Meadow.Foundation\Source\Meadow.Foundation.Peripherals\Leds.Ws2812\Driver\Leds.Ws2812.csproj", "{1A89712F-C591-4F1B-ADED-E5650955128B}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{BDF759CA-4EC1-456A-BC78-7650C1B9E733}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ChromaTek_Sample", "Switches.ChromaTek\Samples\ChromaTek_Sample\ChromaTek_Sample.csproj", "{73AD475C-6928-45D3-A760-37892CB1F12F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -145,6 +157,24 @@ Global
{6DD7AFF8-CDE5-436F-ACA5-835DFF5F1752}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6DD7AFF8-CDE5-436F-ACA5-835DFF5F1752}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6DD7AFF8-CDE5-436F-ACA5-835DFF5F1752}.Release|Any CPU.Build.0 = Release|Any CPU
{0E68CE3B-5E3A-4E82-83B1-EEB73122686B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0E68CE3B-5E3A-4E82-83B1-EEB73122686B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0E68CE3B-5E3A-4E82-83B1-EEB73122686B}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{0E68CE3B-5E3A-4E82-83B1-EEB73122686B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0E68CE3B-5E3A-4E82-83B1-EEB73122686B}.Release|Any CPU.Build.0 = Release|Any CPU
{0E68CE3B-5E3A-4E82-83B1-EEB73122686B}.Release|Any CPU.Deploy.0 = Release|Any CPU
{1A89712F-C591-4F1B-ADED-E5650955128B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1A89712F-C591-4F1B-ADED-E5650955128B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1A89712F-C591-4F1B-ADED-E5650955128B}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{1A89712F-C591-4F1B-ADED-E5650955128B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1A89712F-C591-4F1B-ADED-E5650955128B}.Release|Any CPU.Build.0 = Release|Any CPU
{1A89712F-C591-4F1B-ADED-E5650955128B}.Release|Any CPU.Deploy.0 = Release|Any CPU
{73AD475C-6928-45D3-A760-37892CB1F12F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{73AD475C-6928-45D3-A760-37892CB1F12F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{73AD475C-6928-45D3-A760-37892CB1F12F}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{73AD475C-6928-45D3-A760-37892CB1F12F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{73AD475C-6928-45D3-A760-37892CB1F12F}.Release|Any CPU.Build.0 = Release|Any CPU
{73AD475C-6928-45D3-A760-37892CB1F12F}.Release|Any CPU.Deploy.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -173,6 +203,11 @@ Global
{D55D9CEE-0E03-43A5-8B8A-11B723C3D608} = {FCD85A86-0779-4AC3-A12C-91F3C0C5D161}
{A0C0F999-2D2D-4674-BA32-E244CC53D937} = {B155FD13-EEE6-40B3-9C3A-A0FEADCBE24F}
{6DD7AFF8-CDE5-436F-ACA5-835DFF5F1752} = {20E3A0B4-6103-4EAD-BD90-90C673E07DCC}
{DA79C3C0-E26D-4921-A4F1-FEAF4BE5EF75} = {D507F2A6-DD68-4A6A-A96A-10DEEC6AFDE4}
{0E68CE3B-5E3A-4E82-83B1-EEB73122686B} = {DA79C3C0-E26D-4921-A4F1-FEAF4BE5EF75}
{1A89712F-C591-4F1B-ADED-E5650955128B} = {20E3A0B4-6103-4EAD-BD90-90C673E07DCC}
{BDF759CA-4EC1-456A-BC78-7650C1B9E733} = {DA79C3C0-E26D-4921-A4F1-FEAF4BE5EF75}
{73AD475C-6928-45D3-A760-37892CB1F12F} = {BDF759CA-4EC1-456A-BC78-7650C1B9E733}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BF2FC8CE-57C6-468C-B82D-D8204E6D9360}
Expand Down
64 changes: 64 additions & 0 deletions Source/Switches.ChromaTek/Driver/ButtonCollection.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using Meadow.Foundation.Leds;
using Meadow.Hardware;
using System;
using System.Collections;
using System.Collections.Generic;

namespace Meadow.Foundation.Switches.ChromaTek;

/// <summary>
/// Represents a collection of ChromaTek buttons with WS2812 color LEDs
/// </summary>
public class ButtonCollection : IEnumerable<IChromaTekButton>
{
private Ws2812 ws2812 = default!;
private List<IChromaTekButton> buttons = new();

/// <summary>
/// Creates a collection of buttons
/// </summary>
/// <param name="bus">The SPI bus that all buttons are connected to</param>
/// <param name="buttons">The list of button on the bus</param>
public ButtonCollection(ISpiBus bus, params IChromaTekButton[] buttons)
{
ws2812 = new Ws2812(bus, buttons.Length);
var index = 0;

foreach (var button in buttons)
{
switch (button)
{
case MomentaryButton mb:
mb.LedController = ws2812;
mb.ButtonIndex = index;
this.buttons.Add(mb);
break;
case LatchingButton lb:
lb.LedController = ws2812;
lb.ButtonIndex = index;
this.buttons.Add(lb);
break;
default: throw new ArgumentException("Button is not a ChromaTek button");

};
index++;
}
}

/// <inheritdoc/>
public IChromaTekButton this[int index]
{
get => buttons[index];
}

/// <inheritdoc/>
public IEnumerator<IChromaTekButton> GetEnumerator()
{
return buttons.GetEnumerator();
}

IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
11 changes: 11 additions & 0 deletions Source/Switches.ChromaTek/Driver/IChromaTekButton.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using Meadow.Hardware;
using Meadow.Peripherals.Sensors;

namespace Meadow.Foundation.Switches.ChromaTek;

/// <summary>
/// Represents a ChromaTek button with a WS2812 color LED
/// </summary>
public interface IChromaTekButton : IColorable, ISensor<bool>
{
}
70 changes: 70 additions & 0 deletions Source/Switches.ChromaTek/Driver/LatchingButton.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using Meadow.Foundation.Leds;
using Meadow.Foundation.Sensors.Switches;
using Meadow.Hardware;
using System;

namespace Meadow.Foundation.Switches.ChromaTek;

/// <summary>
/// Represents a latching push button with a WS2812 color LED
/// </summary>
public class LatchingButton : SpstSwitch, IChromaTekButton
{
private ISpiBus? bus = null;
private Color color = Color.Black;

internal Ws2812? LedController { get; set; } = default!;
internal int ButtonIndex { get; set; } = 0;

/// <summary>
/// Creates an instance of a ChromaTekLatchingButton
/// </summary>
/// <param name="bus">The SPI bus COPI line connected to the WS2812 data line</param>
/// <param name="inputPort">The interrupt port connected to the switch</param>
public LatchingButton(IDigitalInterruptPort inputPort, ISpiBus? bus = null)
: base(inputPort)
{
this.bus = bus;
}

/// <summary>
/// Creates an instance of a ChromaTekLatchingButton
/// </summary>
/// <param name="bus">The SPI bus COPI line connected to the WS2812 data line</param>
/// <param name="pin">The IPin connected to the switch</param>
/// <param name="interruptMode">The interrupt mode for the switch pin</param>
/// <param name="resistorMode">The resistor mode for the switch pin</param>
public LatchingButton(IPin pin, InterruptMode interruptMode, ResistorMode resistorMode, ISpiBus? bus = null)
: base(pin, interruptMode, resistorMode)
{
this.bus = bus;
}

private void Initialize()
{
if (LedController != null) return;

if (bus == null)
{
throw new Exception("This button must either be constructed withan ISpiBus or added to a ButtonCollection");
}

LedController = new Ws2812(bus, 1);
}

/// <inheritdoc/>
public void SetColor(Color color)
{
if (LedController == null)
{
Initialize();
}

LedController?.SetLed(ButtonIndex, color);
LedController?.Show();
this.color = color;
}

/// <inheritdoc/>
public Color GetColor() => color;
}
82 changes: 82 additions & 0 deletions Source/Switches.ChromaTek/Driver/MomentaryButton.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
using Meadow.Foundation.Leds;
using Meadow.Foundation.Sensors.Buttons;
using Meadow.Hardware;
using System;

namespace Meadow.Foundation.Switches.ChromaTek;

/// <summary>
/// Represents a momentary push button with a WS2812 color LED
/// </summary>
public class MomentaryButton : PushButton, IChromaTekButton
{
private ISpiBus? bus = null;
private Color color = Color.Black;

internal Ws2812 LedController { get; set; } = default!;
internal int ButtonIndex { get; set; } = 0;

/// <summary>
/// Creates an instance of a ChromaTekMomentaryButton
/// </summary>
/// <param name="bus">The SPI bus COPI line connected to the WS2812 data line</param>
/// <param name="inputPort">The interrupt port connected to the switch</param>
public MomentaryButton(IDigitalInterruptPort inputPort, ISpiBus? bus = null)
: base(inputPort)
{
this.bus = bus;
}

/// <summary>
/// Creates an instance of a ChromaTekMomentaryButton
/// </summary>
/// <param name="bus">The SPI bus COPI line connected to the WS2812 data line</param>
/// <param name="pin">The IPin connected to the switch</param>
/// <param name="resistorMode">The resistor mode for the switch pin</param>
public MomentaryButton(IPin pin, ResistorMode resistorMode, ISpiBus? bus = null)
: base(pin, resistorMode)
{
this.bus = bus;
}

/// <summary>
/// Creates an instance of a ChromaTekMomentaryButton
/// </summary>
/// <param name="bus">The SPI bus COPI line connected to the WS2812 data line</param>
/// <param name="pin">The IPin connected to the switch</param>
/// <param name="resistorMode">The resistor mode for the switch pin</param>
/// <param name="debounceDuration">Debounce duration for the interrupt pin</param>
public MomentaryButton(IPin pin, ResistorMode resistorMode, TimeSpan debounceDuration, ISpiBus? bus = null)
: base(pin, resistorMode, debounceDuration)
{
this.bus = bus;
}

private void Initialize()
{
if (LedController != null) return;

if (bus == null)
{
throw new Exception("This button must either be constructed withan ISpiBus or added to a ButtonCollection");
}

LedController = new Ws2812(bus, 1);
}

/// <inheritdoc/>
public void SetColor(Color color)
{
if (LedController == null)
{
Initialize();
}

LedController?.SetLed(ButtonIndex, color);
LedController?.Show();
this.color = color;
}

/// <inheritdoc/>
public Color GetColor() => color;
}
28 changes: 28 additions & 0 deletions Source/Switches.ChromaTek/Driver/Switches.ChromaTek.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<Project Sdk="Meadow.Sdk/1.1.0">
<PropertyGroup>
<Version>1.11.0</Version>
<LangVersion>10.0</LangVersion>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageIcon>icon.png</PackageIcon>
<Authors>Wilderness Labs, Inc</Authors>
<TargetFramework>netstandard2.1</TargetFramework>
<OutputType>Library</OutputType>
<AssemblyName>Switches.ChromaTek</AssemblyName>
<Company>Wilderness Labs, Inc</Company>
<PackageProjectUrl>http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/</PackageProjectUrl>
<PackageId>Meadow.Foundation.Switches.ChromaTek</PackageId>
<RepositoryUrl>https://github.com/WildernessLabs/Meadow.Foundation</RepositoryUrl>
<PackageTags>Meadow.Foundation,Meadow,WS2812,Neopixel Button,ChromaTek</PackageTags>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Description>SPI-driven ChromaTek multi-color illuminated switches</Description>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<None Include="..\..\icon.png" Pack="true" PackagePath="" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\Meadow.Foundation\Source\Meadow.Foundation.Peripherals\ICs.IOExpanders.Pcx857x\Driver\ICs.IOExpanders.Pcx857x.csproj" />
<ProjectReference Include="..\..\..\..\Meadow.Foundation\Source\Meadow.Foundation.Peripherals\Leds.Ws2812\Driver\Leds.Ws2812.csproj" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<Project Sdk="Meadow.Sdk/1.1.0">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<OutputType>Library</OutputType>
<AssemblyName>App</AssemblyName>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\..\Meadow.Core\Source\implementations\f7\Meadow.F7\Meadow.F7.csproj" />
<ProjectReference Include="..\..\Driver\Switches.ChromaTek.csproj" />
</ItemGroup>
</Project>
43 changes: 43 additions & 0 deletions Source/Switches.ChromaTek/Samples/ChromaTek_Sample/MeadowApp.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using Meadow;
using Meadow.Devices;
using Meadow.Foundation.Switches.ChromaTek;
using Meadow.Units;
using System;
using System.Threading.Tasks;

namespace Switches.ChromaTek_Sample
{
public class MeadowApp : App<F7FeatherV2>
{
//<!=SNIP=>

private MomentaryButton _button = default!;
private readonly Color _normalColor = Color.Green;
private readonly Color _pressedColor = Color.Red;

public override Task Initialize()
{
Resolver.Log.Info("Initialize...");

var bus = Device.CreateSpiBus(new Frequency(2.5, Frequency.UnitType.Megahertz));
_button = new MomentaryButton(Device.Pins.D04, Meadow.Hardware.ResistorMode.InternalPullUp, bus);
_button.SetColor(_normalColor);
_button.Clicked += OnButtonClicked;

return Task.CompletedTask;
}

private void OnButtonClicked(object sender, EventArgs e)
{
Resolver.Log.Info("Click");
Task.Run(async () =>
{
_button.SetColor(_pressedColor);
await Task.Delay(3000);
_button.SetColor(_normalColor);
});
}

//<!=SNOP=>
}
}
Loading

0 comments on commit e68773e

Please sign in to comment.