Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Device: LED segment display 5641AS #2350

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/devices/Display/Display.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
<TargetFrameworks>$(DefaultBindingTfms)</TargetFrameworks>
<EnableDefaultItems>false</EnableDefaultItems>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net6.0|AnyCPU'">
<DebugType>portable</DebugType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|netstandard2.0|AnyCPU'">
<DebugType>portable</DebugType>
</PropertyGroup>
<ItemGroup>
<Compile Include="Alignment.cs" />
<Compile Include="BiColorBarGraph.cs" />
Expand All @@ -11,6 +17,8 @@
<Compile Include="Dot.cs" />
<Compile Include="Font.cs" />
<Compile Include="Font14.cs" />
<Compile Include="LedSegmentDisplay5641AS.cs" />
<Compile Include="LedSegmentDisplay5641ASPinScheme.cs" />
<Compile Include="Segment.cs" />
<Compile Include="Segment14.cs" />
<Compile Include="FontHelper.cs" />
Expand All @@ -22,6 +30,7 @@
<Compile Include="Matrix16x8.cs" />
<Compile Include="Matrix8x8.cs" />
<Compile Include="Matrix8x8Bicolor.cs" />
<Compile Include="SegmentHelpers.cs" />
</ItemGroup>
<ItemGroup>
<None Include="README.md" />
Expand Down
78 changes: 67 additions & 11 deletions src/devices/Display/Display.sln
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26124.0
# Visual Studio Version 17
VisualStudioVersion = 17.10.35122.118
MinimumVisualStudioVersion = 15.0.26124.0
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{20F2E85F-D100-4EE6-BF7D-8BB8748D626C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Large4Digit7SegmentDisplay.sample", "samples\Large4Digit7SegmentDisplay\Large4Digit7SegmentDisplay.sample.csproj", "{C4D7AED7-B340-4DCD-974C-5150C6D5F074}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Large4Digit7SegmentDisplay.sample", "samples\Large4Digit7SegmentDisplay\Large4Digit7SegmentDisplay.sample.csproj", "{C4D7AED7-B340-4DCD-974C-5150C6D5F074}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Matrix.sample", "samples\Matrix\Matrix.sample.csproj", "{C4D7AED7-B340-4DCD-974C-5150C6D5F074}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Matrix.sample", "samples\Matrix\Matrix.sample.csproj", "{938399AC-21ED-4CAD-BC8B-EA75031FCFC3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Matrix8x8Bicolor.sample", "samples\Matrix8x8Bicolor\Matrix8x8Bicolor.sample.csproj", "{C4D7AED7-B340-4DCD-974C-5150C6D5F074}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Matrix8x8Bicolor.sample", "samples\Matrix8x8Bicolor\Matrix8x8Bicolor.sample.csproj", "{59564F6F-CA0A-4138-8D36-EDF770591081}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BiColorBargraph.sample", "samples\BiColorBargraph.sample.csproj", "{C4D7AED7-B340-4DCD-974C-5150C6D5F074}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BiColorBargraph.sample", "samples\BiColorBargraph.sample.csproj", "{A03ED5B0-4A75-418D-B168-290A6568B0D5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Display", "Display.csproj", "{4AAE8B9E-8540-4582-8083-D1F14104BAAC}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Display", "Display.csproj", "{4AAE8B9E-8540-4582-8083-D1F14104BAAC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LedSegmentDisplay5641AS.Sample", "samples\LedSegmentDisplay5641AS.Sample\LedSegmentDisplay5641AS.Sample.csproj", "{9C7E6C39-38F5-40B9-8A9C-6D75749ACFAD}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Button", "..\Button\Button.csproj", "{273B1DA5-52BA-4488-A82F-A24E2C0BEDE9}"
EndProject

Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -25,9 +28,6 @@ Global
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{C4D7AED7-B340-4DCD-974C-5150C6D5F074}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C4D7AED7-B340-4DCD-974C-5150C6D5F074}.Debug|Any CPU.Build.0 = Debug|Any CPU
Expand All @@ -41,6 +41,30 @@ Global
{C4D7AED7-B340-4DCD-974C-5150C6D5F074}.Release|x64.Build.0 = Release|Any CPU
{C4D7AED7-B340-4DCD-974C-5150C6D5F074}.Release|x86.ActiveCfg = Release|Any CPU
{C4D7AED7-B340-4DCD-974C-5150C6D5F074}.Release|x86.Build.0 = Release|Any CPU
{938399AC-21ED-4CAD-BC8B-EA75031FCFC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{938399AC-21ED-4CAD-BC8B-EA75031FCFC3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{938399AC-21ED-4CAD-BC8B-EA75031FCFC3}.Debug|x64.ActiveCfg = Debug|Any CPU
{938399AC-21ED-4CAD-BC8B-EA75031FCFC3}.Debug|x64.Build.0 = Debug|Any CPU
{938399AC-21ED-4CAD-BC8B-EA75031FCFC3}.Debug|x86.ActiveCfg = Debug|Any CPU
{938399AC-21ED-4CAD-BC8B-EA75031FCFC3}.Debug|x86.Build.0 = Debug|Any CPU
{938399AC-21ED-4CAD-BC8B-EA75031FCFC3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{938399AC-21ED-4CAD-BC8B-EA75031FCFC3}.Release|Any CPU.Build.0 = Release|Any CPU
{938399AC-21ED-4CAD-BC8B-EA75031FCFC3}.Release|x64.ActiveCfg = Release|Any CPU
{938399AC-21ED-4CAD-BC8B-EA75031FCFC3}.Release|x64.Build.0 = Release|Any CPU
{938399AC-21ED-4CAD-BC8B-EA75031FCFC3}.Release|x86.ActiveCfg = Release|Any CPU
{938399AC-21ED-4CAD-BC8B-EA75031FCFC3}.Release|x86.Build.0 = Release|Any CPU
{59564F6F-CA0A-4138-8D36-EDF770591081}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{59564F6F-CA0A-4138-8D36-EDF770591081}.Debug|Any CPU.Build.0 = Debug|Any CPU
{59564F6F-CA0A-4138-8D36-EDF770591081}.Debug|x64.ActiveCfg = Debug|Any CPU
{59564F6F-CA0A-4138-8D36-EDF770591081}.Debug|x64.Build.0 = Debug|Any CPU
{59564F6F-CA0A-4138-8D36-EDF770591081}.Debug|x86.ActiveCfg = Debug|Any CPU
{59564F6F-CA0A-4138-8D36-EDF770591081}.Debug|x86.Build.0 = Debug|Any CPU
{59564F6F-CA0A-4138-8D36-EDF770591081}.Release|Any CPU.ActiveCfg = Release|Any CPU
{59564F6F-CA0A-4138-8D36-EDF770591081}.Release|Any CPU.Build.0 = Release|Any CPU
{59564F6F-CA0A-4138-8D36-EDF770591081}.Release|x64.ActiveCfg = Release|Any CPU
{59564F6F-CA0A-4138-8D36-EDF770591081}.Release|x64.Build.0 = Release|Any CPU
{59564F6F-CA0A-4138-8D36-EDF770591081}.Release|x86.ActiveCfg = Release|Any CPU
{59564F6F-CA0A-4138-8D36-EDF770591081}.Release|x86.Build.0 = Release|Any CPU
{4AAE8B9E-8540-4582-8083-D1F14104BAAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4AAE8B9E-8540-4582-8083-D1F14104BAAC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4AAE8B9E-8540-4582-8083-D1F14104BAAC}.Debug|x64.ActiveCfg = Debug|Any CPU
Expand All @@ -53,8 +77,40 @@ Global
{4AAE8B9E-8540-4582-8083-D1F14104BAAC}.Release|x64.Build.0 = Release|Any CPU
{4AAE8B9E-8540-4582-8083-D1F14104BAAC}.Release|x86.ActiveCfg = Release|Any CPU
{4AAE8B9E-8540-4582-8083-D1F14104BAAC}.Release|x86.Build.0 = Release|Any CPU
{9C7E6C39-38F5-40B9-8A9C-6D75749ACFAD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9C7E6C39-38F5-40B9-8A9C-6D75749ACFAD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9C7E6C39-38F5-40B9-8A9C-6D75749ACFAD}.Debug|x64.ActiveCfg = Debug|Any CPU
{9C7E6C39-38F5-40B9-8A9C-6D75749ACFAD}.Debug|x64.Build.0 = Debug|Any CPU
{9C7E6C39-38F5-40B9-8A9C-6D75749ACFAD}.Debug|x86.ActiveCfg = Debug|Any CPU
{9C7E6C39-38F5-40B9-8A9C-6D75749ACFAD}.Debug|x86.Build.0 = Debug|Any CPU
{9C7E6C39-38F5-40B9-8A9C-6D75749ACFAD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9C7E6C39-38F5-40B9-8A9C-6D75749ACFAD}.Release|Any CPU.Build.0 = Release|Any CPU
{9C7E6C39-38F5-40B9-8A9C-6D75749ACFAD}.Release|x64.ActiveCfg = Release|Any CPU
{9C7E6C39-38F5-40B9-8A9C-6D75749ACFAD}.Release|x64.Build.0 = Release|Any CPU
{9C7E6C39-38F5-40B9-8A9C-6D75749ACFAD}.Release|x86.ActiveCfg = Release|Any CPU
{9C7E6C39-38F5-40B9-8A9C-6D75749ACFAD}.Release|x86.Build.0 = Release|Any CPU
{273B1DA5-52BA-4488-A82F-A24E2C0BEDE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{273B1DA5-52BA-4488-A82F-A24E2C0BEDE9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{273B1DA5-52BA-4488-A82F-A24E2C0BEDE9}.Debug|x64.ActiveCfg = Debug|Any CPU
{273B1DA5-52BA-4488-A82F-A24E2C0BEDE9}.Debug|x64.Build.0 = Debug|Any CPU
{273B1DA5-52BA-4488-A82F-A24E2C0BEDE9}.Debug|x86.ActiveCfg = Debug|Any CPU
{273B1DA5-52BA-4488-A82F-A24E2C0BEDE9}.Debug|x86.Build.0 = Debug|Any CPU
{273B1DA5-52BA-4488-A82F-A24E2C0BEDE9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{273B1DA5-52BA-4488-A82F-A24E2C0BEDE9}.Release|Any CPU.Build.0 = Release|Any CPU
{273B1DA5-52BA-4488-A82F-A24E2C0BEDE9}.Release|x64.ActiveCfg = Release|Any CPU
{273B1DA5-52BA-4488-A82F-A24E2C0BEDE9}.Release|x64.Build.0 = Release|Any CPU
{273B1DA5-52BA-4488-A82F-A24E2C0BEDE9}.Release|x86.ActiveCfg = Release|Any CPU
{273B1DA5-52BA-4488-A82F-A24E2C0BEDE9}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{C4D7AED7-B340-4DCD-974C-5150C6D5F074} = {20F2E85F-D100-4EE6-BF7D-8BB8748D626C}
{9C7E6C39-38F5-40B9-8A9C-6D75749ACFAD} = {20F2E85F-D100-4EE6-BF7D-8BB8748D626C}
{273B1DA5-52BA-4488-A82F-A24E2C0BEDE9} = {20F2E85F-D100-4EE6-BF7D-8BB8748D626C}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {DE260CF9-1B56-49A0-AAB0-61D3E71B4E88}
EndGlobalSection
EndGlobal
198 changes: 198 additions & 0 deletions src/devices/Display/LedSegmentDisplay5641AS.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.Device.Gpio;
using System.Linq;
using System.Threading;
using Iot.Device.Display;

namespace Display
{
/// <summary>
/// LED 4-digit 7-segment display, model 5641AS. This class handles driverless, direct-pin access over GPIO.
/// </summary>
/// <remarks>
/// Data Sheet:
/// http://www.xlitx.com/datasheet/5641AS.pdf
/// </remarks>
public class LedSegmentDisplay5641AS : ISevenSegmentDisplay, IDisposable
{
private readonly LedSegmentDisplay5641ASPinScheme _pinScheme;
private readonly GpioController _gpioController;
private readonly bool _shouldDispose;
private bool _disposedValue;

private List<GpioPin> _segmentPins;
private List<GpioPin> _digitPins;

// address, Segment(s)
private Dictionary<int, Segment> _displayBuffer;

/// <inheritdoc />
public int NumberOfDigits => _pinScheme.DigitCount;

/// <inheritdoc />
public Segment this[int address]
{
get => _displayBuffer[address];
set => WriteDigitAtAddress(address, value);
}

/// <summary>
/// Initializes a new instance of the <see cref="LedSegmentDisplay5641AS"/> class.
/// </summary>
public LedSegmentDisplay5641AS(LedSegmentDisplay5641ASPinScheme pinScheme, GpioController? gpioController = null, bool shouldDispose = true)
{
_pinScheme = pinScheme;
_gpioController = gpioController ?? new GpioController();
_shouldDispose = gpioController is null || shouldDispose;

_segmentPins = new(pinScheme.SegmentCountPerDigit);
_digitPins = new(pinScheme.DigitCount);
_displayBuffer = new Dictionary<int, Segment>(pinScheme.DigitCount);

Open();
}

/// <summary>
/// Opens GPIO pins defined in <see cref="LedSegmentDisplay5641ASPinScheme"/> as <see cref="PinMode.Output"/>
/// </summary>
private void Open()
{
foreach (var segmentPinNumBoard in _pinScheme.Segments)
{
_segmentPins.Add(_gpioController.OpenPin(segmentPinNumBoard, PinMode.Output));
}

foreach (var digitPinNumBoard in _pinScheme.Digits)
{
_digitPins.Add(_gpioController.OpenPin(digitPinNumBoard, PinMode.Output));
}
}

/// <summary>
/// Closes GPIO pins defined in <see cref="LedSegmentDisplay5641ASPinScheme"/>
/// </summary>
private void Close()
{
foreach (var segmentPinNumBoard in _pinScheme.Segments)
{
_gpioController.ClosePin(segmentPinNumBoard);
}

foreach (var digitPinNumBoard in _pinScheme.Digits)
{
_gpioController.ClosePin(digitPinNumBoard);
}

_segmentPins = new(_pinScheme.SegmentCountPerDigit);
_digitPins = new(_pinScheme.DigitCount);
}

/// <summary>
/// Clears display by writing <see cref="PinValue.Low"/> to all segments
/// </summary>
public void Clear()
{
foreach (var seg in _segmentPins)
{
seg?.Write(PinValue.Low);
}
}

/// <inheritdoc/>
public void Write(ReadOnlySpan<Segment> digits, int startAddress = 0)
{
if (digits.Length > NumberOfDigits)
{
throw new ArgumentOutOfRangeException(nameof(digits), $"Too many digits specified (max {NumberOfDigits} supported");
}

if (startAddress > NumberOfDigits - 1)
{
throw new ArgumentOutOfRangeException(nameof(startAddress), $"Specified digit address out of range (max {NumberOfDigits} supported");
}

// Characters must be written to the device in reverse order to be displayed in the intended order
Segment[] digitsToWrite = digits.ToArray().Reverse().ToArray();

for (int idx = startAddress; idx < NumberOfDigits; idx++)
{
WriteDigitAtAddress(idx, digitsToWrite[idx]);
Thread.Sleep(5);
}
}

/// <inheritdoc/>
public void Write(ReadOnlySpan<Font> characters, int startAddress = 0)
{
if (characters.Length > NumberOfDigits)
{
throw new ArgumentException($"Too many characters specified (max {NumberOfDigits} supported)", nameof(characters));
}

Write(characters.ToArray().Select(c => (Segment)c).ToArray(), startAddress);
}

private void WriteDigitAtAddress(int digitAddress, Segment segmentsToWrite)
{
ActivateDigit(digitAddress);

ReadOnlySpan<PinValue> mapping = SegmentHelpers.GetPinValuesFromSegment(segmentsToWrite);
SetPinValues(mapping);

_displayBuffer[digitAddress] = segmentsToWrite;
}

private void ActivateDigit(int idx)
{
GpioPin digit = _digitPins[idx];
WriteAll(_digitPins, _pinScheme.DigitDisplayOff);
digit.Write(!_pinScheme.DigitDisplayOff);

static void WriteAll(List<GpioPin> pins, PinValue pinValue) => pins.ForEach(p => p.Write(pinValue));
}

private void SetPinValues(ReadOnlySpan<PinValue> pinValues)
{
for (int i = 0; i < pinValues.Length; i++)
{
PinValue val = pinValues[i];
_segmentPins[i].Write(val);
}
}

/// <summary>
/// Dispose pattern
/// </summary>
/// <param name="disposing">Indicates type is under active disposal</param>
protected virtual void Dispose(bool disposing)
{
if (!_disposedValue)
{
if (disposing)
{
if (_shouldDispose)
{
_gpioController?.Dispose();
}
else
{
Close();
}
}

_disposedValue = true;
}
}

/// <inheritdoc />
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
}
Loading
Loading