Basic functions working, fast encoder rotate error persists

This commit is contained in:
Geens 2024-03-30 16:36:44 +01:00
parent 8cab458c23
commit 9dfcaab35a
23 changed files with 724 additions and 396 deletions

View File

@ -7,7 +7,9 @@ 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
cnmat/OSC@^1
makuna/NeoPixelBus@^2
ruiseixasm/Versatile_RotaryEncoder@^1
ruiseixasm/Versatile_RotaryEncoder@^1
tedtoal/wiring_analog_SAMD_TT@^1
extra_scripts = pre:remove_bluetooth.py

8
remove_bluetooth.py Normal file
View File

@ -0,0 +1,8 @@
import os
header = "./.pio/libdeps/nano_33_iot/OSC/SLIPEncodedBluetoothSerial.h"
if os.path.exists(header):
os.remove(header)
src = "./.pio/libdeps/nano_33_iot/OSC/SLIPEncodedBluetoothSerial.cpp"
if os.path.exists(src):
os.remove(src)

View File

@ -1,48 +0,0 @@
#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;
}

View File

@ -1,5 +1,7 @@
#pragma once
#include <NeoPixelBus.h>
#define COLOR_OFF RgbColor(0, 0, 0)
#define COLOR_RED RgbColor(50, 0, 0)
@ -13,10 +15,15 @@
#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_CHAIN_MENU_GAIN_METER COLOR_RED
#define COLOR_CHAIN_MENU_FADER_METER COLOR_GREEN
#define COLOR_CHAIN_MENU_MASTER_METER COLOR_BLUE
#define COLOR_METER_PRE_FADER COLOR_RED
#define COLOR_METER_POST_FADER COLOR_GREEN
#define COLOR_METER_MASTER COLOR_BLUE
#define COLOR_CHAIN_MENU_GAIN_LEVEL COLOR_CYAN
#define COLOR_CHAIN_MENU_FADER_LEVEL COLOR_MAGENTA
#define COLOR_CHAIN_MENU_MASTER_LEVEL COLOR_YELLOW
#define COLOR_METER_BACKGROUND COLOR_OFF
#define COLOR_METER_LOW COLOR_GREEN
#define COLOR_METER_MEDIUM COLOR_YELLOW
#define COLOR_METER_HIGH COLOR_RED

View File

@ -1,35 +0,0 @@
#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;
}

View File

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

View File

@ -23,28 +23,39 @@ void setup_encoder() {
encoder->setHandlePress(handle_press);
encoder->setHandleRotate(handle_rotate);
xTaskCreate(encoder_task, "encoder_task", 64, NULL, ENCODER_PRIORITY, &encoder_task_handle);
xTaskCreate(encoder_task, "encoder_task", 512, NULL, ENCODER_PRIORITY, &encoder_task_handle);
}
void encoder_task(void *pvParameters) {
for(;;) {
encoder->ReadEncoder();
delay_ms(10);
delay_ms(5);
}
}
void handle_press() {
Serial.println("Pressed");
next_main_menu_item();
if (State::Connecting == get_state()) return;
toggle_chain_mode();
}
void handle_rotate(int8_t rotation) {
Serial.println("Rotated");
rotation = -rotation;
if (rotation > 0) {
next_meter();
} else if (rotation < 0) {
previous_meter();
switch (get_state()) {
case State::Connecting: return;
case State::ChainMenu:
switch (get_chain_mode()) {
case ChainMode::Level:
increment_level(rotation * -0.02);
break;
case ChainMode::Meter:
if (rotation < 0) {
next_chain_menu_item();
} else if (rotation > 0) {
previous_chain_menu_item();
}
break;
}
}
update_fader(rotation);
Serial.println("Rotated done");
}

53
src/input_read.cpp Normal file
View File

@ -0,0 +1,53 @@
#include "input_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 input_read_task(void *pvParameters);
TaskHandle_t input_read_task_handle;
SemaphoreHandle_t input_read_mutex;
InputReadData input_read_data;
void setup_input_read() {
analogReadResolution_SAMD_TT(12);
analogReference_SAMD_TT(AR_DEFAULT);
xTaskCreate(input_read_task, "input_read_task", 256, NULL, INPUT_READ_PRIORITY, &input_read_task_handle);
input_read_mutex = xSemaphoreCreateMutex();
}
void input_read_task(void *pvParameters) {
InputReadData new_values;
for(;;) {
new_values.insert = digitalRead(INSERT_PIN);
new_values.cabinet = digitalRead(CABINET_PIN);
new_values.preamp += 0.05 * ((float)analogRead_SAMD_TT(PREAMP_PIN) - new_values.preamp);
new_values.buzz += 0.05 * ((float)analogRead_SAMD_TT(BUZZ_PIN) - new_values.buzz);
new_values.punch += 0.05 * ((float)analogRead_SAMD_TT(PUNCH_PIN) - new_values.punch);
new_values.crunch += 0.05 * ((float)analogRead_SAMD_TT(CRUNCH_PIN) - new_values.crunch);
new_values.drive += 0.05 * ((float)analogRead_SAMD_TT(DRIVE_PIN) - new_values.drive);
new_values.level += 0.05 * ((float)analogRead_SAMD_TT(LEVEL_PIN) - new_values.level);
new_values.low += 0.05 * ((float)analogRead_SAMD_TT(LOW_PIN) - new_values.low);
new_values.high += 0.05 * ((float)analogRead_SAMD_TT(HIGH_PIN) - new_values.high);
xSemaphoreTake(input_read_mutex, portMAX_DELAY);
input_read_data = new_values;
xSemaphoreGive(input_read_mutex);
}
}
InputReadData get_input_read_data() {
xSemaphoreTake(input_read_mutex, portMAX_DELAY);
InputReadData copy = input_read_data;
xSemaphoreGive(input_read_mutex);
return copy;
}

View File

@ -1,6 +1,8 @@
#pragma once
typedef struct {
bool insert;
bool cabinet;
float preamp;
float buzz;
float punch;
@ -9,8 +11,8 @@ typedef struct {
float level;
float low;
float high;
} AnalogReadData;
} InputReadData;
void setup_analog_read();
void setup_input_read();
AnalogReadData get_analog_read_data();
InputReadData get_input_read_data();

View File

@ -4,6 +4,13 @@
#include "color.h"
#include "main.h"
#include "spinner.h"
void paint_state_led(RgbColor& color);
void paint_led_bar(RgbColor bar[LED_BAR_COUNT]);
void paint_spinner(RgbColor bar[LED_BAR_COUNT]);
void paint_meter(RgbColor bar[LED_BAR_COUNT]);
void paint_level_meter(RgbColor bar[LED_BAR_COUNT]);
SemaphoreHandle_t led_mutex;
@ -15,50 +22,112 @@ void setup_led() {
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;
};
void update_leds() {
RgbColor led_bar[LED_BAR_COUNT];
RgbColor state_led;
paint_led_bar(led_bar);
paint_state_led(state_led);
xSemaphoreTake(led_mutex, portMAX_DELAY);
strip.SetPixelColor(LED_BAR_COUNT, color);
for (size_t i = 0; i < LED_BAR_COUNT; i++) {
strip.SetPixelColor(i, led_bar[i]);
}
strip.SetPixelColor(LED_BAR_COUNT, state_led);
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]);
void paint_state_led(RgbColor& color) {
switch (get_state()) {
case State::Connecting:
color = COLOR_OFF;
break;
case State::ChainMenu:
ChainMode chain_mode = get_chain_mode();
switch (get_chain_menu_item()) {
case ChainMenu::Gain:
if(ChainMode::Level == chain_mode) {
color = COLOR_CHAIN_MENU_GAIN_LEVEL;
} else {
color = COLOR_CHAIN_MENU_GAIN_METER;
}
break;
case ChainMenu::Fader:
if(ChainMode::Level == chain_mode) {
color = COLOR_CHAIN_MENU_FADER_LEVEL;
} else {
color = COLOR_CHAIN_MENU_FADER_METER;
}
break;
case ChainMenu::Master:
if(ChainMode::Level == chain_mode) {
color = COLOR_CHAIN_MENU_MASTER_LEVEL;
} else {
color = COLOR_CHAIN_MENU_MASTER_METER;
}
break;
}
break;
}
}
void paint_led_bar(RgbColor bar[LED_BAR_COUNT]) {
switch (get_state()) {
case State::Connecting:
paint_spinner(bar);
break;
case State::ChainMenu:
paint_level_meter(bar);
break;
};
}
void paint_spinner(RgbColor bar[LED_BAR_COUNT]) {
uint8_t const position = get_spinner_position();
for(size_t i = 0; i < LED_BAR_COUNT; i++) {
if(position == i) {
bar[i] = COLOR_SPINNER_FOREGROUND;
} else {
bar[i] = COLOR_SPINNER_BACKGROUND;
}
}
}
void paint_level_meter(RgbColor bar[LED_BAR_COUNT]) {
float value;
switch(get_chain_mode()) {
case ChainMode::Meter:
value = get_meter();
break;
case ChainMode::Level:
value = get_level();
break;
}
for(size_t i = 0; i < LED_BAR_COUNT; i++) {
float intensity = (value - (0.1 * i)) * 10;
if (intensity < 0) {
bar[i] = COLOR_METER_BACKGROUND;
continue;
}
if (intensity > 1) {
intensity = 1;
}
switch (i) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
bar[i] = COLOR_METER_LOW.Dim(255 * intensity);
break;
case 6:
case 7:
bar[i] = COLOR_METER_MEDIUM.Dim(255 * intensity);
break;
case 8:
case 9:
bar[i] = COLOR_METER_HIGH.Dim(255 * intensity);
break;
}
}
strip.Show();
xSemaphoreGive(led_mutex);
}

View File

@ -5,6 +5,4 @@
#include "mapping.h"
void setup_led();
void set_state_led();
void set_bar_leds(RgbColor bar[LED_BAR_COUNT]);
void update_leds();

View File

@ -1,42 +1,39 @@
#include <Arduino.h>
#include <ArduinoOSCWiFi.h>
#include <FreeRTOS_SAMD21.h>
#include "analog_read.h"
#include "input_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 "osc.h"
#include "spinner.h"
#include "util.h"
SemaphoreHandle_t state_mutex;
State state = State::Connecting;
MainMenuItem main_menu = MainMenuItem::Meter;
Meter meter = Meter::Master;
ChainMenu chain_menu = ChainMenu::Master;
ChainMode chain_mode = ChainMode::Meter;
float meter_value = 0.0;
float level_value = 0.0;
bool level_value_up_to_date = false;
void setup() {
Serial.begin(9600);
setup_analog_read();
setup_input_read();
setup_connect();
setup_digital_read();
setup_encoder();
setup_led();
setup_publish();
setup_osc();
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");
}
@ -47,9 +44,10 @@ void loop() {
void connection_established() {
xSemaphoreTakeRecursive(state_mutex, portMAX_DELAY);
state = State::MainMenu;
state = State::ChainMenu;
stop_spinner();
set_state_led();
update_meter();
update_leds();
xSemaphoreGiveRecursive(state_mutex);
}
@ -57,102 +55,125 @@ void connection_lost() {
xSemaphoreTakeRecursive(state_mutex, portMAX_DELAY);
state = State::Connecting;
start_spinner();
set_state_led();
xSemaphoreGiveRecursive(state_mutex);
}
State current_state() {
State get_state() {
xSemaphoreTakeRecursive(state_mutex, portMAX_DELAY);
State current_state = state;
xSemaphoreGiveRecursive(state_mutex);
return current_state;
}
void next_main_menu_item() {
void toggle_chain_mode() {
xSemaphoreTakeRecursive(state_mutex, portMAX_DELAY);
if (State::Connecting == current_state()) {
xSemaphoreGiveRecursive(state_mutex);
return;
if(ChainMode::Meter == chain_mode) {
chain_mode = ChainMode::Level;
} else {
chain_mode = ChainMode::Meter;
}
switch (main_menu) {
case MainMenuItem::Gain:
main_menu = MainMenuItem::Fader;
xSemaphoreGiveRecursive(state_mutex);
update_leds();
}
ChainMode get_chain_mode() {
xSemaphoreTakeRecursive(state_mutex, portMAX_DELAY);
ChainMode current_chain_mode = chain_mode;
xSemaphoreGiveRecursive(state_mutex);
return current_chain_mode;
}
void previous_chain_menu_item() {
xSemaphoreTakeRecursive(state_mutex, portMAX_DELAY);
switch (chain_menu) {
case ChainMenu::Gain:
break;
case MainMenuItem::Fader:
main_menu = MainMenuItem::Master;
case ChainMenu::Fader:
chain_menu = ChainMenu::Gain;
level_value_up_to_date = false;
update_value();
break;
case MainMenuItem::Master:
main_menu = MainMenuItem::Meter;
break;
case MainMenuItem::Meter:
main_menu = MainMenuItem::Gain;
case ChainMenu::Master:
chain_menu = ChainMenu::Fader;
level_value_up_to_date = false;
update_value();
break;
}
xSemaphoreGiveRecursive(state_mutex);
set_state_led();
update_leds();
}
MainMenuItem current_main_menu_item() {
void next_chain_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:
switch (chain_menu) {
case ChainMenu::Gain:
chain_menu = ChainMenu::Fader;
level_value_up_to_date = false;
update_value();
break;
case Meter::PostFader:
meter = Meter::PreFader;
case ChainMenu::Fader:
chain_menu = ChainMenu::Master;
level_value_up_to_date = false;
update_value();
break;
case Meter::Master:
meter = Meter::PostFader;
case ChainMenu::Master:
break;
}
xSemaphoreGiveRecursive(state_mutex);
set_state_led();
update_leds();
}
void next_meter() {
ChainMenu get_chain_menu_item() {
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;
ChainMenu current_chain_menu = chain_menu;
xSemaphoreGiveRecursive(state_mutex);
return current_chain_menu;
}
void increment_level(float value) {
xSemaphoreTakeRecursive(state_mutex, portMAX_DELAY);
if(level_value_up_to_date) {
level_value += value;
if(state == State::ChainMenu
&& chain_menu == ChainMenu::Gain) {
set_gain(level_value);
} else if(state == State::ChainMenu
&& chain_menu == ChainMenu::Fader) {
set_fader(level_value);
} else if(state == State::ChainMenu
&& chain_menu == ChainMenu::Master) {
set_master(level_value);
}
}
xSemaphoreGiveRecursive(state_mutex);
set_state_led();
update_leds();
}
Meter current_meter() {
void set_level(float value) {
xSemaphoreTakeRecursive(state_mutex, portMAX_DELAY);
Meter current_meter = meter;
level_value = value;
level_value_up_to_date = true;
xSemaphoreGiveRecursive(state_mutex);
return current_meter;
update_leds();
}
void update_fader(uint8_t value) {
float get_level() {
xSemaphoreTakeRecursive(state_mutex, portMAX_DELAY);
float current_level_value = level_value;
xSemaphoreGiveRecursive(state_mutex);
return current_level_value;
}
void set_meter(float value) {
xSemaphoreTakeRecursive(state_mutex, portMAX_DELAY);
meter_value = value;
xSemaphoreGiveRecursive(state_mutex);
update_leds();
}
float get_meter() {
xSemaphoreTakeRecursive(state_mutex, portMAX_DELAY);
float current_meter_value = meter_value;
xSemaphoreGiveRecursive(state_mutex);
return current_meter_value;
}

View File

@ -4,31 +4,33 @@
enum class State {
Connecting,
MainMenu
ChainMenu
};
enum class MainMenuItem {
enum class ChainMenu {
Gain,
Fader,
Master,
Meter
};
enum class Meter {
PreFader,
PostFader,
Master,
enum class ChainMode {
Meter,
Level
};
void connection_established();
void connection_lost();
State current_state();
State get_state();
void next_main_menu_item();
MainMenuItem current_main_menu_item();
void toggle_chain_mode();
ChainMode get_chain_mode();
void previous_meter();
void next_meter();
Meter current_meter();
void previous_chain_menu_item();
void next_chain_menu_item();
ChainMenu get_chain_menu_item();
void update_fader(uint8_t value);
void increment_level(float value);
void set_level(float value);
float get_level();
void set_meter(float value);
float get_meter();

View File

@ -1,10 +1,11 @@
#pragma once
#define ENCODER_PIN_CLK 8
#define ENCODER_PIN_DT 9
#define ENCODER_PIN_SW 10
#define ENCODER_PIN_CLK 9
#define ENCODER_PIN_DT 10
#define ENCODER_PIN_SW 11
#define CABINET_PIN 7
#define INSERT_PIN 7
#define CABINET_PIN 8
#define PREAMP_PIN A0
#define BUZZ_PIN A1
@ -18,6 +19,7 @@
#define LED_PIN 12
#define LED_BAR_COUNT 10
#define INSERT_PAR "/ch/01/insert/on"
#define CABINET_PAR "/fx/1/par/09"
#define PREAMP_PAR "/fx/1/par/01"

329
src/osc.cpp Normal file
View File

@ -0,0 +1,329 @@
#include "osc.h"
#include <Arduino.h>
#include <FreeRTOS_SAMD21.h>
#include <OSCBundle.h>
#include <OSCMessage.h>
#include <WiFiUdp.h>
#include "input_read.h"
#include "main.h"
#include "mapping.h"
#include "network.h"
#include "priority.h"
#include "util.h"
#define SET_LEVEL_TIMEOUT_MS 500
#define GAIN_LEVEL_ADDRESS "/headamp/01/gain"
#define FADER_LEVEL_ADDRESS "/ch/01/mix/fader"
#define MASTER_LEVEL_ADDRESS "/lr/mix/fader"
#define METERS_ADDRESS "/meters"
#define CHANNEL_METER_ADDRESS "/meters/0"
#define MASTER_METER_ADDRESS "/meters/5"
#define PRE_FADER_OFFSET 4
#define POST_FADER_OFFSET 12
#define MASTER_METER_OFFSET 16
void publish_task(void *pvParameters);
void request_meter_task(void *pvParameters);
void request_value_task(void *pvParameters);
void receive_task(void *pvParameters);
void request_master_meter();
void request_channel_meter(uint8_t channel);
void send_input_data();
void send_osc_message(OSCMessage &msg);
float parse_meter_value(const uint8_t* data);
void handle_message(OSCMessage &msg);
void print_osc_message(OSCMessage& m);
TaskHandle_t publish_task_handle;
TaskHandle_t request_meter_task_handle;
TaskHandle_t request_value_task_handle;
TaskHandle_t receive_task_handle;
SemaphoreHandle_t udp_mutex;
SemaphoreHandle_t update_meter_semaphore;
SemaphoreHandle_t update_value_semaphore;
WiFiUDP udp;
unsigned long last_set_time = millis();
void setup_osc() {
xTaskCreate(publish_task, "publish_task", 256, NULL, PUBLISH_PRIORITY, &publish_task_handle);
xTaskCreate(request_meter_task, "request_meter_task", 128, NULL, REQUEST_METER_PRIORITY, &request_meter_task_handle);
xTaskCreate(request_value_task, "request_value_task", 128, NULL, REQUEST_VALUE_PRIORITY, &request_value_task_handle);
xTaskCreate(receive_task, "receive_task", 512, NULL, OSC_UPDATE_PRIORITY, &receive_task_handle);
udp_mutex = xSemaphoreCreateMutex();
update_meter_semaphore = xSemaphoreCreateBinary();
update_value_semaphore = xSemaphoreCreateBinary();
udp.begin(LOCAL_PORT);
}
void set_gain(float gain) {
OSCMessage msg(GAIN_LEVEL_ADDRESS);
msg.add(gain);
send_osc_message(msg);
last_set_time = millis();
}
void set_fader(float fader) {
OSCMessage msg(FADER_LEVEL_ADDRESS);
msg.add(fader);
send_osc_message(msg);
last_set_time = millis();
}
void set_master(float value) {
OSCMessage msg(MASTER_LEVEL_ADDRESS);
msg.add(value);
send_osc_message(msg);
last_set_time = millis();
}
void update_meter() {
xSemaphoreGive(update_meter_semaphore);
}
void update_value() {
xSemaphoreGive(update_value_semaphore);
}
void request_gain_level() {
OSCMessage msg(GAIN_LEVEL_ADDRESS);
send_osc_message(msg);
}
void request_fader_level() {
OSCMessage msg(FADER_LEVEL_ADDRESS);
send_osc_message(msg);
}
void request_master_level() {
OSCMessage msg(MASTER_LEVEL_ADDRESS);
send_osc_message(msg);
}
void request_master_meter() {
OSCMessage meter_msg(METERS_ADDRESS);
meter_msg.add(MASTER_METER_ADDRESS);
send_osc_message(meter_msg);
}
void request_channel_meter(uint8_t channel) {
OSCMessage meter_msg(METERS_ADDRESS);
meter_msg.add(CHANNEL_METER_ADDRESS);
meter_msg.add(channel);
send_osc_message(meter_msg);
}
void send_input_data() {
InputReadData input_read_data = get_input_read_data();
int insert_int = input_read_data.insert ? 0 : 1;
int cabinet_int = input_read_data.cabinet ? 0 : 1;
float preamp_scaled = input_read_data.preamp / 4095.f;
float buzz_scaled = input_read_data.buzz / 4095.f;
float punch_scaled = input_read_data.punch / 4095.f;
float crunch_scaled = input_read_data.crunch / 4095.f;
float drive_scaled = input_read_data.drive / 4095.f;
float level_scaled = input_read_data.level / 4095.f;
float low_scaled = input_read_data.low / 4095.f;
float high_scaled = input_read_data.high / 4095.f;
OSCMessage insert_msg(INSERT_PAR);
insert_msg.add(insert_int);
send_osc_message(insert_msg);
OSCMessage cabinet_msg(CABINET_PAR);
cabinet_msg.add(cabinet_int);
send_osc_message(cabinet_msg);
OSCMessage preamp_msg(PREAMP_PAR);
preamp_msg.add(preamp_scaled);
send_osc_message(preamp_msg);
OSCMessage buzz_msg(BUZZ_PAR);
buzz_msg.add(buzz_scaled);
send_osc_message(buzz_msg);
OSCMessage punch_msg(PUNCH_PAR);
punch_msg.add(punch_scaled);
send_osc_message(punch_msg);
OSCMessage crunch_msg(CRUNCH_PAR);
crunch_msg.add(crunch_scaled);
send_osc_message(crunch_msg);
OSCMessage drive_msg(DRIVE_PAR);
drive_msg.add(drive_scaled);
send_osc_message(drive_msg);
OSCMessage level_msg(LEVEL_PAR);
level_msg.add(level_scaled);
send_osc_message(level_msg);
OSCMessage low_msg(LOW_PAR);
low_msg.add(low_scaled);
send_osc_message(low_msg);
OSCMessage high_msg(HIGH_PAR);
high_msg.add(high_scaled);
send_osc_message(high_msg);
}
void send_osc_message(OSCMessage &msg) {
xSemaphoreTake(udp_mutex, portMAX_DELAY);
udp.beginPacket(XAIR_IP, XAIR_PORT);
msg.send(udp);
udp.endPacket();
msg.empty();
xSemaphoreGive(udp_mutex);
}
void publish_task(void *pvParameters) {
for(;;) {
delay_ms(200);
send_input_data();
}
}
void request_meter_task(void *pvParameters) {
for(;;) {
xSemaphoreTake(update_meter_semaphore, 10000 / portTICK_PERIOD_MS);
if(State::ChainMenu == get_state()) {
request_channel_meter(0);
request_master_meter();
}
}
}
void request_value_task(void *pvParameters) {
for(;;) {
xSemaphoreTake(update_value_semaphore, 200 / portTICK_PERIOD_MS);
if(State::ChainMenu == get_state()) {
switch(get_chain_menu_item()) {
case ChainMenu::Gain:
request_gain_level();
break;
case ChainMenu::Fader:
request_fader_level();
break;
case ChainMenu::Master:
request_master_level();
break;
}
}
}
}
void receive_task(void *pvParameters) {
for(;;) {
delay_ms(10);
xSemaphoreTake(udp_mutex, portMAX_DELAY);
for(;;) {
int size = udp.parsePacket();
if(size <= 0) {
// No more packets
xSemaphoreGive(udp_mutex);
break;
}
OSCMessage msg;
while(size--) {
auto data = udp.read();
msg.fill(data);
}
if(!msg.hasError()) handle_message(msg);
}
}
}
void handle_message(OSCMessage &msg) {
bool handled = false;
if(State::ChainMenu == get_state()) {
switch(get_chain_menu_item()) {
case ChainMenu::Gain:
if(0 == strcmp(msg.getAddress(), CHANNEL_METER_ADDRESS)) {
float post_fader_value = parse_meter_value(&msg.getBlob(0)[PRE_FADER_OFFSET]);
set_meter(post_fader_value);
handled = true;
} else if(0 == strcmp(msg.getAddress(), GAIN_LEVEL_ADDRESS)
&& millis() - last_set_time > SET_LEVEL_TIMEOUT_MS) {
float gain_value = msg.getFloat(0);
set_level(gain_value);
handled = true;
}
break;
case ChainMenu::Fader:
if(0 == strcmp(msg.getAddress(), CHANNEL_METER_ADDRESS)) {
float post_fader_value = parse_meter_value(&msg.getBlob(0)[POST_FADER_OFFSET]);
set_meter(post_fader_value);
handled = true;
} else if(0 == strcmp(msg.getAddress(), FADER_LEVEL_ADDRESS)
&& millis() - last_set_time > SET_LEVEL_TIMEOUT_MS) {
float fader_value = msg.getFloat(0);
set_level(fader_value);
handled = true;
}
break;
case ChainMenu::Master:
if(0 == strcmp(msg.getAddress(), MASTER_METER_ADDRESS)) {
float master_meter_value = parse_meter_value(&msg.getBlob(0)[MASTER_METER_OFFSET]);
set_meter(master_meter_value);
handled = true;
} else if(0 == strcmp(msg.getAddress(), MASTER_LEVEL_ADDRESS)
&& millis() - last_set_time > SET_LEVEL_TIMEOUT_MS) {
float master_value = msg.getFloat(0);
set_level(master_value);
handled = true;
}
break;
}
}
if(!handled) {
//Serial.println("Received OSC message");
//print_osc_message(msg);
}
}
float parse_meter_value(const uint8_t* blob) {
int16_t value = (blob[1] << 8) | blob[2];
return pow(20, (float)value / (float)INT16_MAX) - 0.1;
}
void print_osc_message(OSCMessage& m) {
Serial.println(m.getAddress());
for (int i = 0; i < m.size(); i++) {
Serial.print(m.getType(i));
}
Serial.println();
for (int i = 0; i < m.size(); i++) {
if (m.isBoolean(i)) {
Serial.println(m.getBoolean(i));
} else if (m.isInt((i))) {
Serial.println(m.getInt(i));
} else if (m.isFloat((i))) {
Serial.println(m.getFloat(i));
} else if (m.isDouble((i))) {
Serial.println(m.getDouble(i));
} else if (m.isString((i))) {
OSCData* data = m.getOSCData(i);
Serial.println(data->data.s);
} else if (m.isBlob((i))) {
uint32_t length = m.getBlobLength(i);
const uint8_t* data = m.getBlob(i);
for(uint32_t i = 0; i < length; i++) {
Serial.print(data[i], HEX);
Serial.print(" ");
}
Serial.println("");
} else {
Serial.println("unknown");
}
}
}

10
src/osc.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
void setup_osc();
void set_gain(float value);
void set_fader(float value);
void set_master(float value);
void update_meter();
void update_value();

View File

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

View File

@ -1,68 +0,0 @@
#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);
}
}

View File

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

View File

@ -2,7 +2,6 @@
#include <FreeRTOS_SAMD21.h>
#include "color.h"
#include "led.h"
#include "priority.h"
#include "mapping.h"
@ -12,61 +11,67 @@ void spinner_task(void *pvParameters);
TaskHandle_t spinner_task_handle;
SemaphoreHandle_t spinner_semaphore;
SemaphoreHandle_t spinner_mutex;
uint8_t spinner_position;
bool going_up = true;
void setup_spinner() {
xTaskCreate(spinner_task, "spinner_task", 64, NULL, SPINNER_PRIORITY, &spinner_task_handle);
spinner_semaphore = xSemaphoreCreateBinary();
start_spinner();
spinner_mutex = xSemaphoreCreateMutex();
}
void start_spinner() {
if(!is_spinner_running())
if(!is_spinner_running()) {
going_up = false;
spinner_position = 1;
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);
if(is_spinner_running()) {
xSemaphoreTake(spinner_semaphore, portMAX_DELAY);
spinner_position = 0;
}
set_bar_leds(leds);
}
bool is_spinner_running() {
return uxSemaphoreGetCount(spinner_semaphore);
}
uint8_t get_spinner_position() {
xSemaphoreTake(spinner_mutex, portMAX_DELAY);
uint8_t position = spinner_position;
xSemaphoreGive(spinner_mutex);
return position;
}
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);
// block if not running
if(!is_spinner_running()) {
i = 0;
going_up = true;
xSemaphoreTake(spinner_semaphore, portMAX_DELAY);
xSemaphoreGive(spinner_semaphore);
}
// update position
xSemaphoreTake(spinner_mutex, portMAX_DELAY);
if(going_up) {
spinner_position++;
if(spinner_position == LED_BAR_COUNT - 1) {
going_up = false;
}
} else {
spinner_position--;
if(spinner_position == 0) {
going_up = true;
}
}
xSemaphoreGive(spinner_mutex);
// update leds
update_leds();
// wait for next step
delay_ms(200);
}
}

View File

@ -1,7 +1,9 @@
#pragma once
void setup_spinner();
#include <cstdint>
void setup_spinner();
void start_spinner();
void stop_spinner();
bool is_spinner_running();
bool is_spinner_running();
uint8_t get_spinner_position();

View File

@ -2,32 +2,4 @@
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");
}
}
}

View File

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