Skip to content

Commit 5248595

Browse files
authored
Reword screen drivers for managed initialization, support for low memory (#70)
1 parent 293e3d1 commit 5248595

File tree

7 files changed

+312
-8
lines changed

7 files changed

+312
-8
lines changed

README.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,51 @@
1414
| nanoFramework.Graphics | [![Build Status](https://dev.azure.com/nanoframework/nanoFramework.Graphics/_apis/build/status/nanoframework.lib-nanoFramework.Graphics?branchName=master)](https://dev.azure.com/nanoframework/nanoFramework.Graphics/_build/latest?definitionId=57&branchName=master) | [![NuGet](https://img.shields.io/nuget/v/nanoFramework.Graphics.svg?label=NuGet&style=flat&logo=nuget)](https://www.nuget.org/packages/nanoFramework.Graphics/) |
1515
| nanoFramework.Graphics (preview) | [![Build Status](https://dev.azure.com/nanoframework/nanoFramework.Graphics/_apis/build/status/nanoframework.lib-nanoFramework.Graphics?branchName=develop)](https://dev.azure.com/nanoframework/nanoFramework.Graphics/_build/latest?definitionId=57&branchName=develop) | [![](https://badgen.net/badge/NuGet/preview/D7B023?icon=https://simpleicons.now.sh/azuredevops/fff)](https://dev.azure.com/nanoframework/feed/_packaging?_a=package&feed=sandbox&package=nanoFramework.nanoFramework.Graphics&protocolType=NuGet&view=overview) |
1616

17+
## Usage
18+
19+
**Important**:
20+
21+
- This library is still work in progress. There may be breaking changes happening while work on this library progresses.
22+
- So far only SPI interface has been implemented.
23+
24+
Check the [samples](https://github.com/nanoframework/Samples#graphics-for-screens) for more detailed usage.
25+
26+
### Initializing the screen
27+
28+
It is important to understand that the driver will be loaded when the screen routing will be initialized from the managed code. Also keep in mind that most screens are actually smaller than the size the driver is capable of handling, also that the real screen can start at a position that is not the typical origin (0,0).
29+
30+
You **must** initialize the screen before being able to create a bitmap or display anything.
31+
32+
This code snippet works with the ESP32 WROVER KIT pinout, in this case, the screen size matches the driver size:
33+
34+
```csharp
35+
36+
const int backLightPin = 5;
37+
const int chipSelect = 22;
38+
const int dataCommand = 21;
39+
const int reset = 18;
40+
const int screenWidth = 320;
41+
const int screenHeight = 240;
42+
DisplayControl.Initialize(new SpiConfiguration(1, chipSelect, dataCommand, reset, backLightPin), new ScreenConfiguration(0, 0, screenWidth, screenHeight), screenBufferSize);
43+
```
44+
45+
This code snippet is for a M5 Stick where the screen size is smaller than the driver size and starts an offset position of X=26 and Y=1 coordinate:
46+
47+
```csharp
48+
int backLightPin = -1; // Not managed thru ESP32 but thru AXP192
49+
int chipSelect = 5;
50+
int dataCommand = 23;
51+
int reset = 18;
52+
Configuration.SetPinFunction(4, DeviceFunction.SPI1_MISO); // 4 is unused but necessary
53+
Configuration.SetPinFunction(15, DeviceFunction.SPI1_MOSI);
54+
Configuration.SetPinFunction(13, DeviceFunction.SPI1_CLOCK);
55+
DisplayControl.Initialize(new SpiConfiguration(1, chipSelect, dataCommand, reset, backLightPin), new ScreenConfiguration(26, 1, 80, 160), 10 * 1024);
56+
```
57+
58+
Note that depending on your target, especially for ESP32, you may have to setup the pins. Even if physically not used, the MISO pin **must** be setup to a valid pin.
59+
60+
As you can see it is possible as well not to define the backlight pin. It is the same for the rest pins. Both can be set to -1. Note that in most of the cases, both are connected and needed. In the case of the M5 Stick, the backlight pin is managed thru an AXP192. If you don't switch on the backlight pin, your screen will always be black. It is important to check how this pin can be switched on.
61+
1762
## Feedback and documentation
1863

1964
For documentation, providing feedback, issues and finding out how to contribute please refer to the [Home repo](https://github.com/nanoframework/Home).

nanoFramework.Graphics.sln

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
Microsoft Visual Studio Solution File, Format Version 12.00
32
# Visual Studio Version 16
43
VisualStudioVersion = 16.0.30011.22

nanoFramework.Graphics/Presentation/Media/Color.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,17 @@ public static byte GetBValue(Color color)
5252
{
5353
return (byte)(((uint)color >> 16) & 0xff);
5454
}
55+
56+
/// <summary>
57+
/// Converts color into a 16bit representation.
58+
/// </summary>
59+
/// <param name="color">A color.</param>
60+
/// <returns>a 16 bit encoded representation.</returns>
61+
public static ushort To16Bpp(Color color)
62+
{
63+
// 16 bit colour RRRRRGGGGGGBBBBB mode 565
64+
return (ushort)((((uint)color & 0xFF0000) >> 19) | ((((uint)color & 0x00FF00) >> 10) << 5) | (((uint)color & 0xFF) >> 3) << 11);
65+
}
5566
}
5667

5768
/// <summary>

nanoFramework.Graphics/Primitive/DisplayControl.cs

Lines changed: 105 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
// See LICENSE file in the project root for full license information.
55
//
66

7+
using nanoFramework.Presentation.Media;
8+
using System.Diagnostics;
79
using System.Runtime.CompilerServices;
810

911
namespace nanoFramework.UI
@@ -14,19 +16,19 @@ namespace nanoFramework.UI
1416
public enum DisplayOrientation : int
1517
{
1618
/// <summary>
17-
/// Portrait
19+
/// Portrait
1820
/// </summary>
1921
PORTRAIT,
2022
/// <summary>
21-
/// Portrait 180
23+
/// Portrait 180
2224
/// </summary>
2325
PORTRAIT180,
2426
/// <summary>
25-
/// Landscape
27+
/// Landscape
2628
/// </summary>
2729
LANDSCAPE,
2830
/// <summary>
29-
/// Landscape 180
31+
/// Landscape 180
3032
/// </summary>
3133
LANDSCAPE180
3234
};
@@ -36,23 +38,70 @@ public enum DisplayOrientation : int
3638
/// </summary>
3739
public static class DisplayControl
3840
{
39-
static Bitmap _fullScreen = null;
41+
static private Bitmap _fullScreen = null;
42+
static private ushort[] _point = new ushort[1];
43+
44+
/// <summary>
45+
/// The maximum buffer size for Bitmap in bytes.
46+
/// </summary>
47+
public static uint MaximumBufferSize { get; internal set; }
48+
49+
/// <summary>
50+
/// Initializes the screen for use with Spi configuration.
51+
/// </summary>
52+
/// <param name="spi">Spi configuration.</param>
53+
/// <param name="screen">A screen configuration.</param>
54+
/// <param name="bufferSize">The desired buffer size allocation, 0 for default.</param>
55+
/// <remarks>You may have to configure the pins properly for the Spi configuration to be valid before initializing your screen.</remarks>
56+
/// <returns>The maximum buffer size possible allocation in bytes.</returns>
57+
public static uint Initialize(SpiConfiguration spi, ScreenConfiguration screen, uint bufferSize = 20 * 1024)
58+
{
59+
MaximumBufferSize = NativeInitSpi(spi, screen, bufferSize);
60+
return MaximumBufferSize;
61+
}
62+
63+
/// <summary>
64+
/// Initializes the screen to use with I2C configuration.
65+
/// </summary>
66+
/// <param name="i2c"></param>
67+
/// <param name="screen">A screen configuration.</param>
68+
/// <param name="bufferSize">The desired buffer size allocation, 0 for default.</param>
69+
/// <remarks>You may have to configure the pins properly for the I2C configuration to be valid before initializing your screen.</remarks>
70+
/// <returns>The maximum buffer size possible allocation in bytes.</returns>
71+
public static uint Initialize(I2cConfiguration i2c, ScreenConfiguration screen, uint bufferSize = 20 * 1024)
72+
{
73+
MaximumBufferSize = NativeInitI2c(i2c, screen, bufferSize);
74+
return MaximumBufferSize;
75+
}
4076

4177
/// <summary>
4278
/// Returns a bitmap the size of the current display.
4379
/// </summary>
80+
/// <remarks>Please make sure you check if you have enough memory with IsFullScreenBufferAvailable.
81+
/// If you don't have enough, the BitMap won't get initialized and will be null.</remarks>
4482
public static Bitmap FullScreen
4583
{
4684
get
4785
{
86+
if (!IsFullScreenBufferAvailable)
87+
{
88+
return null;
89+
}
90+
4891
if (_fullScreen == null)
4992
{
5093
_fullScreen = new Bitmap(ScreenWidth, ScreenHeight);
5194
}
95+
5296
return _fullScreen;
5397
}
5498
}
5599

100+
/// <summary>
101+
/// True if a full size buffer is available
102+
/// </summary>
103+
public static bool IsFullScreenBufferAvailable => ScreenWidth * ScreenHeight * 3 / 8 <= MaximumBufferSize; // Internal bit per pixel is 3 bytes
104+
56105
/// <summary>
57106
/// The screens number of pixels for the longer side.
58107
/// </summary>
@@ -125,11 +174,62 @@ static public bool ChangeOrientation(DisplayOrientation Orientation)
125174
_fullScreen.Dispose();
126175
_fullScreen = null;
127176
}
177+
128178
return result;
129179
}
130180

181+
/// <summary>
182+
/// Write a point directly on the screen.
183+
/// </summary>
184+
/// <param name="x">The x coordinate.</param>
185+
/// <param name="y">The y coordinate.</param>
186+
/// <param name="color">The 16 bits color.</param>
187+
public static void WritePoint(ushort x, ushort y, ushort color)
188+
{
189+
_point[0] = color;
190+
Write(x, y, 1, 1, _point);
191+
}
192+
193+
/// <summary>
194+
/// Clears the screen.
195+
/// </summary>
196+
[MethodImplAttribute(MethodImplOptions.InternalCall)]
197+
public extern static void Clear();
198+
199+
/// <summary>
200+
/// Directly write in the screen at coordinate x,y a width,height buffer of 16 bits colors.
201+
/// </summary>
202+
/// <param name="x">The x coordinate.</param>
203+
/// <param name="y">The y coordinate.</param>
204+
/// <param name="width">The width of the area to display.</param>
205+
/// <param name="height">The height of the area to display.</param>
206+
/// <param name="colors">A 16 bits color</param>
207+
[MethodImplAttribute(MethodImplOptions.InternalCall)]
208+
public extern static void Write(ushort x, ushort y, ushort width, ushort height, ushort[] colors);
209+
210+
/// <summary>
211+
/// Directly write on the screen a text at coordinate x,y a width,height with a background and foreground color.
212+
/// </summary>
213+
/// <param name="text">The text to write.</param>
214+
/// <param name="x">The x coordinate.</param>
215+
/// <param name="y">The y coordinate.</param>
216+
/// <param name="width">The width of the area to display.</param>
217+
/// <param name="height">The height of the area to display.</param>
218+
/// <param name="font">The font to use.</param>
219+
/// <param name="foreground">Foreground color.</param>
220+
/// <param name="background">Background color.</param>
221+
[MethodImplAttribute(MethodImplOptions.InternalCall)]
222+
public extern static void Write(string text, ushort x, ushort y, ushort width, ushort height, Font font, Color foreground, Color background);
223+
131224
[MethodImplAttribute(MethodImplOptions.InternalCall)]
132225
private extern static bool NativeChangeOrientation(DisplayOrientation Orientation);
226+
227+
[MethodImplAttribute(MethodImplOptions.InternalCall)]
228+
private extern static uint NativeInitSpi(SpiConfiguration spi, ScreenConfiguration screen, uint bufferSize);
229+
230+
[MethodImplAttribute(MethodImplOptions.InternalCall)]
231+
private extern static uint NativeInitI2c(I2cConfiguration i2c, ScreenConfiguration screen, uint bufferSize);
232+
133233
}
134234
}
135235

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
using System;
2+
3+
namespace nanoFramework.UI
4+
{
5+
/// <summary>
6+
/// The Spi configuration for the scressn
7+
/// </summary>
8+
public struct SpiConfiguration
9+
{
10+
private byte _spiBus;
11+
private int _chipSelect;
12+
private int _dataCommand;
13+
private int _reset;
14+
private int _backLight;
15+
16+
/// <summary>
17+
/// Creates a Spi configuration.
18+
/// </summary>
19+
/// <param name="spiBus">Spi bus.</param>
20+
/// <param name="chipselect">Chip select.</param>
21+
/// <param name="dataCommand">Data command.</param>
22+
/// <param name="reset">Reset.</param>
23+
/// <param name="backLight">Back light.</param>
24+
public SpiConfiguration(byte spiBus, int chipselect, int dataCommand, int reset, int backLight)
25+
{
26+
_spiBus = spiBus;
27+
_chipSelect = chipselect;
28+
_dataCommand = dataCommand;
29+
_reset = reset;
30+
_backLight = backLight;
31+
}
32+
33+
/// <summary>Z
34+
/// Spi bus.
35+
/// </summary>
36+
public byte SpiBus { get => _spiBus; set => _spiBus = value; }
37+
38+
/// <summary>
39+
/// Chip select.
40+
/// </summary>
41+
public int ChipSelect { get => _chipSelect; set => _chipSelect = value; }
42+
43+
/// <summary>
44+
/// Data command.
45+
/// </summary>
46+
public int DataCommand { get => _dataCommand; set => _dataCommand = value; }
47+
48+
/// <summary>
49+
/// Reset.
50+
/// </summary>
51+
public int Reset { get => _reset; set => _reset = value; }
52+
53+
/// <summary>
54+
/// Back light
55+
/// </summary>
56+
public int BackLight { get => _backLight; set => _backLight = value; }
57+
}
58+
59+
/// <summary>
60+
/// I2C configuration.
61+
/// </summary>
62+
public struct I2cConfiguration
63+
{
64+
private byte _i2cBus;
65+
private byte _address;
66+
private bool _fastMode;
67+
68+
/// <summary>
69+
/// Creates an I2C configuration.
70+
/// </summary>
71+
/// <param name="i2cBus">I2C bus.</param>
72+
/// <param name="address">Address.</param>
73+
/// <param name="fastMode">True for I2C fast mode.</param>
74+
public I2cConfiguration(byte i2cBus, byte address, bool fastMode)
75+
{
76+
_i2cBus = i2cBus;
77+
_address = address;
78+
_fastMode = fastMode;
79+
}
80+
81+
/// <summary>
82+
/// I2C bus.
83+
/// </summary>
84+
public byte I2cBus { get => _i2cBus; set => _i2cBus = value; }
85+
86+
/// <summary>
87+
/// Address.
88+
/// </summary>
89+
public byte Address { get => _address; set => _address = value; }
90+
91+
/// <summary>
92+
/// True for I2C fast mode.
93+
/// </summary>
94+
public bool FastMode { get => _fastMode; set => _fastMode = value; }
95+
}
96+
97+
/// <summary>
98+
/// The screen configuration in the driver.
99+
/// </summary>
100+
public struct ScreenConfiguration
101+
{
102+
private ushort _x;
103+
private ushort _y;
104+
private ushort _width;
105+
private ushort _height;
106+
107+
/// <summary>
108+
/// Creates a screen configuration.
109+
/// </summary>
110+
/// <param name="x">The x position the screen starts in the driver.</param>
111+
/// <param name="y">The y position the screen starts in the driver.</param>
112+
/// <param name="width">The width of the screen starts in the driver.</param>
113+
/// <param name="height">The height of the screen starts in the driver.</param>
114+
public ScreenConfiguration(ushort x, ushort y, ushort width, ushort height)
115+
{
116+
_x = x;
117+
_y = y;
118+
_width = width;
119+
_height = height;
120+
}
121+
122+
/// <summary>
123+
/// The x position the screen starts in the driver.
124+
/// </summary>
125+
public ushort X { get => _x; set => _x = value; }
126+
127+
/// <summary>
128+
/// The y position the screen starts in the driver.
129+
/// </summary>
130+
public ushort Y { get => _y; set => _y = value; }
131+
132+
/// <summary>
133+
/// The width of the screen starts in the driver.
134+
/// </summary>
135+
public ushort Width { get => _width; set => _width = value; }
136+
137+
/// <summary>
138+
/// The height of the screen starts in the driver.
139+
/// </summary>
140+
public ushort Height { get => _height; set => _height = value; }
141+
142+
}
143+
}

nanoFramework.Graphics/Properties/AssemblyInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
////////////////////////////////////////////////////////////////
1313
// update this whenever the native assembly signature changes //
14-
[assembly: AssemblyNativeVersion("100.0.0.2")]
14+
[assembly: AssemblyNativeVersion("100.0.0.3")]
1515
////////////////////////////////////////////////////////////////
1616

1717
// Setting ComVisible to false makes the types in this assembly not visible

0 commit comments

Comments
 (0)