Skip to content

Commit

Permalink
Grouping and zig-zag support for ws2811 strips
Browse files Browse the repository at this point in the history
- Output Grouping can be disabled, grouped or zig-zag
- Group size specifies the size of groups or zig-zag period (in LEDs, not dmx channels)
Its implemented in the pixeldriver so both e.131 and effect data use the grouping config
  • Loading branch information
penfold42 committed Jan 6, 2019
1 parent 60ba614 commit 8531ed4
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 11 deletions.
2 changes: 2 additions & 0 deletions ESPixelStick.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ typedef struct {
/* Pixels */
PixelType pixel_type; /* Pixel type */
PixelColor pixel_color; /* Pixel color order */
GroupMode groupMode; /* disabled, grouped, zigzag */
uint16_t groupSize;
bool gamma; /* Use gamma map? */
float gammaVal; /* gamma value to use */
float briteVal; /* brightness lto use */
Expand Down
16 changes: 15 additions & 1 deletion ESPixelStick.ino
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,11 @@ void validateConfig() {
else if (config.channel_count < 1)
config.channel_count = 1;

if (config.groupSize > config.channel_count/3)
config.groupSize = config.channel_count/3;
else if (config.groupSize < 1)
config.groupSize = 1;

// GECE Limits
if (config.pixel_type == PixelType::GECE) {
config.pixel_color = PixelColor::RGB;
Expand Down Expand Up @@ -653,9 +658,14 @@ void updateConfig() {
// Initialize for our pixel type
#if defined(ESPS_MODE_PIXEL)
pixels.begin(config.pixel_type, config.pixel_color, config.channel_count / 3);
pixels.setGroupMode(config.groupMode, config.groupSize);
pixels.setGamma(config.gamma);
updateGammaTable(config.gammaVal, config.briteVal);
effects.begin(&pixels, config.channel_count / 3);
if (config.groupMode == GroupMode::grouped) {
effects.begin(&pixels, config.channel_count / 3 / config.groupSize);
} else {
effects.begin(&pixels, config.channel_count / 3);
}

#elif defined(ESPS_MODE_SERIAL)
serial.begin(&SEROUT_PORT, config.serial_type, config.channel_count, config.baudrate);
Expand Down Expand Up @@ -754,6 +764,8 @@ void dsDeviceConfig(JsonObject &json) {
// Pixel
config.pixel_type = PixelType(static_cast<uint8_t>(json["pixel"]["type"]));
config.pixel_color = PixelColor(static_cast<uint8_t>(json["pixel"]["color"]));
config.groupMode = GroupMode(static_cast<uint8_t>(json["pixel"]["groupMode"]));
config.groupSize = json["pixel"]["groupSize"];
config.gamma = json["pixel"]["gamma"];
config.gammaVal = json["pixel"]["gammaVal"];
config.briteVal = json["pixel"]["briteVal"];
Expand Down Expand Up @@ -877,6 +889,8 @@ void serializeConfig(String &jsonString, bool pretty, bool creds) {
JsonObject &pixel = json.createNestedObject("pixel");
pixel["type"] = static_cast<uint8_t>(config.pixel_type);
pixel["color"] = static_cast<uint8_t>(config.pixel_color);
pixel["groupMode"] = static_cast<uint8_t>(config.groupMode);
pixel["groupSize"] = config.groupSize;
pixel["gamma"] = config.gamma;
pixel["gammaVal"] = config.gammaVal;
pixel["briteVal"] = config.briteVal;
Expand Down
47 changes: 40 additions & 7 deletions PixelDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,15 +257,47 @@ void ICACHE_RAM_ATTR PixelDriver::show() {
if (!pixdata) return;

if (type == PixelType::WS2811) {
uart_buffer = pixdata;
uart_buffer_tail = pixdata + szBuffer;
SET_PERI_REG_MASK(UART_INT_ENA(1), UART_TXFIFO_EMPTY_INT_ENA);
// Copy or group the pixels to the idle buffer
switch (mode) {
case GroupMode::grouped:
for (size_t led=0; led < szBuffer/3; led++) {
asyncdata[3*led+0] = pixdata[3*(led/interval)+0];
asyncdata[3*led+1] = pixdata[3*(led/interval)+1];
asyncdata[3*led+2] = pixdata[3*(led/interval)+2];
}
break;

case GroupMode::zigzag:
for (size_t led=0; led < szBuffer/3; led++) {
if (led/interval%2) { // Odd "zig"
int group = interval * (led / interval);
int this_led = group + interval - (led % interval) - 1;
asyncdata[3*led+0] = pixdata[3*this_led+0];
asyncdata[3*led+1] = pixdata[3*this_led+1];
asyncdata[3*led+2] = pixdata[3*this_led+2];
} else { // Evem "zag"
asyncdata[3*led+0] = pixdata[3*led+0];
asyncdata[3*led+1] = pixdata[3*led+1];
asyncdata[3*led+2] = pixdata[3*led+2];
}
}
break;

case GroupMode::disabled:
memcpy(asyncdata, pixdata, szBuffer);
break;

default:
memcpy(asyncdata, pixdata, szBuffer);
break;
}

uart_buffer = asyncdata;
uart_buffer_tail = asyncdata + szBuffer;

SET_PERI_REG_MASK(UART_INT_ENA(1), UART_TXFIFO_EMPTY_INT_ENA);
startTime = micros();

// Copy the pixels to the idle buffer and swap them
memcpy(asyncdata, pixdata, szBuffer);
std::swap(asyncdata, pixdata);
} else if (type == PixelType::GECE) {
uint32_t packet = 0;
uint32_t pTime = 0;
Expand Down Expand Up @@ -301,5 +333,6 @@ void ICACHE_RAM_ATTR PixelDriver::show() {
}

uint8_t* PixelDriver::getData() {
return pixdata;
return asyncdata; // data post grouping or zigzaging
// return pixdata;
}
19 changes: 17 additions & 2 deletions PixelDriver.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,13 @@ enum class PixelColor : uint8_t {
BGR
};

/* Group Mode */
enum class GroupMode : uint8_t {
disabled,
grouped,
zigzag
};

class PixelDriver {
public:
int begin();
Expand All @@ -102,14 +109,22 @@ class PixelDriver {
pixdata[address] = value;
}

/* Set output mode */
inline void setGroupMode(GroupMode _mode, uint16_t _interval) {
this->mode = _mode;
this->interval = _interval;
}

/* Drop the update if our refresh rate is too high */
inline bool canRefresh() {
return (micros() - startTime) >= refreshTime;
}

private:
PixelType type; // Pixel type
PixelColor color; // Color Order
PixelType type; // Pixel type
PixelColor color; // Color Order
GroupMode mode; // Output modifying mode - normal, grouped, zigzag
uint16_t interval; // Output modifying interval (in LEDs, not channels)
uint8_t pin; // Pin for bit-banging
uint8_t *pixdata; // Pixel buffer
uint8_t *asyncdata; // Async buffer
Expand Down
12 changes: 11 additions & 1 deletion html/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,19 @@
<div id="o_pixel" class="odiv hidden">
<legend class="esps-legend">Pixel Configuration</legend>
<div class="form-group">
<label class="control-label col-sm-2" for="p_count">Pixel Count</label>
<label class="control-label col-sm-2" for="p_count">Physical Pixels</label>
<div class="col-sm-10"><input type="text" class="form-control" id="p_count" name="p_count" placeholder="Enter number of pixels" onchange="refreshPixel()"></div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="p_groupMode">Output Grouping</label>
<div class="col-sm-10">
<select class="form-control" id="p_groupMode" name="p_groupMode"></select>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="p_groupsize">Group Size</label>
<div class="col-sm-10"><input type="text" class="form-control" id="p_groupsize" name="p_groupsize" placeholder="Group size of pixels" onchange="refreshPixel()"></div>
</div>
<div class="form-group">
<label class="control-label col-sm-2" for="p_type">Pixel Type</label>
<div class="col-sm-10">
Expand Down
4 changes: 4 additions & 0 deletions html/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -527,8 +527,10 @@ function getConfig(data) {
mode = 'pixel';
$('#o_pixel').removeClass('hidden');
$('#p_count').val(config.e131.channel_count / 3);
$('#p_groupsize').val(config.pixel.groupSize);
$('#p_type').val(config.pixel.type);
$('#p_color').val(config.pixel.color);
$('#p_groupMode').val(config.pixel.groupMode);
$('#p_gamma').prop('checked', config.pixel.gamma);
$('#p_gammaVal').val(config.pixel.gammaVal);
$('#p_briteVal').val(config.pixel.briteVal);
Expand Down Expand Up @@ -723,6 +725,8 @@ function submitConfig() {
'pixel': {
'type': parseInt($('#p_type').val()),
'color': parseInt($('#p_color').val()),
'groupSize': parseInt($('#p_groupsize').val()),
'groupMode': parseInt($('#p_groupMode').val()),
'gamma': $('#p_gamma').prop('checked'),
'gammaVal': parseFloat($('#p_gammaVal').val()),
'briteVal': parseFloat($('#p_briteVal').val())
Expand Down
6 changes: 6 additions & 0 deletions wshandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,12 @@ void procE(uint8_t *data, AsyncWebSocketClient *client) {
p_color["GBR"] = static_cast<uint8_t>(PixelColor::GBR);
p_color["BGR"] = static_cast<uint8_t>(PixelColor::BGR);

// Pixel Colors
JsonObject &p_groupMode = json.createNestedObject("p_groupMode");
p_groupMode["Disabled"] = static_cast<uint8_t>(GroupMode::disabled);
p_groupMode["Grouped"] = static_cast<uint8_t>(GroupMode::grouped);
p_groupMode["Zig-Zag"] = static_cast<uint8_t>(GroupMode::zigzag);

#elif defined (ESPS_MODE_SERIAL)
// Serial Protocols
JsonObject &s_proto = json.createNestedObject("s_proto");
Expand Down

0 comments on commit 8531ed4

Please sign in to comment.