Skip to content

Commit 812338d

Browse files
authored
Add SetPixel as separate r g b values (#220)
1 parent 9352e9b commit 812338d

File tree

8 files changed

+203
-19
lines changed

8 files changed

+203
-19
lines changed

devices/Ws28xx/BitmapImage.cs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,23 @@ protected BitmapImage(byte[] data, int width, int height, int stride)
5454
/// <param name="x">X coordinate of the pixel</param>
5555
/// <param name="y">Y coordinate of the pixel</param>
5656
/// <param name="color">Color to set the pixel to</param>
57-
public abstract void SetPixel(int x, int y, Color color);
57+
public abstract void SetPixel(int x, int y, Color color);
58+
59+
/// <summary>
60+
/// Sets pixel at specific position
61+
/// </summary>
62+
/// <param name="x">X coordinate of the pixel</param>
63+
/// <param name="y">Y coordinate of the pixel</param>
64+
/// <param name="r">Red color</param>
65+
/// <param name="g">Green color</param>
66+
/// <param name="b">Blue color</param>
67+
public abstract void SetPixel(int x, int y, byte r, byte g, byte b);
5868

5969
/// <summary>
6070
/// Clears the image to specific color
6171
/// </summary>
6272
/// <param name="color">Color to clear the image. Defaults to black.</param>
63-
public virtual void Clear(Color color = default)
73+
public virtual void Clear(Color color)
6474
{
6575
for (int y = 0; y < Height; y++)
6676
{
@@ -70,5 +80,15 @@ public virtual void Clear(Color color = default)
7080
}
7181
}
7282
}
83+
84+
/// <summary>
85+
/// Clears whole image
86+
/// </summary>
87+
public abstract void Clear();
88+
89+
/// <summary>
90+
/// Clears selected pixel
91+
/// </summary>
92+
public abstract void Clear(int x, int y);
7393
}
74-
}
94+
}

devices/Ws28xx/BitmapImageNeo3.cs

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System;
45
using System.Drawing;
56

67
namespace Iot.Device.Ws28xx
@@ -12,7 +13,8 @@ namespace Iot.Device.Ws28xx
1213
internal class BitmapImageNeo3 : BitmapImage
1314
{
1415
private const int BytesPerComponent = 3;
15-
private const int BytesPerPixel = BytesPerComponent * 3;
16+
private const int BytesPerPixel = BytesPerComponent * 3;
17+
1618
// The Neo Pixels require a 50us delay (all zeros) after. Since Spi freq is not exactly
1719
// as requested 100us is used here with good practical results. 100us @ 2.4Mbps and 8bit
1820
// data means we have to add 30 bytes of zero padding.
@@ -37,7 +39,33 @@ public override void SetPixel(int x, int y, Color c)
3739
Data[offset++] = _lookup[c.B * BytesPerComponent + 2];
3840
}
3941

40-
private static readonly byte[] _lookup = new byte[256 * BytesPerComponent];
42+
public override void Clear(int x, int y)
43+
{
44+
var offset = y * Stride + x * BytesPerPixel;
45+
Array.Clear(Data, offset, 9);
46+
}
47+
48+
public override void Clear()
49+
{
50+
Array.Clear(Data, 0, Data.Length);
51+
}
52+
53+
public override void SetPixel(int x, int y, byte r, byte g, byte b)
54+
{
55+
var offset = y * Stride + x * BytesPerPixel;
56+
Data[offset++] = _lookup[g * BytesPerComponent + 0];
57+
Data[offset++] = _lookup[g * BytesPerComponent + 1];
58+
Data[offset++] = _lookup[g * BytesPerComponent + 2];
59+
Data[offset++] = _lookup[r * BytesPerComponent + 0];
60+
Data[offset++] = _lookup[r * BytesPerComponent + 1];
61+
Data[offset++] = _lookup[r * BytesPerComponent + 2];
62+
Data[offset++] = _lookup[b * BytesPerComponent + 0];
63+
Data[offset++] = _lookup[b * BytesPerComponent + 1];
64+
Data[offset++] = _lookup[b * BytesPerComponent + 2];
65+
}
66+
67+
private static readonly byte[] _lookup = new byte[256 * BytesPerComponent];
68+
4169
static BitmapImageNeo3()
4270
{
4371
for (int i = 0; i < 256; i++)
@@ -54,4 +82,4 @@ static BitmapImageNeo3()
5482
}
5583
}
5684
}
57-
}
85+
}

devices/Ws28xx/BitmapImageWs2808.cs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System;
45
using System.Drawing;
56

67
namespace Iot.Device.Ws28xx
@@ -21,5 +22,25 @@ public override void SetPixel(int x, int y, Color c)
2122
Data[offset++] = c.G;
2223
Data[offset++] = c.B;
2324
}
25+
26+
public override void SetPixel(int x, int y, byte r, byte g, byte b)
27+
{
28+
var offset = y * Stride + x * BytesPerPixel;
29+
Data[offset++] = r;
30+
Data[offset++] = g;
31+
Data[offset++] = b;
32+
}
33+
34+
/// <inheritdoc />
35+
public override void Clear()
36+
{
37+
Array.Clear(Data, 0, Data.Length);
38+
}
39+
40+
public override void Clear(int x, int y)
41+
{
42+
var offset = y * Stride + x * BytesPerPixel;
43+
Array.Clear(Data, offset, 3);
44+
}
2445
}
25-
}
46+
}

devices/Ws28xx/Ws28xx.nfproj

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@
2929
<Private>True</Private>
3030
<SpecificVersion>True</SpecificVersion>
3131
</Reference>
32+
<Reference Include="nanoFramework.Runtime.Events, Version=1.10.0.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
33+
<HintPath>packages\nanoFramework.Runtime.Events.1.10.0-preview.1\lib\nanoFramework.Runtime.Events.dll</HintPath>
34+
<Private>True</Private>
35+
<SpecificVersion>True</SpecificVersion>
36+
</Reference>
3237
<Reference Include="System.Device.Gpio, Version=1.0.3.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
3338
<HintPath>packages\nanoFramework.System.Device.Gpio.1.0.3-preview.3\lib\System.Device.Gpio.dll</HintPath>
3439
<Private>True</Private>

devices/Ws28xx/samples/Program.cs

Lines changed: 98 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using nanoFramework.Hardware.Esp32;
66
using System;
77
using System.Device.Spi;
8+
using System.Diagnostics;
89
using System.Drawing;
910

1011
// Configure the count of pixels
@@ -14,7 +15,7 @@
1415
Configuration.SetPinFunction(23, DeviceFunction.SPI2_MOSI);
1516
Configuration.SetPinFunction(19, DeviceFunction.SPI2_MISO);
1617
Configuration.SetPinFunction(18, DeviceFunction.SPI2_CLOCK);
17-
// Pin 22 must be set to ADC to use as the chip selector
18+
// Pin 22 must be set to ADC to use as the chip selector
1819
Configuration.SetPinFunction(22, DeviceFunction.ADC1_CH10);
1920

2021
// Using VSPI on bus 2 for ESP32 and pin 22 for chipselect
@@ -29,27 +30,29 @@
2930
#if WS2808
3031
Ws28xx neo = new Ws2808(spi, count);
3132
#else
32-
Ws28xx neo = new Ws2812b(spi, Count);
33-
#endif
34-
35-
33+
Ws28xx neo = new Ws2812b(spi, Count);
34+
#endif
35+
36+
// BenchmarkClearPixel(); uncomment to benchmark
37+
3638
while (true)
3739
{
40+
ColorFade(neo, Count);
3841
ColorWipe(neo, Color.White, Count);
3942
ColorWipe(neo, Color.Red, Count);
4043
ColorWipe(neo, Color.Green, Count);
41-
ColorWipe(neo, Color.Blue, Count);
42-
44+
ColorWipe(neo, Color.Blue, Count);
45+
4346
TheatreChase(neo, Color.White, Count);
4447
TheatreChase(neo, Color.Red, Count);
4548
TheatreChase(neo, Color.Green, Count);
46-
TheatreChase(neo, Color.Blue, Count);
47-
49+
TheatreChase(neo, Color.Blue, Count);
50+
4851
Rainbow(neo, Count);
4952
RainbowCycle(neo, Count);
5053
TheaterChaseRainbow(neo, Count);
51-
}
52-
54+
}
55+
5356
void ColorWipe(Ws28xx neo, Color color, int count)
5457
{
5558
BitmapImage img = neo.Image;
@@ -60,6 +63,55 @@ void ColorWipe(Ws28xx neo, Color color, int count)
6063
}
6164
}
6265

66+
void ColorFade(Ws28xx neo, int count)
67+
{
68+
BitmapImage img = neo.Image;
69+
70+
// White
71+
for (byte iteration = 0; iteration < 255; iteration++)
72+
{
73+
for (var pixel = 0; pixel < count; pixel++)
74+
{
75+
img.SetPixel(pixel, 0, iteration, iteration, iteration);
76+
}
77+
neo.Update();
78+
System.Threading.Thread.Sleep(10);
79+
}
80+
81+
// Red
82+
for (byte iteration = 0; iteration < 255; iteration++)
83+
{
84+
for (var pixel = 0; pixel < count; pixel++)
85+
{
86+
img.SetPixel(pixel, 0, iteration, 0, 0);
87+
}
88+
neo.Update();
89+
System.Threading.Thread.Sleep(10);
90+
}
91+
92+
// Green
93+
for (byte iteration = 0; iteration < 255; iteration++)
94+
{
95+
for (var pixel = 0; pixel < count; pixel++)
96+
{
97+
img.SetPixel(pixel, 0, 0, iteration, 0);
98+
}
99+
neo.Update();
100+
System.Threading.Thread.Sleep(10);
101+
}
102+
103+
// Blue
104+
for (byte iteration = 0; iteration < 255; iteration++)
105+
{
106+
for (var pixel = 0; pixel < count; pixel++)
107+
{
108+
img.SetPixel(pixel, 0, 0, 0, iteration);
109+
}
110+
neo.Update();
111+
System.Threading.Thread.Sleep(10);
112+
}
113+
}
114+
63115
void TheatreChase(Ws28xx neo, Color color, int count, int iterations = 10)
64116
{
65117
BitmapImage img = neo.Image;
@@ -121,7 +173,7 @@ void RainbowCycle(Ws28xx neo, int count, int iterations = 1)
121173
{
122174
for (var j = 0; j < count; j++)
123175
{
124-
img.SetPixel(j, 0, Wheel(((int)(j * 255 / count) + i) & 255));
176+
img.SetPixel(j, 0, Wheel(((j * 255 / count) + i) & 255));
125177
}
126178

127179
neo.Update();
@@ -150,3 +202,37 @@ void TheaterChaseRainbow(Ws28xx neo, int count)
150202
}
151203
}
152204
}
205+
206+
void BenchmarkClearPixel()
207+
{
208+
Stopwatch sw = new Stopwatch();
209+
210+
sw.Start();
211+
for (int i = 0; i < 1000; i++)
212+
{
213+
neo.Image.Clear();
214+
neo.Update();
215+
}
216+
217+
sw.Stop();
218+
Debug.WriteLine("Clear all" + sw.Elapsed.ToString());
219+
220+
Stopwatch sw2 = new Stopwatch();
221+
222+
sw2.Start();
223+
for (int i = 0; i < 1000; i++)
224+
{
225+
for (int y = 0; y < neo.Image.Height; y++)
226+
{
227+
for (int x = 0; x < neo.Image.Width; x++)
228+
{
229+
neo.Image.Clear(x, y);
230+
}
231+
}
232+
233+
neo.Update();
234+
}
235+
236+
sw2.Stop();
237+
Debug.WriteLine("Clear pixel by pixel " + sw2.Elapsed.ToString());
238+
}

devices/Ws28xx/samples/Ws28xx.Samples.nfproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,12 @@
2828
<Reference Include="nanoFramework.Hardware.Esp32, Version=1.3.5.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
2929
<HintPath>..\packages\nanoFramework.Hardware.Esp32.1.3.5-preview.3\lib\nanoFramework.Hardware.Esp32.dll</HintPath>
3030
<Private>True</Private>
31+
<SpecificVersion>True</SpecificVersion>
3132
</Reference>
3233
<Reference Include="nanoFramework.Runtime.Events, Version=1.10.0.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
3334
<HintPath>..\packages\nanoFramework.Runtime.Events.1.10.0-preview.1\lib\nanoFramework.Runtime.Events.dll</HintPath>
3435
<Private>True</Private>
36+
<SpecificVersion>True</SpecificVersion>
3537
</Reference>
3638
<Reference Include="System.Device.Gpio, Version=1.0.3.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
3739
<HintPath>..\packages\nanoFramework.System.Device.Gpio.1.0.3-preview.3\lib\System.Device.Gpio.dll</HintPath>
@@ -43,11 +45,17 @@
4345
<Private>True</Private>
4446
<SpecificVersion>True</SpecificVersion>
4547
</Reference>
48+
<Reference Include="System.Diagnostics.Stopwatch, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
49+
<HintPath>..\packages\nanoFramework.System.Diagnostics.Stopwatch.1.0.259\lib\System.Diagnostics.Stopwatch.dll</HintPath>
50+
<Private>True</Private>
51+
<SpecificVersion>True</SpecificVersion>
52+
</Reference>
4653
<Reference Include="System.Drawing">
4754
<HintPath>..\packages\nanoFramework.System.Drawing.1.0.268\lib\System.Drawing.dll</HintPath>
4855
</Reference>
4956
</ItemGroup>
5057
<ItemGroup>
58+
<None Include="app.config" />
5159
<None Include="packages.config" />
5260
<!-- INSERT FILE REFERENCES HERE -->
5361
</ItemGroup>

devices/Ws28xx/samples/app.config

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<configuration>
3+
<runtime>
4+
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
5+
<dependentAssembly>
6+
<assemblyIdentity name="nanoFramework.Runtime.Events" publicKeyToken="c07d481e9758c731" culture="neutral" />
7+
<bindingRedirect oldVersion="0.0.0.0-1.10.0.0" newVersion="1.10.0.0" />
8+
</dependentAssembly>
9+
<dependentAssembly>
10+
<assemblyIdentity name="System.Device.Gpio" publicKeyToken="c07d481e9758c731" culture="neutral" />
11+
<bindingRedirect oldVersion="0.0.0.0-1.0.3.0" newVersion="1.0.3.0" />
12+
</dependentAssembly>
13+
</assemblyBinding>
14+
</runtime>
15+
</configuration>

devices/Ws28xx/samples/packages.config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@
66
<package id="nanoFramework.System.Device.Gpio" version="1.0.3-preview.3" targetFramework="netnanoframework10" />
77
<package id="nanoFramework.System.Device.Spi" version="1.0.3-preview.3" targetFramework="netnanoframework10" />
88
<package id="nanoFramework.System.Drawing" version="1.0.268" targetFramework="netnanoframework10" />
9+
<package id="nanoFramework.System.Diagnostics.Stopwatch" version="1.0.259" targetFramework="netnanoframework10" />
910
<package id="Nerdbank.GitVersioning" version="3.4.240" targetFramework="netnanoframework10" developmentDependency="true" />
1011
</packages>

0 commit comments

Comments
 (0)