a lot of new stuff

This commit is contained in:
Tropicananass 2021-09-05 20:04:42 +01:00
parent c93997776d
commit a1033b265e
8 changed files with 481 additions and 53 deletions

View File

@ -21,4 +21,39 @@ biblio:
* ws2812 with dma/smi from Jeremy P Bentham :
* ws2812 - https://iosoft.blog/2020/09/29/raspberry-pi-multi-channel-ws2812/
* dma - https://iosoft.blog/2020/05/25/raspberry-pi-dma-programming/
* smi - https://iosoft.blog/2020/07/16/raspberry-pi-smi/
* smi - https://iosoft.blog/2020/07/16/raspberry-pi-smi/
Raspi Config :
https://makersportal.com/blog/recording-stereo-audio-on-a-raspberry-pi
https://learn.adafruit.com/adafruit-i2s-mems-microphone-breakout/raspberry-pi-wiring-test
sudo apt install python3-pip
sudo pip3 install --upgrade adafruit-python-shell
cd /tmp
sudo wget https://raw.githubusercontent.com/adafruit/Raspberry-Pi-Installer-Scripts/master/i2smic.py
sudo python3 i2smic.py
# plug microphone
sudo reboot
arecord -l
arecord -D plughw:1 -c1 -r 48000 -f S32_LE -t wav -V mono -v file.wav
# Control record volume
cp res/.asoundrc ~/.asoundrc
# alsa API
http://www.equalarea.com/paul/alsa-audio.html
# for project
sudo apt install libasound2-dev wiringpi
# for cava
sudo apt install libfftw3-dev libasound2-dev libtool automake
./autogen.sh
./configure
make
sudo make install
# Access point
grep "Access point conf" $(find /etc -type f)

View File

@ -3,7 +3,7 @@ Description=pixled
After=network.target
[Service]
ExecStart=pixled -n 180 -d 2
ExecStart=pixled -n 60 -d 2
Restart=always
User=root
Group=root

View File

@ -26,6 +26,7 @@
#include "rpi_midi_controller.h"
#include "rpi_param.h"
#include "rpi_pattern.h"
/***************************************************************************************************
* Preprocessor Constants and Macros
@ -40,7 +41,6 @@
**************************************************************************************************/
/* Command-line parameters */
bool IsTestMode = false;
int chanLedCount = 0;
int logLevel = 2;
int previousMode = -1;
@ -79,9 +79,6 @@ void log_lock_helper(bool lock, void *udata);
int main(int argc, char const *argv[]) {
// setup
parseCommandLineArgs(argc, argv);
log_set_level(logLevel);
signal(SIGINT, terminate);
struct sched_param sp;
@ -98,7 +95,7 @@ int main(int argc, char const *argv[]) {
selector_setup();
leddriver_setup();
// setup_cava();
parseCommandLineArgs(argc, argv);
// loop
while (1) {
@ -149,7 +146,7 @@ void parseCommandLineArgs(int argc, char const *argv[]) {
log_error("no numeric value");
exit(-EXIT_FAILURE);
} else {
chanLedCount = atoi(argv[++args]);
param_access->pixled.chanLedCount = atoi(argv[++args]);
}
break;
case 'D': // -D: debug level
@ -158,6 +155,7 @@ void parseCommandLineArgs(int argc, char const *argv[]) {
exit(-EXIT_FAILURE);
} else {
logLevel = atoi(argv[++args]);
log_set_level(logLevel);
}
break;
case 'T': // -T: test mode
@ -189,6 +187,7 @@ void manage_tasks(int previousMode, int currentMode) {
artnet_stop();
break;
case 2:
case 3:
cava_stop();
break;
default:
@ -201,6 +200,7 @@ void manage_tasks(int previousMode, int currentMode) {
artnet_start();
break;
case 2:
case 3:
cava_start();
break;
default:
@ -241,13 +241,14 @@ void execute_test_mode() {
static int i = 0, offset = 0;
for (size_t ledIndex = 0; ledIndex < chanLedCount; ++ledIndex) {
set_color(ledIndex <= offset % chanLedCount ? on_rgbs[i] * .5 : off_rgbs, ledIndex);
for (size_t ledIndex = 0; ledIndex < param_access->pixled.chanLedCount; ++ledIndex) {
set_color(ledIndex <= offset % param_access->pixled.chanLedCount ? on_rgbs[i] * .5 : off_rgbs,
ledIndex);
}
leddriver_refresh();
if (offset < chanLedCount) {
if (offset < param_access->pixled.chanLedCount) {
++offset;
} else {
offset = 0;
@ -267,7 +268,7 @@ void execute_artnet_mode() {
for (size_t ledBar = 0; ledBar < LED_NCHANS; ledBar++) {
if (artnet_get_dmx_data(ledBar, &dmxData) == 0) {
for (size_t i = 0; i < chanLedCount; ++i) {
for (size_t i = 0; i < param_access->pixled.chanLedCount; ++i) {
uint8_t *rgb = dmxData + (i * 3);
rgb_data[i][ledBar] = (rgb[0] << 16) | (rgb[1] << 8) | rgb[2];
rgb_txdata(rgb_data[i], i);
@ -278,17 +279,39 @@ void execute_artnet_mode() {
leddriver_refresh();
}
uint16_t static const minHue = 120 * UINT16_MAX / 360;
uint16_t static const maxHue = 300 * UINT16_MAX / 360;
uint16_t static const hueInterval = UINT16_MAX - (maxHue - minHue);
void execute_autonomous_mode() {
int ret;
uint16_t *buffer;
if ((ret = cava_get_buffer(&buffer)) == 0) {
switch (param_access->auton.pattern) {
case 0:
bounce_led_and_color(buffer, CAVA_BAR_NUMBER);
break;
case 1:
bounce_led(buffer, CAVA_BAR_NUMBER);
break;
case 2:
bounce_led_and_travel(buffer, CAVA_BAR_NUMBER);
break;
default:
break;
}
}
}
unsigned baseLed[LED_NCHANS] = {0};
void execute_manual_mode() {
int ret;
uint16_t *buffer;
if ((ret = cava_get_buffer(&buffer)) == 0) {
for (size_t ledBarIndex = 0; ledBarIndex < LED_NCHANS; ++ledBarIndex) {
uint16_t barMax = 0;
// uint16_t hueInterval = UINT16_MAX - (param_access->ledbar[ledBarIndex].hueInterval -
// param_access->ledbar[ledBarIndex].hueBase);
for (size_t cavaBar = 0; cavaBar < CAVA_BAR_NUMBER / LED_NCHANS; ++cavaBar) {
unsigned barIndex = ledBarIndex * CAVA_BAR_NUMBER / LED_NCHANS + cavaBar;
if (barMax < buffer[barIndex]) {
@ -296,16 +319,17 @@ void execute_autonomous_mode() {
}
}
barMax *= param_access->auton.sensitivity * param_access->ledbar[ledBarIndex].sensitivity;
unsigned ledToLight = barMax * chanLedCount / UINT16_MAX;
unsigned long hueShift = (long)barMax * (long)hueInterval / hueInterval;
uint16_t hue = minHue - hueShift;
uint32_t color = ColorHSV(hue, 255, 100);
unsigned ledToLight = barMax * param_access->pixled.chanLedCount / 2 / UINT16_MAX;
unsigned long hueShift =
(long)barMax * (long)param_access->ledbar[ledBarIndex].hueInterval / UINT16_MAX;
uint16_t hue = param_access->ledbar[ledBarIndex].hueBase - hueShift;
uint32_t color = ColorHSV(hue, 255, param_access->ledbar[ledBarIndex].luminosity);
for (size_t i = 0; i < ledToLight; ++i) {
rgb_data[i][ledBarIndex] = color;
rgb_txdata(rgb_data[i], i);
}
for (size_t i = ledToLight; i < chanLedCount; ++i) {
for (size_t i = ledToLight; i < param_access->pixled.chanLedCount; ++i) {
rgb_data[i][ledBarIndex] = 0x000000;
rgb_txdata(rgb_data[i], i);
}
@ -315,16 +339,6 @@ void execute_autonomous_mode() {
}
}
void execute_manual_mode() {
for (size_t ledBarIndex = 0; ledBarIndex < LED_NCHANS; ++ledBarIndex) {
for (size_t i = 0; i < chanLedCount; ++i) {
rgb_data[i][ledBarIndex] = 0x000000;
rgb_txdata(rgb_data[i], i);
}
}
leddriver_refresh();
}
void adjust_loop(struct timespec const *loopStart) {
struct timespec loopEnd;
long elapsedTimeUs, remainingTimeUs;

View File

@ -18,7 +18,8 @@
* Preprocessor Constants and Macros
**************************************************************************************************/
#define C3 0x30
#define C3 48
#define Gd3 56
/***************************************************************************************************
* Type and Contant Definitions
@ -161,35 +162,52 @@ void handle_in_port_events(snd_seq_event_t *ev) {
destChannel = ev->data.control.value;
log_info("Control param channel %d", ev->data.control.value);
}
} else {
log_debug("PGMCHANGE : ch %#04x - param %u - value %d", ev->data.control.channel,
ev->data.control.param, ev->data.control.value);
} else if (destChannel != GLOBAL_CHANNEL) {
log_info("Control global param");
destChannel = GLOBAL_CHANNEL;
}
break;
case SND_SEQ_EVENT_NOTEON:
if (ev->data.note.note == C3) {
if (destChannel != 0xf) {
destChannel = 0xf;
if (destChannel != GLOBAL_CHANNEL) {
destChannel = GLOBAL_CHANNEL;
log_info("Control global param");
}
} else if (ev->data.note.note >= Gd3) {
set_pattern(ev->data.note.note - Gd3);
} else {
log_debug("NOTEON : ch %#04x - note %d - vel %d", ev->data.note.channel, ev->data.note.note,
ev->data.note.velocity);
}
break;
case SND_SEQ_EVENT_NOTEOFF:
break;
case SND_SEQ_EVENT_CONTROLLER:
switch (ev->data.control.param) {
case 1:
set_sensitivity(destChannel, ev->data.control.value + 1);
set_sensitivity(destChannel, ev->data.control.value);
break;
case 2:
set_luminosity(destChannel, ev->data.control.value);
break;
case 3:
set_hue_base(destChannel, ev->data.control.value);
break;
case 4:
set_hue_interval(destChannel, ev->data.control.value);
break;
case 5:
set_gravity(ev->data.control.value);
break;
default:
log_debug("CONTROLLER : ch %#04x - param %u - value %d", ev->data.control.channel,
ev->data.control.param, ev->data.control.value);
break;
}
log_debug("CONTROLLER : ch %#04x - param %u - value %d", ev->data.control.channel,
ev->data.control.param, ev->data.control.value);
break;
default:

View File

@ -8,8 +8,11 @@
#include "rpi_param.h"
#include <math.h>
#include <stdlib.h>
#include "log.h"
/***************************************************************************************************
* Preprocessor Constants and Macros
**************************************************************************************************/
@ -18,9 +21,10 @@
* Type and Contant Definitions
**************************************************************************************************/
pixled_param_t const dummyPixledParam = {.intensity = .5, .hue = 0};
auton_param_t const dummyAutonParam = {.sensitivity = 1};
ledbar_param_t const dummyLedbarParam = {.sensitivity = 1};
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};
/***************************************************************************************************
* Persistent Variables
@ -39,18 +43,74 @@ param_t param;
void param_setup() {
param.pixled = dummyPixledParam;
param.auton = dummyAutonParam;
for (size_t i = 0; i < 10; ++i) {
for (size_t i = 0; i < LED_NCHANS; ++i) {
param.ledbar[i] = dummyLedbarParam;
}
param_access = &param;
}
void set_sensitivity(int channel, unsigned int sensitivity) {
if (channel >= 10) {
void set_pattern(unsigned int pattern) {
if (pattern != param.auton.pattern) {
param.auton.pattern = pattern;
log_debug("Pattern : %d", pattern);
}
}
void set_gravity(int8_t gravity8) {
param.auton.gravity = gravity8 * 100 / INT8_MAX;
log_debug("Gravity : %d", param.auton.gravity);
}
void set_sensitivity(int channel, int8_t sensitivity8) {
float sensitivity = pow(1.065, sensitivity8 - INT8_MAX / 2);
if (channel >= LED_NCHANS) {
param.auton.sensitivity = sensitivity;
} else {
param.ledbar[channel].sensitivity = sensitivity;
}
log_debug("Sensitivity : %f", sensitivity);
}
void set_hue_base(int channel, int8_t hueBase8) {
uint16_t hueBase = hueBase8 * HUEBASE_MAX / INT8_MAX;
if (channel < LED_NCHANS) {
param.ledbar[channel].hueBase = hueBase;
} else {
for (size_t i = 0; i < LED_NCHANS; ++i) {
param.ledbar[i].hueBase = hueBase;
}
}
log_debug("Hue base : %u", hueBase);
}
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 (channel < LED_NCHANS) {
param.ledbar[channel].hueInterval = hueInterval;
} else {
for (size_t i = 0; i < LED_NCHANS; ++i) {
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);
}
void set_luminosity(int channel, int8_t luminosity8) {
uint8_t luminosity = luminosity8 * UINT8_MAX / INT8_MAX;
if (channel < LED_NCHANS) {
param.ledbar[channel].luminosity = luminosity;
} else {
for (size_t i = 0; i < LED_NCHANS; ++i) {
param.ledbar[i].luminosity = luminosity;
}
}
log_debug("Luminosity : %u", luminosity);
}
/***************************************************************************************************

View File

@ -18,6 +18,18 @@
#define CHAN_MAXLEDS 6 * 60 // Maximum number of LEDs per channel
#define LED_NCHANS 8 // Number of LED channels (8 or 16)
#define GLOBAL_CHANNEL 15
#define HUE_MAX 359
#define HUEBASE_MIN 0
#define HUEBASE_MAX HUE_MAX
#define HUEINTERVAL_MIN -HUE_MAX
#define HUEINTERVAL_MAX HUE_MAX
#define LUMINOSITY_MIN 0
#define LUMINOSITY_MAX 255
#define SATURATION_MIN 0
#define SATURATION_MAX 255
/***************************************************************************************************
* Type and Contant Definitions
**************************************************************************************************/
@ -26,22 +38,27 @@
*
*/
typedef struct {
uint8_t intensity;
int hue;
unsigned int chanLedCount;
} pixled_param_t;
/**
*
*/
typedef struct {
unsigned int sensitivity;
float sensitivity;
unsigned int gravity;
unsigned int pattern;
} auton_param_t;
/**
*
*/
typedef struct {
unsigned int sensitivity;
float sensitivity;
unsigned int hueBase;
int hueInterval;
unsigned int luminosity;
unsigned int saturation;
} ledbar_param_t;
/**
@ -50,7 +67,7 @@ typedef struct {
typedef struct {
pixled_param_t pixled;
auton_param_t auton;
ledbar_param_t ledbar[10];
ledbar_param_t ledbar[LED_NCHANS];
} param_t;
/***************************************************************************************************
@ -68,13 +85,33 @@ param_t *param_access;
*/
void param_setup();
/**
* \brief
*
* \param[in] pattern
*/
void set_pattern(unsigned int pattern);
/**
* \brief
*
* \param[in] pattern
*/
void set_gravity(int8_t gravity8);
/**
* \brief
*
* \param[in] channel
*
* \param[in] sensitivity
* \param[in] sensitivity8
*/
void set_sensitivity(int channel, unsigned int sensitivity);
void set_sensitivity(int channel, int8_t sensitivity8);
void set_hue_base(int channel, int8_t hueBase8);
void set_hue_interval(int channel, int8_t hueInterval8);
void set_luminosity(int channel, int8_t luminosity8);
#endif /* __RPI_PARAM_H__ */

View File

@ -0,0 +1,207 @@
/** \file .c
* \brief This module
*/
/***************************************************************************************************
* Includes
**************************************************************************************************/
#include "rpi_pattern.h"
#include "log.h"
#include "drivers/leddriver/rpi_leddriver.h"
#include "rpi_param.h"
/***************************************************************************************************
* Preprocessor Constants and Macros
**************************************************************************************************/
/***************************************************************************************************
* Type and Contant Definitions
**************************************************************************************************/
/***************************************************************************************************
* Persistent Variables
**************************************************************************************************/
/**
* RGB data buffer. Persistency is not needed but, as of it size, it must be declared in heap
*/
int rgbData[CHAN_MAXLEDS][LED_NCHANS];
/**
* Number of led previously lighted per led bar
*/
int lightedLedCountArray[LED_NCHANS];
/**
* Index of first previously lighted per led bar
*/
int baseLedIndexArray[LED_NCHANS];
/***************************************************************************************************
* Internal Function Prototypes
**************************************************************************************************/
uint16_t get_max_on_interval(uint16_t *array, unsigned int length, size_t intervalMin,
size_t intervalSize);
uint16_t apply_sensitivity(uint16_t value, unsigned int valueIndex);
unsigned int get_led_to_light_count(uint16_t barValue, unsigned int barIndex);
unsigned int get_first_led_to_light(unsigned int barIndex);
/***************************************************************************************************
* External Function Definitions
**************************************************************************************************/
void bounce_led_and_color(uint16_t *spectrumArray, unsigned int spectrumLength) {
for (size_t ledBarIndex = 0; ledBarIndex < LED_NCHANS; ++ledBarIndex) {
size_t intervalSize = spectrumLength / LED_NCHANS;
uint16_t barMax = 0;
unsigned int ledToLightCount = 0;
barMax = get_max_on_interval(spectrumArray, spectrumLength, ledBarIndex * intervalSize,
intervalSize);
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);
for (size_t i = 0; i < ledToLightCount; ++i) {
rgbData[i][ledBarIndex] = color;
rgb_txdata(rgbData[i], i);
}
for (size_t i = ledToLightCount; i < param_access->pixled.chanLedCount; ++i) {
rgbData[i][ledBarIndex] = 0x000000;
rgb_txdata(rgbData[i], i);
}
}
leddriver_refresh();
}
void bounce_led(uint16_t *spectrumArray, unsigned int spectrumLength) {
for (size_t ledBarIndex = 0; ledBarIndex < LED_NCHANS; ++ledBarIndex) {
size_t intervalSize = spectrumLength / LED_NCHANS;
uint16_t barMax = 0;
unsigned int ledToLightCount = 0;
barMax = get_max_on_interval(spectrumArray, spectrumLength, ledBarIndex * intervalSize,
intervalSize);
barMax = apply_sensitivity(barMax, ledBarIndex);
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);
rgbData[i][ledBarIndex] = color;
rgb_txdata(rgbData[i], i);
}
for (size_t i = ledToLightCount; i < param_access->pixled.chanLedCount; ++i) {
rgbData[i][ledBarIndex] = 0x000000;
rgb_txdata(rgbData[i], i);
}
}
leddriver_refresh();
}
void bounce_led_and_travel(uint16_t *spectrumArray, unsigned int spectrumLength) {
for (size_t ledBarIndex = 0; ledBarIndex < LED_NCHANS; ++ledBarIndex) {
size_t intervalSize = spectrumLength / LED_NCHANS;
uint16_t barMax = 0;
unsigned int ledToLightCount = 0, firstLedToLight = get_first_led_to_light(ledBarIndex);
barMax = get_max_on_interval(spectrumArray, spectrumLength, ledBarIndex * intervalSize,
intervalSize);
barMax = apply_sensitivity(barMax, ledBarIndex) / 4;
ledToLightCount = get_led_to_light_count(barMax, ledBarIndex);
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);
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;
rgbData[ledIndex][ledBarIndex] = color;
rgb_txdata(rgbData[ledIndex], ledIndex);
}
for (size_t i = ledToLightCount; i < param_access->pixled.chanLedCount; ++i) {
unsigned int ledIndex = firstLedToLight + i;
ledIndex = ledIndex < param_access->pixled.chanLedCount
? ledIndex
: ledIndex - param_access->pixled.chanLedCount;
rgbData[ledIndex][ledBarIndex] = 0x000000;
rgb_txdata(rgbData[ledIndex], ledIndex);
}
}
leddriver_refresh();
}
/***************************************************************************************************
* Internal Function Definitions
**************************************************************************************************/
uint16_t get_max_on_interval(uint16_t *array, unsigned int length, size_t intervalMin,
size_t intervalSize) {
uint16_t barMax = 0;
for (size_t i = 0; i < intervalSize; ++i) {
unsigned barIndex = intervalMin + i;
if (barMax < array[barIndex]) {
barMax = array[barIndex];
}
}
return barMax;
}
uint16_t apply_sensitivity(uint16_t value, unsigned int valueIndex) {
return value * param_access->auton.sensitivity * param_access->ledbar[valueIndex].sensitivity;
}
unsigned int get_led_to_light_count(uint16_t barValue, unsigned int barIndex) {
unsigned int nbLightedLed = lightedLedCountArray[barIndex];
unsigned int ledToLightCount = barValue * param_access->pixled.chanLedCount / UINT16_MAX;
if (ledToLightCount < nbLightedLed) {
/* apply gravity */
ledToLightCount = ((ledToLightCount * (100 - param_access->auton.gravity)) +
(nbLightedLed * param_access->auton.gravity)) /
100;
}
lightedLedCountArray[barIndex] = ledToLightCount;
return ledToLightCount;
}
unsigned int get_first_led_to_light(unsigned int barIndex) {
unsigned int firstLed = baseLedIndexArray[barIndex];
if (lightedLedCountArray[barIndex] != 0) {
firstLed += lightedLedCountArray[barIndex] / 4 + 1;
firstLed = firstLed < param_access->pixled.chanLedCount
? firstLed
: firstLed - param_access->pixled.chanLedCount;
}
baseLedIndexArray[barIndex] = firstLed;
return firstLed;
}

View File

@ -0,0 +1,57 @@
/** \file .h
* \brief This module
*/
#if !defined(__RPI_PATTERN_H__)
#define __RPI_PATTERN_H__
/***************************************************************************************************
* Includes
**************************************************************************************************/
#include <stdint.h>
/***************************************************************************************************
* Preprocessor Constants and Macros
**************************************************************************************************/
/***************************************************************************************************
* Type and Contant Definitions
**************************************************************************************************/
/***************************************************************************************************
* Global Variables
**************************************************************************************************/
/***************************************************************************************************
* External Function Prototypes
**************************************************************************************************/
/**
* \brief
*
* \param[in] spectrumArray array of value from spectral analysis
*
* \param[in] spectrumLength length of spectrum array
*/
void bounce_led_and_color(uint16_t *spectrumArray, unsigned int spectrumLength);
/**
* \brief
*
* \param[in] spectrumArray array of value from spectral analysis
*
* \param[in] spectrumLength length of spectrum array
*/
void bounce_led(uint16_t *spectrumArray, unsigned int spectrumLength);
/**
* \brief
*
* \param[in] spectrumArray array of value from spectral analysis
*
* \param[in] spectrumLength length of spectrum array
*/
void bounce_led_and_travel(uint16_t *spectrumArray, unsigned int spectrumLength);
#endif /* __RPI_PATTERN_H__ */