Driver goes on ! What is missing:
[ul]display a bitmap,
display line,
display empty rectangle,
display circle.
[/ul]
In codeshare: [url]https://www.ghielectronics.com/community/codeshare/entry/1093[/url]
As codeshare has disappeared (hidden should I say), here is the code:
using System;
using System.Linq;
using System.Threading.Tasks;
using Windows.Devices.Spi;
using GHIElectronics.UWP.GadgeteerCore;
using GHIElectronics.UWP.GadgeteerCore.SocketInterfaces;
using SpiDevice = GHIElectronics.UWP.GadgeteerCore.SocketInterfaces.SpiDevice;
//using SpiDevice = GHIElectronics.UWP.GadgeteerCore.SocketInterfaces.SpiDevice;
namespace Bauland
{
/// <summary>
/// Class to manage N18display
/// </summary>
public class N18Display : Module
{
/// <summary>
/// Module's name
/// </summary>
public override string Name => "N18Display";
/// <summary>
/// Manufacturer's module
/// </summary>
public override string Manufacturer => "GHI";
private SpiDevice _spiDevice;
private DigitalIO _resetIo; // Hardware reset
private DigitalIO _backlightIo; // backlight control
private DigitalIO _cdIo; // command: false, data: true
private byte[] _data;
private ushort[] _ushortData;
private DisplayOrientation _orientation;
private bool _isBgr;
/// <summary>
/// Get or set display orientation. Screen is not clear, so previous text remains on screen.
/// </summary>
public DisplayOrientation Orientation
{
get { return _orientation; }
set
{
_orientation = value;
SetFormat();
}
}
/// <summary>
/// If channel red and blue are swaped for this display, then call one.
/// </summary>
public void SwapRedBlueChannels()
{
_isBgr = !_isBgr;
SetFormat();
}
private void SetFormat()
{
var bgr = (_isBgr ? MADCTL_BGR : 0);
WriteCommand(MADCTL);
switch (_orientation)
{
case DisplayOrientation.Normal:
WriteData((byte)(MADCTL_MX | MADCTL_MY | bgr));
break;
case DisplayOrientation.Cw90:
WriteData((byte)(MADCTL_MV | MADCTL_MY | bgr));
break;
case DisplayOrientation.UpsideDown:
WriteData((byte)(bgr));
break;
case DisplayOrientation.Ccw90:
WriteData((byte)(MADCTL_MV | MADCTL_MX | bgr));
break;
}
}
#region Command for ST7735
private byte CASET = 0x2A;
private byte RASET = 0x2B;
private byte RAMWR = 0x2C;
private byte DISPON = 0x29;
private byte SLPOUT = 0x11;
private byte FRMCTR1 = 0xB1;
private byte FRMCTR2 = 0xB2;
private byte FRMCTR3 = 0xB3;
private byte INVCTR = 0xB4;
private byte PWCTR1 = 0xC0;
private byte PWCTR2 = 0xC1;
private byte PWCTR3 = 0xC2;
private byte PWCTR4 = 0xC3;
private byte PWCTR5 = 0xC4;
private byte VMCTR1 = 0xC5;
private byte GMCTRP1 = 0xE0;
private byte GMCTRN1 = 0xE1;
private byte COLMOD = 0x3A;
private byte MADCTL = 0x36;
private byte MADCTL_BGR = 0x08;
private byte MADCTL_MX = 0x40;
private byte MADCTL_MY = 0x80;
private byte MADCTL_MV = 0x20;
public N18Display()
{
_isBgr = true;
}
#endregion
/// <summary>
/// Initialize module and connect to mainboard
/// </summary>
/// <param name="parentSocket">Socket of mainboard on which module is connected</param>
/// <returns>Task</returns>
protected override async Task Initialize(ISocket parentSocket)
{
parentSocket.EnsureTypeIsSupported(SocketType.S);
_data = null;
_spiDevice =
await
parentSocket.CreateSpiDeviceAsync(new SpiConnectionSettings(0)
{
Mode = SpiMode.Mode0,
ClockFrequency = 10000000,
});
_resetIo = await parentSocket.CreateDigitalIOAsync(SocketPinNumber.Three, false);
_backlightIo = await parentSocket.CreateDigitalIOAsync(SocketPinNumber.Four, true);
_cdIo = await parentSocket.CreateDigitalIOAsync(SocketPinNumber.Five, false);
_data = new byte[1];
_ushortData = new ushort[2];
await HardReset(); // Hard reset
}
/// <summary>
/// Hard reset display.
/// </summary>
/// <returns>Task object</returns>
public async Task HardReset()
{
await Reset();
await ConfigureDisplay();
Clear();
}
private async Task ConfigureDisplay()
{
// ST7735R or ST7735 ???
WriteCommand(SLPOUT); // Exit sleep mode
await Task.Delay(120);
WriteCommand(FRMCTR1);
WriteData(0x01);
WriteData(0x2C);
WriteData(0x2D);
WriteCommand(FRMCTR2);
WriteData(0x01);
WriteData(0x2C);
WriteData(0x2D);
WriteCommand(FRMCTR3);
WriteData(0x01);
WriteData(0x2C);
WriteData(0x2D);
WriteData(0x01);
WriteData(0x2C);
WriteData(0x2D);
WriteCommand(INVCTR); // Column inversion
WriteData(0x07);
// Power Sequence
WriteCommand(PWCTR1);
WriteData(0xA2);
WriteData(0x02);
WriteData(0x84);
WriteCommand(PWCTR2);
WriteData(0xc5);
WriteCommand(PWCTR3);
WriteData(0x0a);
WriteData(0x00);
WriteCommand(PWCTR4);
WriteData(0x8a);
WriteData(0x2a);
WriteCommand(PWCTR5);
WriteData(0x8a);
WriteData(0xee);
// VCOM
WriteCommand(VMCTR1);
WriteData(0x0e);
// Mode address
SetFormat();
// Gamma Sequence
WriteCommand(GMCTRP1);
WriteData(0x0f);
WriteData(0x1a);
WriteData(0x0f);
WriteData(0x18);
WriteData(0x2f);
WriteData(0x28);
WriteData(0x20);
WriteData(0x22);
WriteData(0x1f);
WriteData(0x1b);
WriteData(0x23);
WriteData(0x37);
WriteData(0x00);
WriteData(0x07);
WriteData(0x02);
WriteData(0x10);
WriteCommand(GMCTRN1);
WriteData(0x0f);
WriteData(0x1b);
WriteData(0x0f);
WriteData(0x17);
WriteData(0x33);
WriteData(0x2c);
WriteData(0x29);
WriteData(0x2e);
WriteData(0x30);
WriteData(0x30);
WriteData(0x39);
WriteData(0x3f);
WriteData(0x00);
WriteData(0x07);
WriteData(0x03);
WriteData(0x10);
WriteCommand(CASET);
WriteData(0x00);
WriteData(0x00);
WriteData(0x00);
WriteData(0x7f);
WriteCommand(RASET);
WriteData(0x00);
WriteData(0x00);
WriteData(0x00);
WriteData(0x9f);
//WriteCommand(0xf0); // Enable test command
//WriteData(0x01);
//WriteCommand(0xf6); // Disable ram power save mode
//WriteData(0x00);
WriteCommand(COLMOD); // 65k mode
WriteData(0x55);
WriteCommand(DISPON); // Display on
}
/// <summary>
/// Get or set backlight status. Must be true to see what is displayed.
/// </summary>
public bool Backlight
{
get { return _backlightIo.Read(); }
set { _backlightIo.Write(value); }
}
/// <summary>
/// Soft reset
/// </summary>
/// <returns>Task Object</returns>
public async Task Reset()
{
_resetIo.Write(false);
await Task.Delay(150);
_resetIo.Write(true);
}
private void WriteCommand(byte command)
{
_data[0] = command;
_cdIo.Write(false);
_spiDevice.Write(_data);
}
private void WriteData(byte[] data)
{
_cdIo.Write(true);
_spiDevice.Write(data);
}
private void WriteData(byte data)
{
_data[0] = data;
WriteData(_data);
}
private void WriteData(ushort[] data)
{
_cdIo.Write(true);
foreach (var us in data)
{
_spiDevice.Write(BitConverter.GetBytes(us).Reverse().ToArray());
}
}
/// <summary>
/// Clear Display
/// </summary>
public void Clear()
{
var data = new byte[64 * 80 * 2];
DrawRaw(data, 0, 0, 64, 80);
DrawRaw(data, 64, 0, 64, 80);
DrawRaw(data, 0, 80, 64, 80);
DrawRaw(data, 64, 80, 64, 80);
}
private void DrawRaw(byte[] data, int x, int y, int width, int height)
{
SetClippingArea(x, y, width - 1, height - 1);
WriteCommand(RAMWR);
WriteData(data);
}
private void SetClippingArea(int x, int y, int width, int height)
{
_ushortData[0] = (ushort)x;
_ushortData[1] = (ushort)(x + width);
WriteCommand(CASET);
WriteData(_ushortData);
_ushortData[0] = (ushort)y;
_ushortData[1] = (ushort)(y + height);
WriteCommand(RASET);
WriteData(_ushortData);
}
/// <summary>
/// Draw a pixel on display
/// </summary>
/// <param name="x">x coordinate of pixel</param>
/// <param name="y">y coordinate of pixel</param>
/// <param name="color">color of pixel</param>
public void DrawPixel(int x, int y, Color color)
{
byte[] a = color.To565ByteArray();
DrawRaw(a, x, y, 1, 1);
}
/// <summary>
/// Draw a pixel on display
/// </summary>
/// <param name="x">x coordinate of pixel</param>
/// <param name="y">y coordinate of pixel</param>
/// <param name="r">red channel value</param>
/// <param name="g">green channel value</param>
/// <param name="b">blue channel value</param>
public void DrawPixel(int x, int y, byte r, byte g, byte b)
{
byte[] a = ToRGB565(r, g, b);
DrawRaw(a, x, y, 1, 1);
}
/// <summary>
/// Draw a fill rectangle on display
/// </summary>
/// <param name="x">x coordinate of pixel</param>
/// <param name="y">y coordinate of pixel</param>
/// <param name="width">width of rectangle</param>
/// <param name="height">height of rectangle</param>
/// <param name="color">color of rectangle</param>
public void DrawFillRect(int x, int y, int width, int height, Color color)
{
// Prepare data
byte[] data = new byte[width * height * 2];
byte[] a = color.To565ByteArray();
for (int i = 0; i < width * height; i++)
{
data[i * 2] = a[0];
data[i * 2 + 1] = a[1];
}
DrawRaw(data, x, y, width, height);
}
/// <summary>
/// Draw a fill rectangle on display
/// </summary>
/// <param name="x">x coordinate of pixel</param>
/// <param name="y">y coordinate of pixel</param>
/// <param name="width">width of rectangle</param>
/// <param name="height">height of rectangle</param>
/// <param name="r">red channel value</param>
/// <param name="g">green channel value</param>
/// <param name="b">blue channel value</param>
public void DrawFillRect(int x, int y, int width, int height, byte r, byte g, byte b)
{
// Prepare data
byte[] data = new byte[width * height * 2];
byte[] a = ToRGB565(r, g, b);
for (int i = 0; i < width * height; i++)
{
data[i * 2] = a[0];
data[i * 2 + 1] = a[1];
}
DrawRaw(data, x, y, width, height);
}
private byte[] ToRGB565(byte r, byte g, byte b)
{
byte[] arrayBytes = new byte[2];
r = (byte)(r & 0x1f);
g = (byte)(g & 0x3f);
b = (byte)(b & 0x1f);
arrayBytes[0] = (byte)((b << 3) + (g >> 3));
arrayBytes[1] = (byte)((g << 5) + r);
return arrayBytes;
}
/// <summary>
/// Draw a single character on display
/// </summary>
/// <param name="c">Character to display</param>
/// <param name="font">Font used to display character</param>
/// <param name="x">x coordinate on screen</param>
/// <param name="y">y coordinate on screen</param>
/// <param name="color">Color of character</param>
public void DrawChar(char c, Font font, int x, int y, Color color)
{
var letter = font.GetLetter(c);
int height = 8;
int width = letter.Length;
byte[] abcolor = color.To565ByteArray();
byte[] data = new byte[height * width * 2];
byte mask = 0x01;
bool bit;
for (int j = 0; j < 8; j++)
{
for (int i = 0; i < letter.Length; i++)
{
bit = (letter[i] & mask) == mask;
if (bit)
{
data[2 * (i + j * letter.Length)] = abcolor[0];
data[2 * (i + j * letter.Length) + 1] = abcolor[1];
}
}
mask = (byte)(mask << 1);
}
DrawRaw(data, x, y, width, height);
}
/// <summary>
/// Draw a single character on display
/// </summary>
/// <param name="c">Character to display</param>
/// <param name="font">Font used to display character</param>
/// <param name="x">x coordinate on screen</param>
/// <param name="y">y coordinate on screen</param>
/// <param name="r">red channel value</param>
/// <param name="g">green channel value</param>
/// <param name="b">blue channel value</param>
public void DrawChar(char c, Font font, int x, int y, byte r, byte g, byte b)
{
var letter = font.GetLetter(c);
int height = 8;
int width = letter.Length;
byte[] color = ToRGB565(r, g, b);
byte[] data = new byte[height * width * 2];
byte mask = 0x01;
bool bit;
for (int j = 0; j < 8; j++)
{
for (int i = 0; i < letter.Length; i++)
{
bit = (letter[i] & mask) == mask;
if (bit)
{
data[2 * (i + j * letter.Length)] = color[0];
data[2 * (i + j * letter.Length) + 1] = color[1];
}
}
mask = (byte)(mask << 1);
}
DrawRaw(data, x, y, width, height);
}
/// <summary>
/// Draw a text on display
/// </summary>
/// <param name="text">Text to display</param>
/// <param name="font">Font used to display text</param>
/// <param name="x">x coordinate on screen</param>
/// <param name="y">y coordinate on screen</param>
/// <param name="color">Color of text to display</param>
public void DrawText(string text, Font font, int x, int y, Color color)
{
int fontWidth = font.Width;
int index = 0;
foreach (char c in text)
{
DrawChar(c, font, x + index * (fontWidth + 1), y, color);
index++;
}
}
/// <summary>
/// Draw a text on display
/// </summary>
/// <param name="text">Text to display</param>
/// <param name="font">Font used to display text</param>
/// <param name="x">x coordinate on screen</param>
/// <param name="y">y coordinate on screen</param>
/// <param name="r">red channel value</param>
/// <param name="g">green channel value</param>
/// <param name="b">blue channel value</param>
public void DrawText(string text, Font font, int x, int y, byte r, byte g, byte b)
{
int fontWidth = font.Width;
int index = 0;
foreach (char c in text)
{
DrawChar(c, font, x + index * (fontWidth + 1), y, r, g, b);
index++;
}
}
/// <summary>
/// Orientation value of screen
/// </summary>
public enum DisplayOrientation
{
Normal,
Cw90,
UpsideDown,
Ccw90
}
}
}