Skip to content

Commit

Permalink
Merge pull request #602 from WildernessLabs/sh110x
Browse files Browse the repository at this point in the history
Update SH1106 to SH110x and add SH1107 display driver
  • Loading branch information
adrianstevens authored Apr 10, 2023
2 parents 0eb988a + f8c73e0 commit 2f09092
Show file tree
Hide file tree
Showing 20 changed files with 4,016 additions and 120 deletions.
3,455 changes: 3,455 additions & 0 deletions Meadow.Foundation.sln

Large diffs are not rendered by default.

30 changes: 21 additions & 9 deletions Source/Meadow.Foundation.Core/Communications/I2cPeripheral.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;

namespace Meadow.Hardware
{
Expand All @@ -10,7 +8,14 @@ namespace Meadow.Hardware
/// </summary>
public class I2cPeripheral : II2cPeripheral
{
/// <summary>
/// The I2C address
/// </summary>
public byte Address { get; protected set; }

/// <summary>
/// The I2C bus
/// </summary>
public II2cBus Bus { get; protected set; }

/// <summary>
Expand Down Expand Up @@ -77,9 +82,12 @@ public ushort ReadRegisterAsUShort(byte address, ByteOrder order = ByteOrder.Lit
{
WriteBuffer.Span[0] = address;
Bus.Exchange(this.Address, WriteBuffer[0..1].Span, ReadBuffer[0..2].Span);
if (order == ByteOrder.LittleEndian) {
if (order == ByteOrder.LittleEndian)
{
return (ushort)(ReadBuffer.Span[0] | (ReadBuffer.Span[1] << 8));
} else {
}
else
{
return (ushort)(ReadBuffer.Span[0] << 8 | ReadBuffer.Span[1]);
}
}
Expand Down Expand Up @@ -167,7 +175,8 @@ public void WriteRegister(byte address, ulong value, ByteOrder order = ByteOrder
/// <param name="order">Indicate if the data should be written as big or little endian.</param>
public void WriteRegister(byte address, Span<byte> 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" +
Expand All @@ -179,21 +188,24 @@ public void WriteRegister(byte address, Span<byte> writeBuffer, ByteOrder order

// 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++) {
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.Address, WriteBuffer.Span[0..(writeBuffer.Length + 1)]);
this.Bus.Write(Address, WriteBuffer.Span[0..(writeBuffer.Length + 1)]);
}

public void Exchange(Span<byte> writeBuffer, Span<byte> readBuffer, DuplexType duplex = DuplexType.Half)
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
<Project Sdk="Meadow.Sdk/1.1.0">
<Project Sdk="Meadow.Sdk/1.1.0">
<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageIcon>icon.png</PackageIcon>
<Authors>Wilderness Labs, Inc</Authors>
<TargetFramework>netstandard2.1</TargetFramework>
<OutputType>Library</OutputType>
<AssemblyName>Sh1106</AssemblyName>
<AssemblyName>Sh110x</AssemblyName>
<Company>Wilderness Labs, Inc</Company>
<PackageProjectUrl>http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/</PackageProjectUrl>
<PackageId>Meadow.Foundation.Displays.Sh1106</PackageId>
<RepositoryUrl>https://github.com/WildernessLabs/Meadow.Foundation</RepositoryUrl>
<PackageTags>Meadow, Meadow.Foundation, Displays, LCD, Sh1106</PackageTags>
<PackageTags>Meadow,Meadow.Foundation,Displays,LCD,Sh1106,SH1107,oled,monochrome</PackageTags>
<Version>0.1.0</Version>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Description>Sh1106 SPI monochrome OLED display</Description>
<Description>S1106 and SH1107 SPI and I2C monochrome OLED displays</Description>
</PropertyGroup>
<ItemGroup>
<None Include="..\..\..\icon.png" Pack="true" PackagePath="" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
using Meadow.Hardware;
using System.Threading;

namespace Meadow.Foundation.Displays
{
/// <summary>
/// Represents the Sh1106 family of displays
/// </summary>
public class Sh1106 : Sh110x
{
/// <summary>
/// Create a new Sh1106 object
/// </summary>
/// <param name="i2cBus">I2C bus connected to display</param>
/// <param name="address">I2C address</param>
/// <param name="width">Display width in pixels</param>
/// <param name="height">Display height in pixels</param>
public Sh1106(II2cBus i2cBus, byte address, int width, int height)
: base(i2cBus, address, width, height)
{ }

/// <summary>
/// Create a new Sh1106 object
/// </summary>
/// <param name="spiBus">SPI bus connected to display</param>
/// <param name="chipSelectPin">Chip select pin</param>
/// <param name="dcPin">Data command pin</param>
/// <param name="resetPin">Reset pin</param>
/// <param name="width">Display width in pixels</param>
/// <param name="height">Display height in pixels</param>
public Sh1106(ISpiBus spiBus, IPin chipSelectPin, IPin dcPin, IPin resetPin, int width = 128, int height = 64)
: base(spiBus, chipSelectPin, dcPin, resetPin, width, height)
{ }

/// <summary>
/// Create a new Sh1106 display object
/// </summary>
/// <param name="spiBus">SPI bus connected to display</param>
/// <param name="chipSelectPort">Chip select output port</param>
/// <param name="dataCommandPort">Data command output port</param>
/// <param name="resetPort">Reset output port</param>
/// <param name="width">Display width in pixels</param>
/// <param name="height">Display height in pixels</param>
public Sh1106(ISpiBus spiBus,
IDigitalOutputPort chipSelectPort,
IDigitalOutputPort dataCommandPort,
IDigitalOutputPort resetPort,
int width = 128, int height = 64)
: base(spiBus, chipSelectPort, dataCommandPort, resetPort, width, height)
{ }

/// <summary>
/// Initialize the Sh1106
/// </summary>
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);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
using Meadow.Hardware;
using System.Threading;

namespace Meadow.Foundation.Displays
{
/// <summary>
/// Represents the Sh1107 family of displays
/// </summary>
public class Sh1107 : Sh110x
{
/// <summary>
/// Create a new Sh1107 object
/// </summary>
/// <param name="i2cBus">I2C bus connected to display</param>
/// <param name="address">I2C address</param>
/// <param name="width">Display width in pixels</param>
/// <param name="height">Display height in pixels</param>
public Sh1107(II2cBus i2cBus, byte address, int width = 128, int height = 128)
: base(i2cBus, address, width, height)
{ }

/// <summary>
/// Create a new Sh1107 object
/// </summary>
/// <param name="spiBus">SPI bus connected to display</param>
/// <param name="chipSelectPin">Chip select pin</param>
/// <param name="dcPin">Data command pin</param>
/// <param name="resetPin">Reset pin</param>
/// <param name="width">Display width in pixels</param>
/// <param name="height">Display height in pixels</param>
public Sh1107(ISpiBus spiBus, IPin chipSelectPin, IPin dcPin, IPin resetPin, int width = 128, int height = 128)
: base(spiBus, chipSelectPin, dcPin, resetPin, width, height)
{ }

/// <summary>
/// Create a new Sh1107 display object
/// </summary>
/// <param name="spiBus">SPI bus connected to display</param>
/// <param name="chipSelectPort">Chip select output port</param>
/// <param name="dataCommandPort">Data command output port</param>
/// <param name="resetPort">Reset output port</param>
/// <param name="width">Display width in pixels</param>
/// <param name="height">Display height in pixels</param>
public Sh1107(ISpiBus spiBus,
IDigitalOutputPort chipSelectPort,
IDigitalOutputPort dataCommandPort,
IDigitalOutputPort resetPort,
int width = 128, int height = 128)
: base(spiBus, chipSelectPort, dataCommandPort, resetPort, width, height)
{ }

/// <summary>
/// Initialize the Sh1107
/// </summary>
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);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
namespace Meadow.Foundation.Displays
{
/// <summary>
/// Provide an interface to the Sh1106 family of displays
/// </summary>
public partial class Sh1106
public partial class Sh110x
{
/// <summary>
/// Allow the programmer to set the scroll direction
Expand All @@ -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,
Expand All @@ -47,14 +44,16 @@ enum DisplayCommand : byte
SetDisplayOffset = 0xD3,
OutputFollowsRam = 0xA4,
MemoryMode = 0x20,
ColumnAddress = 0x21,
PageAddress = 0x22,

MultiplexModeSet = 0xA8,
MultiplexDataSet = 0x3F,

SetChargePump = 0x8D,
SetPrecharge = 0xD9,
SetComPins = 0xDA,
SetComDetect = 0xDB,
SetVComDetect = 0xDB,
ComScanInc = 0xC0,
ComScanDec = 0xC8,

Expand All @@ -63,5 +62,40 @@ enum DisplayCommand : byte

SetSegmentRemap = 0xA1,
}

/// <summary>
/// Valid I2C addresses for the display
/// </summary>
public enum Addresses : byte
{
/// <summary>
/// Bus address 0x3C
/// Commonly used with 128x32 displays
/// </summary>
Address_0x3C = 0x3C,
/// <summary>
/// Bus address 0x3D
/// </summary>
Address_0x3D = 0x3D,
/// <summary>
/// Default bus address
/// </summary>
Default = Address_0x3D
}

/// <summary>
/// The display connection type
/// </summary>
public enum ConnectionType
{
/// <summary>
/// SPI
/// </summary>
SPI,
/// <summary>
/// I2C
/// </summary>
I2C,
}
}
}
Loading

0 comments on commit 2f09092

Please sign in to comment.