From e48348e2238ef499033344802fb713f31fa37ed7 Mon Sep 17 00:00:00 2001 From: Marcel Licence Date: Sun, 2 Apr 2023 20:45:47 +0200 Subject: [PATCH] Use centralized modules --- audio_module.ino | 444 ------------------------------ blink.ino | 57 ---- config.h | 7 +- doc/board_info.md | 236 ++++++++++++++++ es8388.ino | 531 ------------------------------------ esp32_audio_kit_module.ino | 327 ---------------------- esp32_multitrack_looper.ino | 5 + i2s_interface.ino | 371 ------------------------- midi_interface.ino | 468 ------------------------------- ml_inline.ino | 4 + z_config.ino | 1 + 11 files changed, 251 insertions(+), 2200 deletions(-) delete mode 100644 audio_module.ino delete mode 100644 blink.ino create mode 100644 doc/board_info.md delete mode 100644 es8388.ino delete mode 100644 esp32_audio_kit_module.ino delete mode 100644 i2s_interface.ino delete mode 100644 midi_interface.ino create mode 100644 ml_inline.ino diff --git a/audio_module.ino b/audio_module.ino deleted file mode 100644 index 9c25181..0000000 --- a/audio_module.ino +++ /dev/null @@ -1,444 +0,0 @@ -/* - * Copyright (c) 2021 Marcel Licence - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * Dieses Programm ist Freie Software: Sie k�nnen es unter den Bedingungen - * der GNU General Public License, wie von der Free Software Foundation, - * Version 3 der Lizenz oder (nach Ihrer Wahl) jeder neueren - * ver�ffentlichten Version, weiter verteilen und/oder modifizieren. - * - * Dieses Programm wird in der Hoffnung bereitgestellt, dass es n�tzlich sein wird, jedoch - * OHNE JEDE GEW�HR,; sogar ohne die implizite - * Gew�hr der MARKTF�HIGKEIT oder EIGNUNG F�R EINEN BESTIMMTEN ZWECK. - * Siehe die GNU General Public License f�r weitere Einzelheiten. - * - * Sie sollten eine Kopie der GNU General Public License zusammen mit diesem - * Programm erhalten haben. Wenn nicht, siehe . - */ - -/** -* @file audio_module.ino -* @author Marcel Licence -* @date 16.12.2021 -* -* @brief this file provides a general audio interface to make it easier working with different platforms -*/ - - -#ifdef __CDT_PARSER__ -#include -#endif - - -#ifdef ESP8266 -#include -#include -#include -#endif - -#ifdef ESP32 -#include -#endif - -#ifdef TEENSYDUINO -#include -#include -#include -#include -#include -#endif - -#ifdef ARDUINO_DAISY_SEED -#include "DaisyDuino.h" -#endif - -#ifdef ARDUINO_RASPBERRY_PI_PICO -#include -#endif - -void Audio_Setup(void) -{ -#if (defined ESP8266) || (defined ESP32) - WiFi.mode(WIFI_OFF); - btStop(); -#endif - -#if 0 //ndef ESP8266 - btStop(); - esp_wifi_deinit(); -#endif - -#ifdef ESP32_AUDIO_KIT -#ifdef ES8388_ENABLED - ES8388_Setup(); - ES8388_SetIn2OoutVOL(0, 0); -#else - ac101_setup(); -#endif -#endif - -#ifdef ESP32 - setup_i2s(); -#endif - -#ifdef ESP8266 -#if 0 - system_update_cpu_freq(160); - i2s_begin(); - i2s_set_rate(SAMPLE_RATE); -#else - I2S_init(); -#endif - pinMode(2, INPUT); //restore GPIOs taken by i2s - pinMode(15, INPUT); -#endif - - -#ifdef TEENSYDUINO - AudioMemory(4); -#endif - -#ifdef ARDUINO_SEEED_XIAO_M0 - SAMD21_Synth_Init(); - pinMode(DAC0, OUTPUT); -#endif - -#ifdef ARDUINO_RASPBERRY_PI_PICO - if (!I2S.begin(SAMPLE_RATE)) - { - Serial.println("Failed to initialize I2S!"); - while (1); // do nothing - } -#endif -} - -#ifdef TEENSYDUINO - -const int ledPin = LED_PIN; /* pin configured in config.h */ - -#if 1 -AudioPlayQueue queue1; -AudioPlayQueue queue2; -AudioOutputI2S i2s1; -AudioConnection patchCord1(queue1, 0, i2s1, 0); /* left channel */ -AudioConnection patchCord2(queue2, 0, i2s1, 1); /* right channel */ -#else - -// GUItool: begin automatically generated code -AudioInputUSB usb1; //xy=134,545 -AudioPlayQueue queue1; //xy=258,380 -AudioPlayQueue queue2; //xy=261,423 -AudioRecordQueue queue6; //xy=265,557 -AudioRecordQueue queue5; //xy=274,516 -AudioPlayQueue queue4; //xy=352,622 -AudioPlayQueue queue3; //xy=380,530 -AudioOutputI2S i2s1; //xy=470,393 -AudioOutputUSB usb2; //xy=494,544 -AudioConnection patchCord1(usb1, 0, queue5, 0); -AudioConnection patchCord2(usb1, 1, queue6, 0); -AudioConnection patchCord3(queue1, 0, i2s1, 0); -AudioConnection patchCord4(queue2, 0, i2s1, 1); -AudioConnection patchCord5(queue3, 0, usb2, 0); -AudioConnection patchCord6(queue4, 0, usb2, 1); -// GUItool: end automatically generated code -#endif - - -static int16_t sampleBuffer[AUDIO_BLOCK_SAMPLES]; -static int16_t sampleBuffer2[AUDIO_BLOCK_SAMPLES]; -static int16_t *queueTransmitBuffer; -static int16_t *queueTransmitBuffer2; - -void Teensy_Setup() -{ - pinMode(ledPin, OUTPUT); - Midi_Setup(); -} - -#endif /* TEENSYDUINO */ - -#ifdef ARDUINO_DAISY_SEED - -static DaisyHardware hw; -static size_t num_channels; - -volatile static bool dataReady = false; -static float out_temp[2][48]; -static float *outCh[2] = {out_temp[0], out_temp[1]}; - -void MyCallback(float **in, float **out, size_t size) -{ - for (size_t i = 0; i < size; i++) - { - - out[0][i] = out_temp[0][i]; - out[1][i] = out_temp[1][i]; - out_temp[0][i] = in[0][i]; - out_temp[1][i] = in[1][i]; - } - dataReady = true; -} - -void DaisySeed_Setup(void) -{ - float sample_rate; - // Initialize for Daisy pod at 48kHz - hw = DAISY.init(DAISY_SEED, AUDIO_SR_48K); - num_channels = hw.num_channels; - sample_rate = DAISY.get_samplerate(); - - DAISY.begin(MyCallback); -} -#endif /* ARDUINO_DAISY_SEED */ - -#ifdef ARDUINO_SEEED_XIAO_M0 - -static int32_t u32buf[SAMPLE_BUFFER_SIZE]; - -inline -void ProcessAudio(uint16_t *buff, size_t len) -{ - /* convert from u16 to u10 */ - for (size_t i = 0; i < len; i++) - { - const int32_t preDiv = 4194304; // 2 ^ (16 + 6) - buff[i] = (uint16_t)(0x200 + (u32buf[i] / (preDiv))); - } -} - -#endif - -void Audio_OutputMono(int32_t *samples) -{ -#ifdef ESP8266 - for (int i = 0; i < SAMPLE_BUFFER_SIZE; i++) - { - int32_t sig = samples[i]; - static uint16_t sig16 = 0; - sig *= 4; - sig16 = sig; - while (!I2S_isNotFull()) - { - /* wait for buffer is not full */ - } - writeDAC(0x8000 + sig16); - } -#endif - -#ifdef ESP32 - float mono[SAMPLE_BUFFER_SIZE]; - for (int i = 0; i < SAMPLE_BUFFER_SIZE; i++) - { - float sigf = samples[i]; - sigf /= INT16_MAX; - mono[i] = sigf; - } - - i2s_write_stereo_samples_buff(mono, mono, SAMPLE_BUFFER_SIZE); -#endif /* ESP32 */ - -#ifdef TEENSYDUINO - { -#ifdef CYCLE_MODULE_ENABLED - calcCycleCountPre(); -#endif - queueTransmitBuffer = queue1.getBuffer(); /* blocking? */ - queueTransmitBuffer2 = queue2.getBuffer(); -#ifdef CYCLE_MODULE_ENABLED - calcCycleCount(); -#endif - if (queueTransmitBuffer) - { - { - for (size_t i = 0; i < AUDIO_BLOCK_SAMPLES; i++) - { - sampleBuffer[i] = (int16_t)((samples[i])); - } - - memcpy(queueTransmitBuffer, sampleBuffer, AUDIO_BLOCK_SAMPLES * 2); - memcpy(queueTransmitBuffer2, sampleBuffer, AUDIO_BLOCK_SAMPLES * 2); - } - queue1.playBuffer(); - queue2.playBuffer(); - } - } -#endif /* TEENSYDUINO */ - -#ifdef ARDUINO_DAISY_SEED - - float sig_f[SAMPLE_BUFFER_SIZE]; - -#ifdef CYCLE_MODULE_ENABLED - calcCycleCountPre(); -#endif - while (!dataReady) - { - /* just do nothing */ - } -#ifdef CYCLE_MODULE_ENABLED - calcCycleCount(); -#endif - - for (size_t i = 0; i < SAMPLE_BUFFER_SIZE; i++) - { - sig_f[i] = ((float)samples[i]) * (1.0f / ((float)INT16_MAX)); - } - - memcpy(out_temp[0], sig_f, sizeof(out_temp[0])); - memcpy(out_temp[1], sig_f, sizeof(out_temp[1])); - - dataReady = false; -#endif /* ARDUINO_DAISY_SEED */ - -#ifdef ARDUINO_SEEED_XIAO_M0 -#ifdef CYCLE_MODULE_ENABLED - calcCycleCountPre(); -#endif - while (!SAMD21_Synth_Process(ProcessAudio)) - { - /* just do nothing */ - } -#ifdef CYCLE_MODULE_ENABLED - calcCycleCount(); -#endif - memcpy(u32buf, samples, sizeof(int32_t)*SAMPLE_BUFFER_SIZE); -#endif /* ARDUINO_SEEED_XIAO_M0 */ - -#ifdef ARDUINO_RASPBERRY_PI_PICO - /* - * @see https://arduino-pico.readthedocs.io/en/latest/i2s.html - * @see https://www.waveshare.com/pico-audio.htm for connections - */ - int16_t u16int[2 * SAMPLE_BUFFER_SIZE]; - - for (int i = 0; i < SAMPLE_BUFFER_SIZE; i++) - { - u16int[2 * i] = samples[i]; - u16int[(2 * i) + 1] = samples[i]; - } -#if 1 - for (int i = 0; i < SAMPLE_BUFFER_SIZE * 2; i++) - { - I2S.write(u16int[i]); - } -#else - /* this does not work, I do not know why :-/ */ - static int16_t u16int_buf[2 * SAMPLE_BUFFER_SIZE]; - memcpy(u16int_buf, u16int, sizeof(u16int)); - I2S.write(u16int_buf, sizeof(u16int)); -#endif -#endif /* ARDUINO_RASPBERRY_PI_PICO */ - -#ifdef ARDUINO_GENERIC_F407VGTX - /* - * Todo Implementation for the STM32F407VGT6 - * Can be found on the ST Discovery Board - */ -#if 0 - int16_t u16int[2 * SAMPLE_BUFFER_SIZE]; - - for (int i = 0; i < SAMPLE_BUFFER_SIZE; i++) - { - u16int[2 * i] = samples[i]; - u16int[(2 * i) + 1] = samples[i]; - } - for (int i = 0; i < SAMPLE_BUFFER_SIZE * 2; i++) - { - I2S.write(u16int[i]); - } -#endif -#endif /* ARDUINO_GENERIC_F407VGTX */ -} - -#if (defined ESP32) || (defined TEENSYDUINO) || (defined ARDUINO_DAISY_SEED) || (defined ARDUINO_GENERIC_F407VGTX) -void Audio_Input(float *left, float *right) -{ -#ifdef ESP32 - i2s_read_stereo_samples_buff(left, right, SAMPLE_BUFFER_SIZE); -#endif /* ESP32 */ -} - -void Audio_Output(float *left, float *right) -{ -#ifdef ESP32 - i2s_write_stereo_samples_buff(left, right, SAMPLE_BUFFER_SIZE); -#endif /* ESP32 */ - -#ifdef TEENSYDUINO - { -#ifdef CYCLE_MODULE_ENABLED - calcCycleCountPre(); -#endif - queueTransmitBuffer = queue1.getBuffer(); /* blocking? */ - queueTransmitBuffer2 = queue2.getBuffer(); -#ifdef CYCLE_MODULE_ENABLED - calcCycleCount(); -#endif - if (queueTransmitBuffer) - { - { - for (size_t i = 0; i < AUDIO_BLOCK_SAMPLES; i++) - { - sampleBuffer[i] = (int16_t)(left[i] * INT16_MAX); - sampleBuffer2[i] = (int16_t)(right[i] * INT16_MAX); - } - - memcpy(queueTransmitBuffer, sampleBuffer, AUDIO_BLOCK_SAMPLES * 2); - memcpy(queueTransmitBuffer2, sampleBuffer2, AUDIO_BLOCK_SAMPLES * 2); - } - - queue1.playBuffer(); - queue2.playBuffer(); - } - } -#endif /* TEENSYDUINO */ - -#ifdef ARDUINO_DAISY_SEED - -#ifdef CYCLE_MODULE_ENABLED - calcCycleCountPre(); -#endif - while (!dataReady) - { - /* just do nothing */ - } -#ifdef CYCLE_MODULE_ENABLED - calcCycleCount(); -#endif - -#if 0 - for (int i = 0; i < SAMPLE_BUFFER_SIZE; i++) - { - left[i] = i * (1.0f / ((float)SAMPLE_BUFFER_SIZE)); - right[i] = i * (1.0f / ((float)SAMPLE_BUFFER_SIZE)); - } -#endif - memcpy(out_temp[0], left, sizeof(out_temp[0])); - memcpy(out_temp[1], right, sizeof(out_temp[1])); - - - dataReady = false; - -#endif /* ARDUINO_DAISY_SEED */ - -#ifdef ARDUINO_GENERIC_F407VGTX - /* - * Todo Implementation for the STM32F407VGT6 - * Can be found on the ST Discovery Board - */ -#endif /* ARDUINO_GENERIC_F407VGTX */ -} -#endif /* (defined ESP32) || (defined TEENSYDUINO) || (defined ARDUINO_DAISY_SEED) || (defined ARDUINO_GENERIC_F407VGTX) */ - diff --git a/blink.ino b/blink.ino deleted file mode 100644 index d2818c5..0000000 --- a/blink.ino +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2021 Marcel Licence - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * Dieses Programm ist Freie Software: Sie können es unter den Bedingungen - * der GNU General Public License, wie von der Free Software Foundation, - * Version 3 der Lizenz oder (nach Ihrer Wahl) jeder neueren - * veröffentlichten Version, weiter verteilen und/oder modifizieren. - * - * Dieses Programm wird in der Hoffnung bereitgestellt, dass es nützlich sein wird, jedoch - * OHNE JEDE GEWÄHR,; sogar ohne die implizite - * Gewähr der MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK. - * Siehe die GNU General Public License für weitere Einzelheiten. - * - * Sie sollten eine Kopie der GNU General Public License zusammen mit diesem - * Programm erhalten haben. Wenn nicht, siehe . - */ - -/* - * this file includes a simple blink task implementation - * - * Author: Marcel Licence - */ - -inline -void Blink_Setup(void) -{ - pinMode(LED_PIN, OUTPUT); -} - - -inline -void Blink_Process(void) -{ - static bool ledOn = true; - if (ledOn) - { - digitalWrite(LED_PIN, HIGH); // turn the LED on (HIGH is the voltage level) - } - else - { - digitalWrite(LED_PIN, LOW); // turn the LED off - } - ledOn = !ledOn; -} diff --git a/config.h b/config.h index 8470798..69b0e18 100644 --- a/config.h +++ b/config.h @@ -47,6 +47,9 @@ #define CONFIG_H_ +#define SERIAL_BAUDRATE 115200 + + //#define BOARD_ML_V1 /* activate this when using the ML PCB V1 */ //#define BOARD_ESP32_AUDIO_KIT_AC101 /* activate this when using the ESP32 Audio Kit v2.2 with the AC101 codec */ #define BOARD_ESP32_AUDIO_KIT_ES8388 /* activate this when using the ESP32 Audio Kit v2.2 with the ES8388 codec */ @@ -69,7 +72,7 @@ * include the board configuration * there you will find the most hardware depending pin settings */ -#include /* requires https://github.com/marcel-licence/ML_SynthTools */ +#include /* requires the ML_Synth library: https://github.com/marcel-licence/ML_SynthTools */ /* our samplerate */ #define SAMPLE_RATE 44100 @@ -81,7 +84,7 @@ /* on board led */ -#define LED_PIN 19 +#define BLINK_LED_PIN 19 #endif /* CONFIG_H_ */ diff --git a/doc/board_info.md b/doc/board_info.md new file mode 100644 index 0000000..9129f67 --- /dev/null +++ b/doc/board_info.md @@ -0,0 +1,236 @@ +

Board Build Variants

+ +Below you will find a list of build which can be configured and should compile without any problems + +
+Core: ESP32 Arduino
+Version: 2.0.0
+Board: ESP32 Dev Module
+
+Program storage space: 725241 bytes
+Dynamic memory: 48892 bytes
+
+PSRAM: Enabled
+Partition Scheme: Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS)
+CPU Frequency: 240MHz (WiFi/BT)
+Flash Mode: QIO
+Flash Frequency: 80MHz
+Flash Size: 4MB (32Mb)
+Upload Speed: 921600
+Arduino Runs On: Core 1
+Events Run On: Core 1
+Core Debug Level: None
+
+Used libraries:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameVersionUrlGitCore library
ML SynthTools1.0.1https://github.com/marcel-licence/ML_SynthToolshttps://github.com/marcel-licence/ML_SynthTools.gitFalse
WiFi2.0.0True
Wire2.0.0http://arduino.cc/en/Reference/WireTrue
Adafruit GFX Library1.10.10https://github.com/adafruit/Adafruit-GFX-LibraryFalse
Adafruit SSD13062.4.5https://github.com/adafruit/Adafruit_SSD1306False
SPI2.0.0http://arduino.cc/en/Reference/SPITrue
Adafruit BusIO1.14.1https://github.com/adafruit/Adafruit_BusIOhttps://github.com/adafruit/Adafruit_BusIOFalse

+Core: ESP32 Arduino
+Version: 2.0.7
+Board: ESP32 Dev Module
+
+Program storage space: 789277 bytes
+Dynamic memory: 53536 bytes
+
+JTAG Adapter: Disabled
+PSRAM: Enabled
+Partition Scheme: Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS)
+CPU Frequency: 240MHz (WiFi/BT)
+Flash Mode: QIO
+Flash Frequency: 80MHz
+Flash Size: 4MB (32Mb)
+Upload Speed: 921600
+Arduino Runs On: Core 1
+Events Run On: Core 1
+Core Debug Level: None
+Erase All Flash Before Sketch Upload: Disabled
+
+Used libraries:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameVersionUrlGitCore library
ML SynthTools1.0.1https://github.com/marcel-licence/ML_SynthToolshttps://github.com/marcel-licence/ML_SynthTools.gitFalse
WiFi2.0.0https://github.com/espressif/arduino-esp32.gitTrue
Wire2.0.0http://arduino.cc/en/Reference/Wirehttps://github.com/espressif/arduino-esp32.gitTrue
Adafruit GFX Library1.10.10https://github.com/adafruit/Adafruit-GFX-LibraryFalse
Adafruit SSD13062.4.5https://github.com/adafruit/Adafruit_SSD1306False
SPI2.0.0http://arduino.cc/en/Reference/SPIhttps://github.com/espressif/arduino-esp32.gitTrue
Adafruit BusIO1.14.1https://github.com/adafruit/Adafruit_BusIOhttps://github.com/adafruit/Adafruit_BusIOFalse

+Core: ESP32 Arduino
+Version: 1.0.6
+Board: ESP32 Dev Module
+
+Program storage space: 769954 bytes
+Dynamic memory: 49272 bytes
+
+PSRAM: Enabled
+Partition Scheme: Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS)
+CPU Frequency: 240MHz (WiFi/BT)
+Flash Mode: QIO
+Flash Frequency: 80MHz
+Flash Size: 4MB (32Mb)
+Upload Speed: 921600
+Core Debug Level: None
+
+Used libraries:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameVersionUrlGitCore library
ML SynthTools1.0.1https://github.com/marcel-licence/ML_SynthToolshttps://github.com/marcel-licence/ML_SynthTools.gitFalse
WiFi1.0True
Wire1.0.1http://arduino.cc/en/Reference/WireTrue
Adafruit GFX Library1.10.10https://github.com/adafruit/Adafruit-GFX-LibraryFalse
Adafruit SSD13062.4.5https://github.com/adafruit/Adafruit_SSD1306False
SPI1.0http://arduino.cc/en/Reference/SPITrue
Adafruit BusIO1.14.1https://github.com/adafruit/Adafruit_BusIOhttps://github.com/adafruit/Adafruit_BusIOFalse
\ No newline at end of file diff --git a/es8388.ino b/es8388.ino deleted file mode 100644 index 345ec79..0000000 --- a/es8388.ino +++ /dev/null @@ -1,531 +0,0 @@ -/* - * Copyright (c) 2021 Marcel Licence - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * Dieses Programm ist Freie Software: Sie können es unter den Bedingungen - * der GNU General Public License, wie von der Free Software Foundation, - * Version 3 der Lizenz oder (nach Ihrer Wahl) jeder neueren - * veröffentlichten Version, weiter verteilen und/oder modifizieren. - * - * Dieses Programm wird in der Hoffnung bereitgestellt, dass es nützlich sein wird, jedoch - * OHNE JEDE GEWÄHR,; sogar ohne die implizite - * Gewähr der MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK. - * Siehe die GNU General Public License für weitere Einzelheiten. - * - * Sie sollten eine Kopie der GNU General Public License zusammen mit diesem - * Programm erhalten haben. Wenn nicht, siehe . - */ - -/** - * @file es8388.ino - * @author Marcel Licence - * @date 22.08.2021 - * - * @brief This module is used to initialize the ES8388 - * - * @see ESP32 Audio Kit AC101 codec failure - Get synthesizer projects working based on ES8388 - https://youtu.be/8UB3fYPjqSk - * @see https://github.com/espressif/esp-adf/blob/master/components/audio_hal/driver/es8388/es8388.c - */ - - -#ifdef __CDT_PARSER__ -#include -#endif - - -#ifdef ES8388_ENABLED -/* - * http://www.everest-semi.com/pdf/ES8388%20DS.pdf - */ - -#include - - -/* ES8388 address */ -//#define ES8388_ADDR 0x20 /*!< 0x22:CE=1;0x20:CE=0*/ -#define ES8388_ADDR 0x10 /*!< 0x22:CE=1;0x20:CE=0*/ - - -/* ES8388 register */ -#define ES8388_CONTROL1 0x00 -#define ES8388_CONTROL2 0x01 - -#define ES8388_CHIPPOWER 0x02 - -#define ES8388_ADCPOWER 0x03 -#define ES8388_DACPOWER 0x04 - -#define ES8388_CHIPLOPOW1 0x05 -#define ES8388_CHIPLOPOW2 0x06 - -#define ES8388_ANAVOLMANAG 0x07 - -#define ES8388_MASTERMODE 0x08 -/* ADC */ -#define ES8388_ADCCONTROL1 0x09 -#define ES8388_ADCCONTROL2 0x0a -#define ES8388_ADCCONTROL3 0x0b -#define ES8388_ADCCONTROL4 0x0c -#define ES8388_ADCCONTROL5 0x0d -#define ES8388_ADCCONTROL6 0x0e -#define ES8388_ADCCONTROL7 0x0f -#define ES8388_ADCCONTROL8 0x10 -#define ES8388_ADCCONTROL9 0x11 -#define ES8388_ADCCONTROL10 0x12 -#define ES8388_ADCCONTROL11 0x13 -#define ES8388_ADCCONTROL12 0x14 -#define ES8388_ADCCONTROL13 0x15 -#define ES8388_ADCCONTROL14 0x16 -/* DAC */ -#define ES8388_DACCONTROL1 0x17 -#define ES8388_DACCONTROL2 0x18 -#define ES8388_DACCONTROL3 0x19 -#define ES8388_DACCONTROL4 0x1a -#define ES8388_DACCONTROL5 0x1b -#define ES8388_DACCONTROL6 0x1c -#define ES8388_DACCONTROL7 0x1d -#define ES8388_DACCONTROL8 0x1e -#define ES8388_DACCONTROL9 0x1f -#define ES8388_DACCONTROL10 0x20 -#define ES8388_DACCONTROL11 0x21 -#define ES8388_DACCONTROL12 0x22 -#define ES8388_DACCONTROL13 0x23 -#define ES8388_DACCONTROL14 0x24 -#define ES8388_DACCONTROL15 0x25 -#define ES8388_DACCONTROL16 0x26 -#define ES8388_DACCONTROL17 0x27 -#define ES8388_DACCONTROL18 0x28 -#define ES8388_DACCONTROL19 0x29 -#define ES8388_DACCONTROL20 0x2a -#define ES8388_DACCONTROL21 0x2b -#define ES8388_DACCONTROL22 0x2c -#define ES8388_DACCONTROL23 0x2d -#define ES8388_DACCONTROL24 0x2e -#define ES8388_DACCONTROL25 0x2f -#define ES8388_DACCONTROL26 0x30 -#define ES8388_DACCONTROL27 0x31 -#define ES8388_DACCONTROL28 0x32 -#define ES8388_DACCONTROL29 0x33 -#define ES8388_DACCONTROL30 0x34 - - -uint8_t ES8388_ReadReg(uint8_t reg) -{ - Wire.beginTransmission(ES8388_ADDR); - Wire.write(reg); - Wire.endTransmission(false); - - uint8_t val = 0u; - if (1 == Wire.requestFrom(uint16_t(ES8388_ADDR), uint8_t(1), true)) - { - val = Wire.read(); - } - Wire.endTransmission(false); - - return val; -} - -bool ES8388_WriteReg(uint8_t reg, uint8_t val) -{ - Wire.beginTransmission(ES8388_ADDR); - Wire.write(reg); - Wire.write(val); - return 0 == Wire.endTransmission(true); -} - -bool ES8388_begin(int sda, int scl, uint32_t frequency) -{ - bool ok = Wire.begin(sda, scl, frequency); - - // Reset all registers, readback default as sanity check - //ok &= WriteReg(CHIP_AUDIO_RS, 0x123); - delay(100); - - Serial.printf("0x00: 0x%02x\n", ES8388_ReadReg(ES8388_CONTROL1)); - Serial.printf("0x01: 0x%02x\n", ES8388_ReadReg(ES8388_CONTROL2)); - - ES8388_WriteReg(ES8388_CONTROL1, 1 << 7); /* do reset! */ - ES8388_WriteReg(ES8388_CONTROL1, 0x06); - ES8388_WriteReg(ES8388_CONTROL2, 0x50); - - ok &= (0x06 == ES8388_ReadReg(ES8388_CONTROL1)); - ok &= (0x50 == ES8388_ReadReg(ES8388_CONTROL2)); - return ok; -} - -void es8388_read_all() -{ - for (int i = 0; i < 53; i++) - { - uint8_t reg = 0; - reg = ES8388_ReadReg(i); - Serial.printf("Reg 0x%02x = 0x%02x\n", i, reg); - } -} - -void ES8388_SetADCVOL(uint8_t unused, float vol) -{ -#ifdef STATUS_ENABLED - Status_ValueChangedInt("ADC Volume /db", (vol - 1) * 97 + 0.5); -#endif - - vol *= -192; - vol += 192; - - uint8_t volu8 = vol; - - if (volu8 > 192) - { - volu8 = 192; - } - - ES8388_WriteReg(0x10, volu8); // LADCVOL - ES8388_WriteReg(0x11, volu8); // RADCVOL -} - -void ES8388_SetDACVOL(uint8_t unused, float vol) -{ -#ifdef STATUS_ENABLED - Status_ValueChangedInt("DAC Volume /db", (vol - 1) * 97 + 0.5); -#endif - - vol *= -192; - vol += 192; - - uint8_t volu8 = vol; - - if (volu8 > 192) - { - volu8 = 192; - } - - ES8388_WriteReg(0x1A, volu8); // LDACVOL - ES8388_WriteReg(0x1B, volu8); // RDACVOL -} - -void ES8388_SetPGAGain(uint8_t unused, float vol) -{ -#ifdef STATUS_ENABLED - Status_ValueChangedInt("PGA Gain /db", vol * 24 + 0.25); -#endif - - vol *= 8; - - uint8_t volu8 = vol; - - if (volu8 > 8) - { - volu8 = 8; - } - // ES8388_ADCCONTROL1 - ES8388_WriteReg(0x09, volu8 + (volu8 << 4)); // MicAmpL, MicAmpR -} - -void ES8388_SetInputCh(uint8_t ch, float var) -{ - if (var > 0) - { - uint8_t in; - switch (ch) - { - case 0: - in = 0; - Serial.printf("AdcCh0!\n"); - break; - - case 1: - in = 1; - Serial.printf("AdcCh1!\n"); - break; - - default: - Serial.printf("Illegal Input ch!\n"); - return; - } - // ES8388_ADCCONTROL2 - ES8388_WriteReg(0x0A, (in << 6) + (in << 4)); // LINSEL , RINSEL , DSSEL , DSR - -#ifdef STATUS_ENABLED - Status_ValueChangedInt("ADC Ch", in); -#endif - } -} - -void ES8388_SetMixInCh(uint8_t ch, float var) -{ - if (var > 0) - { - uint8_t in = 0; - switch (ch) - { - case 0: - in = 0; - Serial.printf("MixCh0!\n"); - break; - - case 1: - in = 1; - Serial.printf("MixCh1!\n"); - break; - - case 2: - in = 3; - Serial.printf("MixChAMPL!\n"); - break; - - default: - Serial.printf("Illegal Mix Input ch!\n"); - return; - } - // ES8388_DACCONTROL16 - ES8388_WriteReg(0x26, in + (in << 3)); // LMIXSEL, RMIXSEL -#ifdef STATUS_ENABLED - Status_ValueChangedInt("Mix In Ch", in); -#endif - } -} - -void ES8388_SetIn2OoutVOL(uint8_t unused, float vol) -{ -#ifdef STATUS_ENABLED - Status_ValueChangedInt("In to out volume /db", (vol - 1) * 16 + 0.5); -#endif - - vol *= -5; - vol += 7; - - uint8_t volu8 = vol; - - if (volu8 > 7) - { - volu8 = 7; - } - - uint8_t var; - - var = ES8388_ReadReg(0x27) & 0xC0; - if (volu8 == 7) - { - var &= ~ 0x40; - } - else - { - var |= 0x40; - } - ES8388_WriteReg(0x27, (volu8 << 3) + var); // LD2LO, LI2LO, LI2LOVOL - - var = ES8388_ReadReg(0x2A) & 0xC0; - if (volu8 == 7) - { - var &= ~ 0x40; - } - else - { - var |= 0x40; - } - ES8388_WriteReg(0x2A, (volu8 << 3) + var); // RD2RO, RI2RO, RI2ROVOL -} - -void ES8388_SetOUT1VOL(uint8_t unused, float vol) -{ -#ifdef STATUS_ENABLED - Status_ValueChangedInt("OUT1VOL /db", (vol - 1) * 31 + 0.5); -#endif - - vol *= 0x1E; - - uint8_t volu8 = vol; - - if (volu8 > 129) - { - volu8 = 129; - } - - ES8388_WriteReg(0x2E, volu8); // LOUT1VOL - ES8388_WriteReg(0x2F, volu8); // ROUT1VOL -} - -void ES8388_SetOUT2VOL(uint8_t unused, float vol) -{ -#ifdef STATUS_ENABLED - Status_ValueChangedInt("OUT2VOL /db", (vol - 1) * 31 + 0.5); -#endif - - vol *= 0x1E; - - uint8_t volu8 = vol; - - if (volu8 > 129) - { - volu8 = 129; - } - - ES8388_WriteReg(0x30, volu8); // LOUT2VOL - ES8388_WriteReg(0x31, volu8); // ROUT2VOL -} - -void ES8388_Setup() -{ - Serial.printf("Connect to ES8388 codec... "); - - while (not ES8388_begin(ES8388_PIN_SDA, ES8388_PIN_SCL, 400000)) - { - Serial.printf("Failed!\n"); - delay(1000); - } - - ES8388_WriteReg(ES8388_CHIPPOWER, 0xFF); //reset and stop es8388 - - - ES8388_WriteReg(0x00, 0x80); /* reset control port register to default */ - ES8388_WriteReg(0x00, 0x06); /* restore default value */ - - - - /* - * https://dl.radxa.com/rock2/docs/hw/ds/ES8388%20user%20Guide.pdf - */ - - /* - * 10.5 Power Down Sequence (To Standby Mode) - */ - ES8388_WriteReg(0x0F, 0x34); /* ADC Mute */ - ES8388_WriteReg(0x19, 0x36); /* DAC Mute */ - - ES8388_WriteReg(0x02, 0xF3); /* Power down DEM and STM */ - - /* - * 10.4 The sequence for Start up bypass mode - */ - /* Set Chip to Slave Mode */ - ES8388_WriteReg(0x08, 0x00); - /* Power down DEM and STM */ - ES8388_WriteReg(0x02, 0x3F); - /* Set same LRCK */ - ES8388_WriteReg(0x2B, 0x80); - /* Set Chip to Play&Record Mode */ - ES8388_WriteReg(0x00, 0x05); - /* Power Up Analog and Ibias */ - ES8388_WriteReg(0x01, 0x40); -#if 0 - /* - * Power down ADC, Power up - * Analog Input for Bypass - */ - ES8388_WriteReg(0x03, 0x3F); -#else - ES8388_WriteReg(0x03, 0x3F); /* adc also on but no bias */ - - ES8388_WriteReg(0x03, 0x00); // PdnAINL, PdinAINR, PdnADCL, PdnADCR, PdnMICB, PdnADCBiasgen, flashLP, Int1LP -#endif - -#if 0 - /* - * Power Down DAC, Power up - * Analog Output for Bypass - */ - ES8388_WriteReg(0x04, 0xFC); -#else - /* - * Power up DAC / Analog Output - * for Record - */ - ES8388_WriteReg(0x04, 0x3C); - - -#if 1 - /* - * Select Analog input channel for ADC - */ - ES8388_WriteReg(0x0A, 0x80); // LINSEL , RINSEL , DSSEL , DSR - - /* Select PGA Gain for ADC analog input */ - ES8388_WriteReg(0x09, 0x00); // PGA gain? - - //ES8388_WriteReg(0x0C, 0x18); // DATSEL, ADCLRP, ADCWL, ADCFORMAT - //ES8388_WriteReg(0x0C, 0x40); // DATSEL, ADCLRP, ADCWL, ADCFORMAT - ES8388_WriteReg(0x0C, 0x0C); // DATSEL, ADCLRP, ADCWL, ADCFORMAT - ES8388_WriteReg(0x0D, 0x02); // ADCFsMode , ADCFsRatio - //ES8388_WriteReg(0x0D, (1<<5) + 0x03); // ADCFsMode , ADCFsRatio Hasan - //ES8388_WriteReg(0x0D, 0); // ADCFsMode , ADCFsRatio Hasan - - /* - * Set ADC Digital Volume - */ -#if 1 - ES8388_SetADCVOL(0, 1.0f); -#else - ES8388_WriteReg(0x10, 0x00); // LADCVOL - ES8388_WriteReg(0x11, 0x00); // RADCVOL -#endif - - /* UnMute ADC */ - ES8388_WriteReg(0x0F, 0x30); // - - ES8388_WriteReg(0x12, 0x16); - - ES8388_WriteReg(0x17, 0x18); // DACLRSWAP, DACLRP, DACWL, DACFORMAT - ES8388_WriteReg(0x18, 0x02); // DACFsMode , DACFsRatio -#endif - - - /* - * Set ADC Digital Volume - */ - ES8388_WriteReg(0x1A, 0x00); - ES8388_WriteReg(0x1B, 0x02); - //ES8388_WriteReg(0x1B, (1<<5) + 0x03); // ADCFsMode , ADCFsRatio Hasan - //ES8388_WriteReg(0x1B, 0); // ADCFsMode , ADCFsRatio Hasan - /* UnMute DAC */ - ES8388_WriteReg(0x19, 0x32); -#endif - /* - * Setup Mixer - */ - ES8388_WriteReg(0x26, 0x09);// ES8388_WriteReg(0x26, 0x00); - ES8388_WriteReg(0x27, 0xD0); // ES8388_DACCONTROL17 - ES8388_WriteReg(0x28, 0x38); - ES8388_WriteReg(0x29, 0x38); - ES8388_WriteReg(0x2A, 0xD0); - - /* Set Lout/Rout Volume */ -#if 1 - ES8388_SetOUT1VOL(0, 1); - ES8388_SetOUT2VOL(0, 1); -#else - ES8388_WriteReg(0x2E, 0x1E); - ES8388_WriteReg(0x2F, 0x1E); - ES8388_WriteReg(0x30, 0x1E); - ES8388_WriteReg(0x31, 0x1E); -#endif - - /* Power up DEM and STM */ -#if 0 - ES8388_WriteReg(0x02, 0xF0); -#else - ES8388_WriteReg(0x02, 0x00); -#endif - - ES8388_SetInputCh(1, 1); - ES8388_SetMixInCh(2, 1); - ES8388_SetPGAGain(0, 1); - ES8388_SetIn2OoutVOL(0, 0); - - Serial.printf("ES8388 setup finished!\n"); - es8388_read_all(); -} - -#endif - diff --git a/esp32_audio_kit_module.ino b/esp32_audio_kit_module.ino deleted file mode 100644 index 25fd6a9..0000000 --- a/esp32_audio_kit_module.ino +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Copyright (c) 2021 Marcel Licence - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * Dieses Programm ist Freie Software: Sie können es unter den Bedingungen - * der GNU General Public License, wie von der Free Software Foundation, - * Version 3 der Lizenz oder (nach Ihrer Wahl) jeder neueren - * veröffentlichten Version, weiter verteilen und/oder modifizieren. - * - * Dieses Programm wird in der Hoffnung bereitgestellt, dass es nützlich sein wird, jedoch - * OHNE JEDE GEWÄHR,; sogar ohne die implizite - * Gewähr der MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK. - * Siehe die GNU General Public License für weitere Einzelheiten. - * - * Sie sollten eine Kopie der GNU General Public License zusammen mit diesem - * Programm erhalten haben. Wenn nicht, siehe . - */ - -/** - * @file esp32_audio_kit_module.ino - * @author Marcel Licence - * @date 12.10.2021 - * - * @brief This file contains basic stuff to work with the ESP32 Audio Kit V2.2 module - * - * @see ESP32 Audio Kit AC101 codec failure - Get synthesizer projects working based on ES8388 - https://youtu.be/8UB3fYPjqSk - * @see Instructions: http://myosuploads3.banggood.com/products/20210306/20210306011116instruction.pdf - * @see Schematic: https://docs.ai-thinker.com/_media/esp32-audio-kit_v2.2_sch.pdf - */ - - -#ifdef __CDT_PARSER__ -#include -#endif - - -#ifdef ESP32_AUDIO_KIT - -#ifdef AC101_ENABLED -#include "AC101.h" /* only compatible with forked repo: https://github.com/marcel-licence/AC101 */ -#endif - - -//#define BUTTON_DEBUG_MSG - - - -#define PIN_LED4 (22) -#define PIN_LED5 (19) - - -#ifdef AUDIO_KIT_BUTTON_DIGITAL -/* - * when not modified and R66-R70 are placed on the board - */ -#define PIN_KEY_1 (36) -#define PIN_KEY_2 (13) -#define PIN_KEY_3 (19) -#define PIN_KEY_4 (23) -#define PIN_KEY_5 (18) -#define PIN_KEY_6 (5) - -#define PIN_PLAY PIN_KEY_4 -#define PIN_VOL_UP PIN_KEY_5 -#define PIN_VOL_DOWN PIN_KEY_6 -#endif - -#ifdef AUDIO_KIT_BUTTON_ANALOG -/* - * modification required: - * - remove R66-R70 - * - insert R60-R64 (0 Ohm or solder bridge) - * - insert R55-R59 using 1.8kOhm (recommended but other values might be possible with tweaking the code) - */ -#ifndef PIN_KEY_ANALOG -#define PIN_KEY_ANALOG (36) -#endif - -#define KEY_SETTLE_VAL 9 /* use higher value if anaog buton detection is unstable */ - -uint32_t keyMin[7] = {4095 - 32, 0, 462 - 32, 925 - 32, 1283 - 32, 1570 - 32, 1800 - 32}; -uint32_t keyMax[7] = {4095 + 32, 0 + 32, 525 + 32, 1006 + 32, 1374 + 32, 1570 + 32, 1800 + 32 }; -#endif - -#define OUTPUT_PIN 0 -#define MCLK_CH 0 -#define PWM_BIT 1 - -#ifdef AC101_ENABLED -static AC101 ac; -#endif - -/* actually only supporting 16 bit */ -#define SAMPLE_SIZE_16BIT -//#define SAMPLE_SIZE_24BIT -//#define SAMPLE_SIZE_32BIT - -#ifndef SAMPLE_RATE -#define SAMPLE_RATE 44100 -#endif -#define CHANNEL_COUNT 2 -#define WORD_SIZE 16 -#define I2S1CLK (512*SAMPLE_RATE) -#define BCLK (SAMPLE_RATE*CHANNEL_COUNT*WORD_SIZE) -#define LRCK (SAMPLE_RATE*CHANNEL_COUNT) - - -typedef void(*audioKitButtonCb)(uint8_t, uint8_t); -extern audioKitButtonCb audioKitButtonCallback; - -#ifdef AC101_ENABLED -/* - * this function could be used to set up the masterclock - * it is not necessary to use the ac101 - */ -void ac101_mclk_setup() -{ - // Put a signal out on pin - uint32_t freq = SAMPLE_RATE * 512; /* The maximal frequency is 80000000 / 2^bit_num */ - Serial.printf("Output frequency: %d\n", freq); - ledcSetup(MCLK_CH, freq, PWM_BIT); - ledcAttachPin(OUTPUT_PIN, MCLK_CH); - ledcWrite(MCLK_CH, 1 << (PWM_BIT - 1)); /* 50% duty -> The available duty levels are (2^bit_num)-1, where bit_num can be 1-15. */ -} - -/* - * complete setup of the ac101 to enable in/output - */ -void ac101_setup() -{ - Serial.printf("Connect to AC101 codec... "); - while (not ac.begin(AC101_PIN_SDA, AC101_PIN_SCL)) - { - Serial.printf("Failed!\n"); - delay(1000); - } - Serial.printf("OK\n"); -#ifdef SAMPLE_SIZE_24BIT - ac.SetI2sWordSize(AC101::WORD_SIZE_24_BITS); -#endif -#ifdef SAMPLE_SIZE_16BIT - ac.SetI2sWordSize(AC101::WORD_SIZE_16_BITS); -#endif - -#if (SAMPLE_RATE==44100)&&(defined(SAMPLE_SIZE_16BIT)) - ac.SetI2sSampleRate(AC101::SAMPLE_RATE_44100); - /* - * BCLK: 44100 * 2 * 16 = 1411200 Hz - * SYSCLK: 512 * fs = 512* 44100 = 22579200 Hz - * - * I2S1CLK/BCLK1 -> 512 * 44100 / 44100*2*16 - * BCLK1/LRCK -> 44100*2*16 / 44100 Obacht ... ein clock cycle goes high and low - * means 32 when 32 bits are in a LR word channel * word_size - */ - ac.SetI2sClock(AC101::BCLK_DIV_16, false, AC101::LRCK_DIV_32, false); - ac.SetI2sMode(AC101::MODE_SLAVE); - ac.SetI2sWordSize(AC101::WORD_SIZE_16_BITS); - ac.SetI2sFormat(AC101::DATA_FORMAT_I2S); -#endif - - ac.SetVolumeSpeaker(3); - ac.SetVolumeHeadphone(99); - -#if 1 - ac.SetLineSource(); -#else - ac.SetMicSource(); /* handle with care: mic is very sensitive and might cause feedback using amp!!! */ -#endif - -#if 0 - ac.DumpRegisters(); -#endif - - // Enable amplifier -#if 0 /* amplifier only required when speakers attached? */ - pinMode(GPIO_PA_EN, OUTPUT); - digitalWrite(GPIO_PA_EN, HIGH); -#endif -} -#endif /* #ifdef AC101_ENABLED */ - -/* - * pullup required to enable reading the buttons (buttons will connect them to ground if pressed) - */ -void button_setup() -{ -#ifdef AUDIO_KIT_BUTTON_DIGITAL - // Configure keys on ESP32 Audio Kit board - pinMode(PIN_PLAY, INPUT_PULLUP); - pinMode(PIN_VOL_UP, INPUT_PULLUP); - pinMode(PIN_VOL_DOWN, INPUT_PULLUP); -#endif -#ifdef AUDIO_KIT_BUTTON_ANALOG_OLD - adcAttachPin(PIN_KEY_ANALOG); - analogReadResolution(10); - analogSetAttenuation(ADC_11db); -#endif -} - -#ifdef AC101_ENABLED -/* - * selects the microphone as audio source - * handle with care: mic is very sensitive and might cause feedback using amp!!! - */ -void ac101_setSourceMic(void) -{ - ac.SetMicSource(); -} - -/* - * selects the line in as input - */ -void ac101_setSourceLine(void) -{ - ac.SetLineSource(); -} -#endif /* #ifdef AC101_ENABLED */ - -/* - * very bad implementation checking the button state - * there is some work required for a better functionality - */ -void button_loop() -{ -#ifdef AUDIO_KIT_BUTTON_DIGITAL - if (digitalRead(PIN_PLAY) == LOW) - { - Serial.println("PIN_PLAY pressed"); - if (buttonMapping.key4_pressed != NULL) - { - buttonMapping.key4_pressed(); - } - } - if (digitalRead(PIN_VOL_UP) == LOW) - { - Serial.println("PIN_VOL_UP pressed"); - if (buttonMapping.key5_pressed != NULL) - { - buttonMapping.key5_pressed(); - } - } - if (digitalRead(PIN_VOL_DOWN) == LOW) - { - Serial.println("PIN_VOL_DOWN pressed"); - if (buttonMapping.key6_pressed != NULL) - { - buttonMapping.key6_pressed(); - } - } -#endif -#ifdef AUDIO_KIT_BUTTON_ANALOG - static uint32_t lastKeyAD = 0xFFFF; - static uint32_t keyAD = 0; - static uint8_t pressedKey = 0; - static uint8_t newPressedKey = 0; - static uint8_t pressedKeyLast = 0; - static uint8_t keySettle = 0; - - keyAD = analogRead(PIN_KEY_ANALOG); - if (keyAD != lastKeyAD) - { - //Serial.printf("keyAd: %d\n", keyAD); - lastKeyAD = keyAD; - - //pressedKey = 0; - for (int i = 0; i < 7; i ++) - { - if ((keyAD >= keyMin[i]) && (keyAD < keyMax[i])) - { - newPressedKey = i; - } - } - if (newPressedKey != pressedKey) - { - keySettle = KEY_SETTLE_VAL; - pressedKey = newPressedKey; - } - } - - if (keySettle > 0) - { - keySettle--; - if (keySettle == 0) - { - if (pressedKey != pressedKeyLast) - { - if (pressedKeyLast > 0) - { -#ifdef BUTTON_DEBUG_MSG - Serial.printf("Key %d up\n", pressedKeyLast); -#endif - if (audioKitButtonCallback != NULL) - { - audioKitButtonCallback(pressedKeyLast - 1, 0); - } - } - if (pressedKey > 0) - { -#ifdef BUTTON_DEBUG_MSG - Serial.printf("Key %d down\n", pressedKey); -#endif - if (audioKitButtonCallback != NULL) - { - audioKitButtonCallback(pressedKey - 1, 1); - } - } - pressedKeyLast = pressedKey; - } - } - } -#endif -} - -#endif - diff --git a/esp32_multitrack_looper.ino b/esp32_multitrack_looper.ino index 612fc44..f8702ea 100644 --- a/esp32_multitrack_looper.ino +++ b/esp32_multitrack_looper.ino @@ -83,6 +83,11 @@ #endif +#define ML_SYNTH_INLINE_DECLARATION +#include +#undef ML_SYNTH_INLINE_DECLARATION + + /* to avoid the high click when turning on the microphone */ static float click_supp_gain = 0.0f; diff --git a/i2s_interface.ino b/i2s_interface.ino deleted file mode 100644 index 9849f8b..0000000 --- a/i2s_interface.ino +++ /dev/null @@ -1,371 +0,0 @@ -/* - * Copyright (c) 2022 Marcel Licence - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * Dieses Programm ist Freie Software: Sie können es unter den Bedingungen - * der GNU General Public License, wie von der Free Software Foundation, - * Version 3 der Lizenz oder (nach Ihrer Wahl) jeder neueren - * veröffentlichten Version, weiter verteilen und/oder modifizieren. - * - * Dieses Programm wird in der Hoffnung bereitgestellt, dass es nützlich sein wird, jedoch - * OHNE JEDE GEWÄHR,; sogar ohne die implizite - * Gewähr der MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK. - * Siehe die GNU General Public License für weitere Einzelheiten. - * - * Sie sollten eine Kopie der GNU General Public License zusammen mit diesem - * Programm erhalten haben. Wenn nicht, siehe . - */ - -/** - * @file i2s_interface.ino - * @author Marcel Licence - * @date 13.10.2021 - * - * @brief this file includes all required function to setup and drive the i2s interface - */ - - -#ifdef __CDT_PARSER__ -#include -#endif - - -#include - - -/* - * no dac not tested within this code - * - it has the purpose to generate a quasy analog signal without a DAC - */ -//#define I2S_NODAC - - -const i2s_port_t i2s_port_number = I2S_NUM_0; - -/* - * please refer to https://www.hackster.io/janost/audio-hacking-on-the-esp8266-fa9464#toc-a-simple-909-drum-synth-0 - * for the following implementation - */ -#ifdef I2S_NODAC -/* todo integrate code, or external module from hack a day using i2s signal wire as DAC */ -#else - -bool i2s_write_sample_32ch2(uint8_t *sample); - -bool i2s_write_sample_32ch2(uint8_t *sample) -{ - static size_t bytes_written = 0; - static size_t bytes_read = 0; - i2s_read(i2s_port_number, (char *)sample, 8, &bytes_read, portMAX_DELAY); - - i2s_write(i2s_port_number, (const char *)sample, 8, &bytes_written, portMAX_DELAY); - - if (bytes_written > 0) - { - return true; - } - else - { - return false; - } -} - -#ifdef SAMPLE_SIZE_24BIT - -bool i2s_write_sample_24ch2(uint8_t *sample); - -bool i2s_write_sample_24ch2(uint8_t *sample) -{ - static size_t bytes_written1 = 0; - static size_t bytes_written2 = 0; - i2s_write(i2s_port_number, (const char *)&sample[1], 3, &bytes_written1, portMAX_DELAY); - i2s_write(i2s_port_number, (const char *)&sample[5], 3, &bytes_written2, portMAX_DELAY); - - if ((bytes_written1 + bytes_written2) > 0) - { - return true; - } - else - { - return false; - } -} - -#endif - -bool i2s_write_stereo_samples(float *fl_sample, float *fr_sample) -{ -#ifdef SAMPLE_SIZE_32BIT - static union sampleTUNT - { - uint64_t sample; - int32_t ch[2]; - } sampleDataU; -#endif -#ifdef SAMPLE_SIZE_24BIT -#if 0 - static union sampleTUNT - { - uint8_t sample[8]; - int32_t ch[2]; - } sampleDataU; -#else - static union sampleTUNT - { - int32_t ch[2]; - uint8_t bytes[8]; - } sampleDataU; -#endif -#endif -#ifdef SAMPLE_SIZE_16BIT - static union sampleTUNT - { - uint32_t sample; - int16_t ch[2]; - } sampleDataU; -#endif - - /* - * using RIGHT_LEFT format - */ -#ifdef SAMPLE_SIZE_16BIT - sampleDataU.ch[0] = int16_t(*fr_sample * 16383.0f); /* some bits missing here */ - sampleDataU.ch[1] = int16_t(*fl_sample * 16383.0f); -#endif -#ifdef SAMPLE_SIZE_32BIT - sampleDataU.ch[0] = int32_t(*fr_sample * 1073741823.0f); /* some bits missing here */ - sampleDataU.ch[1] = int32_t(*fl_sample * 1073741823.0f); -#endif - - size_t bytes_written = 0; - -#ifdef SAMPLE_SIZE_16BIT - i2s_write(i2s_port_number, (const char *)&sampleDataU.sample, 4, &bytes_written, portMAX_DELAY); -#endif -#ifdef SAMPLE_SIZE_32BIT - i2s_write(i2s_port_number, (const char *)&sampleDataU.sample, 8, &bytes_written, portMAX_DELAY); -#endif - - if (bytes_written > 0) - { - return true; - } - else - { - return false; - } -} - -#ifdef SAMPLE_BUFFER_SIZE -bool i2s_write_stereo_samples_buff(float *fl_sample, float *fr_sample, const int buffLen) -{ -#ifdef SAMPLE_SIZE_32BIT - static union sampleTUNT - { - uint64_t sample; - int32_t ch[2]; - } sampleDataU[SAMPLE_BUFFER_SIZE]; -#endif -#ifdef SAMPLE_SIZE_24BIT -#if 0 - static union sampleTUNT - { - uint8_t sample[8]; - int32_t ch[2]; - } sampleDataU[SAMPLE_BUFFER_SIZE]; -#else - static union sampleTUNT - { - int32_t ch[2]; - uint8_t bytes[8]; - } sampleDataU[SAMPLE_BUFFER_SIZE]; -#endif -#endif -#ifdef SAMPLE_SIZE_16BIT - static union sampleTUNT - { - uint32_t sample; - int16_t ch[2]; - } sampleDataU[SAMPLE_BUFFER_SIZE]; -#endif - - for (int n = 0; n < buffLen; n++) - { - /* - * using RIGHT_LEFT format - */ -#ifdef SAMPLE_SIZE_16BIT - sampleDataU[n].ch[0] = int16_t(fr_sample[n] * 16383.0f); /* some bits missing here */ - sampleDataU[n].ch[1] = int16_t(fl_sample[n] * 16383.0f); -#endif -#ifdef SAMPLE_SIZE_32BIT - sampleDataU[n].ch[0] = int32_t(fr_sample[n] * 1073741823.0f); /* some bits missing here */ - sampleDataU[n].ch[1] = int32_t(fl_sample[n] * 1073741823.0f); -#endif - } - - static size_t bytes_written = 0; - - i2s_write(i2s_port_number, (const char *)&sampleDataU[0].sample, 4 * buffLen, &bytes_written, portMAX_DELAY); - - if (bytes_written > 0) - { - return true; - } - else - { - return false; - } -} -#endif /* #ifdef SAMPLE_BUFFER_SIZE */ - -void i2s_read_stereo_samples(float *fl_sample, float *fr_sample) -{ - static size_t bytes_read = 0; - - static union - { - uint32_t sample; - int16_t ch[2]; - } sampleData; - - - i2s_read(i2s_port_number, (char *)&sampleData.sample, 4, &bytes_read, portMAX_DELAY); - - //sampleData.ch[0] &= 0xFFFE; - //sampleData.ch[1] &= 0; - - /* - * using RIGHT_LEFT format - */ - *fr_sample = ((float)sampleData.ch[0] * (5.5f / 65535.0f)); - *fl_sample = ((float)sampleData.ch[1] * (5.5f / 65535.0f)); -} - -#ifdef SAMPLE_BUFFER_SIZE -void i2s_read_stereo_samples_buff(float *fl_sample, float *fr_sample, const int buffLen) -{ -#ifdef I2S_DIN_PIN - static size_t bytes_read = 0; - -#ifdef SAMPLE_SIZE_16BIT - static union - { - uint32_t sample; - int16_t ch[2]; - } sampleData[SAMPLE_BUFFER_SIZE]; -#endif - - i2s_read(i2s_port_number, (char *)&sampleData[0].sample, 4 * buffLen, &bytes_read, portMAX_DELAY); - - //sampleData.ch[0] &= 0xFFFE; - //sampleData.ch[1] &= 0; - - for (int n = 0; n < buffLen; n++) - { - /* - * using RIGHT_LEFT format - */ - //fr_sample[n] = ((float)sampleData[n].ch[0] * (5.5f / 65535.0f)); - //fl_sample[n] = ((float)sampleData[n].ch[1] * (5.5f / 65535.0f)); - fr_sample[n] = ((float)sampleData[n].ch[0] / (16383.0f)); - fl_sample[n] = ((float)sampleData[n].ch[1] / (16383.0f)); - } -#endif -} -#endif /* #ifdef SAMPLE_BUFFER_SIZE */ - -#endif - -/* - * i2s configuration - */ -i2s_config_t i2s_configuration = -{ -#ifdef I2S_DIN_PIN - .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_RX), // | I2S_MODE_DAC_BUILT_IN -#else - .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX), -#endif - .sample_rate = SAMPLE_RATE, -#ifdef I2S_NODAC - .bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT, - .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT, -#ifdef ARDUINO_RUNNING_CORE /* tested with arduino esp32 core version 2.0.2 */ - .communication_format = I2S_COMM_FORMAT_STAND_I2S, -#else - .communication_format = (i2s_comm_format_t)I2S_COMM_FORMAT_I2S_MSB, -#endif -#else -#ifdef SAMPLE_SIZE_32BIT - .bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT, /* the DAC module will only take the 8bits from MSB */ -#endif -#ifdef SAMPLE_SIZE_24BIT - .bits_per_sample = I2S_BITS_PER_SAMPLE_24BIT, /* the DAC module will only take the 8bits from MSB */ -#endif -#ifdef SAMPLE_SIZE_16BIT - .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, /* the DAC module will only take the 8bits from MSB */ -#endif - .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, -#ifdef ARDUINO_RUNNING_CORE /* tested with arduino esp32 core version 2.0.2 */ - .communication_format = I2S_COMM_FORMAT_STAND_I2S, -#else - .communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB), -#endif -#endif - .intr_alloc_flags = 0, // default interrupt priority - .dma_buf_count = 8, - .dma_buf_len = 64, -#ifdef I2S_USE_APLL - .use_apll = true, -#else - .use_apll = false, -#endif -}; - - -#ifdef I2S_NODAC -i2s_pin_config_t pins = -{ - .bck_io_num = I2S_PIN_NO_CHANGE, - .ws_io_num = I2S_PIN_NO_CHANGE, - .data_out_num = I2S_NODAC_OUT_PIN, - .data_in_num = I2S_PIN_NO_CHANGE -}; -#else -i2s_pin_config_t pins = -{ - .bck_io_num = I2S_BCLK_PIN, - .ws_io_num = I2S_WCLK_PIN, - .data_out_num = I2S_DOUT_PIN, -#ifdef I2S_DIN_PIN - .data_in_num = I2S_DIN_PIN -#else - .data_in_num = I2S_PIN_NO_CHANGE -#endif -}; -#endif - -void setup_i2s() -{ - i2s_driver_install(i2s_port_number, &i2s_configuration, 0, NULL); - i2s_set_pin(I2S_NUM_0, &pins); - i2s_set_sample_rates(i2s_port_number, SAMPLE_RATE); - i2s_start(i2s_port_number); -#ifdef ES8388_ENABLED - REG_WRITE(PIN_CTRL, 0xFFFFFFF0); - PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1); -#endif -} diff --git a/midi_interface.ino b/midi_interface.ino deleted file mode 100644 index f36c718..0000000 --- a/midi_interface.ino +++ /dev/null @@ -1,468 +0,0 @@ -/* - * Copyright (c) 2021 Marcel Licence - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * Dieses Programm ist Freie Software: Sie können es unter den Bedingungen - * der GNU General Public License, wie von der Free Software Foundation, - * Version 3 der Lizenz oder (nach Ihrer Wahl) jeder neueren - * veröffentlichten Version, weiter verteilen und/oder modifizieren. - * - * Dieses Programm wird in der Hoffnung bereitgestellt, dass es nützlich sein wird, jedoch - * OHNE JEDE GEWÄHR,; sogar ohne die implizite - * Gewähr der MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK. - * Siehe die GNU General Public License für weitere Einzelheiten. - * - * Sie sollten eine Kopie der GNU General Public License zusammen mit diesem - * Programm erhalten haben. Wenn nicht, siehe . - */ - -/** - * @file midi_interface.ino - * @author Marcel Licence - * @date 04.10.2021 - * - * @brief This file contains an implementation of a simple MIDI interpreter to parse incoming messages - * - * MIDI_DUMP_Serial1_TO_SERIAL <- when active received data will be output as hex on serial(1) - * MIDI_SERIAL1_BAUDRATE <- use define to override baud-rate for MIDI, otherwise default of 31250 will be used - * - * @see https://www.midi.org/specifications-old/item/table-1-summary-of-midi-message - */ - - -#ifdef __CDT_PARSER__ -#include -#endif - - -/* - * look for midi interface using 1N136 - * to convert the MIDI din signal to - * a uart compatible signal - */ - -#ifndef MIDI_SERIAL1_BAUDRATE -#define MIDI_SERIAL1_BAUDRATE 31250 -#endif - -#ifndef MIDI_SERIAL2_BAUDRATE -#define MIDI_SERIAL2_BAUDRATE 31250 -#endif - -/* use define to dump midi data */ -//#define MIDI_DUMP_SERIAL2_TO_SERIAL - - -#if (defined MIDI_RX_PIN) || (defined MIDI_RECV_FROM_SERIAL) -#define MIDI_PORT_ACTIVE -#endif - -#ifdef MIDI_RX1_PIN -#define MIDI_PORT1_ACTIVE -#endif - -#ifdef MIDI_RX2_PIN -#define MIDI_PORT2_ACTIVE -#endif - -struct midi_port_s -{ - Stream *serial; /* this can be software or hardware serial */ - uint32_t inMsgWd ; - uint8_t inMsg[3]; - uint8_t inMsgIndex ; -}; - -#ifdef ARDUINO_DAISY_SEED -HardwareSerial Serial2(USART1); -#endif - -#ifdef ARDUINO_GENERIC_F407VGTX -HardwareSerial Serial2(USART3); /* PB11 */ -#endif - - -#ifdef MIDI_PORT_ACTIVE -struct midi_port_s MidiPort; -#endif - -#ifdef MIDI_PORT1_ACTIVE -struct midi_port_s MidiPort1; -#endif - -#ifdef MIDI_PORT2_ACTIVE -struct midi_port_s MidiPort2; -#endif - -/* - * structure is used to build the mapping table - */ -struct midiControllerMapping -{ - uint8_t channel; - uint8_t data1; - const char *desc; - void(*callback_mid)(uint8_t ch, uint8_t data1, uint8_t data2); -#ifdef MIDI_FMT_INT - void(*callback_val)(uint8_t userdata, uint8_t value); -#else - void(*callback_val)(uint8_t userdata, float value); -#endif - uint8_t user_data; -}; - -struct midiMapping_s -{ - void (*rawMsg)(uint8_t *msg); -#ifdef MIDI_FMT_INT - void (*noteOn)(uint8_t ch, uint8_t note, uint8_t vel); - void (*noteOff)(uint8_t ch, uint8_t note); - void (*pitchBend)(uint8_t ch, uint8_t bend); - void (*modWheel)(uint8_t ch, uint8_t value); -#else - void (*noteOn)(uint8_t ch, uint8_t note, float vel); - void (*noteOff)(uint8_t ch, uint8_t note); - void (*pitchBend)(uint8_t ch, float bend); - void (*modWheel)(uint8_t ch, float value); -#endif - void (*rttMsg)(uint8_t msg); - void (*songPos)(uint16_t pos); - - struct midiControllerMapping *controlMapping; - int mapSize; -}; - -extern struct midiMapping_s midiMapping; /* definition in z_config.ino */ - -/* constant to normalize midi value to 0.0 - 1.0f */ -#define NORM127MUL 0.007874f - -inline void Midi_NoteOn(uint8_t ch, uint8_t note, uint8_t vel) -{ - if (vel > 127) - { - /* we will end up here in case of problems with the MIDI connection */ - vel = 127; - Serial.printf("to loud note detected!!!!!!!!!!!!!!!!!!!!!!!\n"); - } - - if (midiMapping.noteOn != NULL) - { -#ifdef MIDI_FMT_INT - midiMapping.noteOn(ch, note, vel); -#else - midiMapping.noteOn(ch, note, pow(2, ((vel * NORM127MUL) - 1.0f) * 6)); -#endif - } -} - -inline void Midi_NoteOff(uint8_t ch, uint8_t note) -{ - if (midiMapping.noteOff != NULL) - { - midiMapping.noteOff(ch, note); - } -} - -/* - * this function will be called when a control change message has been received - */ -inline void Midi_ControlChange(uint8_t channel, uint8_t data1, uint8_t data2) -{ - for (int i = 0; i < midiMapping.mapSize; i++) - { - if ((midiMapping.controlMapping[i].channel == channel) && (midiMapping.controlMapping[i].data1 == data1)) - { - if (midiMapping.controlMapping[i].callback_mid != NULL) - { - midiMapping.controlMapping[i].callback_mid(channel, data1, data2); - } - if (midiMapping.controlMapping[i].callback_val != NULL) - { -#ifdef MIDI_FMT_INT - midiMapping.controlMapping[i].callback_val(midiMapping.controlMapping[i].user_data, data2); -#else - midiMapping.controlMapping[i].callback_val(midiMapping.controlMapping[i].user_data, (float)data2 * NORM127MUL); -#endif - } - } - } - - if (data1 == 1) - { - if (midiMapping.modWheel != NULL) - { -#ifdef MIDI_FMT_INT - midiMapping.modWheel(channel, data2); -#else - midiMapping.modWheel(channel, (float)data2 * NORM127MUL); -#endif - } - } -} - -inline void Midi_PitchBend(uint8_t ch, uint16_t bend) -{ - float value = ((float)bend - 8192.0f) * (1.0f / 8192.0f) - 1.0f; - if (midiMapping.pitchBend != NULL) - { - midiMapping.pitchBend(ch, value); - } -} - -inline void Midi_SongPositionPointer(uint16_t pos) -{ - if (midiMapping.songPos != NULL) - { - midiMapping.songPos(pos); - } -} - -/* - * function will be called when a short message has been received over midi - */ -inline void Midi_HandleShortMsg(uint8_t *data, uint8_t cable __attribute__((unused))) -{ - uint8_t ch = data[0] & 0x0F; - - switch (data[0] & 0xF0) - { - /* note on */ - case 0x90: - if (data[2] > 0) - { - Midi_NoteOn(ch, data[1], data[2]); - } - else - { - Midi_NoteOff(ch, data[1]); - } - break; - /* note off */ - case 0x80: - Midi_NoteOff(ch, data[1]); - break; - case 0xb0: - Midi_ControlChange(ch, data[1], data[2]); - break; - /* pitchbend */ - case 0xe0: - Midi_PitchBend(ch, ((((uint16_t)data[1])) + ((uint16_t)data[2] << 8))); - break; - /* song position pointer */ - case 0xf2: - Midi_SongPositionPointer(((((uint16_t)data[1])) + ((uint16_t)data[2] << 8))); - break; - } -} - -inline void Midi_RealTimeMessage(uint8_t msg) -{ - if (midiMapping.rttMsg != NULL) - { - midiMapping.rttMsg(msg); - } -} - -static void Midi_PortSetup(struct midi_port_s *port) -{ - /* reset the watchdog variables */ - port->inMsgWd = 0; - memset(port->inMsg, 0, sizeof(port->inMsg)); - port->inMsgIndex = 0; -} - -void Midi_Setup() -{ -#ifdef MIDI_RECV_FROM_SERIAL - MidiPort.serial = &Serial; -#endif /* MIDI_RECV_FROM_SERIAL */ - -#ifdef MIDI_PORT_ACTIVE -#ifdef SWAP_SERIAL - Serial.printf("Switch Serial to Midi!\n"); - delay(20); - Serial.end(); - Serial.begin(MIDI_BAUDRATE); - Serial.swap(); /* using alternative rx and tx pin for Midi communication */ - delay(20); -#endif - MidiPort.serial = &Serial; - Midi_PortSetup(&MidiPort); -#endif - -#ifdef MIDI_PORT1_ACTIVE - -#ifdef MIDI_RX1_PIN -#ifdef MIDI_TX1_PIN - Serial.printf("Setup Serial1 with %d baud with rx: %d and tx %d\n", MIDI_SERIAL1_BAUDRATE, MIDI_RX1_PIN, MIDI_TX1_PIN); - Serial1.begin(MIDI_SERIAL1_BAUDRATE, SERIAL_8N1, MIDI_RX1_PIN, MIDI_TX1_PIN); -#else - Serial.printf("Setup Serial1 with %d baud with rx: %d only\n", MIDI_SERIAL1_BAUDRATE, MIDI_RX1_PIN); - Serial1.begin(MIDI_SERIAL1_BAUDRATE, SERIAL_8N1, MIDI_RX1_PIN); -#endif - pinMode(MIDI_RX1_PIN, INPUT_PULLUP); /* can be connected to open collector output */ -#else - Serial.printf("Setup Serial1 with %d baud with rx: RX1 pin\n", MIDI_SERIAL1_BAUDRATE); - Serial1.begin(MIDI_SERIAL1_BAUDRATE); -#endif - -#ifdef ARDUINO_SEEED_XIAO_M0 - pinMode(PIN_SERIAL1_RX, INPUT_PULLUP); -#endif - - MidiPort1.serial = &Serial1; - Midi_PortSetup(&MidiPort1); -#endif /* MIDI_PORT1_ACTIVE */ - - -#ifdef MIDI_PORT2_ACTIVE - -#ifdef MIDI_RX2_PIN -#ifdef MIDI_TX2_PIN - Serial.printf("Setup Serial2 with %d baud with rx: %d and tx %d\n", MIDI_SERIAL2_BAUDRATE, MIDI_RX2_PIN, MIDI_TX2_PIN); - Serial2.begin(MIDI_SERIAL2_BAUDRATE, SERIAL_8N1, MIDI_RX2_PIN, MIDI_TX2_PIN); -#else - Serial.printf("Setup Serial2 with %d baud with rx: %d only\n", MIDI_SERIAL2_BAUDRATE, MIDI_RX2_PIN); - Serial2.begin(MIDI_SERIAL2_BAUDRATE, SERIAL_8N1, MIDI_RX2_PIN); -#endif - pinMode(MIDI_RX2_PIN, INPUT_PULLUP); /* can be connected to open collector output */ -#else - Serial.printf("Setup Serial2 with %d baud with rx: RX2 pin\n", MIDI_SERIAL2_BAUDRATE); - Serial2.begin(MIDI_SERIAL2_BAUDRATE); -#endif - - MidiPort2.serial = &Serial2; - Midi_PortSetup(&MidiPort2); - Serial.printf("Setup MidiPort2 using Serial2\n"); -#endif /* MIDI_PORT2_ACTIVE */ -} - -void Midi_CheckMidiPort(struct midi_port_s *port) -{ - //Choose Serial1 or Serial2 as required - - if (port->serial->available()) - { - uint8_t incomingByte = port->serial->read(); - -#ifdef MIDI_DUMP_SERIAL2_TO_SERIAL - Serial.printf("%02x", incomingByte); -#endif - /* ignore live messages */ - if ((incomingByte & 0xF0) == 0xF0) - { - Midi_RealTimeMessage(incomingByte); - return; - } - - if (port->inMsgIndex == 0) - { - if ((incomingByte & 0x80) != 0x80) - { - port->inMsgIndex = 1; - } - } - - port->inMsg[port->inMsgIndex] = incomingByte; - port->inMsgIndex += 1; - - if ((port->inMsgIndex >= 3) || - ( - (((port->inMsg[0] & 0xF0) == 0xD0) - || ((port->inMsg[0] & 0xF0) == 0xC0)) - && (port->inMsgIndex >= 2)) - ) - { -#ifdef MIDI_DUMP_SERIAL2_TO_SERIAL - if (port->inMsgIndex >= 3) - { - Serial.printf("\n>%02x %02x %02x<\n", port->inMsg[0], port->inMsg[1], port->inMsg[2]); - } - else - { - Serial.printf("\n>%02x %02x<\n", port->inMsg[0], port->inMsg[1]); - } -#endif - Midi_HandleShortMsg(port->inMsg, 0); - port->inMsgIndex = 0; - } - - /* - * reset watchdog to allow new bytes to be received - */ - port->inMsgWd = 0; - } - else - { - if (port->inMsgIndex > 0) - { - port->inMsgWd++; - if (port->inMsgWd == 0xFFF) - { - port->inMsgIndex = 0; - } - } - } -} - -/* - * this function should be called continuously to ensure that incoming messages can be processed - */ -inline -void Midi_Process() -{ -#ifdef MIDI_PORT_ACTIVE - Midi_CheckMidiPort(&MidiPort); -#endif -#ifdef MIDI_PORT1_ACTIVE - Midi_CheckMidiPort(&MidiPort1); -#endif -#ifdef MIDI_PORT2_ACTIVE - Midi_CheckMidiPort(&MidiPort2); -#endif -} - -#ifndef ARDUINO_SEEED_XIAO_M0 -#ifndef SWAP_SERIAL -void Midi_SendShortMessage(uint8_t *msg) -{ -#ifdef MIDI_TX2_PIN - MidiPort2.serial->write(msg, 3); -#endif -} - -void Midi_SendRaw(uint8_t *msg) -{ -#ifdef MIDI_TX2_PIN - /* sysex */ - if (msg[0] == 0xF0) - { - int i = 2; - while (msg[i] != 0xF7) - { - i++; - } - MidiPort2.serial->write(msg, i + 1); - } - else - { - MidiPort2.serial->write(msg, 3); - } -#endif -} -#endif -#endif - diff --git a/ml_inline.ino b/ml_inline.ino new file mode 100644 index 0000000..1fecd6c --- /dev/null +++ b/ml_inline.ino @@ -0,0 +1,4 @@ + +#define ML_SYNTH_INLINE_DEFINITION +#include +#undef ML_SYNTH_INLINE_DEFINITION diff --git a/z_config.ino b/z_config.ino index 2f38435..ce3aaf4 100644 --- a/z_config.ino +++ b/z_config.ino @@ -128,6 +128,7 @@ struct midiMapping_s midiMapping = NULL, NULL, NULL, + NULL, edirolMapping, sizeof(edirolMapping) / sizeof(edirolMapping[0]), };