diff --git a/wled00/FX.cpp b/wled00/FX.cpp index b6d26532e..5e43430ae 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -211,7 +211,7 @@ uint16_t color_wipe(bool rev, bool useRandomColors) { if (useRandomColors) { if (SEGENV.call == 0) { - SEGENV.aux0 = random8(); + SEGENV.aux0 = hw_random8(); SEGENV.step = 3; } if (SEGENV.step == 1) { //if flag set, change to new random color @@ -303,7 +303,7 @@ uint16_t mode_random_color(void) { } if (SEGENV.call == 0) { - SEGENV.aux0 = random8(); + SEGENV.aux0 = hw_random8(); SEGENV.step = 2; } if (it != SEGENV.step) //new color @@ -328,7 +328,7 @@ uint16_t mode_dynamic(void) { if(SEGENV.call == 0) { //SEGMENT.fill(BLACK); - for (unsigned i = 0; i < SEGLEN; i++) SEGENV.data[i] = random8(); + for (unsigned i = 0; i < SEGLEN; i++) SEGENV.data[i] = hw_random8(); } uint32_t cycleTime = 50 + (255 - SEGMENT.speed)*15; @@ -336,7 +336,7 @@ uint16_t mode_dynamic(void) { if (it != SEGENV.step && SEGMENT.speed != 0) //new color { for (unsigned i = 0; i < SEGLEN; i++) { - if (random8() <= SEGMENT.intensity) SEGENV.data[i] = random8(); // random color index + if (hw_random8() <= SEGMENT.intensity) SEGENV.data[i] = hw_random8(); // random color index } SEGENV.step = it; } @@ -617,7 +617,7 @@ uint16_t mode_twinkle(void) { if (SEGENV.aux0 >= maxOn) { SEGENV.aux0 = 0; - SEGENV.aux1 = random16(); //new seed for our PRNG + SEGENV.aux1 = hw_random(); //new seed for our PRNG } SEGENV.aux0++; SEGENV.step = it; @@ -651,9 +651,9 @@ uint16_t dissolve(uint32_t color) { } for (unsigned j = 0; j <= SEGLEN / 15; j++) { - if (random8() <= SEGMENT.intensity) { + if (hw_random8() <= SEGMENT.intensity) { for (size_t times = 0; times < 10; times++) { //attempt to spawn a new pixel 10 times - unsigned i = random16(SEGLEN); + unsigned i = hw_random16(SEGLEN); unsigned index = i >> 3; unsigned bitNum = i & 0x07; bool fadeUp = bitRead(SEGENV.data[index], bitNum); @@ -693,7 +693,7 @@ uint16_t dissolve(uint32_t color) { * Blink several LEDs on and then off */ uint16_t mode_dissolve(void) { - return dissolve(SEGMENT.check1 ? SEGMENT.color_wheel(random8()) : SEGCOLOR(0)); + return dissolve(SEGMENT.check1 ? SEGMENT.color_wheel(hw_random8()) : SEGCOLOR(0)); } static const char _data_FX_MODE_DISSOLVE[] PROGMEM = "Dissolve@Repeat speed,Dissolve speed,,,,Random;!,!;!"; @@ -702,7 +702,7 @@ static const char _data_FX_MODE_DISSOLVE[] PROGMEM = "Dissolve@Repeat speed,Diss * Blink several LEDs on and then off in random colors */ uint16_t mode_dissolve_random(void) { - return dissolve(SEGMENT.color_wheel(random8())); + return dissolve(SEGMENT.color_wheel(hw_random8())); } static const char _data_FX_MODE_DISSOLVE_RANDOM[] PROGMEM = "Dissolve Rnd@Repeat speed,Dissolve speed;,!;!"; @@ -719,7 +719,7 @@ uint16_t mode_sparkle(void) { uint32_t it = strip.now / cycleTime; if (it != SEGENV.step) { - SEGENV.aux0 = random16(SEGLEN); // aux0 stores the random led index + SEGENV.aux0 = hw_random16(SEGLEN); // aux0 stores the random led index SEGENV.step = it; } @@ -739,8 +739,8 @@ uint16_t mode_flash_sparkle(void) { } if (strip.now - SEGENV.aux0 > SEGENV.step) { - if(random8((255-SEGMENT.intensity) >> 4) == 0) { - SEGMENT.setPixelColor(random16(SEGLEN), SEGCOLOR(1)); //flash + if(hw_random8((255-SEGMENT.intensity) >> 4) == 0) { + SEGMENT.setPixelColor(hw_random16(SEGLEN), SEGCOLOR(1)); //flash } SEGENV.step = strip.now; SEGENV.aux0 = 255-SEGMENT.speed; @@ -760,10 +760,10 @@ uint16_t mode_hyper_sparkle(void) { } if (strip.now - SEGENV.aux0 > SEGENV.step) { - if (random8((255-SEGMENT.intensity) >> 4) == 0) { + if (hw_random8((255-SEGMENT.intensity) >> 4) == 0) { int len = max(1, (int)SEGLEN/3); for (int i = 0; i < len; i++) { - SEGMENT.setPixelColor(random16(SEGLEN), SEGCOLOR(1)); + SEGMENT.setPixelColor(hw_random16(SEGLEN), SEGCOLOR(1)); } } SEGENV.step = strip.now; @@ -1133,7 +1133,7 @@ static const char _data_FX_MODE_RUNNING_COLOR[] PROGMEM = "Chase 2@!,Width;!,!;! uint16_t mode_running_random(void) { uint32_t cycleTime = 25 + (3 * (uint32_t)(255 - SEGMENT.speed)); uint32_t it = strip.now / cycleTime; - if (SEGENV.call == 0) SEGENV.aux0 = random16(); // random seed for PRNG on start + if (SEGENV.call == 0) SEGENV.aux0 = hw_random(); // random seed for PRNG on start unsigned zoneSize = ((255-SEGMENT.intensity) >> 4) +1; uint16_t PRNG16 = SEGENV.aux0; @@ -1278,11 +1278,11 @@ uint16_t mode_fireworks() { } for (int i=0; i> 1)) == 0) { - uint16_t index = random16(width*height); + if (hw_random8(129 - (SEGMENT.intensity >> 1)) == 0) { + uint16_t index = hw_random16(width*height); x = index % width; y = index / width; - uint32_t col = SEGMENT.color_from_palette(random8(), false, false, 0); + uint32_t col = SEGMENT.color_from_palette(hw_random8(), false, false, 0); if (SEGMENT.is2D()) SEGMENT.setPixelColorXY(x, y, col); else SEGMENT.setPixelColor(index, col); SEGENV.aux1 = SEGENV.aux0; // old spark @@ -1344,7 +1344,7 @@ uint16_t mode_fire_flicker(void) { byte lum = (SEGMENT.palette == 0) ? MAX(w, MAX(r, MAX(g, b))) : 255; lum /= (((256-SEGMENT.intensity)/16)+1); for (unsigned i = 0; i < SEGLEN; i++) { - byte flicker = random8(lum); + byte flicker = hw_random8(lum); if (SEGMENT.palette == 0) { SEGMENT.setPixelColor(i, MAX(r - flicker, 0), MAX(g - flicker, 0), MAX(b - flicker, 0), MAX(w - flicker, 0)); } else { @@ -1475,11 +1475,11 @@ uint16_t mode_fairy() { if (stateTime > flashers[f].stateDur * 10) { flashers[f].stateOn = !flashers[f].stateOn; if (flashers[f].stateOn) { - flashers[f].stateDur = 12 + random8(12 + ((255 - SEGMENT.speed) >> 2)); //*10, 250ms to 1250ms + flashers[f].stateDur = 12 + hw_random8(12 + ((255 - SEGMENT.speed) >> 2)); //*10, 250ms to 1250ms } else { - flashers[f].stateDur = 20 + random8(6 + ((255 - SEGMENT.speed) >> 2)); //*10, 250ms to 1250ms + flashers[f].stateDur = 20 + hw_random8(6 + ((255 - SEGMENT.speed) >> 2)); //*10, 250ms to 1250ms } - //flashers[f].stateDur = 51 + random8(2 + ((255 - SEGMENT.speed) >> 1)); + //flashers[f].stateDur = 51 + hw_random8(2 + ((255 - SEGMENT.speed) >> 1)); flashers[f].stateStart = now16; if (stateTime < 255) { flashers[f].stateStart -= 255 -stateTime; //start early to get correct bri @@ -1535,15 +1535,15 @@ uint16_t mode_fairytwinkle() { flashers[f].stateOn = !flashers[f].stateOn; bool init = !flashers[f].stateDur; if (flashers[f].stateOn) { - flashers[f].stateDur = riseFallTime/100 + ((255 - SEGMENT.intensity) >> 2) + random8(12 + ((255 - SEGMENT.intensity) >> 1)) +1; + flashers[f].stateDur = riseFallTime/100 + ((255 - SEGMENT.intensity) >> 2) + hw_random8(12 + ((255 - SEGMENT.intensity) >> 1)) +1; } else { - flashers[f].stateDur = riseFallTime/100 + random8(3 + ((255 - SEGMENT.speed) >> 6)) +1; + flashers[f].stateDur = riseFallTime/100 + hw_random8(3 + ((255 - SEGMENT.speed) >> 6)) +1; } flashers[f].stateStart = now16; stateTime = 0; if (init) { flashers[f].stateStart -= riseFallTime; //start lit - flashers[f].stateDur = riseFallTime/100 + random8(12 + ((255 - SEGMENT.intensity) >> 1)) +5; //fire up a little quicker + flashers[f].stateDur = riseFallTime/100 + hw_random8(12 + ((255 - SEGMENT.intensity) >> 1)) +5; //fire up a little quicker stateTime = riseFallTime; } } @@ -1611,13 +1611,13 @@ uint16_t mode_icu(void) { SEGMENT.setPixelColor(dest + SEGLEN/space, col); if(SEGENV.aux0 == dest) { // pause between eye movements - if(random8(6) == 0) { // blink once in a while + if(hw_random8(6) == 0) { // blink once in a while SEGMENT.setPixelColor(dest, SEGCOLOR(1)); SEGMENT.setPixelColor(dest + SEGLEN/space, SEGCOLOR(1)); return 200; } - SEGENV.aux0 = random16(SEGLEN-SEGLEN/space); - return 1000 + random16(2000); + SEGENV.aux0 = hw_random16(SEGLEN-SEGLEN/space); + return 1000 + hw_random16(2000); } if(SEGENV.aux0 > SEGENV.step) { @@ -1747,7 +1747,7 @@ uint16_t mode_multi_comet(void) { } comets[i]++; } else { - if(!random16(SEGLEN)) { + if(!hw_random16(SEGLEN)) { comets[i] = 0; } } @@ -1831,12 +1831,12 @@ uint16_t mode_oscillate(void) { oscillators[i].pos = 0; oscillators[i].dir = 1; // make bigger steps for faster speeds - oscillators[i].speed = SEGMENT.speed > 100 ? random8(2, 4):random8(1, 3); + oscillators[i].speed = SEGMENT.speed > 100 ? hw_random8(2, 4):hw_random8(1, 3); } if((oscillators[i].dir == 1) && (oscillators[i].pos >= (SEGLEN - 1))) { oscillators[i].pos = SEGLEN - 1; oscillators[i].dir = -1; - oscillators[i].speed = SEGMENT.speed > 100 ? random8(2, 4):random8(1, 3); + oscillators[i].speed = SEGMENT.speed > 100 ? hw_random8(2, 4):hw_random8(1, 3); } } @@ -1859,13 +1859,13 @@ static const char _data_FX_MODE_OSCILLATE[] PROGMEM = "Oscillate"; //TODO uint16_t mode_lightning(void) { if (SEGLEN == 1) return mode_static(); - unsigned ledstart = random16(SEGLEN); // Determine starting location of flash - unsigned ledlen = 1 + random16(SEGLEN -ledstart); // Determine length of flash (not to go beyond NUM_LEDS-1) - uint8_t bri = 255/random8(1, 3); + unsigned ledstart = hw_random16(SEGLEN); // Determine starting location of flash + unsigned ledlen = 1 + hw_random16(SEGLEN -ledstart); // Determine length of flash (not to go beyond NUM_LEDS-1) + uint8_t bri = 255/hw_random8(1, 3); if (SEGENV.aux1 == 0) //init, leader flash { - SEGENV.aux1 = random8(4, 4 + SEGMENT.intensity/20); //number of flashes + SEGENV.aux1 = hw_random8(4, 4 + SEGMENT.intensity/20); //number of flashes SEGENV.aux1 *= 2; bri = 52; //leader has lower brightness @@ -1882,15 +1882,15 @@ uint16_t mode_lightning(void) { SEGENV.aux1--; SEGENV.step = strip.now; - //return random8(4, 10); // each flash only lasts one frame/every 24ms... originally 4-10 milliseconds + //return hw_random8(4, 10); // each flash only lasts one frame/every 24ms... originally 4-10 milliseconds } else { if (strip.now - SEGENV.step > SEGENV.aux0) { SEGENV.aux1--; if (SEGENV.aux1 < 2) SEGENV.aux1 = 0; - SEGENV.aux0 = (50 + random8(100)); //delay between flashes + SEGENV.aux0 = (50 + hw_random8(100)); //delay between flashes if (SEGENV.aux1 == 2) { - SEGENV.aux0 = (random8(255 - SEGMENT.speed) * 100); // delay between strikes + SEGENV.aux0 = (hw_random8(255 - SEGMENT.speed) * 100); // delay between strikes } SEGENV.step = strip.now; } @@ -2103,7 +2103,7 @@ uint16_t mode_fire_2012() { // Step 1. Cool down every cell a little for (unsigned i = 0; i < SEGLEN; i++) { - uint8_t cool = (it != SEGENV.step) ? random8((((20 + SEGMENT.speed/3) * 16) / SEGLEN)+2) : random8(4); + uint8_t cool = (it != SEGENV.step) ? hw_random8((((20 + SEGMENT.speed/3) * 16) / SEGLEN)+2) : hw_random8(4); uint8_t minTemp = (i> 3; unsigned bitNum = i & 0x07; bitWrite(SEGENV.data[index], bitNum, true); - SEGMENT.setPixelColor(i, ColorFromPalette(SEGPALETTE, random8(), 64, NOBLEND)); + SEGMENT.setPixelColor(i, ColorFromPalette(SEGPALETTE, hw_random8(), 64, NOBLEND)); break; //only spawn 1 new pixel per frame per 50 LEDs } } @@ -2386,14 +2386,14 @@ uint16_t mode_meteor() { // fade all leds to colors[1] in LEDs one step for (unsigned i = 0; i < SEGLEN; i++) { uint32_t col; - if (random8() <= 255 - SEGMENT.intensity) { + if (hw_random8() <= 255 - SEGMENT.intensity) { if(meteorSmooth) { - int change = trail[i] + 4 - random8(24); //change each time between -20 and +4 + int change = trail[i] + 4 - hw_random8(24); //change each time between -20 and +4 trail[i] = constrain(change, 0, max); col = SEGMENT.check1 ? SEGMENT.color_from_palette(i, true, false, 0, trail[i]) : SEGMENT.color_from_palette(trail[i], false, true, 255); } else { - trail[i] = scale8(trail[i], 128 + random8(127)); + trail[i] = scale8(trail[i], 128 + hw_random8(127)); int index = trail[i]; int idx = 255; int bri = SEGMENT.palette==35 || SEGMENT.palette==36 ? 255 : trail[i]; @@ -2410,8 +2410,8 @@ uint16_t mode_meteor() { // draw meteor for (unsigned j = 0; j < meteorSize; j++) { - unsigned index = (meteorstart + j) % SEGLEN; - if(meteorSmooth) { + unsigned index = (meteorstart + j) % SEGLEN; + if(meteorSmooth) { trail[index] = max; uint32_t col = SEGMENT.check1 ? SEGMENT.color_from_palette(index, true, false, 0, trail[index]) : SEGMENT.color_from_palette(trail[index], false, true, 255); SEGMENT.setPixelColor(index, col); @@ -2422,7 +2422,7 @@ uint16_t mode_meteor() { if (!SEGMENT.check1) { i = map(index,0,SEGLEN,0,max); idx = 0; - } + } uint32_t col = SEGMENT.color_from_palette(i, false, false, idx, 255); // full brightness SEGMENT.setPixelColor(index, col); } @@ -2523,10 +2523,10 @@ static uint16_t ripple_base(uint8_t blurAmount = 0) { ripplestate += rippledecay; ripples[i].state = (ripplestate > 254) ? 0 : ripplestate; } else {//randomly create new wave - if (random16(IBN + 10000) <= (SEGMENT.intensity >> (SEGMENT.is2D()*3))) { + if (hw_random16(IBN + 10000) <= (SEGMENT.intensity >> (SEGMENT.is2D()*3))) { ripples[i].state = 1; - ripples[i].pos = SEGMENT.is2D() ? ((random8(SEG_W)<<8) | (random8(SEG_H))) : random16(SEGLEN); - ripples[i].color = random8(); //color + ripples[i].pos = SEGMENT.is2D() ? ((hw_random8(SEG_W)<<8) | (hw_random8(SEG_H))) : hw_random16(SEGLEN); + ripples[i].color = hw_random8(); //color } } } @@ -2551,11 +2551,11 @@ static const char _data_FX_MODE_RIPPLE[] PROGMEM = "Ripple@!,Wave #,Blur,,,,Over uint16_t mode_ripple_rainbow(void) { if (SEGLEN == 1) return mode_static(); if (SEGENV.call ==0) { - SEGENV.aux0 = random8(); - SEGENV.aux1 = random8(); + SEGENV.aux0 = hw_random8(); + SEGENV.aux1 = hw_random8(); } if (SEGENV.aux0 == SEGENV.aux1) { - SEGENV.aux1 = random8(); + SEGENV.aux1 = hw_random8(); } else if (SEGENV.aux1 > SEGENV.aux0) { SEGENV.aux0++; } else { @@ -2750,10 +2750,10 @@ uint16_t mode_halloween_eyes() // - select a duration // - immediately switch to eyes on state. - data.startPos = random16(0, maxWidth - eyeLength - 1); - data.color = random8(); - if (strip.isMatrix) SEGMENT.offset = random16(SEG_H-1); // a hack: reuse offset since it is not used in matrices - duration = 128u + random16(SEGMENT.intensity*64u); + data.startPos = hw_random16(0, maxWidth - eyeLength - 1); + data.color = hw_random8(); + if (strip.isMatrix) SEGMENT.offset = hw_random16(SEG_H-1); // a hack: reuse offset since it is not used in matrices + duration = 128u + hw_random16(SEGMENT.intensity*64u); data.duration = duration; data.state = eyeState::on; [[fallthrough]]; @@ -2780,11 +2780,11 @@ uint16_t mode_halloween_eyes() } else if (elapsedTime > minimumOnTimeBegin) { const uint32_t remainingTime = (elapsedTime >= duration) ? 0u : (duration - elapsedTime); if (remainingTime > minimumOnTimeEnd) { - if (random8() < 4u) + if (hw_random8() < 4u) { c = backgroundColor; data.state = eyeState::blink; - data.blinkEndTime = strip.now + random8(8, 128); + data.blinkEndTime = strip.now + hw_random8(8, 128); } } } @@ -2818,7 +2818,7 @@ uint16_t mode_halloween_eyes() // - immediately switch to eyes-off state const unsigned eyeOffTimeBase = SEGMENT.speed*128u; - duration = eyeOffTimeBase + random16(eyeOffTimeBase); + duration = eyeOffTimeBase + hw_random16(eyeOffTimeBase); data.duration = duration; data.state = eyeState::off; [[fallthrough]]; @@ -3008,7 +3008,7 @@ uint16_t mode_bouncing_balls(void) { balls[i].lastBounceTime = time; if (balls[i].impactVelocity < 0.015f) { - float impactVelocityStart = sqrtf(-2.0f * gravity) * random8(5,11)/10.0f; // randomize impact velocity + float impactVelocityStart = sqrtf(-2.0f * gravity) * hw_random8(5,11)/10.0f; // randomize impact velocity balls[i].impactVelocity = impactVelocityStart; } } else if (balls[i].height > 1.0f) { @@ -3071,10 +3071,10 @@ static uint16_t rolling_balls(void) { SEGMENT.fill(hasCol2 ? BLACK : SEGCOLOR(1)); // start clean for (unsigned i = 0; i < maxNumBalls; i++) { balls[i].lastBounceUpdate = strip.now; - balls[i].velocity = 20.0f * float(random16(1000, 10000))/10000.0f; // number from 1 to 10 - if (random8()<128) balls[i].velocity = -balls[i].velocity; // 50% chance of reverse direction - balls[i].height = (float(random16(0, 10000)) / 10000.0f); // from 0. to 1. - balls[i].mass = (float(random16(1000, 10000)) / 10000.0f); // from .1 to 1. + balls[i].velocity = 20.0f * float(hw_random16(1000, 10000))/10000.0f; // number from 1 to 10 + if (hw_random8()<128) balls[i].velocity = -balls[i].velocity; // 50% chance of reverse direction + balls[i].height = (float(hw_random16(0, 10000)) / 10000.0f); // from 0. to 1. + balls[i].mass = (float(hw_random16(1000, 10000)) / 10000.0f); // from .1 to 1. } } @@ -3090,7 +3090,7 @@ static uint16_t rolling_balls(void) { float thisHeight = balls[i].height + balls[i].velocity * timeSinceLastUpdate; // this method keeps higher resolution // test if intensity level was increased and some balls are way off the track then put them back if (thisHeight < -0.5f || thisHeight > 1.5f) { - thisHeight = balls[i].height = (float(random16(0, 10000)) / 10000.0f); // from 0. to 1. + thisHeight = balls[i].height = (float(hw_random16(0, 10000)) / 10000.0f); // from 0. to 1. balls[i].lastBounceUpdate = strip.now; } // check if reached ends of the strip @@ -3200,7 +3200,7 @@ static const char _data_FX_MODE_SINELON_RAINBOW[] PROGMEM = "Sinelon Rainbow@!,T // utility function that will add random glitter to SEGMENT void glitter_base(uint8_t intensity, uint32_t col = ULTRAWHITE) { - if (intensity > random8()) SEGMENT.setPixelColor(random16(SEGLEN), col); + if (intensity > hw_random8()) SEGMENT.setPixelColor(hw_random16(SEGLEN), col); } //Glitter with palette background, inspired by https://gist.github.com/kriegsman/062e10f7f07ba8518af6 @@ -3277,18 +3277,18 @@ uint16_t mode_popcorn(void) { popcorn[i].pos += popcorn[i].vel; popcorn[i].vel += gravity; } else { // if kernel is inactive, randomly pop it - if (random8() < 2) { // POP!!! + if (hw_random8() < 2) { // POP!!! popcorn[i].pos = 0.01f; - unsigned peakHeight = 128 + random8(128); //0-255 + unsigned peakHeight = 128 + hw_random8(128); //0-255 peakHeight = (peakHeight * (SEGLEN -1)) >> 8; popcorn[i].vel = sqrtf(-2.0f * gravity * peakHeight); if (SEGMENT.palette) { - popcorn[i].colIndex = random8(); + popcorn[i].colIndex = hw_random8(); } else { - byte col = random8(0, NUM_COLORS); + byte col = hw_random8(0, NUM_COLORS); if (!SEGCOLOR(2) || !SEGCOLOR(col)) col = 0; popcorn[i].colIndex = col; } @@ -3350,7 +3350,7 @@ uint16_t candle(bool multi) s = SEGENV.data[d]; s_target = SEGENV.data[d+1]; fadeStep = SEGENV.data[d+2]; } if (fadeStep == 0) { //init vals - s = 128; s_target = 130 + random8(4); fadeStep = 1; + s = 128; s_target = 130 + hw_random8(4); fadeStep = 1; } bool newTarget = false; @@ -3363,8 +3363,8 @@ uint16_t candle(bool multi) } if (newTarget) { - s_target = random8(rndval) + random8(rndval); //between 0 and rndval*2 -2 = 252 - if (s_target < (rndval >> 1)) s_target = (rndval >> 1) + random8(rndval); + s_target = hw_random8(rndval) + hw_random8(rndval); //between 0 and rndval*2 -2 = 252 + if (s_target < (rndval >> 1)) s_target = (rndval >> 1) + hw_random8(rndval); unsigned offset = (255 - valrange); s_target += offset; @@ -3450,19 +3450,19 @@ uint16_t mode_starburst(void) { for (unsigned j = 0; j < numStars; j++) { // speed to adjust chance of a burst, max is nearly always. - if (random8((144-(SEGMENT.speed >> 1))) == 0 && stars[j].birth == 0) + if (hw_random8((144-(SEGMENT.speed >> 1))) == 0 && stars[j].birth == 0) { // Pick a random color and location. - unsigned startPos = random16(SEGLEN-1); - float multiplier = (float)(random8())/255.0f * 1.0f; + unsigned startPos = hw_random16(SEGLEN-1); + float multiplier = (float)(hw_random8())/255.0f * 1.0f; - stars[j].color = CRGB(SEGMENT.color_wheel(random8())); + stars[j].color = CRGB(SEGMENT.color_wheel(hw_random8())); stars[j].pos = startPos; - stars[j].vel = maxSpeed * (float)(random8())/255.0f * multiplier; + stars[j].vel = maxSpeed * (float)(hw_random8())/255.0f * multiplier; stars[j].birth = it; stars[j].last = it; // more fragments means larger burst effect - int num = random8(3,6 + (SEGMENT.intensity >> 5)); + int num = hw_random8(3,6 + (SEGMENT.intensity >> 5)); for (int i=0; i < STARBURST_MAX_FRAG; i++) { if (i < num) stars[j].fragment[i] = startPos; @@ -3578,11 +3578,11 @@ uint16_t mode_exploding_fireworks(void) if (SEGENV.aux0 < 2) { //FLARE if (SEGENV.aux0 == 0) { //init flare flare->pos = 0; - flare->posX = SEGMENT.is2D() ? random16(2,cols-3) : (SEGMENT.intensity > random8()); // will enable random firing side on 1D - unsigned peakHeight = 75 + random8(180); //0-255 + flare->posX = SEGMENT.is2D() ? hw_random16(2,cols-3) : (SEGMENT.intensity > hw_random8()); // will enable random firing side on 1D + unsigned peakHeight = 75 + hw_random8(180); //0-255 peakHeight = (peakHeight * (rows -1)) >> 8; flare->vel = sqrtf(-2.0f * gravity * peakHeight); - flare->velX = SEGMENT.is2D() ? (random8(9)-4)/64.0f : 0; // no X velocity on 1D + flare->velX = SEGMENT.is2D() ? (hw_random8(9)-4)/64.0f : 0; // no X velocity on 1D flare->col = 255; //brightness SEGENV.aux0 = 1; } @@ -3610,7 +3610,7 @@ uint16_t mode_exploding_fireworks(void) * Explosion happens where the flare ended. * Size is proportional to the height. */ - unsigned nSparks = flare->pos + random8(4); + unsigned nSparks = flare->pos + hw_random8(4); nSparks = std::max(nSparks, 4U); // This is not a standard constrain; numSparks is not guaranteed to be at least 4 nSparks = std::min(nSparks, numSparks); @@ -3619,12 +3619,12 @@ uint16_t mode_exploding_fireworks(void) for (unsigned i = 1; i < nSparks; i++) { sparks[i].pos = flare->pos; sparks[i].posX = flare->posX; - sparks[i].vel = (float(random16(20001)) / 10000.0f) - 0.9f; // from -0.9 to 1.1 + sparks[i].vel = (float(hw_random16(20001)) / 10000.0f) - 0.9f; // from -0.9 to 1.1 sparks[i].vel *= rows<32 ? 0.5f : 1; // reduce velocity for smaller strips - sparks[i].velX = SEGMENT.is2D() ? (float(random16(20001)) / 10000.0f) - 1.0f : 0; // from -1 to 1 + sparks[i].velX = SEGMENT.is2D() ? (float(hw_random16(20001)) / 10000.0f) - 1.0f : 0; // from -1 to 1 sparks[i].col = 345;//abs(sparks[i].vel * 750.0); // set colors before scaling velocity to keep them bright //sparks[i].col = constrain(sparks[i].col, 0, 345); - sparks[i].colIndex = random8(); + sparks[i].colIndex = hw_random8(); sparks[i].vel *= flare->pos/rows; // proportional to height sparks[i].velX *= SEGMENT.is2D() ? flare->posX/cols : 0; // proportional to width sparks[i].vel *= -gravity *50; @@ -3662,7 +3662,7 @@ uint16_t mode_exploding_fireworks(void) if (SEGMENT.check3) SEGMENT.blur(16); *dying_gravity *= .8f; // as sparks burn out they fall slower } else { - SEGENV.aux0 = 6 + random8(10); //wait for this many frames + SEGENV.aux0 = 6 + hw_random8(10); //wait for this many frames } } else { SEGENV.aux0--; @@ -3717,7 +3717,7 @@ uint16_t mode_drip(void) drops[j].col += map(SEGMENT.speed, 0, 255, 1, 6); // swelling - if (random8() < drops[j].col/10) { // random drop + if (hw_random8() < drops[j].col/10) { // random drop drops[j].colIndex=2; //fall drops[j].col=255; } @@ -3803,17 +3803,17 @@ uint16_t mode_tetrix(void) { // speed calculation: a single brick should reach bottom of strip in X seconds // if the speed is set to 1 this should take 5s and at 255 it should take 0.25s // as this is dependant on SEGLEN it should be taken into account and the fact that effect runs every FRAMETIME s - int speed = SEGMENT.speed ? SEGMENT.speed : random8(1,255); + int speed = SEGMENT.speed ? SEGMENT.speed : hw_random8(1,255); speed = map(speed, 1, 255, 5000, 250); // time taken for full (SEGLEN) drop drop->speed = float(SEGLEN * FRAMETIME) / float(speed); // set speed drop->pos = SEGLEN; // start at end of segment (no need to subtract 1) - if (!SEGMENT.check1) drop->col = random8(0,15)<<4; // limit color choices so there is enough HUE gap + if (!SEGMENT.check1) drop->col = hw_random8(0,15)<<4; // limit color choices so there is enough HUE gap drop->step = 1; // drop state (0 init, 1 forming, 2 falling) - drop->brick = (SEGMENT.intensity ? (SEGMENT.intensity>>5)+1 : random8(1,5)) * (1+(SEGLEN>>6)); // size of brick + drop->brick = (SEGMENT.intensity ? (SEGMENT.intensity>>5)+1 : hw_random8(1,5)) * (1+(SEGLEN>>6)); // size of brick } if (drop->step == 1) { // forming - if (random8()>>6) { // random drop + if (hw_random8()>>6) { // random drop drop->step = 2; // fall } } @@ -3862,7 +3862,7 @@ static const char _data_FX_MODE_TETRIX[] PROGMEM = "Tetrix@!,Width,,,,One color; uint16_t mode_plasma(void) { // initialize phases on start if (SEGENV.call == 0) { - SEGENV.aux0 = random8(0,2); // add a bit of randomness + SEGENV.aux0 = hw_random8(0,2); // add a bit of randomness } unsigned thisPhase = beatsin8_t(6+SEGENV.aux0,-64,64); unsigned thatPhase = beatsin8_t(7+SEGENV.aux0,-64,64); @@ -4206,8 +4206,8 @@ uint16_t mode_noisepal(void) { // Slow noise { SEGENV.step = strip.now; - unsigned baseI = random8(); - palettes[1] = CRGBPalette16(CHSV(baseI+random8(64), 255, random8(128,255)), CHSV(baseI+128, 255, random8(128,255)), CHSV(baseI+random8(92), 192, random8(128,255)), CHSV(baseI+random8(92), 255, random8(128,255))); + unsigned baseI = hw_random8(); + palettes[1] = CRGBPalette16(CHSV(baseI+hw_random8(64), 255, hw_random8(128,255)), CHSV(baseI+128, 255, hw_random8(128,255)), CHSV(baseI+hw_random8(92), 192, hw_random8(128,255)), CHSV(baseI+hw_random8(92), 255, hw_random8(128,255))); } //EVERY_N_MILLIS(10) { //(don't have to time this, effect function is only called every 24ms) @@ -4374,16 +4374,16 @@ uint16_t mode_dancing_shadows(void) } if (initialize || respawn) { - spotlights[i].colorIdx = random8(); - spotlights[i].width = random8(1, 10); + spotlights[i].colorIdx = hw_random8(); + spotlights[i].width = hw_random8(1, 10); - spotlights[i].speed = 1.0/random8(4, 50); + spotlights[i].speed = 1.0/hw_random8(4, 50); if (initialize) { - spotlights[i].position = random16(SEGLEN); - spotlights[i].speed *= random8(2) ? 1.0 : -1.0; + spotlights[i].position = hw_random16(SEGLEN); + spotlights[i].speed *= hw_random8(2) ? 1.0 : -1.0; } else { - if (random8(2)) { + if (hw_random8(2)) { spotlights[i].position = SEGLEN + spotlights[i].width; spotlights[i].speed *= -1.0; }else { @@ -4392,7 +4392,7 @@ uint16_t mode_dancing_shadows(void) } spotlights[i].lastUpdateTime = time; - spotlights[i].type = random8(SPOT_TYPES_COUNT); + spotlights[i].type = hw_random8(SPOT_TYPES_COUNT); } uint32_t color = SEGMENT.color_from_palette(spotlights[i].colorIdx, false, false, 255); @@ -4551,10 +4551,10 @@ uint16_t mode_tv_simulator(void) { // create a new sceene if (((strip.now - tvSimulator->sceeneStart) >= tvSimulator->sceeneDuration) || SEGENV.aux1 == 0) { tvSimulator->sceeneStart = strip.now; // remember the start of the new sceene - tvSimulator->sceeneDuration = random16(60* 250* colorSpeed, 60* 750 * colorSpeed); // duration of a "movie sceene" which has similar colors (5 to 15 minutes with max speed slider) - tvSimulator->sceeneColorHue = random16( 0, 768); // random start color-tone for the sceene - tvSimulator->sceeneColorSat = random8 ( 100, 130 + colorIntensity); // random start color-saturation for the sceene - tvSimulator->sceeneColorBri = random8 ( 200, 240); // random start color-brightness for the sceene + tvSimulator->sceeneDuration = hw_random16(60* 250* colorSpeed, 60* 750 * colorSpeed); // duration of a "movie sceene" which has similar colors (5 to 15 minutes with max speed slider) + tvSimulator->sceeneColorHue = hw_random16( 0, 768); // random start color-tone for the sceene + tvSimulator->sceeneColorSat = hw_random8 ( 100, 130 + colorIntensity); // random start color-saturation for the sceene + tvSimulator->sceeneColorBri = hw_random8 ( 200, 240); // random start color-brightness for the sceene SEGENV.aux1 = 1; SEGENV.aux0 = 0; } @@ -4562,16 +4562,16 @@ uint16_t mode_tv_simulator(void) { // slightly change the color-tone in this sceene if (SEGENV.aux0 == 0) { // hue change in both directions - j = random8(4 * colorIntensity); - hue = (random8() < 128) ? ((j < tvSimulator->sceeneColorHue) ? tvSimulator->sceeneColorHue - j : 767 - tvSimulator->sceeneColorHue - j) : // negative + j = hw_random8(4 * colorIntensity); + hue = (hw_random8() < 128) ? ((j < tvSimulator->sceeneColorHue) ? tvSimulator->sceeneColorHue - j : 767 - tvSimulator->sceeneColorHue - j) : // negative ((j + tvSimulator->sceeneColorHue) < 767 ? tvSimulator->sceeneColorHue + j : tvSimulator->sceeneColorHue + j - 767) ; // positive // saturation - j = random8(2 * colorIntensity); + j = hw_random8(2 * colorIntensity); sat = (tvSimulator->sceeneColorSat - j) < 0 ? 0 : tvSimulator->sceeneColorSat - j; // brightness - j = random8(100); + j = hw_random8(100); bri = (tvSimulator->sceeneColorBri - j) < 0 ? 0 : tvSimulator->sceeneColorBri - j; // calculate R,G,B from HSV @@ -4597,9 +4597,9 @@ uint16_t mode_tv_simulator(void) { SEGENV.aux0 = 1; // randomize total duration and fade duration for the actual color - tvSimulator->totalTime = random16(250, 2500); // Semi-random pixel-to-pixel time - tvSimulator->fadeTime = random16(0, tvSimulator->totalTime); // Pixel-to-pixel transition time - if (random8(10) < 3) tvSimulator->fadeTime = 0; // Force scene cut 30% of time + tvSimulator->totalTime = hw_random16(250, 2500); // Semi-random pixel-to-pixel time + tvSimulator->fadeTime = hw_random16(0, tvSimulator->totalTime); // Pixel-to-pixel transition time + if (hw_random8(10) < 3) tvSimulator->fadeTime = 0; // Force scene cut 30% of time tvSimulator->startTime = strip.now; } // end of initialization @@ -4664,15 +4664,15 @@ class AuroraWave { public: void init(uint32_t segment_length, CRGB color) { - ttl = random16(500, 1501); + ttl = hw_random16(500, 1501); basecolor = color; - basealpha = random8(60, 101) / (float)100; + basealpha = hw_random8(60, 101) / (float)100; age = 0; - width = random16(segment_length / 20, segment_length / W_WIDTH_FACTOR); //half of width to make math easier + width = hw_random16(segment_length / 20, segment_length / W_WIDTH_FACTOR); //half of width to make math easier if (!width) width = 1; - center = random8(101) / (float)100 * segment_length; - goingleft = random8(0, 2) == 0; - speed_factor = (random8(10, 31) / (float)100 * W_MAX_SPEED / 255); + center = hw_random8(101) / (float)100 * segment_length; + goingleft = hw_random8(0, 2) == 0; + speed_factor = (hw_random8(10, 31) / (float)100 * W_MAX_SPEED / 255); alive = true; } @@ -4757,7 +4757,7 @@ uint16_t mode_aurora(void) { waves = reinterpret_cast(SEGENV.data); for (int i = 0; i < SEGENV.aux1; i++) { - waves[i].init(SEGLEN, CRGB(SEGMENT.color_from_palette(random8(), false, false, random8(0, 3)))); + waves[i].init(SEGLEN, CRGB(SEGMENT.color_from_palette(hw_random8(), false, false, hw_random8(0, 3)))); } } else { waves = reinterpret_cast(SEGENV.data); @@ -4769,7 +4769,7 @@ uint16_t mode_aurora(void) { if(!(waves[i].stillAlive())) { //If a wave dies, reinitialize it starts over. - waves[i].init(SEGLEN, CRGB(SEGMENT.color_from_palette(random8(), false, false, random8(0, 3)))); + waves[i].init(SEGLEN, CRGB(SEGMENT.color_from_palette(hw_random8(), false, false, hw_random8(0, 3)))); } } @@ -5124,15 +5124,14 @@ uint16_t mode_2Dgameoflife(void) { // Written by Ewoud Wijma, inspired by https: if (SEGENV.call == 0 || strip.now - SEGMENT.step > 3000) { SEGENV.step = strip.now; SEGENV.aux0 = 0; - //random16_set_seed(millis()>>2); //seed the random generator //give the leds random state and colors (based on intensity, colors from palette or all posible colors are chosen) for (int x = 0; x < cols; x++) for (int y = 0; y < rows; y++) { - unsigned state = random8()%2; + unsigned state = hw_random8()%2; if (state == 0) SEGMENT.setPixelColorXY(x,y, backgroundColor); else - SEGMENT.setPixelColorXY(x,y, SEGMENT.color_from_palette(random8(), false, PALETTE_SOLID_WRAP, 255)); + SEGMENT.setPixelColorXY(x,y, SEGMENT.color_from_palette(hw_random8(), false, PALETTE_SOLID_WRAP, 255)); } for (int y = 0; y < rows; y++) for (int x = 0; x < cols; x++) prevLeds[XY(x,y)] = CRGB::Black; @@ -5187,9 +5186,9 @@ uint16_t mode_2Dgameoflife(void) { // Written by Ewoud Wijma, inspired by https: for (int i=0; i<9 && colorsCount[i].count != 0; i++) if (colorsCount[i].count > dominantColorCount.count) dominantColorCount = colorsCount[i]; // assign the dominant color w/ a bit of randomness to avoid "gliders" - if (dominantColorCount.count > 0 && random8(128)) SEGMENT.setPixelColorXY(x,y, dominantColorCount.color); - } else if ((col == bgc) && (neighbors == 2) && !random8(128)) { // Mutation - SEGMENT.setPixelColorXY(x,y, SEGMENT.color_from_palette(random8(), false, PALETTE_SOLID_WRAP, 255)); + if (dominantColorCount.count > 0 && hw_random8(128)) SEGMENT.setPixelColorXY(x,y, dominantColorCount.color); + } else if ((col == bgc) && (neighbors == 2) && !hw_random8(128)) { // Mutation + SEGMENT.setPixelColorXY(x,y, SEGMENT.color_from_palette(hw_random8(), false, PALETTE_SOLID_WRAP, 255)); } // else do nothing! } //x,y @@ -5433,8 +5432,8 @@ uint16_t mode_2Dmatrix(void) { // Matrix2D. By Jeremy Williams. } // spawn new falling code - if (random8() <= SEGMENT.intensity || emptyScreen) { - uint8_t spawnX = random8(cols); + if (hw_random8() <= SEGMENT.intensity || emptyScreen) { + uint8_t spawnX = hw_random8(cols); SEGMENT.setPixelColorXY(spawnX, 0, spawnColor); // update hint for next run unsigned index = XY(spawnX, 0) >> 3; @@ -5787,11 +5786,11 @@ uint16_t mode_2Dspaceships(void) { //// Space ships by stepko (c)05.02.21 [ht uint32_t tb = strip.now >> 12; // every ~4s if (tb > SEGENV.step) { int dir = ++SEGENV.aux0; - dir += (int)random8(3)-1; + dir += (int)hw_random8(3)-1; if (dir > 7) SEGENV.aux0 = 0; else if (dir < 0) SEGENV.aux0 = 7; else SEGENV.aux0 = dir; - SEGENV.step = tb + random8(4); + SEGENV.step = tb + hw_random8(4); } SEGMENT.fadeToBlackBy(map(SEGMENT.speed, 0, 255, 248, 16)); @@ -5921,9 +5920,8 @@ uint16_t mode_2Dghostrider(void) { if (SEGENV.aux0 != cols || SEGENV.aux1 != rows) { SEGENV.aux0 = cols; SEGENV.aux1 = rows; - //random16_set_seed(strip.now); - lighter->angleSpeed = random8(0,20) - 10; - lighter->gAngle = random16(); + lighter->angleSpeed = hw_random8(0,20) - 10; + lighter->gAngle = hw_random16(); lighter->Vspeed = 5; lighter->gPosX = (cols/2) * 10; lighter->gPosY = (rows/2) * 10; @@ -5951,7 +5949,7 @@ uint16_t mode_2Dghostrider(void) { if (lighter->gPosY < 0) lighter->gPosY = (rows - 1) * 10; if (lighter->gPosY > (rows - 1) * 10) lighter->gPosY = 0; for (size_t i = 0; i < maxLighters; i++) { - lighter->time[i] += random8(5, 20); + lighter->time[i] += hw_random8(5, 20); if (lighter->time[i] >= 255 || (lighter->lightersPosX[i] <= 0) || (lighter->lightersPosX[i] >= (cols - 1) * 10) || @@ -5962,7 +5960,7 @@ uint16_t mode_2Dghostrider(void) { if (lighter->reg[i]) { lighter->lightersPosY[i] = lighter->gPosY; lighter->lightersPosX[i] = lighter->gPosX; - lighter->Angle[i] = lighter->gAngle + ((int)random8(20) - 10); + lighter->Angle[i] = lighter->gAngle + ((int)hw_random8(20) - 10); lighter->time[i] = 0; lighter->reg[i] = false; } else { @@ -6008,12 +6006,12 @@ uint16_t mode_2Dfloatingblobs(void) { SEGENV.aux1 = rows; //SEGMENT.fill(BLACK); for (size_t i = 0; i < MAX_BLOBS; i++) { - blob->r[i] = random8(1, cols>8 ? (cols/4) : 2); - blob->sX[i] = (float) random8(3, cols) / (float)(256 - SEGMENT.speed); // speed x - blob->sY[i] = (float) random8(3, rows) / (float)(256 - SEGMENT.speed); // speed y - blob->x[i] = random8(0, cols-1); - blob->y[i] = random8(0, rows-1); - blob->color[i] = random8(); + blob->r[i] = hw_random8(1, cols>8 ? (cols/4) : 2); + blob->sX[i] = (float) hw_random8(3, cols) / (float)(256 - SEGMENT.speed); // speed x + blob->sY[i] = (float) hw_random8(3, rows) / (float)(256 - SEGMENT.speed); // speed y + blob->x[i] = hw_random8(0, cols-1); + blob->y[i] = hw_random8(0, rows-1); + blob->color[i] = hw_random8(); blob->grow[i] = (blob->r[i] < 1.f); if (blob->sX[i] == 0) blob->sX[i] = 1; if (blob->sY[i] == 0) blob->sY[i] = 1; @@ -6052,19 +6050,19 @@ uint16_t mode_2Dfloatingblobs(void) { else blob->y[i] += blob->sY[i]; // bounce x if (blob->x[i] < 0.01f) { - blob->sX[i] = (float)random8(3, cols) / (256 - SEGMENT.speed); + blob->sX[i] = (float)hw_random8(3, cols) / (256 - SEGMENT.speed); blob->x[i] = 0.01f; } else if (blob->x[i] > (float)cols - 1.01f) { - blob->sX[i] = (float)random8(3, cols) / (256 - SEGMENT.speed); + blob->sX[i] = (float)hw_random8(3, cols) / (256 - SEGMENT.speed); blob->sX[i] = -blob->sX[i]; blob->x[i] = (float)cols - 1.01f; } // bounce y if (blob->y[i] < 0.01f) { - blob->sY[i] = (float)random8(3, rows) / (256 - SEGMENT.speed); + blob->sY[i] = (float)hw_random8(3, rows) / (256 - SEGMENT.speed); blob->y[i] = 0.01f; } else if (blob->y[i] > (float)rows - 1.01f) { - blob->sY[i] = (float)random8(3, rows) / (256 - SEGMENT.speed); + blob->sY[i] = (float)hw_random8(3, rows) / (256 - SEGMENT.speed); blob->sY[i] = -blob->sY[i]; blob->y[i] = (float)rows - 1.01f; } @@ -6306,13 +6304,13 @@ uint16_t mode_ripplepeak(void) { // * Ripple peak. By Andrew Tuli break; case 255: // Initialize ripple variables. - ripples[i].pos = random16(SEGLEN); + ripples[i].pos = hw_random16(SEGLEN); #ifdef ESP32 if (FFT_MajorPeak > 1) // log10(0) is "forbidden" (throws exception) ripples[i].color = (int)(log10f(FFT_MajorPeak)*128); else ripples[i].color = 0; #else - ripples[i].color = random8(); + ripples[i].color = hw_random8(); #endif ripples[i].state = 0; break; @@ -6760,7 +6758,7 @@ uint16_t mode_puddles_base(bool peakdetect) { if (SEGLEN == 1) return mode_static(); unsigned size = 0; uint8_t fadeVal = map(SEGMENT.speed, 0, 255, 224, 254); - unsigned pos = random16(SEGLEN); // Set a random starting position. + unsigned pos = hw_random16(SEGLEN); // Set a random starting position. SEGMENT.fade_out(fadeVal); um_data_t *um_data = getAudioData(); @@ -6823,7 +6821,7 @@ uint16_t mode_pixels(void) { // Pixels. By Andrew Tuline. SEGMENT.fade_out(64+(SEGMENT.speed>>1)); for (int i=0; i SPEED_FORMULA_L) { - unsigned segLoc = random16(SEGLEN); + unsigned segLoc = hw_random16(SEGLEN); SEGMENT.setPixelColor(segLoc, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(2*fftResult[SEGENV.aux0%16]*240/max(1, (int)SEGLEN-1), false, PALETTE_SOLID_WRAP, 0), uint8_t(2*fftResult[SEGENV.aux0%16]))); ++(SEGENV.aux0) %= 16; // make sure it doesn't cross 16 @@ -7005,7 +7003,7 @@ uint16_t mode_freqpixels(void) { // Freqpixel. By Andrew Tuline. uint8_t pixCol = (log10f(FFT_MajorPeak) - 1.78f) * 255.0f/(MAX_FREQ_LOG10 - 1.78f); // Scale log10 of frequency values to the 255 colour index. if (FFT_MajorPeak < 61.0f) pixCol = 0; // handle underflow for (int i=0; i < SEGMENT.intensity/32+1; i++) { - unsigned locn = random16(0,SEGLEN); + unsigned locn = hw_random16(0,SEGLEN); SEGMENT.setPixelColor(locn, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(SEGMENT.intensity+pixCol, false, PALETTE_SOLID_WRAP, 0), (uint8_t)my_magnitude)); } @@ -7473,9 +7471,9 @@ uint16_t mode_2Dsoap() { // init if (SEGENV.call == 0) { - *noise32_x = random16(); - *noise32_y = random16(); - *noise32_z = random16(); + *noise32_x = hw_random(); + *noise32_y = hw_random(); + *noise32_z = hw_random(); } else { *noise32_x += mov; *noise32_y += mov; diff --git a/wled00/colors.cpp b/wled00/colors.cpp index 5c4b9ac41..e64cf6758 100644 --- a/wled00/colors.cpp +++ b/wled00/colors.cpp @@ -124,86 +124,86 @@ void setRandomColor(byte* rgb) */ CRGBPalette16 generateHarmonicRandomPalette(CRGBPalette16 &basepalette) { - CHSV palettecolors[4]; //array of colors for the new palette - uint8_t keepcolorposition = random8(4); //color position of current random palette to keep - palettecolors[keepcolorposition] = rgb2hsv(basepalette.entries[keepcolorposition*5]); //read one of the base colors of the current palette - palettecolors[keepcolorposition].hue += random8(10)-5; // +/- 5 randomness of base color - //generate 4 saturation and brightness value numbers - //only one saturation is allowed to be below 200 creating mostly vibrant colors - //only one brightness value number is allowed below 200, creating mostly bright palettes + CHSV palettecolors[4]; // array of colors for the new palette + uint8_t keepcolorposition = hw_random8(4); // color position of current random palette to keep + palettecolors[keepcolorposition] = rgb2hsv(basepalette.entries[keepcolorposition*5]); // read one of the base colors of the current palette + palettecolors[keepcolorposition].hue += hw_random8(10)-5; // +/- 5 randomness of base color + // generate 4 saturation and brightness value numbers + // only one saturation is allowed to be below 200 creating mostly vibrant colors + // only one brightness value number is allowed below 200, creating mostly bright palettes - for (int i = 0; i < 3; i++) { //generate three high values - palettecolors[i].saturation = random8(200,255); - palettecolors[i].value = random8(220,255); + for (int i = 0; i < 3; i++) { // generate three high values + palettecolors[i].saturation = hw_random8(200,255); + palettecolors[i].value = hw_random8(220,255); } - //allow one to be lower - palettecolors[3].saturation = random8(20,255); - palettecolors[3].value = random8(80,255); + // allow one to be lower + palettecolors[3].saturation = hw_random8(20,255); + palettecolors[3].value = hw_random8(80,255); - //shuffle the arrays + // shuffle the arrays for (int i = 3; i > 0; i--) { - std::swap(palettecolors[i].saturation, palettecolors[random8(i + 1)].saturation); - std::swap(palettecolors[i].value, palettecolors[random8(i + 1)].value); + std::swap(palettecolors[i].saturation, palettecolors[hw_random8(i + 1)].saturation); + std::swap(palettecolors[i].value, palettecolors[hw_random8(i + 1)].value); } - //now generate three new hues based off of the hue of the chosen current color + // now generate three new hues based off of the hue of the chosen current color uint8_t basehue = palettecolors[keepcolorposition].hue; - uint8_t harmonics[3]; //hues that are harmonic but still a little random - uint8_t type = random8(5); //choose a harmony type + uint8_t harmonics[3]; // hues that are harmonic but still a little random + uint8_t type = hw_random8(5); // choose a harmony type switch (type) { case 0: // analogous - harmonics[0] = basehue + random8(30, 50); - harmonics[1] = basehue + random8(10, 30); - harmonics[2] = basehue - random8(10, 30); + harmonics[0] = basehue + hw_random8(30, 50); + harmonics[1] = basehue + hw_random8(10, 30); + harmonics[2] = basehue - hw_random8(10, 30); break; case 1: // triadic - harmonics[0] = basehue + 113 + random8(15); - harmonics[1] = basehue + 233 + random8(15); - harmonics[2] = basehue - 7 + random8(15); + harmonics[0] = basehue + 113 + hw_random8(15); + harmonics[1] = basehue + 233 + hw_random8(15); + harmonics[2] = basehue - 7 + hw_random8(15); break; case 2: // split-complementary - harmonics[0] = basehue + 145 + random8(10); - harmonics[1] = basehue + 205 + random8(10); - harmonics[2] = basehue - 5 + random8(10); + harmonics[0] = basehue + 145 + hw_random8(10); + harmonics[1] = basehue + 205 + hw_random8(10); + harmonics[2] = basehue - 5 + hw_random8(10); break; case 3: // square - harmonics[0] = basehue + 85 + random8(10); - harmonics[1] = basehue + 175 + random8(10); - harmonics[2] = basehue + 265 + random8(10); + harmonics[0] = basehue + 85 + hw_random8(10); + harmonics[1] = basehue + 175 + hw_random8(10); + harmonics[2] = basehue + 265 + hw_random8(10); break; case 4: // tetradic - harmonics[0] = basehue + 80 + random8(20); - harmonics[1] = basehue + 170 + random8(20); - harmonics[2] = basehue - 15 + random8(30); + harmonics[0] = basehue + 80 + hw_random8(20); + harmonics[1] = basehue + 170 + hw_random8(20); + harmonics[2] = basehue - 15 + hw_random8(30); break; } - if (random8() < 128) { - //50:50 chance of shuffling hues or keep the color order + if (hw_random8() < 128) { + // 50:50 chance of shuffling hues or keep the color order for (int i = 2; i > 0; i--) { - std::swap(harmonics[i], harmonics[random8(i + 1)]); + std::swap(harmonics[i], harmonics[hw_random8(i + 1)]); } } - //now set the hues + // now set the hues int j = 0; for (int i = 0; i < 4; i++) { - if (i==keepcolorposition) continue; //skip the base color + if (i==keepcolorposition) continue; // skip the base color palettecolors[i].hue = harmonics[j]; j++; } bool makepastelpalette = false; - if (random8() < 25) { //~10% chance of desaturated 'pastel' colors + if (hw_random8() < 25) { // ~10% chance of desaturated 'pastel' colors makepastelpalette = true; } - //apply saturation & gamma correction + // apply saturation & gamma correction CRGB RGBpalettecolors[4]; for (int i = 0; i < 4; i++) { if (makepastelpalette && palettecolors[i].saturation > 180) { @@ -219,12 +219,12 @@ CRGBPalette16 generateHarmonicRandomPalette(CRGBPalette16 &basepalette) RGBpalettecolors[3]); } -CRGBPalette16 generateRandomPalette() //generate fully random palette +CRGBPalette16 generateRandomPalette() // generate fully random palette { - return CRGBPalette16(CHSV(random8(), random8(160, 255), random8(128, 255)), - CHSV(random8(), random8(160, 255), random8(128, 255)), - CHSV(random8(), random8(160, 255), random8(128, 255)), - CHSV(random8(), random8(160, 255), random8(128, 255))); + return CRGBPalette16(CHSV(hw_random8(), hw_random8(160, 255), hw_random8(128, 255)), + CHSV(hw_random8(), hw_random8(160, 255), hw_random8(128, 255)), + CHSV(hw_random8(), hw_random8(160, 255), hw_random8(128, 255)), + CHSV(hw_random8(), hw_random8(160, 255), hw_random8(128, 255))); } void hsv2rgb(const CHSV32& hsv, uint32_t& rgb) // convert HSV (16bit hue) to RGB (32bit with white = 0) diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index c98eef5c9..bc5206b7a 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -458,6 +458,12 @@ void userConnected(); void userLoop(); //util.cpp +#ifdef ESP8266 +#define HW_RND_REGISTER RANDOM_REG32 +#else // ESP32 family +#include "soc/wdev_reg.h" +#define HW_RND_REGISTER REG_READ(WDEV_RND_REG) +#endif int getNumVal(const String* req, uint16_t pos); void parseNumber(const char* str, byte* val, byte minv=0, byte maxv=255); bool getVal(JsonVariant elem, byte* val, byte minv=0, byte maxv=255); // getVal supports inc/decrementing and random ("X~Y(r|~[w][-][Z])" form) @@ -485,6 +491,23 @@ void enumerateLedmaps(); uint8_t get_random_wheel_index(uint8_t pos); float mapf(float x, float in_min, float in_max, float out_min, float out_max); +// fast (true) random numbers using hardware RNG, all functions return values in the range lowerlimit to upperlimit-1 +// note: for true random numbers with high entropy, do not call faster than every 200ns (5MHz) +// tests show it is still highly random reading it quickly in a loop (better than fastled PRNG) +// for 8bit and 16bit random functions: no limit check is done for best speed +// 32bit inputs are used for speed and code size, limits don't work if inverted or out of range +// inlining does save code size except for random(a,b) and 32bit random with limits +#define random hw_random // replace arduino random() +inline uint32_t hw_random() { return HW_RND_REGISTER; }; +uint32_t hw_random(uint32_t upperlimit); // not inlined for code size +int32_t hw_random(int32_t lowerlimit, int32_t upperlimit); +inline uint16_t hw_random16() { return HW_RND_REGISTER; }; +inline uint16_t hw_random16(uint32_t upperlimit) { return (hw_random16() * upperlimit) >> 16; }; // input range 0-65535 (uint16_t) +inline int16_t hw_random16(int32_t lowerlimit, int32_t upperlimit) { int32_t range = upperlimit - lowerlimit; return lowerlimit + hw_random16(range); }; // signed limits, use int16_t ranges +inline uint8_t hw_random8() { return HW_RND_REGISTER; }; +inline uint8_t hw_random8(uint32_t upperlimit) { return (hw_random8() * upperlimit) >> 8; }; // input range 0-255 +inline uint8_t hw_random8(uint32_t lowerlimit, uint32_t upperlimit) { uint32_t range = upperlimit - lowerlimit; return lowerlimit + hw_random8(range); }; // input range 0-255 + // RAII guard class for the JSON Buffer lock // Modeled after std::lock_guard class JSONBufferGuard { diff --git a/wled00/ir.cpp b/wled00/ir.cpp index 48061238c..f01e2c320 100644 --- a/wled00/ir.cpp +++ b/wled00/ir.cpp @@ -593,7 +593,7 @@ static void decodeIRJson(uint32_t code) decBrightness(); } else if (cmdStr.startsWith(F("!presetF"))) { //!presetFallback uint8_t p1 = fdo["PL"] | 1; - uint8_t p2 = fdo["FX"] | random8(strip.getModeCount() -1); + uint8_t p2 = fdo["FX"] | hw_random8(strip.getModeCount() -1); uint8_t p3 = fdo["FP"] | 0; presetFallback(p1, p2, p3); } diff --git a/wled00/remote.cpp b/wled00/remote.cpp index 9bc5430c0..eb19cc1f3 100644 --- a/wled00/remote.cpp +++ b/wled00/remote.cpp @@ -146,7 +146,7 @@ static bool remoteJson(int button) parsed = true; } else if (cmdStr.startsWith(F("!presetF"))) { //!presetFallback uint8_t p1 = fdo["PL"] | 1; - uint8_t p2 = fdo["FX"] | random8(strip.getModeCount() -1); + uint8_t p2 = fdo["FX"] | hw_random8(strip.getModeCount() -1); uint8_t p3 = fdo["FP"] | 0; presetWithFallback(p1, p2, p3); parsed = true; diff --git a/wled00/util.cpp b/wled00/util.cpp index 41e3d6c23..d9f1c00b9 100644 --- a/wled00/util.cpp +++ b/wled00/util.cpp @@ -14,7 +14,7 @@ int getNumVal(const String* req, uint16_t pos) void parseNumber(const char* str, byte* val, byte minv, byte maxv) { if (str == nullptr || str[0] == '\0') return; - if (str[0] == 'r') {*val = random8(minv,maxv?maxv:255); return;} // maxv for random cannot be 0 + if (str[0] == 'r') {*val = hw_random8(minv,maxv?maxv:255); return;} // maxv for random cannot be 0 bool wrap = false; if (str[0] == 'w' && strlen(str) > 1) {str++; wrap = true;} if (str[0] == '~') { @@ -474,9 +474,9 @@ um_data_t* simulateSound(uint8_t simulationId) break; case UMS_WeWillRockYou: if (ms%2000 < 200) { - volumeSmth = random8(255); + volumeSmth = hw_random8(); for (int i = 0; i<5; i++) - fftResult[i] = random8(255); + fftResult[i] = hw_random8(); } else if (ms%2000 < 400) { volumeSmth = 0; @@ -484,9 +484,9 @@ um_data_t* simulateSound(uint8_t simulationId) fftResult[i] = 0; } else if (ms%2000 < 600) { - volumeSmth = random8(255); + volumeSmth = hw_random8(); for (int i = 5; i<11; i++) - fftResult[i] = random8(255); + fftResult[i] = hw_random8(); } else if (ms%2000 < 800) { volumeSmth = 0; @@ -494,9 +494,9 @@ um_data_t* simulateSound(uint8_t simulationId) fftResult[i] = 0; } else if (ms%2000 < 1000) { - volumeSmth = random8(255); + volumeSmth = hw_random8(); for (int i = 11; i<16; i++) - fftResult[i] = random8(255); + fftResult[i] = hw_random8(); } else { volumeSmth = 0; @@ -516,7 +516,7 @@ um_data_t* simulateSound(uint8_t simulationId) break; } - samplePeak = random8() > 250; + samplePeak = hw_random8() > 250; FFT_MajorPeak = 21 + (volumeSmth*volumeSmth) / 8.0f; // walk thru full range of 21hz...8200hz maxVol = 31; // this gets feedback fro UI binNum = 8; // this gets feedback fro UI @@ -582,7 +582,7 @@ void enumerateLedmaps() { uint8_t get_random_wheel_index(uint8_t pos) { uint8_t r = 0, x = 0, y = 0, d = 0; while (d < 42) { - r = random8(); + r = hw_random8(); x = abs(pos - r); y = 255 - x; d = MIN(x, y); @@ -594,3 +594,18 @@ uint8_t get_random_wheel_index(uint8_t pos) { float mapf(float x, float in_min, float in_max, float out_min, float out_max) { return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } + +// 32 bit random number generator, inlining uses more code, use hw_random16() if speed is critical (see fcn_declare.h) +uint32_t hw_random(uint32_t upperlimit) { + uint32_t rnd = hw_random(); + uint64_t scaled = uint64_t(rnd) * uint64_t(upperlimit); + return scaled >> 32; +} + +int32_t hw_random(int32_t lowerlimit, int32_t upperlimit) { + if(lowerlimit >= upperlimit) { + return lowerlimit; + } + uint32_t diff = upperlimit - lowerlimit; + return hw_random(diff) + lowerlimit; +} \ No newline at end of file diff --git a/wled00/wled.cpp b/wled00/wled.cpp index afed485e0..1f978a39b 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -544,14 +544,8 @@ void WLED::setup() #endif // Seed FastLED random functions with an esp random value, which already works properly at this point. -#if defined(ARDUINO_ARCH_ESP32) - const uint32_t seed32 = esp_random(); -#elif defined(ARDUINO_ARCH_ESP8266) - const uint32_t seed32 = RANDOM_REG32; -#else - const uint32_t seed32 = random(std::numeric_limits::max()); -#endif - random16_set_seed((uint16_t)((seed32 & 0xFFFF) ^ (seed32 >> 16))); + const uint32_t seed32 = hw_random(); + random16_set_seed((uint16_t)seed32); #if WLED_WATCHDOG_TIMEOUT > 0 enableWatchdog();