Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(wip) AC minor patch cluster #2, and some goodies for 8266 #152

Draft
wants to merge 14 commits into
base: mdev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
717 changes: 717 additions & 0 deletions lib/ESP8266PWM/src/core_esp8266_waveform_pwm.cpp

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,8 @@ lib_deps =
ESPAsyncTCP @ 1.2.2
ESPAsyncUDP
;; makuna/NeoPixelBus @ 2.6.9 ;; WLEDMM use if you have problems with 2.7.5
makuna/NeoPixelBus @ 2.7.5
makuna/NeoPixelBus @ 2.7.9 ;; 2.7.9 has improved stability of bitbang outputs on 8266
ESP8266PWM
${env.lib_deps}

;; compatibilty flags - same as 0.14.0 which seems to work better on some 8266 boards. Not using PIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48
Expand Down
37 changes: 37 additions & 0 deletions tools/stress_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#!/bin/bash
# Some web server stress tests
#
# Perform a large number of parallel requests, stress testing the web server
# TODO: some kind of performance metrics

# Accepts three command line arguments:
# - first argument - mandatory - IP or hostname of target server
# - second argument - target type (optional)
# - third argument - xfer count (for replicated targets) (optional)
HOST=$1
declare -n TARGET_STR="${2:-JSON_LARGER}_TARGETS"
REPLICATE_COUNT=$(("${3:-10}"))

PARALLEL_MAX=${PARALLEL_MAX:-50}

CURL_ARGS="--compressed --parallel --parallel-immediate --parallel-max ${PARALLEL_MAX}"
CURL_PRINT_RESPONSE_ARGS="-w %{http_code}\n"

JSON_TARGETS=('json/state' 'json/info' 'json/si', 'json/palettes' 'json/fxdata' 'settings/s.js?p=2')
FILE_TARGETS=('' 'iro.js' 'rangetouch.js' 'settings' 'settings/wifi')
# Replicate one target many times
function replicate() {
printf "${1}?%d " $(seq 1 ${REPLICATE_COUNT})
}
read -a JSON_TINY_TARGETS <<< $(replicate "json/nodes")
read -a JSON_SMALL_TARGETS <<< $(replicate "json/info")
read -a JSON_LARGE_TARGETS <<< $(replicate "json/si")
read -a JSON_LARGER_TARGETS <<< $(replicate "json/fxdata")

# Expand target URLS to full arguments for curl
TARGETS=(${TARGET_STR[@]})
#echo "${TARGETS[@]}"
FULL_TGT_OPTIONS=$(printf "http://${HOST}/%s -o /dev/null " "${TARGETS[@]}")
#echo ${FULL_TGT_OPTIONS}

time curl ${CURL_ARGS} ${FULL_TGT_OPTIONS}
46 changes: 46 additions & 0 deletions tools/udp_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import numpy as np
import socket

class WledRealtimeClient:
def __init__(self, wled_controller_ip, num_pixels, udp_port=21324, max_pixels_per_packet=126):
self.wled_controller_ip = wled_controller_ip
self.num_pixels = num_pixels
self.udp_port = udp_port
self.max_pixels_per_packet = max_pixels_per_packet
self._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self._prev_pixels = np.full((3, self.num_pixels), 253, dtype=np.uint8)
self.pixels = np.full((3, self.num_pixels), 1, dtype=np.uint8)

def update(self):
# Truncate values and cast to integer
self.pixels = np.clip(self.pixels, 0, 255).astype(np.uint8)
p = np.copy(self.pixels)

idx = np.where(~np.all(p == self._prev_pixels, axis=0))[0]
num_pixels = len(idx)
n_packets = (num_pixels + self.max_pixels_per_packet - 1) // self.max_pixels_per_packet
idx_split = np.array_split(idx, n_packets)

header = bytes([1, 2]) # WARLS protocol header
for packet_indices in idx_split:
data = bytearray(header)
for i in packet_indices:
data.extend([i, *p[:, i]]) # Index and RGB values
self._sock.sendto(bytes(data), (self.wled_controller_ip, self.udp_port))

self._prev_pixels = np.copy(p)



################################## LED blink test ##################################
if __name__ == "__main__":
WLED_CONTROLLER_IP = "192.168.1.153"
NUM_PIXELS = 255 # Amount of LEDs on your strip
import time
wled = WledRealtimeClient(WLED_CONTROLLER_IP, NUM_PIXELS)
print('Starting LED blink test')
while True:
for i in range(NUM_PIXELS):
wled.pixels[1, i] = 255 if wled.pixels[1, i] == 0 else 0
wled.update()
time.sleep(.01)
6 changes: 3 additions & 3 deletions wled00/FX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4116,7 +4116,7 @@ uint16_t mode_pacifica()

// Increment the four "color index start" counters, one for each wave layer.
// Each is incremented at a different speed, and the speeds vary over time.
uint16_t sCIStart1 = SEGENV.aux0, sCIStart2 = SEGENV.aux1, sCIStart3 = SEGENV.step, sCIStart4 = SEGENV.step >> 16;
unsigned sCIStart1 = SEGENV.aux0, sCIStart2 = SEGENV.aux1, sCIStart3 = SEGENV.step & 0xFFFF, sCIStart4 = (SEGENV.step >> 16);
uint32_t deltams = (FRAMETIME >> 2) + ((FRAMETIME * SEGMENT.speed) >> 7);
uint64_t deltat = (strip.now >> 2) + ((strip.now * SEGMENT.speed) >> 7);
strip.now = deltat;
Expand All @@ -4131,7 +4131,7 @@ uint16_t mode_pacifica()
sCIStart3 -= (deltams1 * beatsin88(501,5,7));
sCIStart4 -= (deltams2 * beatsin88(257,4,6));
SEGENV.aux0 = sCIStart1; SEGENV.aux1 = sCIStart2;
SEGENV.step = sCIStart4; SEGENV.step = (SEGENV.step << 16) + sCIStart3;
SEGENV.step = (sCIStart4 << 16) | (sCIStart3 & 0xFFFF);

// Clear out the LED array to a dim background blue-green
//SEGMENT.fill(132618);
Expand Down Expand Up @@ -4162,7 +4162,7 @@ uint16_t mode_pacifica()
c.green = scale8(c.green, 200);
c |= CRGB( 2, 5, 7);

SEGMENT.setPixelColor(i, c.red, c.green, c.blue);
SEGMENT.setPixelColor(i, c);
}

strip.now = nowOld;
Expand Down
2 changes: 1 addition & 1 deletion wled00/const.h
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@

// string temp buffer (now stored in stack locally) // WLEDMM ...which is actually not the greatest design choice on ESP32
#ifdef ESP8266
#define SETTINGS_STACK_BUF_SIZE 2048
#define SETTINGS_STACK_BUF_SIZE 2560
#else
#if !defined(USERMOD_AUDIOREACTIVE)
#define SETTINGS_STACK_BUF_SIZE 3834 // WLEDMM added 696+32 bytes of margin (was 3096)
Expand Down
3 changes: 2 additions & 1 deletion wled00/data/update.htm
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
<h2>MoonMod WLED Software Update</h2>
<form method='POST' action='/update' id='uf' enctype='multipart/form-data' onsubmit="U()">
<span class="sip">##VERSION##</span><br> <!--WLEDMM: show bin name-->
Download the latest release: <a href="https://github.com/MoonModules/WLED/releases" target="_blank">
Download the latest binary:&nbsp;<a href="https://github.com/MoonModules/WLED/releases" target="_blank"
style="vertical-align: text-bottom; display: inline-flex;">
<img src="https://img.shields.io/github/release/MoonModules/WLED.svg?style=flat-square"></a><br>
<input type='file' name='update' required><br> <!--should have accept='.bin', but it prevents file upload from android app-->
<button type="submit">Update!</button><br>
Expand Down
5 changes: 2 additions & 3 deletions wled00/json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,11 +267,11 @@ bool deserializeSegment(JsonObject elem, byte it, byte presetId)
// lx parser
#ifdef WLED_ENABLE_LOXONE
int lx = elem[F("lx")] | -1;
if (lx > 0) {
if (lx >= 0) {
parseLxJson(lx, id, false);
}
int ly = elem[F("ly")] | -1;
if (ly > 0) {
if (ly >= 0) {
parseLxJson(ly, id, true);
}
#endif
Expand Down Expand Up @@ -573,7 +573,6 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
ps = presetCycCurr;
if (root["win"].isNull() && getVal(root["ps"], &ps, 0, 0) && ps > 0 && ps < 251 && ps != currentPreset) {
// b) preset ID only or preset that does not change state (use embedded cycling limits if they exist in getVal())
presetCycCurr = ps;
unloadPlaylist(); // applying a preset unloads the playlist
applyPreset(ps, callMode); // async load from file system (only preset ID was specified)
if (iAmGroot) suspendStripService = false; // WLEDMM release lock
Expand Down
12 changes: 11 additions & 1 deletion wled00/presets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,21 @@ void initPresetsFile()
f.close();
}

#if 0 // not used in WLEDMM
bool applyPresetFromPlaylist(byte index)
{
DEBUG_PRINTF_P(PSTR("Request to apply preset: %d\n"), index);
presetToApply = presetCycCurr = index;
callModeToApply = CALL_MODE_DIRECT_CHANGE;
return true;
}
#endif

bool applyPreset(byte index, byte callMode)
{
DEBUG_PRINT(F("Request to apply preset: "));
DEBUG_PRINTLN(index);
presetToApply = index;
presetToApply = presetCycCurr = index;
callModeToApply = callMode;
return true;
}
Expand Down
39 changes: 26 additions & 13 deletions wled00/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,21 +215,33 @@ bool isAsterisksOnly(const char* str, byte maxLen)
//threading/network callback details: https://github.com/Aircoookie/WLED/pull/2336#discussion_r762276994
bool requestJSONBufferLock(uint8_t module)
{
unsigned long now = millis();

while (jsonBufferLock && millis()-now < 1100) delay(1); // wait for fraction for buffer lock

#if defined(ARDUINO_ARCH_ESP32)
// Use a recursive mutex type in case our task is the one holding the JSON buffer.
// This can happen during large JSON web transactions. In this case, we continue immediately
// and then will return out below if the lock is still held.
if (xSemaphoreTakeRecursive(jsonBufferLockMutex, 1100) == pdFALSE) return false; // timed out waiting
#elif defined(ARDUINO_ARCH_ESP8266)
// If we're in system context, delay() won't return control to the user context, so there's
// no point in waiting.
if (can_yield()) {
unsigned long now = millis();
while (jsonBufferLock && (millis()-now < 1100)) delay(1); // wait for fraction for buffer lock
}
#else
#error Unsupported task framework - fix requestJSONBufferLock
#endif
// If the lock is still held - by us, or by another task
if (jsonBufferLock) {
USER_PRINT(F("ERROR: Locking JSON buffer failed! (still locked by "));
USER_PRINT(jsonBufferLock);
USER_PRINTLN(")");
return false; // waiting time-outed
DEBUG_PRINTF_P(PSTR("ERROR: Locking JSON buffer (%d) failed! (still locked by %d)\n"), module, jsonBufferLock);
#ifdef ARDUINO_ARCH_ESP32
xSemaphoreGiveRecursive(jsonBufferLockMutex);
#endif
return false;
}

jsonBufferLock = module ? module : 255;
DEBUG_PRINT(F("JSON buffer locked. ("));
DEBUG_PRINT(jsonBufferLock);
DEBUG_PRINTLN(")");
DEBUG_PRINTF_P(PSTR("JSON buffer locked. (%d)\n"), jsonBufferLock);
fileDoc = &doc; // used for applying presets (presets.cpp)
doc.clear();
return true;
Expand All @@ -238,11 +250,12 @@ bool requestJSONBufferLock(uint8_t module)

void releaseJSONBufferLock()
{
DEBUG_PRINT(F("JSON buffer released. ("));
DEBUG_PRINT(jsonBufferLock);
DEBUG_PRINTLN(")");
fileDoc = nullptr;
DEBUG_PRINTF_P(PSTR("JSON buffer released. (%d)\n"), jsonBufferLock);
jsonBufferLock = 0;
#ifdef ARDUINO_ARCH_ESP32
xSemaphoreGiveRecursive(jsonBufferLockMutex);
#endif
}


Expand Down
8 changes: 8 additions & 0 deletions wled00/wled.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ static int wledmm_get_tcp_stacksize(void) {
}
#endif


extern "C" void usePWMFixedNMI(); // PWM bugfix for 8266

/*
* Main WLED class implementation. Mostly initialization and connection logic
*/
Expand Down Expand Up @@ -634,6 +637,11 @@ void WLED::setup()
#else
DEBUG_PRINTLN(F("PSRAM not used."));
#endif

#ifdef ESP8266
usePWMFixedNMI(); // link the 8266 NMI fix
#endif

#endif
#if defined(ARDUINO_ARCH_ESP32)
if (strncmp("ESP32-PICO", ESP.getChipModel(), 10) == 0) { // WLEDMM detect pico board at runtime
Expand Down
10 changes: 8 additions & 2 deletions wled00/wled.h
Original file line number Diff line number Diff line change
Expand Up @@ -337,8 +337,6 @@ WLED_GLOBAL int8_t irPin _INIT(IRPIN);
constexpr uint8_t hardwareTX = 1;
#endif

//WLED_GLOBAL byte presetToApply _INIT(0);

WLED_GLOBAL char ntpServerName[33] _INIT("0.wled.pool.ntp.org"); // NTP server to use

// WiFi CONFIG (all these can be changed via web UI, no need to set them here)
Expand Down Expand Up @@ -374,7 +372,11 @@ WLED_GLOBAL byte bootPreset _INIT(0); // save preset to load
//if true, a segment per bus will be created on boot and LED settings save
//if false, only one segment spanning the total LEDs is created,
//but not on LED settings save if there is more than one segment currently
#ifdef WLED_AUTOSEGMENTS
WLED_GLOBAL bool autoSegments _INIT(true);
#else
WLED_GLOBAL bool autoSegments _INIT(false);
#endif
WLED_GLOBAL bool correctWB _INIT(false); // CCT color correction of RGB color
WLED_GLOBAL bool cctFromRgb _INIT(false); // CCT is calculated from RGB instead of using seg.cct
WLED_GLOBAL bool gammaCorrectCol _INIT(true ); // use gamma correction on colors // WLEDMM that's what you would think, but the code tells a different story.
Expand Down Expand Up @@ -822,6 +824,10 @@ WLED_GLOBAL StaticJsonDocument<JSON_BUFFER_SIZE> doc;
#endif // WLEDMM end
WLED_GLOBAL volatile uint8_t jsonBufferLock _INIT(0);

#if defined(ARDUINO_ARCH_ESP32)
WLED_GLOBAL SemaphoreHandle_t jsonBufferLockMutex _INIT(xSemaphoreCreateRecursiveMutex());
#endif

// enable additional debug output
//WLEDMM: switch between netdebug and serial
// cannot do this on -S2, due to buggy USBCDC serial driver: canUseSerial
Expand Down
5 changes: 4 additions & 1 deletion wled00/wled00.ino → wled00/wled_main.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
#include <Arduino.h>
/*
* WLED Arduino IDE compatibility file.
* (this is the former wled00.ino)
*
* Where has everything gone?
*
* In April 2020, the project's structure underwent a major change.
* In April 2020, the project's structure underwent a major change.
* We now use the platformIO build system, and building WLED in Arduino IDE is not supported any more.
* Global variables are now found in file "wled.h"
* Global function declarations are found in "fcn_declare.h"
*
Expand Down