Skip to content

Commit 303340f

Browse files
authored
Add WS28xx, SK2816 for Esp32 using RMT (#334)
1 parent 2fc020d commit 303340f

34 files changed

+1464
-92
lines changed

devices/Ws28xx.Esp32/BitmapImage.cs

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.Drawing;
6+
7+
namespace Iot.Device.Ws28xx.Esp32
8+
{
9+
/// <summary>
10+
/// Represents bitmap image
11+
/// </summary>
12+
public abstract class BitmapImage
13+
{
14+
/// <summary>
15+
/// Initializes a <see cref="T:Iot.Device.Graphics.BitmapImage" /> instance with the specified data, width, height and stride.
16+
/// </summary>
17+
/// <param name="data">Data representing the image (derived class defines a specific format)</param>
18+
/// <param name="width">Width of the image</param>
19+
/// <param name="height">Height of the image</param>
20+
/// <param name="stride">Number of bytes per row</param>
21+
protected BitmapImage(byte[] data, int width, int height, int stride)
22+
{
23+
_data = data;
24+
Width = width;
25+
Height = height;
26+
Stride = stride;
27+
}
28+
29+
private byte[] _data;
30+
31+
/// <summary>
32+
/// Data related to the image (derived class defines a specific format)
33+
/// </summary>
34+
public byte[] Data => _data;
35+
36+
/// <summary>
37+
/// Width of the image
38+
/// </summary>
39+
public int Width { get; }
40+
41+
/// <summary>
42+
/// Height of the image
43+
/// </summary>
44+
public int Height { get; }
45+
46+
/// <summary>
47+
/// Number of bytes per row
48+
/// </summary>
49+
public int Stride { get; }
50+
51+
/// <summary>
52+
/// Sets pixel at specific position
53+
/// </summary>
54+
/// <param name="x">X coordinate of the pixel</param>
55+
/// <param name="y">Y coordinate of the pixel</param>
56+
/// <param name="color">Color to set the pixel to</param>
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);
68+
69+
/// <summary>
70+
/// Clears the image to specific color
71+
/// </summary>
72+
/// <param name="color">Color to clear the image. Defaults to black.</param>
73+
public virtual void Clear(Color color)
74+
{
75+
for (int y = 0; y < Height; y++)
76+
{
77+
for (int x = 0; x < Width; x++)
78+
{
79+
SetPixel(x, y, color);
80+
}
81+
}
82+
}
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);
93+
}
94+
}
+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.Drawing;
6+
7+
namespace Iot.Device.Ws28xx.Esp32
8+
{
9+
/// <summary>
10+
/// Special 24bit RGB format for Neo pixel LEDs where each bit is converted to 3 bits.
11+
/// A one is converted to 110, a zero is converted to 100.
12+
/// </summary>
13+
internal class BitmapImageNeo3 : BitmapImage
14+
{
15+
protected const int BytesPerComponent = 3;
16+
protected const int BytesPerPixel = BytesPerComponent * 3;
17+
18+
public BitmapImageNeo3(int width, int height)
19+
: base(new byte[width * height * BytesPerPixel], width, height, width * BytesPerPixel)
20+
{
21+
}
22+
23+
public override void SetPixel(int x, int y, Color c)
24+
{
25+
var offset = y * Stride + x * BytesPerPixel;
26+
Data[offset++] = _lookup[c.G * BytesPerComponent + 0];
27+
Data[offset++] = _lookup[c.G * BytesPerComponent + 1];
28+
Data[offset++] = _lookup[c.G * BytesPerComponent + 2];
29+
Data[offset++] = _lookup[c.R * BytesPerComponent + 0];
30+
Data[offset++] = _lookup[c.R * BytesPerComponent + 1];
31+
Data[offset++] = _lookup[c.R * BytesPerComponent + 2];
32+
Data[offset++] = _lookup[c.B * BytesPerComponent + 0];
33+
Data[offset++] = _lookup[c.B * BytesPerComponent + 1];
34+
Data[offset++] = _lookup[c.B * BytesPerComponent + 2];
35+
}
36+
37+
public override void Clear(int x, int y)
38+
{
39+
var offset = y * Stride + x * BytesPerPixel;
40+
Array.Clear(Data, offset, 9);
41+
}
42+
43+
public override void Clear()
44+
{
45+
Array.Clear(Data, 0, Data.Length);
46+
}
47+
48+
public override void SetPixel(int x, int y, byte r, byte g, byte b)
49+
{
50+
var offset = y * Stride + x * BytesPerPixel;
51+
Data[offset++] = _lookup[g * BytesPerComponent + 0];
52+
Data[offset++] = _lookup[g * BytesPerComponent + 1];
53+
Data[offset++] = _lookup[g * BytesPerComponent + 2];
54+
Data[offset++] = _lookup[r * BytesPerComponent + 0];
55+
Data[offset++] = _lookup[r * BytesPerComponent + 1];
56+
Data[offset++] = _lookup[r * BytesPerComponent + 2];
57+
Data[offset++] = _lookup[b * BytesPerComponent + 0];
58+
Data[offset++] = _lookup[b * BytesPerComponent + 1];
59+
Data[offset++] = _lookup[b * BytesPerComponent + 2];
60+
}
61+
62+
protected static readonly byte[] _lookup = new byte[256 * BytesPerComponent];
63+
64+
static BitmapImageNeo3()
65+
{
66+
for (int i = 0; i < 256; i++)
67+
{
68+
int data = 0;
69+
for (int j = 7; j >= 0; j--)
70+
{
71+
data = (data << 3) | 0b100 | ((i >> j) << 1) & 2;
72+
}
73+
74+
_lookup[i * BytesPerComponent + 0] = unchecked((byte)(data >> 16));
75+
_lookup[i * BytesPerComponent + 1] = unchecked((byte)(data >> 8));
76+
_lookup[i * BytesPerComponent + 2] = unchecked((byte)(data >> 0));
77+
}
78+
}
79+
}
80+
}
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.Drawing;
5+
6+
namespace Iot.Device.Ws28xx.Esp32
7+
{
8+
/// <summary>
9+
/// Special 24bit RGB format for Neo pixel LEDs where each bit is converted to 3 bits.
10+
/// A one is converted to 110, a zero is converted to 100.
11+
/// </summary>
12+
/// <seealso cref="Iot.Device.Ws28xx.BitmapImageNeo3" />
13+
internal class BitmapImageNeo3Rgb : BitmapImageNeo3
14+
{
15+
public BitmapImageNeo3Rgb(int width, int height)
16+
: base(width, height)
17+
{
18+
}
19+
20+
public override void SetPixel(int x, int y, Color c)
21+
{
22+
var offset = y * Stride + x * BytesPerPixel;
23+
Data[offset++] = _lookup[c.R * BytesPerComponent + 0];
24+
Data[offset++] = _lookup[c.R * BytesPerComponent + 1];
25+
Data[offset++] = _lookup[c.R * BytesPerComponent + 2];
26+
Data[offset++] = _lookup[c.G * BytesPerComponent + 0];
27+
Data[offset++] = _lookup[c.G * BytesPerComponent + 1];
28+
Data[offset++] = _lookup[c.G * BytesPerComponent + 2];
29+
Data[offset++] = _lookup[c.B * BytesPerComponent + 0];
30+
Data[offset++] = _lookup[c.B * BytesPerComponent + 1];
31+
Data[offset++] = _lookup[c.B * BytesPerComponent + 2];
32+
}
33+
}
34+
}
+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.Drawing;
5+
6+
namespace Iot.Device.Ws28xx.Esp32
7+
{
8+
internal class BitmapImageNeo4 : BitmapImage
9+
{
10+
private const int BytesPerComponent = 3;
11+
private const int BytesPerPixel = BytesPerComponent * 4;
12+
13+
// This field defines the count within the lookup table. The length correlates to the possible values of a single byte.
14+
private const int LookupCount = 256;
15+
16+
private static readonly byte[] _lookup = new byte[LookupCount * BytesPerComponent];
17+
18+
static BitmapImageNeo4()
19+
{
20+
ClearInternal();
21+
}
22+
23+
public BitmapImageNeo4(int width, int height)
24+
: base(new byte[width * height * BytesPerPixel], width, height, width * BytesPerPixel)
25+
{
26+
}
27+
28+
public override void Clear() => ClearInternal();
29+
30+
private static void ClearInternal()
31+
{
32+
for (int i = 0; i < LookupCount; i++)
33+
{
34+
int data = 0;
35+
for (int j = 7; j >= 0; j--)
36+
{
37+
data = (data << 3) | 0b100 | ((i >> j) << 1) & 2;
38+
}
39+
40+
_lookup[i * BytesPerComponent + 0] = unchecked((byte)(data >> 16));
41+
_lookup[i * BytesPerComponent + 1] = unchecked((byte)(data >> 8));
42+
_lookup[i * BytesPerComponent + 2] = unchecked((byte)(data >> 0));
43+
}
44+
}
45+
46+
public override void Clear(int x, int y) => SetPixel(x, y, Color.Black);
47+
48+
public override void SetPixel(int x, int y, Color c)
49+
{
50+
// Alpha is used as white.
51+
var offset = y * Stride + x * BytesPerPixel;
52+
Data[offset++] = _lookup[c.G * BytesPerComponent + 0];
53+
Data[offset++] = _lookup[c.G * BytesPerComponent + 1];
54+
Data[offset++] = _lookup[c.G * BytesPerComponent + 2];
55+
Data[offset++] = _lookup[c.R * BytesPerComponent + 0];
56+
Data[offset++] = _lookup[c.R * BytesPerComponent + 1];
57+
Data[offset++] = _lookup[c.R * BytesPerComponent + 2];
58+
Data[offset++] = _lookup[c.B * BytesPerComponent + 0];
59+
Data[offset++] = _lookup[c.B * BytesPerComponent + 1];
60+
Data[offset++] = _lookup[c.B * BytesPerComponent + 2];
61+
Data[offset++] = _lookup[c.A * BytesPerComponent + 0];
62+
Data[offset++] = _lookup[c.A * BytesPerComponent + 1];
63+
Data[offset++] = _lookup[c.A * BytesPerComponent + 2];
64+
}
65+
66+
public override void SetPixel(int x, int y, byte r, byte g, byte b) => SetPixel(x, y, Color.FromArgb(r, g, b));
67+
}
68+
}
+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.Drawing;
6+
7+
namespace Iot.Device.Ws28xx.Esp32
8+
{
9+
internal class BitmapImageWs2808 : BitmapImage
10+
{
11+
private const int BytesPerPixel = 3;
12+
13+
public BitmapImageWs2808(int width, int height)
14+
: base(new byte[width * height * BytesPerPixel], width, height, width * BytesPerPixel)
15+
{
16+
}
17+
18+
public override void SetPixel(int x, int y, Color c)
19+
{
20+
var offset = y * Stride + x * BytesPerPixel;
21+
Data[offset++] = c.R;
22+
Data[offset++] = c.G;
23+
Data[offset++] = c.B;
24+
}
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+
}
45+
}
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.Drawing;
6+
7+
namespace Iot.Device.Ws28xx.Esp32
8+
{
9+
internal class BitmapImageWs2808Grb : BitmapImage
10+
{
11+
private const int BytesPerPixel = 3;
12+
13+
public BitmapImageWs2808Grb(int width, int height)
14+
: base(new byte[width * height * BytesPerPixel], width, height, width * BytesPerPixel)
15+
{
16+
}
17+
18+
public override void SetPixel(int x, int y, Color c)
19+
{
20+
var offset = y * Stride + x * BytesPerPixel;
21+
Data[offset++] = c.G;
22+
Data[offset++] = c.R;
23+
Data[offset++] = c.B;
24+
}
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++] = g;
30+
Data[offset++] = r;
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+
}
45+
}
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using System.Reflection;
2+
using System.Runtime.InteropServices;
3+
4+
[assembly: AssemblyTitle("Iot.Device.Ws28xx.Esp32")]
5+
[assembly: AssemblyCompany("nanoFramework Contributors")]
6+
[assembly: AssemblyCopyright("Copyright(c).NET Foundation and Contributors")]
7+
8+
[assembly: ComVisible(false)]
9+

0 commit comments

Comments
 (0)