a lot of new stuff
This commit is contained in:
parent
c93997776d
commit
a1033b265e
@ -21,4 +21,39 @@ biblio:
|
|||||||
* ws2812 with dma/smi from Jeremy P Bentham :
|
* ws2812 with dma/smi from Jeremy P Bentham :
|
||||||
* ws2812 - https://iosoft.blog/2020/09/29/raspberry-pi-multi-channel-ws2812/
|
* ws2812 - https://iosoft.blog/2020/09/29/raspberry-pi-multi-channel-ws2812/
|
||||||
* dma - https://iosoft.blog/2020/05/25/raspberry-pi-dma-programming/
|
* 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)
|
@ -3,7 +3,7 @@ Description=pixled
|
|||||||
After=network.target
|
After=network.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
ExecStart=pixled -n 180 -d 2
|
ExecStart=pixled -n 60 -d 2
|
||||||
Restart=always
|
Restart=always
|
||||||
User=root
|
User=root
|
||||||
Group=root
|
Group=root
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
#include "rpi_midi_controller.h"
|
#include "rpi_midi_controller.h"
|
||||||
#include "rpi_param.h"
|
#include "rpi_param.h"
|
||||||
|
#include "rpi_pattern.h"
|
||||||
|
|
||||||
/***************************************************************************************************
|
/***************************************************************************************************
|
||||||
* Preprocessor Constants and Macros
|
* Preprocessor Constants and Macros
|
||||||
@ -40,7 +41,6 @@
|
|||||||
**************************************************************************************************/
|
**************************************************************************************************/
|
||||||
/* Command-line parameters */
|
/* Command-line parameters */
|
||||||
bool IsTestMode = false;
|
bool IsTestMode = false;
|
||||||
int chanLedCount = 0;
|
|
||||||
int logLevel = 2;
|
int logLevel = 2;
|
||||||
|
|
||||||
int previousMode = -1;
|
int previousMode = -1;
|
||||||
@ -79,9 +79,6 @@ void log_lock_helper(bool lock, void *udata);
|
|||||||
|
|
||||||
int main(int argc, char const *argv[]) {
|
int main(int argc, char const *argv[]) {
|
||||||
// setup
|
// setup
|
||||||
parseCommandLineArgs(argc, argv);
|
|
||||||
log_set_level(logLevel);
|
|
||||||
|
|
||||||
signal(SIGINT, terminate);
|
signal(SIGINT, terminate);
|
||||||
|
|
||||||
struct sched_param sp;
|
struct sched_param sp;
|
||||||
@ -98,7 +95,7 @@ int main(int argc, char const *argv[]) {
|
|||||||
selector_setup();
|
selector_setup();
|
||||||
leddriver_setup();
|
leddriver_setup();
|
||||||
|
|
||||||
// setup_cava();
|
parseCommandLineArgs(argc, argv);
|
||||||
|
|
||||||
// loop
|
// loop
|
||||||
while (1) {
|
while (1) {
|
||||||
@ -149,7 +146,7 @@ void parseCommandLineArgs(int argc, char const *argv[]) {
|
|||||||
log_error("no numeric value");
|
log_error("no numeric value");
|
||||||
exit(-EXIT_FAILURE);
|
exit(-EXIT_FAILURE);
|
||||||
} else {
|
} else {
|
||||||
chanLedCount = atoi(argv[++args]);
|
param_access->pixled.chanLedCount = atoi(argv[++args]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'D': // -D: debug level
|
case 'D': // -D: debug level
|
||||||
@ -158,6 +155,7 @@ void parseCommandLineArgs(int argc, char const *argv[]) {
|
|||||||
exit(-EXIT_FAILURE);
|
exit(-EXIT_FAILURE);
|
||||||
} else {
|
} else {
|
||||||
logLevel = atoi(argv[++args]);
|
logLevel = atoi(argv[++args]);
|
||||||
|
log_set_level(logLevel);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'T': // -T: test mode
|
case 'T': // -T: test mode
|
||||||
@ -189,6 +187,7 @@ void manage_tasks(int previousMode, int currentMode) {
|
|||||||
artnet_stop();
|
artnet_stop();
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
|
case 3:
|
||||||
cava_stop();
|
cava_stop();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -201,6 +200,7 @@ void manage_tasks(int previousMode, int currentMode) {
|
|||||||
artnet_start();
|
artnet_start();
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
|
case 3:
|
||||||
cava_start();
|
cava_start();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -241,13 +241,14 @@ void execute_test_mode() {
|
|||||||
|
|
||||||
static int i = 0, offset = 0;
|
static int i = 0, offset = 0;
|
||||||
|
|
||||||
for (size_t ledIndex = 0; ledIndex < chanLedCount; ++ledIndex) {
|
for (size_t ledIndex = 0; ledIndex < param_access->pixled.chanLedCount; ++ledIndex) {
|
||||||
set_color(ledIndex <= offset % chanLedCount ? on_rgbs[i] * .5 : off_rgbs, ledIndex);
|
set_color(ledIndex <= offset % param_access->pixled.chanLedCount ? on_rgbs[i] * .5 : off_rgbs,
|
||||||
|
ledIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
leddriver_refresh();
|
leddriver_refresh();
|
||||||
|
|
||||||
if (offset < chanLedCount) {
|
if (offset < param_access->pixled.chanLedCount) {
|
||||||
++offset;
|
++offset;
|
||||||
} else {
|
} else {
|
||||||
offset = 0;
|
offset = 0;
|
||||||
@ -267,7 +268,7 @@ void execute_artnet_mode() {
|
|||||||
|
|
||||||
for (size_t ledBar = 0; ledBar < LED_NCHANS; ledBar++) {
|
for (size_t ledBar = 0; ledBar < LED_NCHANS; ledBar++) {
|
||||||
if (artnet_get_dmx_data(ledBar, &dmxData) == 0) {
|
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);
|
uint8_t *rgb = dmxData + (i * 3);
|
||||||
rgb_data[i][ledBar] = (rgb[0] << 16) | (rgb[1] << 8) | rgb[2];
|
rgb_data[i][ledBar] = (rgb[0] << 16) | (rgb[1] << 8) | rgb[2];
|
||||||
rgb_txdata(rgb_data[i], i);
|
rgb_txdata(rgb_data[i], i);
|
||||||
@ -278,17 +279,39 @@ void execute_artnet_mode() {
|
|||||||
leddriver_refresh();
|
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() {
|
void execute_autonomous_mode() {
|
||||||
int ret;
|
int ret;
|
||||||
uint16_t *buffer;
|
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) {
|
if ((ret = cava_get_buffer(&buffer)) == 0) {
|
||||||
for (size_t ledBarIndex = 0; ledBarIndex < LED_NCHANS; ++ledBarIndex) {
|
for (size_t ledBarIndex = 0; ledBarIndex < LED_NCHANS; ++ledBarIndex) {
|
||||||
uint16_t barMax = 0;
|
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) {
|
for (size_t cavaBar = 0; cavaBar < CAVA_BAR_NUMBER / LED_NCHANS; ++cavaBar) {
|
||||||
unsigned barIndex = ledBarIndex * CAVA_BAR_NUMBER / LED_NCHANS + cavaBar;
|
unsigned barIndex = ledBarIndex * CAVA_BAR_NUMBER / LED_NCHANS + cavaBar;
|
||||||
if (barMax < buffer[barIndex]) {
|
if (barMax < buffer[barIndex]) {
|
||||||
@ -296,16 +319,17 @@ void execute_autonomous_mode() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
barMax *= param_access->auton.sensitivity * param_access->ledbar[ledBarIndex].sensitivity;
|
barMax *= param_access->auton.sensitivity * param_access->ledbar[ledBarIndex].sensitivity;
|
||||||
unsigned ledToLight = barMax * chanLedCount / UINT16_MAX;
|
unsigned ledToLight = barMax * param_access->pixled.chanLedCount / 2 / UINT16_MAX;
|
||||||
unsigned long hueShift = (long)barMax * (long)hueInterval / hueInterval;
|
unsigned long hueShift =
|
||||||
uint16_t hue = minHue - hueShift;
|
(long)barMax * (long)param_access->ledbar[ledBarIndex].hueInterval / UINT16_MAX;
|
||||||
uint32_t color = ColorHSV(hue, 255, 100);
|
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) {
|
for (size_t i = 0; i < ledToLight; ++i) {
|
||||||
rgb_data[i][ledBarIndex] = color;
|
rgb_data[i][ledBarIndex] = color;
|
||||||
rgb_txdata(rgb_data[i], i);
|
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_data[i][ledBarIndex] = 0x000000;
|
||||||
rgb_txdata(rgb_data[i], i);
|
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) {
|
void adjust_loop(struct timespec const *loopStart) {
|
||||||
struct timespec loopEnd;
|
struct timespec loopEnd;
|
||||||
long elapsedTimeUs, remainingTimeUs;
|
long elapsedTimeUs, remainingTimeUs;
|
||||||
|
@ -18,7 +18,8 @@
|
|||||||
* Preprocessor Constants and Macros
|
* Preprocessor Constants and Macros
|
||||||
**************************************************************************************************/
|
**************************************************************************************************/
|
||||||
|
|
||||||
#define C3 0x30
|
#define C3 48
|
||||||
|
#define Gd3 56
|
||||||
|
|
||||||
/***************************************************************************************************
|
/***************************************************************************************************
|
||||||
* Type and Contant Definitions
|
* Type and Contant Definitions
|
||||||
@ -161,35 +162,52 @@ void handle_in_port_events(snd_seq_event_t *ev) {
|
|||||||
destChannel = ev->data.control.value;
|
destChannel = ev->data.control.value;
|
||||||
log_info("Control param channel %d", ev->data.control.value);
|
log_info("Control param channel %d", ev->data.control.value);
|
||||||
}
|
}
|
||||||
} else {
|
} else if (destChannel != GLOBAL_CHANNEL) {
|
||||||
log_debug("PGMCHANGE : ch %#04x - param %u - value %d", ev->data.control.channel,
|
log_info("Control global param");
|
||||||
ev->data.control.param, ev->data.control.value);
|
destChannel = GLOBAL_CHANNEL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SND_SEQ_EVENT_NOTEON:
|
case SND_SEQ_EVENT_NOTEON:
|
||||||
if (ev->data.note.note == C3) {
|
if (ev->data.note.note == C3) {
|
||||||
if (destChannel != 0xf) {
|
if (destChannel != GLOBAL_CHANNEL) {
|
||||||
destChannel = 0xf;
|
destChannel = GLOBAL_CHANNEL;
|
||||||
log_info("Control global param");
|
log_info("Control global param");
|
||||||
}
|
}
|
||||||
|
} else if (ev->data.note.note >= Gd3) {
|
||||||
|
set_pattern(ev->data.note.note - Gd3);
|
||||||
} else {
|
} else {
|
||||||
log_debug("NOTEON : ch %#04x - note %d - vel %d", ev->data.note.channel, ev->data.note.note,
|
log_debug("NOTEON : ch %#04x - note %d - vel %d", ev->data.note.channel, ev->data.note.note,
|
||||||
ev->data.note.velocity);
|
ev->data.note.velocity);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SND_SEQ_EVENT_NOTEOFF:
|
||||||
|
break;
|
||||||
|
|
||||||
case SND_SEQ_EVENT_CONTROLLER:
|
case SND_SEQ_EVENT_CONTROLLER:
|
||||||
switch (ev->data.control.param) {
|
switch (ev->data.control.param) {
|
||||||
case 1:
|
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;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
log_debug("CONTROLLER : ch %#04x - param %u - value %d", ev->data.control.channel,
|
||||||
|
ev->data.control.param, ev->data.control.value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
log_debug("CONTROLLER : ch %#04x - param %u - value %d", ev->data.control.channel,
|
|
||||||
ev->data.control.param, ev->data.control.value);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -8,8 +8,11 @@
|
|||||||
|
|
||||||
#include "rpi_param.h"
|
#include "rpi_param.h"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
/***************************************************************************************************
|
/***************************************************************************************************
|
||||||
* Preprocessor Constants and Macros
|
* Preprocessor Constants and Macros
|
||||||
**************************************************************************************************/
|
**************************************************************************************************/
|
||||||
@ -18,9 +21,10 @@
|
|||||||
* Type and Contant Definitions
|
* Type and Contant Definitions
|
||||||
**************************************************************************************************/
|
**************************************************************************************************/
|
||||||
|
|
||||||
pixled_param_t const dummyPixledParam = {.intensity = .5, .hue = 0};
|
pixled_param_t const dummyPixledParam = {.chanLedCount = 0};
|
||||||
auton_param_t const dummyAutonParam = {.sensitivity = 1};
|
auton_param_t const dummyAutonParam = {.sensitivity = 10, .gravity = 80, .pattern = 2};
|
||||||
ledbar_param_t const dummyLedbarParam = {.sensitivity = 1};
|
ledbar_param_t const dummyLedbarParam = {
|
||||||
|
.sensitivity = 1., .hueBase = 121, .hueInterval = -100, .luminosity = 20, .saturation = 255};
|
||||||
|
|
||||||
/***************************************************************************************************
|
/***************************************************************************************************
|
||||||
* Persistent Variables
|
* Persistent Variables
|
||||||
@ -39,18 +43,74 @@ param_t param;
|
|||||||
void param_setup() {
|
void param_setup() {
|
||||||
param.pixled = dummyPixledParam;
|
param.pixled = dummyPixledParam;
|
||||||
param.auton = dummyAutonParam;
|
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.ledbar[i] = dummyLedbarParam;
|
||||||
}
|
}
|
||||||
param_access = ¶m;
|
param_access = ¶m;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_sensitivity(int channel, unsigned int sensitivity) {
|
void set_pattern(unsigned int pattern) {
|
||||||
if (channel >= 10) {
|
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;
|
param.auton.sensitivity = sensitivity;
|
||||||
} else {
|
} else {
|
||||||
param.ledbar[channel].sensitivity = sensitivity;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************************************************
|
/***************************************************************************************************
|
||||||
|
@ -18,6 +18,18 @@
|
|||||||
#define CHAN_MAXLEDS 6 * 60 // Maximum number of LEDs per channel
|
#define CHAN_MAXLEDS 6 * 60 // Maximum number of LEDs per channel
|
||||||
#define LED_NCHANS 8 // Number of LED channels (8 or 16)
|
#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
|
* Type and Contant Definitions
|
||||||
**************************************************************************************************/
|
**************************************************************************************************/
|
||||||
@ -26,22 +38,27 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t intensity;
|
unsigned int chanLedCount;
|
||||||
int hue;
|
|
||||||
} pixled_param_t;
|
} pixled_param_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned int sensitivity;
|
float sensitivity;
|
||||||
|
unsigned int gravity;
|
||||||
|
unsigned int pattern;
|
||||||
} auton_param_t;
|
} auton_param_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned int sensitivity;
|
float sensitivity;
|
||||||
|
unsigned int hueBase;
|
||||||
|
int hueInterval;
|
||||||
|
unsigned int luminosity;
|
||||||
|
unsigned int saturation;
|
||||||
} ledbar_param_t;
|
} ledbar_param_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,7 +67,7 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
pixled_param_t pixled;
|
pixled_param_t pixled;
|
||||||
auton_param_t auton;
|
auton_param_t auton;
|
||||||
ledbar_param_t ledbar[10];
|
ledbar_param_t ledbar[LED_NCHANS];
|
||||||
} param_t;
|
} param_t;
|
||||||
|
|
||||||
/***************************************************************************************************
|
/***************************************************************************************************
|
||||||
@ -68,13 +85,33 @@ param_t *param_access;
|
|||||||
*/
|
*/
|
||||||
void param_setup();
|
void param_setup();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* \param[in] pattern
|
||||||
|
*/
|
||||||
|
void set_pattern(unsigned int pattern);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* \param[in] pattern
|
||||||
|
*/
|
||||||
|
void set_gravity(int8_t gravity8);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief
|
* \brief
|
||||||
*
|
*
|
||||||
* \param[in] channel
|
* \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__ */
|
#endif /* __RPI_PARAM_H__ */
|
207
RpiLedBars/src/rpi_pattern.c
Normal file
207
RpiLedBars/src/rpi_pattern.c
Normal 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;
|
||||||
|
}
|
57
RpiLedBars/src/rpi_pattern.h
Normal file
57
RpiLedBars/src/rpi_pattern.h
Normal 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__ */
|
Loading…
Reference in New Issue
Block a user