diff --git a/README.md b/README.md index adbd414..67dd4de 100644 --- a/README.md +++ b/README.md @@ -276,7 +276,7 @@ Create a `main.cpp` and copy one of the example files into it. Remember to add ` # using FTDI You will need something like this: https://www.adafruit.com/product/3309 -To connect a usb->fdti module to your WVR, connect **D0** to **RX**, **D1** to **TX**, and **GND** to **GND**. Open the sketch examples/wvr_ftdi, where you will see ```wvr->useFTDI = true```. The ESP32 on the WVR needs to be booted into a special FTDI boot mode, to do this, ground **D6** and ground the small copper pad on the top of the WVR labeled "boot" (it's right next to the eMMC), and hit reset. You can release D6 and the boot pad now. The ESP32 is now in FTDI boot mode, and if you have a serial monitor attached the WVR, it should print ```waiting for download```. Now you can use the **UPLOAD** button in the Arduin IDE, at the end of flashing it will print "hard resetting", now restart the WVR. If you open the Arduino Serial Console, you will see some logs form the WVR boot process. With FTDI, you can also use ```./wvr.sh ftdi``` to flash, and Arduino Serial Monitor (or any Serial monitor app you like) to get logs from WVR +To connect a usb->fdti module to your WVR, connect **D0** to **TX**, **D1** to **RX**, and **GND** to **GND**. Open the sketch examples/wvr_ftdi, where you will see ```wvr->useFTDI = true```. The ESP32 on the WVR needs to be booted into a special FTDI boot mode, to do this, ground **D6** and ground the small copper pad on the top of the WVR labeled "TP1" (it's right next to the eMMC), and hit reset. You can release D6 and the boot pad now. The ESP32 is now in FTDI boot mode, and if you have a serial monitor attached the WVR, it should print ```waiting for download```. Now you can use the **UPLOAD** button in the Arduin IDE, at the end of flashing it will print "hard resetting", now restart the WVR. If you open the Arduino Serial Console, you will see some logs form the WVR boot process. With FTDI, you can also use ```./wvr.sh ftdi``` to flash, and Arduino Serial Monitor (or any Serial monitor app you like) to get logs from WVR # hardware considerations * **Pin D6** is a "strapping pin" for the ESP32, it corresponds to **GPIO_0** on the ESP32. This is a feature of ESP32 which **cannot be disabled**. If **D6** is held **LOW** at boot by external circuitry, the ESP32 will enter bootloader mode, and the firmware will not run, it will wait for upload until reset. diff --git a/examples/wwr_osc_receive/send_osc_message.pd b/examples/wwr_osc_receive/send_osc_message.pd new file mode 100644 index 0000000..b191970 --- /dev/null +++ b/examples/wwr_osc_receive/send_osc_message.pd @@ -0,0 +1,16 @@ +#N canvas 92 117 450 300 12; +#X obj 135 237 netsend -u -b; +#X obj 27 12 loadbang; +#X msg 136 77 connect 192.168.4.1 4000; +#X msg 66 120 format i; +#X text 135 50 connect UDP to wvr ip address on port 4000; +#X text 144 119 set format to integer; +#X obj 304 167 tgl 19 0 empty empty empty 0 -10 0 12 #fcfcfc #000000 #000000 0 1; +#X text 332 167 switch LED; +#X obj 161 208 oscformat led; +#X connect 1 0 2 0; +#X connect 1 0 3 0; +#X connect 2 0 0 0; +#X connect 3 0 8 0; +#X connect 6 0 8 0; +#X connect 8 0 0 0; diff --git a/examples/wwr_osc_receive/wvr_osc_receive/wvr_osc_receive.ino b/examples/wwr_osc_receive/wvr_osc_receive/wvr_osc_receive.ino new file mode 100644 index 0000000..b2cc6a3 --- /dev/null +++ b/examples/wwr_osc_receive/wvr_osc_receive/wvr_osc_receive.ino @@ -0,0 +1,44 @@ +// +// Created by patrice colet on 26/07/2024. +// + +#include "Arduino.h" + +#include +#include +#include +#include +#include +#include +#include + +WVR wvr; + + +#define LED1 D3 + +void led(OSCMessage &msg) { + bool letToggle = msg.getInt(0); + digitalWrite(LED1, letToggle); +} +void oscHookLED(OSCMessage *msg) { + msg->dispatch("/led", led); +} + + +void setup() { + wvr.useFTDI = true; + wvr.useUsbMidi = false; + wvr.begin(); + wvr.wifiIsOn = get_metadata()->wifi_starts_on; + log_i("wifi is %s", wvr.wifiIsOn ? "on" : "off"); + //LEDs + wvr.resetPin(LED1); + pinMode(LED1, OUTPUT); + wvr.setOSCHook(oscHookLED); +} + +void loop() { + // vTaskDelay(portMAX_DELAY); + vTaskDelete(NULL); +} \ No newline at end of file diff --git a/src/OSCx.cpp b/src/OSCx.cpp new file mode 100644 index 0000000..a6847c6 --- /dev/null +++ b/src/OSCx.cpp @@ -0,0 +1,79 @@ +// +// Created by patrice colet on 01/08/2024. +// +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include +#include +#include +#include +#include "OSCx.h" + + + +esp_err_t ret; + +WiFiUDP Udp; +uint16_t localPort = 4000; +OSCErrorCode error; + +// nullptr to prevent no initialized pointer +void(*osc_hook)(OSCMessage *in) = nullptr; + +void test(OSCMessage &msg) { + Serial.printf("OSC MESSAGE FLOAT = %f \n", msg.getFloat(0)); + Serial.printf("OSC MESSAGE INT = %d \n", msg.getInt(0)); + Serial.printf("OSC MESSAGE ADDRESS = %s \n", msg.getAddress()); + Serial.printf("OSC MESSAGE LENGTH = %d \n", msg.getDataLength(0)); +} + +static void OSC_handle(OSCMessage *msg){ + osc_hook(msg); + msg->dispatch("/led", test); +} + + +static void OSC_task(void*) { +// Serial.print("OSC task \n"); + + Udp.begin(localPort); + OSCMessage msg; + for(;;) { + OSCMessage msg; + int size = Udp.parsePacket(); + if (size > 0) { +// Serial.print("Parsing OSC \n"); + while (size--) { + msg.fill(Udp.read()); + } + if (!msg.hasError()) { +// Serial.print("OSC received!!!! \n"); + osc_hook(&msg); +// msg.dispatch("/led", test); + } else { + error = msg.getError(); + Serial.print("error: "); + Serial.println(error); + } + } + vTaskDelay(10); + } +} + +extern "C" void OSC_init(bool useOsc, uint16_t oscPort) { + if (useOsc) { + Serial.printf("Using OSC with port %d \n", oscPort); + osc_hook = osc_hook_default; + localPort = oscPort; + xTaskCreatePinnedToCore(OSC_task, "OSC_task", 4096, NULL, 3, NULL, 0); + } +} +void osc_hook_default(OSCMessage * in) +{ + return; +} + +void set_osc_hook(void(*fn)(OSCMessage * in)) +{ + osc_hook = fn; +} \ No newline at end of file diff --git a/src/OSCx.h b/src/OSCx.h new file mode 100644 index 0000000..fcad2a0 --- /dev/null +++ b/src/OSCx.h @@ -0,0 +1,19 @@ +#ifndef OSCX_H +#define OSCX_H + + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +static void handle_OSC(OSCMessage * msg); + +void set_osc_hook(void(*fn)(OSCMessage *in)); +void osc_hook_default(OSCMessage * in); +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/src/WVR.cpp b/src/WVR.cpp index 5fee8e7..890bd71 100644 --- a/src/WVR.cpp +++ b/src/WVR.cpp @@ -6,19 +6,21 @@ #include "file_system.h" #include "encoder.h" #include "midi_in.h" +#include "OSCx.h" WVR::WVR() { this->wifiIsOn = get_wifi_is_on(); this->useFTDI = false; this->useUsbMidi = false; + this->oscPort = 4000; this->forceWifiOn = false; this->checkRecoveryModePin = true; } void WVR::begin() { - wvr_init(useFTDI, useUsbMidi, checkRecoveryModePin); + wvr_init(useFTDI, useUsbMidi, checkRecoveryModePin, useOsc, oscPort); } void WVR::play(uint8_t voice, uint8_t note, uint8_t velocity) @@ -79,6 +81,11 @@ void WVR::setMidiHook(void(*fn)(uint8_t *in)) set_midi_hook(fn); } +void WVR::setOSCHook(void(*fn)(OSCMessage *in)) +{ + set_osc_hook(fn); +} + void WVR::encoderInit(int encA, int encB) { encoder_init(encA, encB); diff --git a/src/WVR.h b/src/WVR.h index 37f82d6..93bc946 100644 --- a/src/WVR.h +++ b/src/WVR.h @@ -7,7 +7,7 @@ #define WVR_H #include "Arduino.h" - +#include class WVR { public: @@ -23,6 +23,7 @@ class WVR { void mute(void); void unmute(void); void setMidiHook(void(*fn)(uint8_t *in)); + void setOSCHook(void(*fn)(OSCMessage *in)); void encoderInit(int encA, int encB); void onEncoder(void (*handleEncoder)(bool up)); void resetPin(int pin); @@ -31,6 +32,8 @@ class WVR { bool wifiIsOn; bool useFTDI; bool useUsbMidi; + bool useOsc; + uint16_t oscPort; bool forceWifiOn; bool checkRecoveryModePin; }; diff --git a/src/server.cpp b/src/server.cpp index 641f46a..f21414f 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -11,17 +11,13 @@ #include "bundle.h" #include "favicon.h" #include -#include "soc/rtc_wdt.h" #include "cJSON.h" #include "ws_log.h" #include "wvr_0.3.h" -#include "server.h" #include "file_system.h" -#include "server.h" #include "esp_wifi.h" #include "boot.h" #include "wav_player.h" -#include "file_system.h" #include "gpio.h" extern "C" size_t find_gap_in_file_system(size_t size); @@ -158,7 +154,7 @@ void handleUpdateSingleVoiceConfig(AsyncWebServerRequest *request, uint8_t *data if(index==0){ //start // log_i("start free ram : %d",ESP.getFreeHeap()); - AsyncWebHeader* num_voice_string = request->getHeader("numVoice"); + const AsyncWebHeader* num_voice_string = request->getHeader("numVoice"); sscanf(num_voice_string->value().c_str(), "%d", &num_voice); voice_config_json = (uint8_t*)ps_malloc(total + 1); if(!voice_config_json){ @@ -246,16 +242,16 @@ void handleWav(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t //start //wav_player_pause(); // log_i("start len %d", len); - AsyncWebHeader* size_string = request->getHeader("size"); + const AsyncWebHeader* size_string = request->getHeader("size"); sscanf(size_string->value().c_str(), "%d", &w_size); // log_i("size %d", w_size); - AsyncWebHeader* name = request->getHeader("name"); + const AsyncWebHeader* name = request->getHeader("name"); strcpy(&w_name[0], name->value().c_str()); // log_i("name %s", w_name); - AsyncWebHeader* voice_string = request->getHeader("voice"); + const AsyncWebHeader* voice_string = request->getHeader("voice"); sscanf(voice_string->value().c_str(), "%d", &w_voice); // log_i("voice %d", w_voice); - AsyncWebHeader* note_string = request->getHeader("note"); + const AsyncWebHeader* note_string = request->getHeader("note"); sscanf(note_string->value().c_str(), "%d", &w_note); // log_i("note %d", w_note); // log_i("%s w_size %d w_voice %d w_note %d", w_name, w_size, w_voice, w_note); @@ -340,11 +336,11 @@ void handleNewFirmware(AsyncWebServerRequest *request, uint8_t *data, size_t len //once if(index==0){ //wav_player_pause(); - AsyncWebHeader* firmware_slot_string = request->getHeader("slot-index"); + const AsyncWebHeader* firmware_slot_string = request->getHeader("slot-index"); sscanf(firmware_slot_string->value().c_str(), "%d", &f_firmware_slot); - AsyncWebHeader* firmware_size_string = request->getHeader("firmware-size"); + const AsyncWebHeader* firmware_size_string = request->getHeader("firmware-size"); sscanf(firmware_size_string->value().c_str(), "%d", &f_firmware_size); - AsyncWebHeader* firmware_name_string = request->getHeader("firmware-name"); + const AsyncWebHeader* firmware_name_string = request->getHeader("firmware-name"); strcpy(&f_firmware_name[0], firmware_name_string->value().c_str()); log_i("firmware size %u, firmware name %s",f_firmware_size,f_firmware_name); @@ -382,7 +378,7 @@ void handleNewRecoveryFirmware(AsyncWebServerRequest *request, uint8_t *data, si //once if(index==0){ //wav_player_pause(); - AsyncWebHeader* firmware_size_string = request->getHeader("firmware-size"); + const AsyncWebHeader* firmware_size_string = request->getHeader("firmware-size"); sscanf(firmware_size_string->value().c_str(), "%d", &rf_firmware_size); } if(rf_firmware_size > MAX_FIRMWARE_SIZE){ @@ -412,7 +408,7 @@ void handleVoiceJSON(AsyncWebServerRequest *request){ // wav_player_pause(); int numVoice; // log_i("start : %d", ESP.getFreeHeap()); - AsyncWebHeader* voice_string = request->getHeader("voice"); + const AsyncWebHeader* voice_string = request->getHeader("voice"); sscanf(voice_string->value().c_str(), "%d", &numVoice); char *json = print_voice_json(numVoice); feedLoopWDT(); @@ -643,7 +639,7 @@ void handleRPC(AsyncWebServerRequest *request){ void handleBootFromEmmc(AsyncWebServerRequest *request){ //wav_player_pause(); char index = 0; - AsyncWebHeader* firmware_slot_string = request->getHeader("index"); + const AsyncWebHeader* firmware_slot_string = request->getHeader("index"); sscanf(firmware_slot_string->value().c_str(), "%d", &index); request->send(204); bootFromEmmc(index); @@ -651,7 +647,7 @@ void handleBootFromEmmc(AsyncWebServerRequest *request){ void handleDeleteFirmware(AsyncWebServerRequest *request){ char index = 0; - AsyncWebHeader* firmware_slot_string = request->getHeader("index"); + const AsyncWebHeader* firmware_slot_string = request->getHeader("index"); sscanf(firmware_slot_string->value().c_str(), "%d", &index); request->send(204); delete_firmware(index); @@ -669,9 +665,9 @@ void handlePlayWav(AsyncWebServerRequest *request){ uint8_t note; uint8_t velocity; - AsyncWebHeader* voice_string = request->getHeader("voice"); - AsyncWebHeader* note_string = request->getHeader("note"); - AsyncWebHeader* velocity_string = request->getHeader("velocity"); + const AsyncWebHeader* voice_string = request->getHeader("voice"); + const AsyncWebHeader* note_string = request->getHeader("note"); + const AsyncWebHeader* velocity_string = request->getHeader("velocity"); sscanf(voice_string->value().c_str(), "%d", &voice); sscanf(note_string->value().c_str(), "%d", ¬e); sscanf(velocity_string->value().c_str(), "%d", &velocity); diff --git a/src/wvr_0.3.cpp b/src/wvr_0.3.cpp index 6318fb7..9e21b37 100644 --- a/src/wvr_0.3.cpp +++ b/src/wvr_0.3.cpp @@ -28,6 +28,7 @@ void recovery_server_begin(void); extern "C" void emmc_init(void); extern "C" void dac_init(void); extern "C" void midi_init(bool useUsbMidi); +extern "C" void OSC_init(bool useOsc, uint16_t oscPort); extern "C" void wav_player_start(void); extern "C" void touch_test(void); extern "C" void pot_init(void); @@ -79,7 +80,7 @@ void logRam(){ struct metadata_t metadata; -void wvr_init(bool useFTDI, bool useUsbMidi, bool checkRecoveryModePin) { +void wvr_init(bool useFTDI, bool useUsbMidi, bool checkRecoveryModePin, bool useOsc, uint16_t oscPort) { Serial.begin(115200); logRam(); log_i("arduino setup running on core %u",xPortGetCoreID()); @@ -128,6 +129,8 @@ void wvr_init(bool useFTDI, bool useUsbMidi, bool checkRecoveryModePin) { server_begin(); logSize("server"); + OSC_init(useOsc,oscPort); + logSize("osc"); log_i("do_station_mode:%d network:%s pass:%s",get_metadata()->do_station_mode,get_metadata()->station_ssid,get_metadata()->station_passphrase); // if(get_metadata()->do_station_mode == 1) diff --git a/src/wvr_0.3.h b/src/wvr_0.3.h index 974c590..ad90ed8 100644 --- a/src/wvr_0.3.h +++ b/src/wvr_0.3.h @@ -3,6 +3,6 @@ #define VERSION_CODE "3.10.0" -void wvr_init(bool useFTDI, bool useUsbMidi, bool checkRecoveryModePin); +void wvr_init(bool useFTDI, bool useUsbMidi, bool checkRecoveryModePin,bool useOsc, uint16_t oscPort); #endif \ No newline at end of file