No meters

This commit is contained in:
Geens 2024-03-24 16:25:56 +01:00
commit 8cab458c23
24 changed files with 780 additions and 0 deletions

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
.pio
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/extensions.json
.vscode/ipch
.vscode/launch.json
.vscode/settings.json

13
platformio.ini Normal file
View File

@ -0,0 +1,13 @@
[env:nano_33_iot]
platform = atmelsam
board = nano_33_iot
framework = arduino
build_flags="-DconfigTICK_RATE_HZ ((TickType_t)2000)"
lib_deps =
briscoetech/FreeRTOS_SAMD21@^2
arduino-libraries/WiFiNINA@^1
hideakitai/ArduinoOSC@^0.4
tedtoal/wiring_analog_SAMD_TT@^1
makuna/NeoPixelBus@^2
ruiseixasm/Versatile_RotaryEncoder@^1

48
src/analog_read.cpp Normal file
View File

@ -0,0 +1,48 @@
#include "analog_read.h"
#include <Arduino.h>
#include <FreeRTOS_SAMD21.h>
#include <wiring_analog_SAMD_TT.h>
#include <wiring_private.h>
#include "mapping.h"
#include "priority.h"
#include "util.h"
void analog_read_task(void *pvParameters);
TaskHandle_t analog_read_task_handle;
SemaphoreHandle_t analog_read_mutex;
AnalogReadData analog_read_data;
void setup_analog_read() {
analogReadResolution_SAMD_TT(12);
analogReference_SAMD_TT(AR_DEFAULT);
xTaskCreate(analog_read_task, "analog_read_task", 256, NULL, ANALOG_READ_PRIORITY, &analog_read_task_handle);
analog_read_mutex = xSemaphoreCreateMutex();
}
void analog_read_task(void *pvParameters) {
for(;;) {
xSemaphoreTake(analog_read_mutex, portMAX_DELAY);
analog_read_data.preamp += 0.1 * ((float) analogRead_SAMD_TT(PREAMP_PIN) - analog_read_data.preamp);
analog_read_data.buzz += 0.1 * ((float) analogRead_SAMD_TT(BUZZ_PIN) - analog_read_data.buzz);
analog_read_data.punch += 0.1 * ((float) analogRead_SAMD_TT(PUNCH_PIN) - analog_read_data.punch);
analog_read_data.crunch += 0.1 * ((float) analogRead_SAMD_TT(CRUNCH_PIN) - analog_read_data.crunch);
analog_read_data.drive += 0.1 * ((float) analogRead_SAMD_TT(DRIVE_PIN) - analog_read_data.drive);
analog_read_data.level += 0.1 * ((float) analogRead_SAMD_TT(LEVEL_PIN) - analog_read_data.level);
analog_read_data.low += 0.1 * ((float) analogRead_SAMD_TT(LOW_PIN) - analog_read_data.low);
analog_read_data.high += 0.1 * ((float) analogRead_SAMD_TT(HIGH_PIN) - analog_read_data.high);
xSemaphoreGive(analog_read_mutex);
delay_ms(30);
}
}
AnalogReadData get_analog_read_data() {
xSemaphoreTake(analog_read_mutex, portMAX_DELAY);
AnalogReadData copy = analog_read_data;
xSemaphoreGive(analog_read_mutex);
return copy;
}

16
src/analog_read.h Normal file
View File

@ -0,0 +1,16 @@
#pragma once
typedef struct {
float preamp;
float buzz;
float punch;
float crunch;
float drive;
float level;
float low;
float high;
} AnalogReadData;
void setup_analog_read();
AnalogReadData get_analog_read_data();

22
src/color.h Normal file
View File

@ -0,0 +1,22 @@
#pragma once
#define COLOR_OFF RgbColor(0, 0, 0)
#define COLOR_RED RgbColor(50, 0, 0)
#define COLOR_GREEN RgbColor(0, 50, 0)
#define COLOR_BLUE RgbColor(0, 0, 50)
#define COLOR_CYAN RgbColor(0, 25, 25)
#define COLOR_MAGENTA RgbColor(25, 0, 25)
#define COLOR_YELLOW RgbColor(25, 25, 0)
#define COLOR_SPINNER_FOREGROUND COLOR_BLUE
#define COLOR_SPINNER_BACKGROUND COLOR_OFF
#define COLOR_MAIN_MENU_GAIN COLOR_CYAN
#define COLOR_MAIN_MENU_FADER COLOR_MAGENTA
#define COLOR_MAIN_MENU_MASTER COLOR_YELLOW
#define COLOR_METER_PRE_FADER COLOR_RED
#define COLOR_METER_POST_FADER COLOR_GREEN
#define COLOR_METER_MASTER COLOR_BLUE

62
src/connect.cpp Normal file
View File

@ -0,0 +1,62 @@
#include "connect.h"
#include <Arduino.h>
#include <FreeRTOS_SAMD21.h>
#include <WiFi.h>
#include "main.h"
#include "network.h"
#include "priority.h"
#include "util.h"
void check_connection_task(void *pvParameters);
void connect_task(void *pvParameters);
TaskHandle_t check_connection_task_handle;
TaskHandle_t connect_task_handle;
SemaphoreHandle_t connect_semaphore;
wl_status_t wifi_status = WL_IDLE_STATUS;
void setup_connect() {
xTaskCreate(check_connection_task, "check_connection_task", 64, NULL, CHECK_CONNECT_PRIORITY, &check_connection_task_handle);
xTaskCreate(connect_task, "connect_task", 128, NULL, CONNECT_PRIORITY, &connect_task_handle);
connect_semaphore = xSemaphoreCreateBinary();
}
void check_connection_task(void *pvParameters) {
for(;;) {
if (wifi_status != WL_CONNECTED) {
xSemaphoreGive(connect_semaphore);
delay_ms(15000);
} else {
delay_ms(5000);
}
}
}
void connect_task(void *pvParameters) {
for(;;) {
xSemaphoreTake(connect_semaphore, portMAX_DELAY);
connection_lost();
Serial.println("Connecting");
wifi_status = (wl_status_t) WiFi.begin(WIFI_SSID, WIFI_PASS);
for (int i = 0; i < 10; i++) {
delay_ms(1000);
wifi_status = (wl_status_t) WiFi.status();
if (wifi_status == WL_CONNECTED) {
connection_established();
Serial.print("Connected with ip ");
Serial.println(WiFi.localIP());
break;
}
}
}
}
bool connected() {
return wifi_status == WL_CONNECTED;
}

5
src/connect.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
void setup_connect();
bool connected();

35
src/digital_read.cpp Normal file
View File

@ -0,0 +1,35 @@
#include "digital_read.h"
#include <FreeRTOS_SAMD21.h>
#include "mapping.h"
#include "priority.h"
#include "util.h"
void digital_read_task(void *pvParameters);
TaskHandle_t digital_read_task_handle;
SemaphoreHandle_t digital_read_mutex;
DigitalReadData digital_read_data;
void setup_digital_read() {
xTaskCreate(digital_read_task, "digital_read_task", 256, NULL, DIGITAL_READ_PRIORITY, &digital_read_task_handle);
digital_read_mutex = xSemaphoreCreateMutex();
}
void digital_read_task(void *pvParameters) {
for (;;) {
xSemaphoreTake(digital_read_mutex, portMAX_DELAY);
digital_read_data.cabinet = digitalRead(CABINET_PIN);
xSemaphoreGive(digital_read_mutex);
delay_ms(100);
}
}
DigitalReadData get_digital_read_data() {
xSemaphoreTake(digital_read_mutex, portMAX_DELAY);
DigitalReadData copy = digital_read_data;
xSemaphoreGive(digital_read_mutex);
return copy;
}

9
src/digital_read.h Normal file
View File

@ -0,0 +1,9 @@
#pragma once
typedef struct {
bool cabinet;
} DigitalReadData;
void setup_digital_read();
DigitalReadData get_digital_read_data();

50
src/encoder.cpp Normal file
View File

@ -0,0 +1,50 @@
#include "encoder.h"
#include <Arduino.h>
#include <FreeRTOS_SAMD21.h>
#include <Versatile_RotaryEncoder.h>
#include "main.h"
#include "mapping.h"
#include "priority.h"
#include "spinner.h"
#include "util.h"
void handle_press();
void handle_rotate(int8_t rotation);
void encoder_task(void *pvParameters);
TaskHandle_t encoder_task_handle;
Versatile_RotaryEncoder *encoder;
void setup_encoder() {
encoder = new Versatile_RotaryEncoder(ENCODER_PIN_CLK, ENCODER_PIN_DT, ENCODER_PIN_SW);
encoder->setHandlePress(handle_press);
encoder->setHandleRotate(handle_rotate);
xTaskCreate(encoder_task, "encoder_task", 64, NULL, ENCODER_PRIORITY, &encoder_task_handle);
}
void encoder_task(void *pvParameters) {
for(;;) {
encoder->ReadEncoder();
delay_ms(10);
}
}
void handle_press() {
Serial.println("Pressed");
next_main_menu_item();
}
void handle_rotate(int8_t rotation) {
Serial.println("Rotated");
rotation = -rotation;
if (rotation > 0) {
next_meter();
} else if (rotation < 0) {
previous_meter();
}
update_fader(rotation);
}

3
src/encoder.h Normal file
View File

@ -0,0 +1,3 @@
#pragma once
void setup_encoder();

64
src/led.cpp Normal file
View File

@ -0,0 +1,64 @@
#include "led.h"
#include <FreeRTOS_SAMD21.h>
#include "color.h"
#include "main.h"
SemaphoreHandle_t led_mutex;
NeoPixelBus<NeoRgbFeature, NeoWs2811Method> strip(LED_BAR_COUNT + 1, LED_PIN);
void setup_led() {
pinMode(LED_PIN, OUTPUT);
strip.Begin();
led_mutex = xSemaphoreCreateMutex();
}
void set_state_led() {
RgbColor color;
switch (current_state()) {
case State::Connecting:
color = COLOR_OFF;
break;
case State::MainMenu:
switch (current_main_menu_item()) {
case MainMenuItem::Gain:
color = COLOR_MAIN_MENU_GAIN;
break;
case MainMenuItem::Fader:
color = COLOR_MAIN_MENU_FADER;
break;
case MainMenuItem::Master:
color = COLOR_MAIN_MENU_MASTER;
break;
case MainMenuItem::Meter:
switch (current_meter()) {
case Meter::PreFader:
color = COLOR_METER_PRE_FADER;
break;
case Meter::PostFader:
color = COLOR_METER_POST_FADER;
break;
case Meter::Master:
color = COLOR_METER_MASTER;
break;
}
break;
}
break;
};
xSemaphoreTake(led_mutex, portMAX_DELAY);
strip.SetPixelColor(LED_BAR_COUNT, color);
strip.Show();
xSemaphoreGive(led_mutex);
}
void set_bar_leds(RgbColor bar[LED_BAR_COUNT]) {
xSemaphoreTake(led_mutex, portMAX_DELAY);
for (size_t i = 0; i < LED_BAR_COUNT; i++) {
strip.SetPixelColor(i, bar[i]);
}
strip.Show();
xSemaphoreGive(led_mutex);
}

10
src/led.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
#include <NeoPixelBus.h>
#include "mapping.h"
void setup_led();
void set_state_led();
void set_bar_leds(RgbColor bar[LED_BAR_COUNT]);

158
src/main.cpp Normal file
View File

@ -0,0 +1,158 @@
#include <Arduino.h>
#include <ArduinoOSCWiFi.h>
#include <FreeRTOS_SAMD21.h>
#include "analog_read.h"
#include "connect.h"
#include "color.h"
#include "digital_read.h"
#include "encoder.h"
#include "led.h"
#include "main.h"
#include "mapping.h"
#include "network.h"
#include "publish.h"
#include "spinner.h"
#include "util.h"
SemaphoreHandle_t state_mutex;
State state = State::Connecting;
MainMenuItem main_menu = MainMenuItem::Meter;
Meter meter = Meter::Master;
void setup() {
Serial.begin(9600);
setup_analog_read();
setup_connect();
setup_digital_read();
setup_encoder();
setup_led();
setup_publish();
setup_spinner();
state_mutex = xSemaphoreCreateMutex();
OscWiFi.publish(XAIR_IP, XAIR_PORT, "/xinfo")->setFrameRate(0.1);
OscWiFi.subscribe(LOCAL_PORT, "/*", print_osc_message);
vTaskStartScheduler();
Serial.println("Start scheduler failed");
}
void loop() {
for(;;) {}
}
void connection_established() {
xSemaphoreTakeRecursive(state_mutex, portMAX_DELAY);
state = State::MainMenu;
stop_spinner();
set_state_led();
xSemaphoreGiveRecursive(state_mutex);
}
void connection_lost() {
xSemaphoreTakeRecursive(state_mutex, portMAX_DELAY);
state = State::Connecting;
start_spinner();
set_state_led();
xSemaphoreGiveRecursive(state_mutex);
}
State current_state() {
xSemaphoreTakeRecursive(state_mutex, portMAX_DELAY);
State current_state = state;
xSemaphoreGiveRecursive(state_mutex);
return current_state;
}
void next_main_menu_item() {
xSemaphoreTakeRecursive(state_mutex, portMAX_DELAY);
if (State::Connecting == current_state()) {
xSemaphoreGiveRecursive(state_mutex);
return;
}
switch (main_menu) {
case MainMenuItem::Gain:
main_menu = MainMenuItem::Fader;
break;
case MainMenuItem::Fader:
main_menu = MainMenuItem::Master;
break;
case MainMenuItem::Master:
main_menu = MainMenuItem::Meter;
break;
case MainMenuItem::Meter:
main_menu = MainMenuItem::Gain;
break;
}
xSemaphoreGiveRecursive(state_mutex);
set_state_led();
}
MainMenuItem current_main_menu_item() {
xSemaphoreTakeRecursive(state_mutex, portMAX_DELAY);
MainMenuItem current_main_menu = main_menu;
xSemaphoreGiveRecursive(state_mutex);
return current_main_menu;
}
void previous_meter() {
xSemaphoreTakeRecursive(state_mutex, portMAX_DELAY);
if (State::Connecting == current_state()) {
xSemaphoreGiveRecursive(state_mutex);
return;
}
if (MainMenuItem::Meter != current_main_menu_item()) {
xSemaphoreGiveRecursive(state_mutex);
return;
}
switch (meter) {
case Meter::PreFader:
break;
case Meter::PostFader:
meter = Meter::PreFader;
break;
case Meter::Master:
meter = Meter::PostFader;
break;
}
xSemaphoreGiveRecursive(state_mutex);
set_state_led();
}
void next_meter() {
xSemaphoreTakeRecursive(state_mutex, portMAX_DELAY);
if (State::Connecting == current_state()) {
xSemaphoreGiveRecursive(state_mutex);
return;
}
if (MainMenuItem::Meter != current_main_menu_item()) {
xSemaphoreGiveRecursive(state_mutex);
return;
}
switch (meter) {
case Meter::PreFader:
meter = Meter::PostFader;
break;
case Meter::PostFader:
meter = Meter::Master;
break;
case Meter::Master:
break;
}
xSemaphoreGiveRecursive(state_mutex);
set_state_led();
}
Meter current_meter() {
xSemaphoreTakeRecursive(state_mutex, portMAX_DELAY);
Meter current_meter = meter;
xSemaphoreGiveRecursive(state_mutex);
return current_meter;
}
void update_fader(uint8_t value) {
}

34
src/main.h Normal file
View File

@ -0,0 +1,34 @@
#pragma once
#include <cstdint>
enum class State {
Connecting,
MainMenu
};
enum class MainMenuItem {
Gain,
Fader,
Master,
Meter
};
enum class Meter {
PreFader,
PostFader,
Master,
};
void connection_established();
void connection_lost();
State current_state();
void next_main_menu_item();
MainMenuItem current_main_menu_item();
void previous_meter();
void next_meter();
Meter current_meter();
void update_fader(uint8_t value);

30
src/mapping.h Normal file
View File

@ -0,0 +1,30 @@
#pragma once
#define ENCODER_PIN_CLK 8
#define ENCODER_PIN_DT 9
#define ENCODER_PIN_SW 10
#define CABINET_PIN 7
#define PREAMP_PIN A0
#define BUZZ_PIN A1
#define PUNCH_PIN A2
#define CRUNCH_PIN A3
#define DRIVE_PIN 5
#define LEVEL_PIN 4
#define LOW_PIN A6
#define HIGH_PIN A7
#define LED_PIN 12
#define LED_BAR_COUNT 10
#define CABINET_PAR "/fx/1/par/09"
#define PREAMP_PAR "/fx/1/par/01"
#define BUZZ_PAR "/fx/1/par/02"
#define PUNCH_PAR "/fx/1/par/03"
#define CRUNCH_PAR "/fx/1/par/04"
#define DRIVE_PAR "/fx/1/par/05"
#define LEVEL_PAR "/fx/1/par/06"
#define LOW_PAR "/fx/1/par/07"
#define HIGH_PAR "/fx/1/par/08"

9
src/network.h Normal file
View File

@ -0,0 +1,9 @@
#pragma once
#define WIFI_SSID "telenet-D6A9117"
#define WIFI_PASS "gewoonzonderhoofdletters"
#define XAIR_IP "192.168.0.4"
#define XAIR_PORT 10024
#define LOCAL_PORT 12345

14
src/priority.h Normal file
View File

@ -0,0 +1,14 @@
#pragma once
#define CHECK_CONNECT_PRIORITY 1
#define SPINNER_PRIORITY 1
#define ANALOG_READ_PRIORITY 2
#define DIGITAL_READ_PRIORITY 2
#define PUBLISH_PRIORITY 3
#define OSC_UPDATE_PRIORITY 4
#define ENCODER_PRIORITY 5
#define CONNECT_PRIORITY 5

68
src/publish.cpp Normal file
View File

@ -0,0 +1,68 @@
#include "publish.h"
#include <ArduinoOSCWiFi.h>
#include <FreeRTOS_SAMD21.h>
#include "analog_read.h"
#include "digital_read.h"
#include "mapping.h"
#include "network.h"
#include "priority.h"
#include "util.h"
void publish_task(void *pvParameters);
void osc_update_task(void *pvParameters);
TaskHandle_t publish_task_handle;
TaskHandle_t osc_update_task_handle;
SemaphoreHandle_t osc_mutex;
void setup_publish() {
xTaskCreate(publish_task, "publish_task", 256, NULL, PUBLISH_PRIORITY, &publish_task_handle);
xTaskCreate(osc_update_task, "osc_update_task", 256, NULL, OSC_UPDATE_PRIORITY, &osc_update_task_handle);
osc_mutex = xSemaphoreCreateMutex();
OscWiFi.getClient().localPort(LOCAL_PORT);
}
void publish_task(void *pvParameters) {
for(;;) {
delay_ms(100);
DigitalReadData digital_read_data = get_digital_read_data();
int cabinet_int = digital_read_data.cabinet ? 0 : 1;
AnalogReadData analog_read_data = get_analog_read_data();
float preamp_scaled = analog_read_data.preamp / 4095.f;
float buzz_scaled = analog_read_data.buzz / 4095.f;
float punch_scaled = analog_read_data.punch / 4095.f;
float crunch_scaled = analog_read_data.crunch / 4095.f;
float drive_scaled = analog_read_data.drive / 4095.f;
float level_scaled = analog_read_data.level / 4095.f;
float low_scaled = analog_read_data.low / 4095.f;
float high_scaled = analog_read_data.high / 4095.f;
xSemaphoreTake(osc_mutex, portMAX_DELAY);
OscWiFi.publish(XAIR_IP, XAIR_PORT, CABINET_PAR, cabinet_int);
OscWiFi.publish(XAIR_IP, XAIR_PORT, PREAMP_PAR, preamp_scaled);
OscWiFi.publish(XAIR_IP, XAIR_PORT, BUZZ_PAR, buzz_scaled);
OscWiFi.publish(XAIR_IP, XAIR_PORT, PUNCH_PAR, punch_scaled);
OscWiFi.publish(XAIR_IP, XAIR_PORT, CRUNCH_PAR, crunch_scaled);
OscWiFi.publish(XAIR_IP, XAIR_PORT, DRIVE_PAR, drive_scaled);
OscWiFi.publish(XAIR_IP, XAIR_PORT, LEVEL_PAR, level_scaled);
OscWiFi.publish(XAIR_IP, XAIR_PORT, LOW_PAR, low_scaled);
OscWiFi.publish(XAIR_IP, XAIR_PORT, HIGH_PAR, high_scaled);
xSemaphoreGive(osc_mutex);
}
}
void osc_update_task(void *pvParameters) {
for(;;) {
xSemaphoreTake(osc_mutex, portMAX_DELAY);
OscWiFi.update();
xSemaphoreGive(osc_mutex);
delay_ms(10);
}
}

3
src/publish.h Normal file
View File

@ -0,0 +1,3 @@
#pragma once
void setup_publish();

72
src/spinner.cpp Normal file
View File

@ -0,0 +1,72 @@
#include "spinner.h"
#include <FreeRTOS_SAMD21.h>
#include "color.h"
#include "led.h"
#include "priority.h"
#include "mapping.h"
#include "util.h"
void spinner_task(void *pvParameters);
TaskHandle_t spinner_task_handle;
SemaphoreHandle_t spinner_semaphore;
void setup_spinner() {
xTaskCreate(spinner_task, "spinner_task", 64, NULL, SPINNER_PRIORITY, &spinner_task_handle);
spinner_semaphore = xSemaphoreCreateBinary();
start_spinner();
}
void start_spinner() {
if(!is_spinner_running())
xSemaphoreGive(spinner_semaphore);
}
void stop_spinner() {
xSemaphoreTake(spinner_semaphore, portMAX_DELAY);
RgbColor leds[LED_BAR_COUNT];
for(size_t led = 0; led < LED_BAR_COUNT; led++) {
leds[led] = RgbColor(0, 0, 0);
}
set_bar_leds(leds);
}
bool is_spinner_running() {
return uxSemaphoreGetCount(spinner_semaphore);
}
void spinner_task(void *pvParameters) {
bool going_up = true;
size_t i = 0;
for(;;) {
RgbColor leds[LED_BAR_COUNT];
for(size_t led = 0; led < LED_BAR_COUNT; led++) {
if(led == i) {
leds[led] = COLOR_SPINNER_FOREGROUND;
} else {
leds[led] = COLOR_SPINNER_BACKGROUND;
}
}
set_bar_leds(leds);
if(going_up) {
i++;
if(i == LED_BAR_COUNT - 1) {
going_up = false;
}
} else {
i--;
if(i == 0) {
going_up = true;
}
}
delay_ms(200);
if(!is_spinner_running()) {
i = 0;
going_up = true;
xSemaphoreTake(spinner_semaphore, portMAX_DELAY);
xSemaphoreGive(spinner_semaphore);
}
}
}

7
src/spinner.h Normal file
View File

@ -0,0 +1,7 @@
#pragma once
void setup_spinner();
void start_spinner();
void stop_spinner();
bool is_spinner_running();

33
src/util.cpp Normal file
View File

@ -0,0 +1,33 @@
#include "util.h"
void delay_ms(TickType_t ms) {
vTaskDelay(ms / portTICK_PERIOD_MS);
}
void print_osc_message(OscMessage& m) {
Serial.println(m.address());
Serial.println(m.typeTags());
for (size_t i = 0; i < m.size(); i++) {
if (m.isBool(i)) {
Serial.println(m.getArgAsBool(i));
} else if (m.isInt32((i))) {
Serial.println(m.getArgAsInt32(i));
} else if (m.isInt64((i))) {
Serial.println(m.getArgAsInt64(i));
} else if (m.isFloat((i))) {
Serial.println(m.getArgAsFloat(i));
} else if (m.isDouble((i))) {
Serial.println(m.getArgAsDouble(i));
} else if (m.isStr((i))) {
Serial.println(m.getArgAsString(i));
} else if (m.isBlob((i))) {
for (auto c: m.getArgAsBlob(i)) {
Serial.print(c, HEX);
Serial.print(" ");
}
Serial.println("");
} else {
Serial.println("unknown");
}
}
}

8
src/util.h Normal file
View File

@ -0,0 +1,8 @@
#pragma once
#include <ArduinoOSCWiFi.h>
#include <FreeRTOS_SAMD21.h>
void delay_ms(TickType_t ms);
void print_osc_message(OscMessage& m);