-
Notifications
You must be signed in to change notification settings - Fork 607
Add AIP31068 LCD binding with contrast control, sample, and docs #2434
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
Open
asp2286
wants to merge
1
commit into
dotnet:main
Choose a base branch
from
asp2286:main
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+273
−0
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,167 @@ | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|
|
||
| using System.Device; | ||
| using System.Device.I2c; | ||
| using System.Drawing; | ||
|
|
||
| namespace Iot.Device.CharacterLcd | ||
| { | ||
| /// <summary> | ||
| /// 16x2 LCD controller based on the AIP31068, which exposes an HD44780 compatible interface with | ||
| /// an integrated I2C controller. | ||
| /// </summary> | ||
| public class Aip31068Lcd : Hd44780 | ||
| { | ||
| private const byte ContrastMask = 0x3F; | ||
| private const byte ContrastSetCommand = 0x70; | ||
| private const byte PowerIconContrastCommand = 0x50; | ||
| private const byte IconDisplayFlag = 0x08; | ||
| private const byte BoosterFlag = 0x04; | ||
| private const byte FollowerControlCommand = 0x6C; | ||
| private const byte InternalOscillatorCommand = 0x14; | ||
| private const byte DefaultContrast = 0x20; | ||
|
|
||
| private byte _contrast; | ||
| private bool _iconDisplayEnabled; | ||
| private bool _boosterEnabled; | ||
|
|
||
| // Static members must appear before non-static members (SA1204) | ||
| private static byte NormalizeContrast(byte value) | ||
| { | ||
| return value > ContrastMask ? ContrastMask : (byte)(value & ContrastMask); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Initializes a new instance of the <see cref="Aip31068Lcd"/> class using the specified I2C device. | ||
| /// </summary> | ||
| /// <param name="device">The I2C device used to communicate with the LCD controller.</param> | ||
| /// <param name="contrast">Initial contrast value. Valid range: 0-63.</param> | ||
| /// <param name="iconDisplayEnabled">True to enable the icon display, false to disable it.</param> | ||
| /// <param name="boosterEnabled">True to enable the internal voltage booster, false to disable it.</param> | ||
| public Aip31068Lcd(I2cDevice device, byte contrast = DefaultContrast, bool iconDisplayEnabled = false, bool boosterEnabled = true) | ||
| : base(new Size(16, 2), LcdInterface.CreateI2c(device, true)) | ||
| { | ||
| _contrast = NormalizeContrast(contrast); | ||
| _iconDisplayEnabled = iconDisplayEnabled; | ||
| _boosterEnabled = boosterEnabled; | ||
|
|
||
| InitializeController(); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Initializes a new instance of the <see cref="Aip31068Lcd"/> class using an existing LCD interface. | ||
| /// </summary> | ||
| /// <param name="lcdInterface">The LCD interface used to communicate with the controller.</param> | ||
| /// <param name="contrast">Initial contrast value. Valid range: 0-63.</param> | ||
| /// <param name="iconDisplayEnabled">True to enable the icon display, false to disable it.</param> | ||
| /// <param name="boosterEnabled">True to enable the internal voltage booster, false to disable it.</param> | ||
| public Aip31068Lcd(LcdInterface lcdInterface, byte contrast = DefaultContrast, bool iconDisplayEnabled = false, bool boosterEnabled = true) | ||
| : base(new Size(16, 2), lcdInterface) | ||
| { | ||
| _contrast = NormalizeContrast(contrast); | ||
| _iconDisplayEnabled = iconDisplayEnabled; | ||
| _boosterEnabled = boosterEnabled; | ||
|
|
||
| InitializeController(); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the display contrast (0-63). | ||
| /// </summary> | ||
| public byte Contrast | ||
| { | ||
| get => _contrast; | ||
| set | ||
| { | ||
| byte normalized = NormalizeContrast(value); | ||
| if (_contrast == normalized) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| _contrast = normalized; | ||
| UpdateContrastConfiguration(); | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets a value indicating whether the icon display is enabled. | ||
| /// </summary> | ||
| public bool IconDisplayEnabled | ||
| { | ||
| get => _iconDisplayEnabled; | ||
| set | ||
| { | ||
| if (_iconDisplayEnabled == value) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| _iconDisplayEnabled = value; | ||
| UpdateContrastConfiguration(); | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets a value indicating whether the voltage booster is enabled. | ||
| /// </summary> | ||
| public bool BoosterEnabled | ||
| { | ||
| get => _boosterEnabled; | ||
| set | ||
| { | ||
| if (_boosterEnabled == value) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| _boosterEnabled = value; | ||
| UpdateContrastConfiguration(); | ||
| } | ||
| } | ||
|
|
||
| private void InitializeController() | ||
| { | ||
| EnterExtendedInstructionSet(); | ||
| SendCommandAndWait(InternalOscillatorCommand); | ||
| SendContrastCommands(); | ||
| SendCommandAndWait(FollowerControlCommand); | ||
| DelayHelper.DelayMilliseconds(200, allowThreadYield: true); | ||
| ExitExtendedInstructionSet(); | ||
|
|
||
| // Re-issue the standard configuration commands expected after extended setup. | ||
| SendCommandAndWait((byte)_displayControl); | ||
| Clear(); | ||
| SendCommandAndWait((byte)_displayMode); | ||
| } | ||
|
|
||
| private void UpdateContrastConfiguration() | ||
| { | ||
| EnterExtendedInstructionSet(); | ||
| SendContrastCommands(); | ||
| ExitExtendedInstructionSet(); | ||
| } | ||
|
|
||
| private void SendContrastCommands() | ||
| { | ||
| SendCommandAndWait((byte)(ContrastSetCommand | (_contrast & 0x0F))); | ||
| byte value = (byte)(PowerIconContrastCommand | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same here, a pointer on the doc for maintenance would definitely help! |
||
| | (_iconDisplayEnabled ? IconDisplayFlag : 0) | ||
| | (_boosterEnabled ? BoosterFlag : 0) | ||
| | ((_contrast >> 4) & 0x03)); | ||
| SendCommandAndWait(value); | ||
| } | ||
|
|
||
| private void EnterExtendedInstructionSet() | ||
| { | ||
| SendCommandAndWait((byte)(_displayFunction | DisplayFunction.ExtendedInstructionSet)); | ||
| } | ||
|
|
||
| private void ExitExtendedInstructionSet() | ||
| { | ||
| SendCommandAndWait((byte)(_displayFunction & ~DisplayFunction.ExtendedInstructionSet)); | ||
| } | ||
| } | ||
| } | ||
|
|
||
This file contains hidden or 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
This file contains hidden or 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
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -44,6 +44,18 @@ using LcdRgb lcd = new LcdRgb(new Size(16, 2), i2cLcdDevice, i2cRgbDevice); | |||||
| } | ||||||
| ``` | ||||||
|
|
||||||
| AIP31068 based LCDs expose the same HD44780 compatible instruction set but require an extended | ||||||
| initialization sequence. The <code>Aip31068Lcd</code> binding performs the necessary configuration and allows | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| adjusting the display contrast: | ||||||
|
|
||||||
| ```csharp | ||||||
| var i2cDevice = I2cDevice.Create(new I2cConnectionSettings(busId: 1, deviceAddress: 0x3E)); | ||||||
| using Aip31068Lcd lcd = new(i2cDevice); | ||||||
| lcd.Clear(); | ||||||
| lcd.Write("Hello from AIP31068!"); | ||||||
| lcd.Contrast = 36; // optional: tune the contrast (0-63) | ||||||
| ``` | ||||||
|
|
||||||
| PCF8574T/PCF8574AT Sample | ||||||
| The I2C backpack based on the PCF8574T/AT IC uses specific pin mapping, to consume this device binding on this backpack use like so | ||||||
|
|
||||||
|
|
||||||
This file contains hidden or 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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,87 @@ | ||
| // 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.Device.I2c; | ||
| using System.Threading; | ||
|
|
||
| namespace Iot.Device.CharacterLcd.Samples | ||
| { | ||
| internal static class Aip31068Sample | ||
| { | ||
| private const int DefaultBusId = 1; | ||
| private const int DefaultAddress = 0x3E; | ||
|
|
||
| public static void Run() | ||
| { | ||
| using I2cDevice device = I2cDevice.Create(new I2cConnectionSettings(DefaultBusId, DefaultAddress)); | ||
| using Aip31068Lcd lcd = new(device); | ||
|
|
||
| lcd.Clear(); | ||
| lcd.SetCursorPosition(0, 0); | ||
| lcd.Write("AIP31068 sample"); | ||
| DisplayContrast(lcd); | ||
|
|
||
| Console.WriteLine("AIP31068 LCD sample ready."); | ||
| Console.WriteLine("Use '+' or '-' to adjust contrast, 'B' to toggle the booster, 'I' to toggle icons."); | ||
| Console.WriteLine("Press Esc to exit."); | ||
|
|
||
| while (true) | ||
| { | ||
| if (!Console.KeyAvailable) | ||
| { | ||
| Thread.Sleep(50); | ||
| continue; | ||
| } | ||
|
|
||
| ConsoleKeyInfo key = Console.ReadKey(intercept: true); | ||
| if (key.Key == ConsoleKey.Escape) | ||
| { | ||
| break; | ||
| } | ||
|
|
||
| switch (key.Key) | ||
| { | ||
| case ConsoleKey.Add: | ||
| case ConsoleKey.OemPlus: | ||
| AdjustContrast(lcd, +1); | ||
| break; | ||
| case ConsoleKey.Subtract: | ||
| case ConsoleKey.OemMinus: | ||
| AdjustContrast(lcd, -1); | ||
| break; | ||
| case ConsoleKey.B: | ||
| lcd.BoosterEnabled = !lcd.BoosterEnabled; | ||
| Console.WriteLine($"Booster {(lcd.BoosterEnabled ? "enabled" : "disabled")}."); | ||
| break; | ||
| case ConsoleKey.I: | ||
| lcd.IconDisplayEnabled = !lcd.IconDisplayEnabled; | ||
| Console.WriteLine($"Icon display {(lcd.IconDisplayEnabled ? "enabled" : "disabled")}."); | ||
| break; | ||
| default: | ||
| continue; | ||
| } | ||
|
|
||
| DisplayContrast(lcd); | ||
| } | ||
|
|
||
| lcd.Clear(); | ||
| lcd.Write("Goodbye!"); | ||
| } | ||
|
|
||
| private static void AdjustContrast(Aip31068Lcd lcd, int delta) | ||
| { | ||
| int contrast = lcd.Contrast + delta; | ||
| contrast = Math.Clamp(contrast, 0, 63); | ||
| lcd.Contrast = (byte)contrast; | ||
| Console.WriteLine($"Contrast set to {lcd.Contrast}."); | ||
| } | ||
|
|
||
| private static void DisplayContrast(Aip31068Lcd lcd) | ||
| { | ||
| lcd.SetCursorPosition(0, 1); | ||
| lcd.Write($"Contrast: {lcd.Contrast:D2} "); | ||
| } | ||
| } | ||
| } | ||
|
|
This file contains hidden or 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
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you point where in the documentation this can be found? Will make it easier for maintenance. Including the delay. Thanks!