From 9dfcaab35a95d104801c1f9ba1ecaa7c380ea3c5 Mon Sep 17 00:00:00 2001 From: Geens Date: Sat, 30 Mar 2024 16:36:44 +0100 Subject: [PATCH] Basic functions working, fast encoder rotate error persists --- platformio.ini | 8 +- remove_bluetooth.py | 8 + src/analog_read.cpp | 48 ---- src/color.h | 19 +- src/digital_read.cpp | 35 --- src/digital_read.h | 9 - src/encoder.cpp | 29 ++- src/input_read.cpp | 53 +++++ src/{analog_read.h => input_read.h} | 8 +- src/led.cpp | 149 +++++++++---- src/led.h | 4 +- src/main.cpp | 175 ++++++++------- src/main.h | 30 +-- src/mapping.h | 10 +- src/osc.cpp | 329 ++++++++++++++++++++++++++++ src/osc.h | 10 + src/priority.h | 15 +- src/publish.cpp | 68 ------ src/publish.h | 3 - src/spinner.cpp | 71 +++--- src/spinner.h | 6 +- src/util.cpp | 28 --- src/util.h | 5 +- 23 files changed, 724 insertions(+), 396 deletions(-) create mode 100644 remove_bluetooth.py delete mode 100644 src/analog_read.cpp delete mode 100644 src/digital_read.cpp delete mode 100644 src/digital_read.h create mode 100644 src/input_read.cpp rename src/{analog_read.h => input_read.h} (58%) create mode 100644 src/osc.cpp create mode 100644 src/osc.h delete mode 100644 src/publish.cpp delete mode 100644 src/publish.h diff --git a/platformio.ini b/platformio.ini index 7fd9f48..c9546b2 100644 --- a/platformio.ini +++ b/platformio.ini @@ -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 \ No newline at end of file + ruiseixasm/Versatile_RotaryEncoder@^1 + tedtoal/wiring_analog_SAMD_TT@^1 + +extra_scripts = pre:remove_bluetooth.py \ No newline at end of file diff --git a/remove_bluetooth.py b/remove_bluetooth.py new file mode 100644 index 0000000..759f969 --- /dev/null +++ b/remove_bluetooth.py @@ -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) \ No newline at end of file diff --git a/src/analog_read.cpp b/src/analog_read.cpp deleted file mode 100644 index 500d649..0000000 --- a/src/analog_read.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "analog_read.h" - -#include -#include -#include -#include - -#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; -} \ No newline at end of file diff --git a/src/color.h b/src/color.h index 458d32b..5cdabed 100644 --- a/src/color.h +++ b/src/color.h @@ -1,5 +1,7 @@ #pragma once +#include + #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 \ No newline at end of file +#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 \ No newline at end of file diff --git a/src/digital_read.cpp b/src/digital_read.cpp deleted file mode 100644 index 822db8a..0000000 --- a/src/digital_read.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include "digital_read.h" - -#include - -#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; -} \ No newline at end of file diff --git a/src/digital_read.h b/src/digital_read.h deleted file mode 100644 index 871f03c..0000000 --- a/src/digital_read.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -typedef struct { - bool cabinet; -} DigitalReadData; - -void setup_digital_read(); - -DigitalReadData get_digital_read_data(); \ No newline at end of file diff --git a/src/encoder.cpp b/src/encoder.cpp index f863af4..df625e8 100644 --- a/src/encoder.cpp +++ b/src/encoder.cpp @@ -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"); } \ No newline at end of file diff --git a/src/input_read.cpp b/src/input_read.cpp new file mode 100644 index 0000000..6f1aa2e --- /dev/null +++ b/src/input_read.cpp @@ -0,0 +1,53 @@ +#include "input_read.h" + +#include +#include +#include +#include + +#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; +} \ No newline at end of file diff --git a/src/analog_read.h b/src/input_read.h similarity index 58% rename from src/analog_read.h rename to src/input_read.h index 9bf8290..dfa286a 100644 --- a/src/analog_read.h +++ b/src/input_read.h @@ -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(); \ No newline at end of file +InputReadData get_input_read_data(); \ No newline at end of file diff --git a/src/led.cpp b/src/led.cpp index 8d0ea30..d31268a 100644 --- a/src/led.cpp +++ b/src/led.cpp @@ -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); } \ No newline at end of file diff --git a/src/led.h b/src/led.h index acabbb4..12082c8 100644 --- a/src/led.h +++ b/src/led.h @@ -5,6 +5,4 @@ #include "mapping.h" void setup_led(); - -void set_state_led(); -void set_bar_leds(RgbColor bar[LED_BAR_COUNT]); \ No newline at end of file +void update_leds(); \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index fe6f7f1..614dfb8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,42 +1,39 @@ #include -#include #include -#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; } \ No newline at end of file diff --git a/src/main.h b/src/main.h index 54977de..b3fbda7 100644 --- a/src/main.h +++ b/src/main.h @@ -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); \ No newline at end of file +void increment_level(float value); +void set_level(float value); +float get_level(); +void set_meter(float value); +float get_meter(); \ No newline at end of file diff --git a/src/mapping.h b/src/mapping.h index 9bd75a4..de8ec75 100644 --- a/src/mapping.h +++ b/src/mapping.h @@ -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" diff --git a/src/osc.cpp b/src/osc.cpp new file mode 100644 index 0000000..25b8deb --- /dev/null +++ b/src/osc.cpp @@ -0,0 +1,329 @@ +#include "osc.h" + +#include +#include +#include +#include +#include + +#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"); + } + } +} \ No newline at end of file diff --git a/src/osc.h b/src/osc.h new file mode 100644 index 0000000..fff4adc --- /dev/null +++ b/src/osc.h @@ -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(); \ No newline at end of file diff --git a/src/priority.h b/src/priority.h index b35bc70..177bffe 100644 --- a/src/priority.h +++ b/src/priority.h @@ -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 \ No newline at end of file diff --git a/src/publish.cpp b/src/publish.cpp deleted file mode 100644 index 2d73697..0000000 --- a/src/publish.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#include "publish.h" - -#include -#include - -#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); - } -} \ No newline at end of file diff --git a/src/publish.h b/src/publish.h deleted file mode 100644 index 3a2d570..0000000 --- a/src/publish.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -void setup_publish(); \ No newline at end of file diff --git a/src/spinner.cpp b/src/spinner.cpp index 3c117b0..4c9afd8 100644 --- a/src/spinner.cpp +++ b/src/spinner.cpp @@ -2,7 +2,6 @@ #include -#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); } } \ No newline at end of file diff --git a/src/spinner.h b/src/spinner.h index 68bf92b..5a91bc7 100644 --- a/src/spinner.h +++ b/src/spinner.h @@ -1,7 +1,9 @@ #pragma once -void setup_spinner(); +#include +void setup_spinner(); void start_spinner(); void stop_spinner(); -bool is_spinner_running(); \ No newline at end of file +bool is_spinner_running(); +uint8_t get_spinner_position(); \ No newline at end of file diff --git a/src/util.cpp b/src/util.cpp index 174f7cc..a08a37e 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -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"); - } - } } \ No newline at end of file diff --git a/src/util.h b/src/util.h index 7d3a4c2..fe0dd29 100644 --- a/src/util.h +++ b/src/util.h @@ -1,8 +1,5 @@ #pragma once -#include #include -void delay_ms(TickType_t ms); - -void print_osc_message(OscMessage& m); \ No newline at end of file +void delay_ms(TickType_t ms); \ No newline at end of file