Skip to content

Commit a939653

Browse files
author
bitluni
committed
Support for RGBW and parallel led data lanes
1 parent 222d953 commit a939653

17 files changed

+566
-60
lines changed

.vscode/arduino.json

-5
This file was deleted.

.vscode/c_cpp_properties.json

-17
This file was deleted.

.vscode/settings.json

-8
This file was deleted.

Utilities/SpriteEditor.html

+14-2
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,17 @@
194194
var rf, rshift, gf, gshift, bf, bshift, af, ashift, type, bytesPerPixel;
195195
switch(pixelformat)
196196
{
197+
case "R8G8B8A8":
198+
{
199+
rf = gf = bf = af = 255.;
200+
rshift = 0;
201+
gshift = 8;
202+
bshift = 16;
203+
ashift = 24;
204+
type = "unsigned long";
205+
bytesPerPixel = 4;
206+
break;
207+
}
197208
case "R2G2B2A2":
198209
{
199210
rf = gf = bf = af = 3.;
@@ -274,8 +285,8 @@
274285
var b = s[j + 2];
275286
var a = s[j + 3];
276287
var c = 0;
277-
c = (Math.round(r / 255. * rf) << rshift) + (Math.round(g / 255. * gf) << gshift) + (Math.round(b / 255. * bf) << bshift) + (Math.round(a / 255. * af) << ashift);
278-
text += c + ", ";
288+
c = ((Math.round(r / 255. * rf) << rshift) + (Math.round(g / 255. * gf) << gshift) + (Math.round(b / 255. * bf) << bshift) + (Math.round(a / 255. * af) << ashift)) >>> 0;
289+
text += "0x" + c.toString(16) + ", ";
279290
k++;
280291
if((k & 31) == 0)
281292
text += "\n";
@@ -601,6 +612,7 @@ <h1>bitluni's Sprite Editor</h1>
601612
<input id="addimages" type="file" onchange="addFiles(event)" accept="image/*" multiple hidden>
602613
<button title="Export sprite header" onclick="saveHeader();" style="font-size: 15px; font-weight:bold">.h</button>
603614
<select id="pixelformat" title="Export pixel format">
615+
<option vlaue="R8G8B8A8">R8G8B8A8</option>
604616
<option vlaue="R2G2B2A2">R2G2B2A2</option>
605617
<option vlaue="R5G5B4A2">R5G5B4A2</option>
606618
<option vlaue="R4G4B4A4">R4G4B4A4</option>

src/Composite/Composite.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,20 @@ bool Composite::init(const ModeComposite &mode, const int *pinMap, const int bit
5353
return true;
5454
}
5555

56+
void Composite::getClockSetting(long *sampleRate, int *n, int *a, int *b, int *div)
57+
{
58+
if(sampleRate)
59+
*sampleRate = mode.pixelClock;
60+
if(n)
61+
*n = 2;
62+
if(a)
63+
*a = 1;
64+
if(b)
65+
*b = 0;
66+
if(div)
67+
*div = 6;
68+
}
69+
5670
int Composite::burst(int sampleNumber, bool even)
5771
{
5872
return blankLevel;

src/Composite/Composite.h

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class Composite : public I2S
5252
virtual void allocateLineBuffers() = 0;
5353
virtual void allocateLineBuffers(void **frameBuffer);
5454
virtual void propagateResolution(const int xres, const int yres) = 0;
55+
virtual void getClockSetting(long *sampleRate, int *n, int *a, int *b, int *div);
5556

5657
protected:
5758
virtual void interrupt();

src/ESP32Lib.h

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
#include <Composite/CompositePAL8.h>
1111

1212
#include <LED/SerialLED.h>
13+
#include <LED/ParallelLED.h>
14+
#include <LED/ParallelLEDGraphics.h>
1315

1416
#include <Graphics/Sprites.h>
1517
#include <Graphics/Mesh.h>

src/Graphics/Graphics.h

+74
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,80 @@ class Graphics: public ImageDrawer
636636
return RGBA(r, g, b, a);
637637
}
638638

639+
virtual Color R4G4B4A4ToColor(unsigned short c)
640+
{
641+
int r = (((c << 1) & 0x1e) * 255 + 1) / 0x1e;
642+
int g = (((c >> 3) & 0x1e) * 255 + 1) / 0x1e;
643+
int b = (((c >> 7) & 0x1e) * 255 + 1) / 0x1e;
644+
int a = (((c >> 11) & 0x1e) * 255 + 1) / 0x1e;
645+
return RGBA(r, g, b, a);
646+
}
647+
648+
virtual Color R8G8B8A8ToColor(unsigned long c)
649+
{
650+
return RGBA(c & 255, (c >> 8) & 255, (c >> 16) & 255, (c >> 24) & 255);
651+
}
652+
653+
virtual void imageR8G8B8A8(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres)
654+
{
655+
for (int py = 0; py < srcYres; py++)
656+
{
657+
int i = srcX + (py + srcY) * image.xres;
658+
for (int px = 0; px < srcXres; px++)
659+
dot(px + x, py + y, R8G8B8A8ToColor(((unsigned long*)image.pixels)[i++]));
660+
}
661+
}
662+
663+
virtual void imageAddR8G8B8A8(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres)
664+
{
665+
for (int py = 0; py < srcYres; py++)
666+
{
667+
int i = srcX + (py + srcY) * image.xres;
668+
for (int px = 0; px < srcXres; px++)
669+
dotAdd(px + x, py + y, R8G8B8A8ToColor(((unsigned long*)image.pixels)[i++]));
670+
}
671+
}
672+
673+
virtual void imageMixR8G8B8A8(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres)
674+
{
675+
for (int py = 0; py < srcYres; py++)
676+
{
677+
int i = srcX + (py + srcY) * image.xres;
678+
for (int px = 0; px < srcXres; px++)
679+
dotMix(px + x, py + y, R8G8B8A8ToColor(((unsigned long*)image.pixels)[i++]));
680+
}
681+
}
682+
683+
virtual void imageR4G4B4A4(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres)
684+
{
685+
for (int py = 0; py < srcYres; py++)
686+
{
687+
int i = srcX + (py + srcY) * image.xres;
688+
for (int px = 0; px < srcXres; px++)
689+
dot(px + x, py + y, R4G4B4A4ToColor(((unsigned short*)image.pixels)[i++]));
690+
}
691+
}
692+
693+
virtual void imageAddR4G4B4A4(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres)
694+
{
695+
for (int py = 0; py < srcYres; py++)
696+
{
697+
int i = srcX + (py + srcY) * image.xres;
698+
for (int px = 0; px < srcXres; px++)
699+
dotAdd(px + x, py + y, R4G4B4A4ToColor(((unsigned short*)image.pixels)[i++]));
700+
}
701+
}
702+
703+
virtual void imageMixR4G4B4A4(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres)
704+
{
705+
for (int py = 0; py < srcYres; py++)
706+
{
707+
int i = srcX + (py + srcY) * image.xres;
708+
for (int px = 0; px < srcXres; px++)
709+
dotMix(px + x, py + y, R4G4B4A4ToColor(((unsigned short*)image.pixels)[i++]));
710+
}
711+
}
712+
639713
virtual void imageR5G5B4A2(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres)
640714
{
641715
for (int py = 0; py < srcYres; py++)

src/Graphics/ImageDrawer.h

+42
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,35 @@
1414
class ImageDrawer
1515
{
1616
public:
17+
virtual void imageR8G8B8A8(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres) = 0;
18+
virtual void imageAddR8G8B8A8(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres) = 0;
19+
virtual void imageMixR8G8B8A8(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres) = 0;
1720
virtual void imageR5G5B4A2(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres) = 0;
1821
virtual void imageAddR5G5B4A2(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres) = 0;
1922
virtual void imageMixR5G5B4A2(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres) = 0;
2023
virtual void imageR2G2B2A2(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres) = 0;
2124
virtual void imageAddR2G2B2A2(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres) = 0;
2225
virtual void imageMixR2G2B2A2(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres) = 0;
26+
virtual void imageR4G4B4A4(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres) = 0;
27+
virtual void imageAddR4G4B4A4(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres) = 0;
28+
virtual void imageMixR4G4B4A4(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres) = 0;
2329

2430
void image(Image &image, int x, int y, int srcX, int srcY, int srcXres, int srcYres)
2531
{
2632
switch(image.pixelFormat)
2733
{
34+
case Image::R8G8B8A8:
35+
imageR8G8B8A8(image, x, y, srcX, srcY, srcXres, srcYres);
36+
break;
2837
case Image::R5G5B4A2:
2938
imageR5G5B4A2(image, x, y, srcX, srcY, srcXres, srcYres);
3039
break;
3140
case Image::R2G2B2A2:
3241
imageR2G2B2A2(image, x, y, srcX, srcY, srcXres, srcYres);
3342
break;
43+
case Image::R4G4B4A4:
44+
imageR4G4B4A4(image, x, y, srcX, srcY, srcXres, srcYres);
45+
break;
3446
default:
3547
break;
3648
}
@@ -40,12 +52,18 @@ class ImageDrawer
4052
{
4153
switch(image.pixelFormat)
4254
{
55+
case Image::R8G8B8A8:
56+
imageAddR8G8B8A8(image, x, y, srcX, srcY, srcXres, srcYres);
57+
break;
4358
case Image::R5G5B4A2:
4459
imageAddR5G5B4A2(image, x, y, srcX, srcY, srcXres, srcYres);
4560
break;
4661
case Image::R2G2B2A2:
4762
imageAddR2G2B2A2(image, x, y, srcX, srcY, srcXres, srcYres);
4863
break;
64+
case Image::R4G4B4A4:
65+
imageAddR4G4B4A4(image, x, y, srcX, srcY, srcXres, srcYres);
66+
break;
4967
default:
5068
break;
5169
}
@@ -55,12 +73,18 @@ class ImageDrawer
5573
{
5674
switch(image.pixelFormat)
5775
{
76+
case Image::R8G8B8A8:
77+
imageMixR8G8B8A8(image, x, y, srcX, srcY, srcXres, srcYres);
78+
break;
5879
case Image::R5G5B4A2:
5980
imageMixR5G5B4A2(image, x, y, srcX, srcY, srcXres, srcYres);
6081
break;
6182
case Image::R2G2B2A2:
6283
imageMixR2G2B2A2(image, x, y, srcX, srcY, srcXres, srcYres);
6384
break;
85+
case Image::R4G4B4A4:
86+
imageMixR4G4B4A4(image, x, y, srcX, srcY, srcXres, srcYres);
87+
break;
6488
default:
6589
break;
6690
}
@@ -70,12 +94,18 @@ class ImageDrawer
7094
{
7195
switch(image.pixelFormat)
7296
{
97+
case Image::R8G8B8A8:
98+
imageR8G8B8A8(image, x, y, 0, 0, image.xres, image.yres);
99+
break;
73100
case Image::R5G5B4A2:
74101
imageR5G5B4A2(image, x, y, 0, 0, image.xres, image.yres);
75102
break;
76103
case Image::R2G2B2A2:
77104
imageR2G2B2A2(image, x, y, 0, 0, image.xres, image.yres);
78105
break;
106+
case Image::R4G4B4A4:
107+
imageR4G4B4A4(image, x, y, 0, 0, image.xres, image.yres);
108+
break;
79109
default:
80110
break;
81111
}
@@ -85,12 +115,18 @@ class ImageDrawer
85115
{
86116
switch(image.pixelFormat)
87117
{
118+
case Image::R8G8B8A8:
119+
imageAddR8G8B8A8(image, x, y, 0, 0, image.xres, image.yres);
120+
break;
88121
case Image::R5G5B4A2:
89122
imageAddR5G5B4A2(image, x, y, 0, 0, image.xres, image.yres);
90123
break;
91124
case Image::R2G2B2A2:
92125
imageAddR2G2B2A2(image, x, y, 0, 0, image.xres, image.yres);
93126
break;
127+
case Image::R4G4B4A4:
128+
imageAddR4G4B4A4(image, x, y, 0, 0, image.xres, image.yres);
129+
break;
94130
default:
95131
break;
96132
}
@@ -100,12 +136,18 @@ class ImageDrawer
100136
{
101137
switch(image.pixelFormat)
102138
{
139+
case Image::R8G8B8A8:
140+
imageMixR8G8B8A8(image, x, y, 0, 0, image.xres, image.yres);
141+
break;
103142
case Image::R5G5B4A2:
104143
imageMixR5G5B4A2(image, x, y, 0, 0, image.xres, image.yres);
105144
break;
106145
case Image::R2G2B2A2:
107146
imageMixR2G2B2A2(image, x, y, 0, 0, image.xres, image.yres);
108147
break;
148+
case Image::R4G4B4A4:
149+
imageMixR4G4B4A4(image, x, y, 0, 0, image.xres, image.yres);
150+
break;
109151
default:
110152
break;
111153
}

src/I2S/I2S.cpp

+24-7
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,21 @@ bool I2S::useInterrupt()
126126
return false;
127127
};
128128

129+
void I2S::getClockSetting(long *sampleRate, int *n, int *a, int *b, int *div)
130+
{
131+
if(sampleRate)
132+
*sampleRate = 2000000;
133+
if(n)
134+
*n = 2;
135+
if(a)
136+
*a = 1;
137+
if(b)
138+
*b = 0;
139+
if(div)
140+
*div = 1;
141+
}
142+
143+
129144
bool I2S::initParallelInputMode(const int *pinMap, long sampleRate, const int bitCount, int wordSelect, int baseClock)
130145
{
131146
volatile i2s_dev_t &i2s = *i2sDevices[i2sIndex];
@@ -223,7 +238,7 @@ bool I2S::initParallelOutputMode(const int *pinMap, long sampleRate, const int b
223238
{
224239
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[pinMap[i]], PIN_FUNC_GPIO);
225240
gpio_set_direction((gpio_num_t)pinMap[i], (gpio_mode_t)GPIO_MODE_DEF_OUTPUT);
226-
rtc_gpio_set_drive_capability((gpio_num_t)pinMap[i], (gpio_drive_cap_t)GPIO_DRIVE_CAP_3 );
241+
//rtc_gpio_set_drive_capability((gpio_num_t)pinMap[i], (gpio_drive_cap_t)GPIO_DRIVE_CAP_3 );
227242
if(i2sIndex == 1)
228243
{
229244
if(bitCount == 16)
@@ -265,7 +280,9 @@ bool I2S::initParallelOutputMode(const int *pinMap, long sampleRate, const int b
265280
i2s.sample_rate_conf.val = 0;
266281
i2s.sample_rate_conf.tx_bits_mod = bitCount;
267282
//clock setup
268-
283+
int clockN = 2, clockA = 1, clockB = 0, clockDiv = 1;
284+
if(sampleRate == 0)
285+
getClockSetting(&sampleRate, &clockN, &clockA, &clockB, &clockDiv);
269286
if(sampleRate > 0)
270287
{
271288
//xtal is 40M
@@ -299,11 +316,11 @@ bool I2S::initParallelOutputMode(const int *pinMap, long sampleRate, const int b
299316
}
300317

301318
i2s.clkm_conf.val = 0;
302-
i2s.clkm_conf.clka_en = 1;
303-
i2s.clkm_conf.clkm_div_num = 2; //clockN;
304-
i2s.clkm_conf.clkm_div_a = 1; //clockA;
305-
i2s.clkm_conf.clkm_div_b = 0; //clockB;
306-
i2s.sample_rate_conf.tx_bck_div_num = 1;//1;
319+
i2s.clkm_conf.clka_en = sampleRate > 0 ? 1 : 0;
320+
i2s.clkm_conf.clkm_div_num = clockN;
321+
i2s.clkm_conf.clkm_div_a = clockA;
322+
i2s.clkm_conf.clkm_div_b = clockB;
323+
i2s.sample_rate_conf.tx_bck_div_num = clockDiv;
307324

308325
i2s.fifo_conf.val = 0;
309326
i2s.fifo_conf.tx_fifo_mod_force_en = 1;

src/I2S/I2S.h

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ class I2S
5151

5252
void allocateDMABuffers(int count, int bytes);
5353
void deleteDMABuffers();
54+
virtual void getClockSetting(long *sampleRate, int *n, int *a, int *b, int *div);
5455

5556
protected:
5657
virtual void interrupt() = 0;

0 commit comments

Comments
 (0)