| 110 | } |
| 111 | |
| 112 | uint8_t getPaletteIndex(uint32_t millis32, int width, int max_width, int height, int max_height, |
| 113 | uint32_t y_speed) { |
| 114 | // This function calculates which color to use from our palette for each LED |
| 115 | |
| 116 | // Get the scale factor from the UI slider |
| 117 | uint16_t scale = scaleXY.as<uint16_t>(); |
| 118 | |
| 119 | // Convert width position to an angle (0-255 represents 0-360 degrees) |
| 120 | // This maps our flat coordinate to a position on a cylinder |
| 121 | float xf = (float)width / (float)max_width; // Normalized position (0.0 to 1.0) |
| 122 | uint8_t x = (uint8_t)(xf * 255); // Convert to 0-255 range for trig functions |
| 123 | |
| 124 | // Calculate the sine and cosine of this angle to get 3D coordinates on the cylinder |
| 125 | uint32_t cosx = cos8(x); // cos8 returns a value 0-255 representing cosine |
| 126 | uint32_t sinx = sin8(x); // sin8 returns a value 0-255 representing sine |
| 127 | |
| 128 | // Apply scaling to the sine/cosine values |
| 129 | // This controls how "wide" the noise pattern is around the cylinder |
| 130 | float trig_scale = scale * scaleX.value(); |
| 131 | cosx *= trig_scale; |
| 132 | sinx *= trig_scale; |
| 133 | |
| 134 | // Calculate Y coordinate (vertical position) with speed offset for movement |
| 135 | uint32_t y = height * scale + y_speed; |
| 136 | |
| 137 | // Calculate Z coordinate (time dimension) - controls how the pattern changes over time |
| 138 | uint16_t z = millis32 / invSpeedZ.as<uint16_t>(); |
| 139 | FL_UNUSED(z); // Suppress unused variable warning |
| 140 | |
| 141 | // Generate 16-bit Perlin noise using our 4D coordinates (x,y,z,t) |
| 142 | // The << 8 shifts values left by 8 bits (multiplies by 256) to use the full 16-bit range |
| 143 | // The last parameter (0) could be replaced with another time variable for more variation |
| 144 | uint16_t noise16 = inoise16(cosx << 8, sinx << 8, y << 8, 0); |
| 145 | |
| 146 | // Convert 16-bit noise to 8-bit by taking the high byte |
| 147 | uint8_t noise_val = noise16 >> 8; |
| 148 | |
| 149 | // Calculate how much to subtract based on vertical position (height) |
| 150 | // This creates the fade-out effect from bottom to top |
| 151 | // The formula maps height from 0 to max_height-1 to a value from 255 to 0 |
| 152 | int8_t subtraction_factor = abs8(height - (max_height - 1)) * 255 / |
| 153 | (max_height - 1); |
| 154 | |
| 155 | // Subtract the factor from the noise value (with underflow protection) |
| 156 | // qsub8 is a "saturating subtraction" - it won't go below 0 |
| 157 | return qsub8(noise_val, subtraction_factor); |
| 158 | } |
| 159 | fl::CRGBPalette16 getPalette() { |
| 160 | // This function returns the appropriate color palette based on the UI selection |
| 161 | switch (palette) { |