diff --git a/wled00/FX.cpp b/wled00/FX.cpp index be19f00e..599dea0d 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -79,6 +79,24 @@ static float mapf(float x, float in_min, float in_max, float out_min, float out_ return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } +// more accurate integer version of map() - based on map3() proposed in https://forum.arduino.cc/t/how-map-loses-precision-and-how-to-fix-it/371026/3 +// rounding instead of truncation, better handling of inverted ranges +static long map2(long x, long in_min, long in_max, long out_min, long out_max) +{ + long out_range = out_max - out_min; + if (out_range > 0) out_range ++; + else if (out_range < 0) out_range --; + else return out_min; // output range is 0 + + long in_range = in_max - in_min; + if (in_range > 0) in_range++; + else if (in_range < 0) in_range --; + else return out_min; // input range is 0 - Result is actually infinity but long has no such thing. The least negative long is another choice. + + return ((x - in_min) * out_range) / in_range + out_min; +} + + // effect functions /* @@ -1986,7 +2004,7 @@ uint16_t mode_partyjerk() { if (SEGENV.aux1 > 254) { SEGENV.aux1 = 0; } - if (SEGENV.aux0 > map(SEGMENT.custom1, 0, 255, 0, 14)) { + if (SEGENV.aux0 > map2(SEGMENT.custom1, 0, 255, 0, 14)) { SEGENV.aux0 = 0; SEGENV.aux1++; } @@ -1995,7 +2013,7 @@ uint16_t mode_partyjerk() { uint16_t counter = 0; if (volumeSmth * 2 > (255 - SEGMENT.intensity)) { - speed = SEGMENT.speed * map(SEGMENT.custom2, 0, 255, 0, 100); + speed = SEGMENT.speed * map2(SEGMENT.custom2, 0, 255, 0, 100); } else { speed = SEGMENT.speed; }; @@ -4768,7 +4786,7 @@ uint16_t mode_aurora(void) { if(SEGENV.aux0 != SEGMENT.intensity || SEGENV.call == 0) { //Intensity slider changed or first call - SEGENV.aux1 = map(SEGMENT.intensity, 0, 255, 2, W_MAX_COUNT); + SEGENV.aux1 = map2(SEGMENT.intensity, 0, 255, 2, W_MAX_COUNT); SEGENV.aux0 = SEGMENT.intensity; if(!SEGENV.allocateData(sizeof(AuroraWave) * SEGENV.aux1)) { // 26 on 32 segment ESP32, 9 on 16 segment ESP8266 @@ -5187,9 +5205,9 @@ uint16_t mode_2Dgameoflife(void) { // Written by Ewoud Wijma, inspired by https: bool allColors = SEGMENT.check1; bool overlayBG = SEGMENT.check2; bool wrap = SEGMENT.check3; - byte blur = map(SEGMENT.custom1, 0, 255, 255, 0); + byte blur = map2(SEGMENT.custom1, 0, 255, 255, 0); bool bgBlendMode = SEGMENT.custom1 > 220 && !overlayBG; // if blur is high and not overlaying, use bg blend mode - byte bgBlur = map(SEGMENT.custom1 - 220, 0, 35, 255, 128); + byte bgBlur = map2(SEGMENT.custom1 - 220, 0, 35, 255, 128); uint32_t bgColor = SEGCOLOR(1); uint32_t color = allColors ? random16() * random16() : SEGMENT.color_from_palette(0, false, PALETTE_SOLID_WRAP, 0); uint16_t cIndex; @@ -5748,7 +5766,7 @@ uint16_t mode_2DPolarLights(void) { // By: Kostyantyn Matviyevskyy https } float adjustHeight = mapf(rows, 8, maxRows, 28, minScale); // maybe use mapf() ??? // WLEDMM yes! - uint16_t adjScale = map(cols, 8, 64, 310, 63); + uint16_t adjScale = map2(cols, 8, 64, 310, 63); adjustHeight = max(min(adjustHeight, 28.0f), minScale); // WLEDMM bugfix for larger fixtures adjScale = max(min(adjScale, uint16_t(310)), uint16_t(63)); // WLEDMM @@ -5767,8 +5785,8 @@ uint16_t mode_2DPolarLights(void) { // By: Kostyantyn Matviyevskyy https } } */ - uint16_t _scale = map(SEGMENT.intensity, 0, 255, 30, adjScale); - byte _speed = map(SEGMENT.speed, 0, 255, 128, 16); + uint16_t _scale = map2(SEGMENT.intensity, 0, 255, 30, adjScale); + byte _speed = map2(SEGMENT.speed, 0, 255, 128, 16); //WLEDMM add SuperSync control uint16_t xStart, xEnd, yStart, yEnd; @@ -6439,6 +6457,10 @@ static const char _data_FX_MODE_2DDRIFTROSE[] PROGMEM = "Drift Rose@Fade,Blur;;; volumeSmth = *(float*) um_data->u_data[0]; volumeRaw = *(int16_t*) um_data->u_data[1]; fftResult = (uint8_t*) um_data->u_data[2]; +or + uint8_t fftResult[NUM_GEQ_CHANNELS] = {0}; + if (um_data->u_data != nullptr) memcpy(fftResult, um_data->u_data[2], sizeof(fftResult)); // WLEDMM to buffer curent values + samplePeak = *(uint8_t*) um_data->u_data[3]; FFT_MajorPeak = *(float*) um_data->u_data[4]; my_magnitude = *(float*) um_data->u_data[5]; @@ -6456,6 +6478,8 @@ static const char _data_FX_MODE_2DDRIFTROSE[] PROGMEM = "Drift Rose@Fade,Blur;;; // a few constants needed for AudioReactive effects +#define NUM_GEQ_CHANNELS 16 // number of audioreactive frequency channels. + // for 22Khz sampling #define MIN_FREQUENCY 80 // 80 HZ - due to lower resolution #define MIN_FREQ_LOG10 1.90309f // log10(MIN_FREQUENCY) @@ -7018,7 +7042,7 @@ uint16_t mode_noisemeter(void) { // Noisemeter. By Andrew Tuline. if (SEGENV.call == 0) {SEGENV.setUpLeds(); SEGMENT.fill(BLACK);} // WLEDMM use lossless getPixelColor() //uint8_t fadeRate = map(SEGMENT.speed,0,255,224,255); - uint8_t fadeRate = map(SEGMENT.speed,0,255,200,254); + uint8_t fadeRate = map2(SEGMENT.speed,0,255,200,254); SEGMENT.fade_out(fadeRate); float tmpSound2 = volumeRaw * 2.0 * (float)SEGMENT.intensity / 255.0; @@ -7128,7 +7152,7 @@ static const char _data_FX_MODE_PLASMOID[] PROGMEM = "Plasmoid@Phase,# of pixels uint16_t mode_puddlepeak(void) { // Puddlepeak. By Andrew Tuline. uint16_t size = 0; - uint8_t fadeVal = map(SEGMENT.speed,0,255, 224, 254); + uint8_t fadeVal = map2(SEGMENT.speed,0,255, 224, 254); uint16_t pos = random16(SEGLEN); // Set a random starting position. um_data_t *um_data; @@ -7174,7 +7198,7 @@ static const char _data_FX_MODE_PUDDLEPEAK[] PROGMEM = "Puddlepeak@Fade rate,Pud ////////////////////// uint16_t mode_puddles(void) { // Puddles. By Andrew Tuline. uint16_t size = 0; - uint8_t fadeVal = map(SEGMENT.speed, 0, 255, 224, 254); + uint8_t fadeVal = map2(SEGMENT.speed, 0, 255, 224, 254); uint16_t pos = random16(SEGLEN); // Set a random starting position. if (SEGENV.call == 0) { @@ -7380,7 +7404,7 @@ uint16_t mode_DJLight(void) { // Written by Stefan Petrick, Ad //if (color.getLuma() > 12) color.maximizeBrightness(); // for testing //SEGMENT.setPixelColor(mid, color.fadeToBlackBy(map(fftResult[4], 0, 255, 255, 4))); // 0.13.x fade -> 180hz-260hz - uint8_t fadeVal = map(fftResult[3], 0, 255, 255, 4); // 0.14.x fade -> 216hz-301hz + uint8_t fadeVal = map2(fftResult[3], 0, 255, 255, 4); // 0.14.x fade -> 216hz-301hz if (SEGENV.check1) fadeVal = constrain(fadeVal, 0, 176); // "candy factory" mode - avoid complete fade-out SEGMENT.setPixelColor(mid, color.fadeToBlackBy(fadeVal)); @@ -7684,7 +7708,8 @@ uint16_t mode_noisemove(void) { // Noisemove. By: Andrew Tuli // add support for no audio um_data = simulateSound(SEGMENT.soundSim); } - uint8_t *fftResult = (uint8_t*)um_data->u_data[2]; + uint8_t fftResult[NUM_GEQ_CHANNELS] = {0}; + if (um_data->u_data != nullptr) memcpy(fftResult, um_data->u_data[2], sizeof(fftResult)); // WLEDMM buffer curent values if (SEGENV.call == 0) { SEGENV.setUpLeds(); // WLEDMM use lossless getPixelColor() @@ -7694,11 +7719,11 @@ uint16_t mode_noisemove(void) { // Noisemove. By: Andrew Tuli int fadeoutDelay = (256 - SEGMENT.speed) / 96; if ((fadeoutDelay <= 1 ) || ((SEGENV.call % fadeoutDelay) == 0)) SEGMENT.fadeToBlackBy(4+ SEGMENT.speed/4); - uint8_t numBins = map(SEGMENT.intensity,0,255,0,16); // Map slider to fftResult bins. + uint8_t numBins = map2(SEGMENT.intensity,0,255,0,16); // Map slider to fftResult bins. for (int i=0; iRO
DMX TX: DI
DMX Enable: RE+DE
-
DMX Port:
+ DMX Port:

This firmware build does not include DMX Input support.
diff --git a/wled00/dmx_input.cpp b/wled00/dmx_input.cpp index 77ebc859..821481e5 100644 --- a/wled00/dmx_input.cpp +++ b/wled00/dmx_input.cpp @@ -106,6 +106,7 @@ bool DMXInput::installDriver() { const auto config = createConfig(); + USER_PRINTF("DMX port: %u\n", inputPortNum); if (!dmx_driver_install(inputPortNum, &config, DMX_INTR_FLAGS_DEFAULT)) { USER_PRINTF("Error: Failed to install dmx driver\n"); return false; @@ -134,7 +135,7 @@ void DMXInput::init(uint8_t rxPin, uint8_t txPin, uint8_t enPin, uint8_t inputPo // } #endif - if (inputPortNum < 3 && inputPortNum > 0) { + if (inputPortNum <= (SOC_UART_NUM - 1) && inputPortNum > 0) { this->inputPortNum = inputPortNum; } else {