diff --git a/RpiLedBars/README.md b/RpiLedBars/README.md index 07d2f15..53ceb4b 100644 --- a/RpiLedBars/README.md +++ b/RpiLedBars/README.md @@ -55,7 +55,7 @@ sudo apt install libasound2-dev wiringpi ~~~bash sudo apt install libfftw3-dev libasound2-dev libtool automake -cd cava +cd cava_ ./autogen.sh ./configure make @@ -68,6 +68,8 @@ sudo make install grep "Access point conf" $(find /etc -type f) ~~~ +* https://learn.sparkfun.com/tutorials/setting-up-a-raspberry-pi-3-as-an-access-point/all + ## Biblio: ### Art-Net diff --git a/RpiLedBars/src/rpi_midi_controller.c b/RpiLedBars/src/rpi_midi_controller.c index 36daade..c656194 100644 --- a/RpiLedBars/src/rpi_midi_controller.c +++ b/RpiLedBars/src/rpi_midi_controller.c @@ -187,6 +187,7 @@ void handle_in_port_events(snd_seq_event_t *ev) { case SND_SEQ_EVENT_CONTROLLER: switch (ev->data.control.param) { + /* Pots */ case 1: set_sensitivity(destChannel, ev->data.control.value); break; @@ -202,6 +203,20 @@ void handle_in_port_events(snd_seq_event_t *ev) { case 5: set_gravity(ev->data.control.value); break; + case 6: + set_saturation(destChannel, ev->data.control.value); + break; + case 7: + set_hue_auto_shift_interval(destChannel, ev->data.control.value); + break; + case 8: + set_hue_auto_shift_speed(destChannel, ev->data.control.value); + break; + + /* Pads in CC */ + case 26: + set_hue_auto_shift(ev->data.control.value != 0); + break; default: log_debug("CONTROLLER : ch %#04x - param %u - value %d", ev->data.control.channel, diff --git a/RpiLedBars/src/rpi_param.c b/RpiLedBars/src/rpi_param.c index 82e38e1..fb66dae 100644 --- a/RpiLedBars/src/rpi_param.c +++ b/RpiLedBars/src/rpi_param.c @@ -22,9 +22,17 @@ **************************************************************************************************/ pixled_param_t const dummyPixledParam = {.chanLedCount = 0}; -auton_param_t const dummyAutonParam = {.sensitivity = 10, .gravity = 80, .pattern = 2}; -ledbar_param_t const dummyLedbarParam = { - .sensitivity = 1., .hueBase = 121, .hueInterval = -100, .luminosity = 20, .saturation = 255}; +auton_param_t const dummyAutonParam = { + .sensitivity = 10, .gravity = 80, .pattern = 1, .isHueAutoShiftEnabled = true}; +ledbar_param_t const dummyLedbarParam = {.sensitivity = 1., + .hueBase = 121, + .hueInterval = -100, + .hueAutoShift = 0, + .hueAutoShiftInterval = 0, + .hueAutoShiftSpeed = 1., + .isIncreasing = false, + .luminosity = 20, + .saturation = 180}; /*************************************************************************************************** * Persistent Variables @@ -61,6 +69,18 @@ void set_gravity(int8_t gravity8) { log_debug("Gravity : %d", param.auton.gravity); } +void set_hue_auto_shift(bool HasToBeEnabled) { + if (HasToBeEnabled != param.auton.isHueAutoShiftEnabled) { + param.auton.isHueAutoShiftEnabled = HasToBeEnabled; + log_debug("Hue auto shift : %s", HasToBeEnabled ? "Enabled" : "Disabled"); + if (!HasToBeEnabled) { + for (size_t i = 0; i < LED_NCHANS; ++i) { + param.ledbar[i].hueAutoShift = 0; + } + } + } +} + void set_sensitivity(int channel, int8_t sensitivity8) { float sensitivity = pow(1.065, sensitivity8 - INT8_MAX / 2); if (channel >= LED_NCHANS) { @@ -85,8 +105,12 @@ void set_hue_base(int channel, int8_t hueBase8) { void set_hue_interval(int channel, int8_t hueInterval8) { int16_t hueInterval = hueInterval8 - ((INT8_MAX + 1) / 2); - if (hueInterval != 0) { - hueInterval = hueInterval * HUEINTERVAL_MAX / (INT8_MAX / 2); + if (-30 <= hueInterval && hueInterval <= 30) { + hueInterval = hueInterval * (HUEINTERVAL_MAX + 1) / 30; + } else if (hueInterval <= -30) { + hueInterval = 22 * (hueInterval + 30) - HUEINTERVAL_MAX; + } else { + hueInterval = 22 * (hueInterval - 30) + HUEINTERVAL_MAX; } if (channel < LED_NCHANS) { @@ -96,9 +120,39 @@ void set_hue_interval(int channel, int8_t hueInterval8) { param.ledbar[i].hueInterval = hueInterval; } } - log_debug("Hue interval [%2d] : %d - [%u, %hu]", channel, hueInterval, - param.ledbar[0].hueBase * UINT16_MAX / HUE_MAX, - (param.ledbar[0].hueBase + hueInterval) * UINT16_MAX / HUE_MAX); + log_debug("Hue interval [%2d] : %d", channel, hueInterval); +} + +void set_hue_auto_shift_interval(int channel, int8_t hueInterval8) { + int16_t hueInterval = hueInterval8 - ((INT8_MAX + 1) / 2); + if (-30 <= hueInterval && hueInterval <= 30) { + hueInterval = hueInterval * (HUEINTERVAL_MAX + 1) / 30; + } else if (hueInterval <= -30) { + hueInterval = 22 * (hueInterval + 30) - HUEINTERVAL_MAX; + } else { + hueInterval = 22 * (hueInterval - 30) + HUEINTERVAL_MAX; + } + + if (channel < LED_NCHANS) { + param.ledbar[channel].hueAutoShiftInterval = hueInterval; + } else { + for (size_t i = 0; i < LED_NCHANS; ++i) { + param.ledbar[i].hueAutoShiftInterval = hueInterval; + } + } + log_debug("Hue auto shift interval [%2d] : %d", channel, hueInterval); +} + +void set_hue_auto_shift_speed(int channel, int8_t hueSpeed8) { + float hueSpeed = pow(1.065, hueSpeed8 - INT8_MAX / 2); + if (channel < LED_NCHANS) { + param.ledbar[channel].hueAutoShiftSpeed = hueSpeed; + } else { + for (size_t i = 0; i < LED_NCHANS; ++i) { + param.ledbar[i].hueAutoShiftSpeed = hueSpeed; + } + } + log_debug("Hue auto shift speed [%2d] : %d", channel, hueSpeed); } void set_luminosity(int channel, int8_t luminosity8) { @@ -113,6 +167,18 @@ void set_luminosity(int channel, int8_t luminosity8) { log_debug("Luminosity : %u", luminosity); } +void set_saturation(int channel, int8_t saturation8) { + uint8_t saturation = saturation8 * UINT8_MAX / INT8_MAX; + if (channel < LED_NCHANS) { + param.ledbar[channel].saturation = saturation; + } else { + for (size_t i = 0; i < LED_NCHANS; ++i) { + param.ledbar[i].saturation = saturation; + } + } + log_debug("Saturation : %u", saturation); +} + /*************************************************************************************************** * Internal Function Definitions **************************************************************************************************/ diff --git a/RpiLedBars/src/rpi_param.h b/RpiLedBars/src/rpi_param.h index 5573107..105b434 100644 --- a/RpiLedBars/src/rpi_param.h +++ b/RpiLedBars/src/rpi_param.h @@ -9,14 +9,15 @@ * Includes **************************************************************************************************/ +#include #include /*************************************************************************************************** * Preprocessor Constants and Macros **************************************************************************************************/ -#define CHAN_MAXLEDS 6 * 60 // Maximum number of LEDs per channel -#define LED_NCHANS 8 // Number of LED channels (8 or 16) +#define CHAN_MAXLEDS 60 // Maximum number of LEDs per channel +#define LED_NCHANS 8 // Number of LED channels (8 or 16) #define GLOBAL_CHANNEL 15 @@ -48,6 +49,7 @@ typedef struct { float sensitivity; unsigned int gravity; unsigned int pattern; + bool isHueAutoShiftEnabled; } auton_param_t; /** @@ -57,6 +59,10 @@ typedef struct { float sensitivity; unsigned int hueBase; int hueInterval; + unsigned int hueAutoShift; + int hueAutoShiftInterval; + float hueAutoShiftSpeed; + bool isIncreasing; unsigned int luminosity; unsigned int saturation; } ledbar_param_t; @@ -95,7 +101,14 @@ void set_pattern(unsigned int pattern); /** * \brief * - * \param[in] pattern + * \param[in] HasToBeEnabled + */ +void set_hue_auto_shift(bool HasToBeEnabled); + +/** + * \brief + * + * \param[in] gravity8 */ void set_gravity(int8_t gravity8); @@ -112,6 +125,12 @@ void set_hue_base(int channel, int8_t hueBase8); void set_hue_interval(int channel, int8_t hueInterval8); +void set_hue_auto_shift_interval(int channel, int8_t hueInterval8); + +void set_hue_auto_shift_speed(int channel, int8_t hueSpeed8); + void set_luminosity(int channel, int8_t luminosity8); +void set_saturation(int channel, int8_t saturation8); + #endif /* __RPI_PARAM_H__ */ \ No newline at end of file diff --git a/RpiLedBars/src/rpi_pattern.c b/RpiLedBars/src/rpi_pattern.c index 1c90390..8fceffc 100644 --- a/RpiLedBars/src/rpi_pattern.c +++ b/RpiLedBars/src/rpi_pattern.c @@ -8,6 +8,8 @@ #include "rpi_pattern.h" +#include + #include "log.h" #include "drivers/leddriver/rpi_leddriver.h" @@ -25,6 +27,11 @@ * Persistent Variables **************************************************************************************************/ +/** + * Index to channel translattion + */ +int channelTranslation[LED_NCHANS] = {0, 1, 2, 3, 4, 6, 7, 5}; + /** * RGB data buffer. Persistency is not needed but, as of it size, it must be declared in heap */ @@ -53,6 +60,10 @@ unsigned int get_led_to_light_count(uint16_t barValue, unsigned int barIndex); unsigned int get_first_led_to_light(unsigned int barIndex); +uint32_t get_hsv_color(unsigned int barIndex, float shiftRatio); + +void increment_autoshift(unsigned int barIndex); + /*************************************************************************************************** * External Function Definitions **************************************************************************************************/ @@ -68,14 +79,8 @@ void bounce_led_and_color(uint16_t *spectrumArray, unsigned int spectrumLength) barMax = apply_sensitivity(barMax, ledBarIndex); ledToLightCount = get_led_to_light_count(barMax, ledBarIndex); - int hueShift = (long)(ledToLightCount - 1) * param_access->ledbar[ledBarIndex].hueInterval / - (long)param_access->pixled.chanLedCount; - uint16_t hue = param_access->ledbar[ledBarIndex].hueBase + hueShift; - // log_trace("light %u leds on bar %u - hueShift : %d, hue %u", ledToLightCount, ledBarIndex, - // hueShift, hue); - uint32_t color = - ColorHSV(hue * UINT16_MAX / HUEBASE_MAX, param_access->ledbar[ledBarIndex].saturation, - param_access->ledbar[ledBarIndex].luminosity); + uint32_t color = get_hsv_color(ledBarIndex, (ledToLightCount - 1) / + (float)param_access->pixled.chanLedCount); for (size_t i = 0; i < ledToLightCount; ++i) { rgbData[i][ledBarIndex] = color; @@ -85,6 +90,8 @@ void bounce_led_and_color(uint16_t *spectrumArray, unsigned int spectrumLength) rgbData[i][ledBarIndex] = 0x000000; rgb_txdata(rgbData[i], i); } + + increment_autoshift(ledBarIndex); } leddriver_refresh(); @@ -102,12 +109,8 @@ void bounce_led(uint16_t *spectrumArray, unsigned int spectrumLength) { ledToLightCount = get_led_to_light_count(barMax, ledBarIndex); for (size_t i = 0; i < ledToLightCount; ++i) { - unsigned long hueShift = (long)i * param_access->ledbar[ledBarIndex].hueInterval / - (long)param_access->pixled.chanLedCount; - uint16_t hue = param_access->ledbar[ledBarIndex].hueBase + hueShift; - uint32_t color = - ColorHSV(hue * UINT16_MAX / HUEBASE_MAX, param_access->ledbar[ledBarIndex].saturation, - param_access->ledbar[ledBarIndex].luminosity); + + uint32_t color = get_hsv_color(ledBarIndex, i / (float)param_access->pixled.chanLedCount); rgbData[i][ledBarIndex] = color; rgb_txdata(rgbData[i], i); } @@ -115,6 +118,8 @@ void bounce_led(uint16_t *spectrumArray, unsigned int spectrumLength) { rgbData[i][ledBarIndex] = 0x000000; rgb_txdata(rgbData[i], i); } + + increment_autoshift(ledBarIndex); } leddriver_refresh(); @@ -125,25 +130,26 @@ void bounce_led_and_travel(uint16_t *spectrumArray, unsigned int spectrumLength) size_t intervalSize = spectrumLength / LED_NCHANS; uint16_t barMax = 0; unsigned int ledToLightCount = 0, firstLedToLight = get_first_led_to_light(ledBarIndex); + uint32_t color = 0; barMax = get_max_on_interval(spectrumArray, spectrumLength, ledBarIndex * intervalSize, intervalSize); barMax = apply_sensitivity(barMax, ledBarIndex) / 4; - ledToLightCount = get_led_to_light_count(barMax, ledBarIndex); + ledToLightCount = get_led_to_light_count(barMax, ledBarIndex) + 1; - unsigned long hueShift = (long)(ledToLightCount - 1) * 4L * - param_access->ledbar[ledBarIndex].hueInterval / - (long)param_access->pixled.chanLedCount; - uint16_t hue = param_access->ledbar[ledBarIndex].hueBase + hueShift; - uint32_t color = - ColorHSV(hue * UINT16_MAX / HUEBASE_MAX, param_access->ledbar[ledBarIndex].saturation, - param_access->ledbar[ledBarIndex].luminosity); + if (!param_access->auton.isHueAutoShiftEnabled) { + color = get_hsv_color(ledBarIndex, + (ledToLightCount - 1) * 4L / (float)param_access->pixled.chanLedCount); + } for (size_t i = 0; i < ledToLightCount; ++i) { unsigned int ledIndex = firstLedToLight + i; ledIndex = ledIndex < param_access->pixled.chanLedCount ? ledIndex : ledIndex - param_access->pixled.chanLedCount; + if (param_access->auton.isHueAutoShiftEnabled) { + color = get_hsv_color(ledBarIndex, ledIndex / (float)param_access->pixled.chanLedCount); + } rgbData[ledIndex][ledBarIndex] = color; rgb_txdata(rgbData[ledIndex], ledIndex); } @@ -155,6 +161,8 @@ void bounce_led_and_travel(uint16_t *spectrumArray, unsigned int spectrumLength) rgbData[ledIndex][ledBarIndex] = 0x000000; rgb_txdata(rgbData[ledIndex], ledIndex); } + + increment_autoshift(ledBarIndex); } leddriver_refresh(); @@ -204,4 +212,49 @@ unsigned int get_first_led_to_light(unsigned int barIndex) { } baseLedIndexArray[barIndex] = firstLed; return firstLed; +} + +uint32_t get_hsv_color(unsigned int barIndex, float shiftRatio) { + int hueShift = shiftRatio * param_access->ledbar[barIndex].hueInterval; + uint16_t hue = param_access->ledbar[barIndex].hueBase + + (param_access->ledbar[barIndex].hueAutoShift) + hueShift; + // log_trace("hueAutoShift : %010x, hueShift : %d, hue %u", + // param_access->ledbar[barIndex].hueAutoShift, hueShift, hue); + uint32_t color = + ColorHSV(hue * UINT16_MAX / HUEBASE_MAX, param_access->ledbar[barIndex].saturation, + param_access->ledbar[barIndex].luminosity); + return color; +} + +void increment_autoshift(unsigned int barIndex) { + static float increment[LED_NCHANS]; + if (param_access->auton.isHueAutoShiftEnabled) { + int const hueInterval = param_access->ledbar[barIndex].hueAutoShiftInterval; + int hueAutoShift = param_access->ledbar[barIndex].hueAutoShift; + if ((hueInterval > 0 && param_access->ledbar[barIndex].isIncreasing) || + (hueInterval < 0 && !param_access->ledbar[barIndex].isIncreasing)) { + increment[barIndex] += param_access->ledbar[barIndex].hueAutoShiftSpeed; + } else if (hueInterval != 0) { + increment[barIndex] -= param_access->ledbar[barIndex].hueAutoShiftSpeed; + } + + if (abs(increment[barIndex]) > 1) { + hueAutoShift += increment[barIndex]; + increment[barIndex] = increment[barIndex] - (int)increment[barIndex]; + } + + if ((hueInterval > 0 && hueAutoShift < 0) || (hueInterval < 0 && hueAutoShift > 0)) { + hueAutoShift = -hueAutoShift; + param_access->ledbar[barIndex].isIncreasing = !param_access->ledbar[barIndex].isIncreasing; + } else if ((hueInterval > 0 && hueAutoShift > hueInterval) || + (hueInterval < 0 && hueAutoShift < hueInterval)) { + hueAutoShift = hueInterval; + param_access->ledbar[barIndex].isIncreasing = !param_access->ledbar[barIndex].isIncreasing; + } + if (barIndex == 0) { + log_trace("hueInterval : %d, hueAutoShift : %d, increase : %s", hueInterval, hueAutoShift, + param_access->ledbar[barIndex].isIncreasing ? "yes" : "no"); + } + param_access->ledbar[barIndex].hueAutoShift = hueAutoShift; + } } \ No newline at end of file