diff --git a/click_module.ino b/click_module.ino
index ed56b92..72cd25b 100644
--- a/click_module.ino
+++ b/click_module.ino
@@ -73,26 +73,26 @@ void Click_Process(float *left, float *right)
{
if (seq_bar == 0)
{
- /* create highest pitch sound for the first beat of the first bar */
+ /* create highest pitch sound for the first beat of the first bar */
*left += ((float)((seq_counter & 16) / 16)) * 0.1f;
*right += ((float)((seq_counter & 16) / 16)) * 0.1f;
}
else
{
- /* generate middle pitched sound for the first beat of all other bars */
+ /* generate middle pitched sound for the first beat of all other bars */
*left += ((float)((seq_counter & 32) / 32)) * 0.1f;
*right += ((float)((seq_counter & 32) / 32)) * 0.1f;
}
}
else if ((seq_pos % 4) == 0)
{
- /* generate sound with lowest pitch for 2, 3, 4 */
+ /* generate sound with lowest pitch for 2, 3, 4 */
*left += ((float)((seq_counter & 64) / 64)) * 0.1f;
*right += ((float)((seq_counter & 64) / 64)) * 0.1f;
}
}
- /* only if module is active the loop should be reset when jumping to first beat in first bar */
+ /* only if module is active the loop should be reset when jumping to first beat in first bar */
if (seq_tempo)
{
if ((seq_pos == 0) && (seq_counter == 0) && (seq_bar == 0))
diff --git a/config.h b/config.h
new file mode 100644
index 0000000..8a4b998
--- /dev/null
+++ b/config.h
@@ -0,0 +1,70 @@
+/*
+ * 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 config.h
+ * @author Marcel Licence
+ * @date 02.01.2021
+ *
+ * @brief This file contains the project configuration
+ *
+ * All definitions are visible in the entire project
+ *
+ * Put all your project settings here (defines, numbers, etc.)
+ * configurations which are requiring knowledge of types etc.
+ * shall be placed in z_config.ino (will be included at the end)
+ */
+
+
+#ifndef CONFIG_H_
+#define CONFIG_H_
+
+
+#ifdef __CDT_PARSER__
+#include
+#endif
+
+/*
+ * include the board configuration
+ * there you will find the most hardware depending pin settings
+ */
+#define BOARD_ESP32_AUDIO_KIT_AC101
+
+#include /* requires https://github.com/marcel-licence/ML_SynthTools */
+
+/* our samplerate */
+#define SAMPLE_RATE 44100
+
+/* on board led */
+#define LED_PIN 19
+
+
+#endif /* CONFIG_H_ */
+
diff --git a/es8388.ino b/es8388.ino
index 51c14c1..345ec79 100644
--- a/es8388.ino
+++ b/es8388.ino
@@ -1,6 +1,4 @@
/*
- * The GNU GENERAL PUBLIC LICENSE (GNU GPLv3)
- *
* Copyright (c) 2021 Marcel Licence
*
* This program is free software: you can redistribute it and/or modify
@@ -30,17 +28,23 @@
* Programm erhalten haben. Wenn nicht, siehe .
*/
-/*
- * es8388.ino
+/**
+ * @file es8388.ino
+ * @author Marcel Licence
+ * @date 22.08.2021
*
- * Created on: 22.08.2021
- * Author: Marcel Licence
+ * @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
@@ -171,16 +175,6 @@ void es8388_read_all()
}
}
-#define ES8388_PIN_SDA 18
-#define ES8388_PIN_SCL 23
-
-#define ES8388_PIN_MCLK 0
-#define ES8388_PIN_SCLK 5
-#define ES8388_PIN_LRCK 25
-#define ES8388_PIN_DIN 26
-#define ES8388_PIN_DOUT 35
-
-
void ES8388_SetADCVOL(uint8_t unused, float vol)
{
#ifdef STATUS_ENABLED
diff --git a/esp32_audio_kit_module.ino b/esp32_audio_kit_module.ino
index d6c80c2..25fd6a9 100644
--- a/esp32_audio_kit_module.ino
+++ b/esp32_audio_kit_module.ino
@@ -1,6 +1,4 @@
/*
- * The GNU GENERAL PUBLIC LICENSE (GNU GPLv3)
- *
* Copyright (c) 2021 Marcel Licence
*
* This program is free software: you can redistribute it and/or modify
@@ -30,52 +28,99 @@
* Programm erhalten haben. Wenn nicht, siehe .
*/
-/*
- * this file contains the module controlling the tempo of the looper
- * it counts always 4 bars
- * min tempo will be calculated depending on the max loop length
+/**
+ * @file esp32_audio_kit_module.ino
+ * @author Marcel Licence
+ * @date 12.10.2021
*
- * Author: Marcel Licence
+ * @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
-/* AC101 pins */
-#define IIS_SCLK 27
-#define IIS_LCLK 26
-#define IIS_DSIN 25
-#define IIS_DSOUT 35
-#define IIC_CLK 32
-#define IIC_DATA 33
+//#define BUTTON_DEBUG_MSG
-#define GPIO_PA_EN GPIO_NUM_21
-#define GPIO_SEL_PA_EN GPIO_SEL_21
-#define PIN_KEY_2 (13)
-#define PIN_PLAY (23) // KEY 4
-#define PIN_VOL_UP (18) // KEY 5
-#define PIN_VOL_DOWN (5) // KEY 6
+#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
+#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
-#define SAMPLE_RATE 44100
-#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)
+#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
@@ -96,7 +141,7 @@ void ac101_mclk_setup()
void ac101_setup()
{
Serial.printf("Connect to AC101 codec... ");
- while (not ac.begin(IIC_DATA, IIC_CLK))
+ while (not ac.begin(AC101_PIN_SDA, AC101_PIN_SCL))
{
Serial.printf("Failed!\n");
delay(1000);
@@ -112,7 +157,8 @@ void ac101_setup()
#if (SAMPLE_RATE==44100)&&(defined(SAMPLE_SIZE_16BIT))
ac.SetI2sSampleRate(AC101::SAMPLE_RATE_44100);
/*
- * BCLK: 44100 * 2 * 16 =
+ * 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
@@ -138,21 +184,32 @@ void ac101_setup()
#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!!!
@@ -169,6 +226,7 @@ void ac101_setSourceLine(void)
{
ac.SetLineSource();
}
+#endif /* #ifdef AC101_ENABLED */
/*
* very bad implementation checking the button state
@@ -176,16 +234,94 @@ void ac101_setSourceLine(void)
*/
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 3a4b665..e8afa7b 100644
--- a/esp32_multitrack_looper.ino
+++ b/esp32_multitrack_looper.ino
@@ -1,6 +1,4 @@
/*
- * The GNU GENERAL PUBLIC LICENSE (GNU GPLv3)
- *
* Copyright (c) 2021 Marcel Licence
*
* This program is free software: you can redistribute it and/or modify
@@ -38,12 +36,28 @@
* Author: Marcel Licence
*/
+#ifdef __CDT_PARSER__
+#include
+#endif
+
+/*
+ *
+ /$$$$$$$$ /$$ /$$ /$$$$$$$ /$$$$$$ /$$$$$$$ /$$$$$$ /$$ /$$ /$$ /$$
+| $$_____/ | $$ | $$ | $$__ $$ /$$__ $$| $$__ $$ /$$__ $$| $$$ /$$$| $$| $$
+| $$ /$$$$$$$ /$$$$$$ | $$$$$$$ | $$ /$$$$$$ | $$ \ $$| $$ \__/| $$ \ $$| $$ \ $$| $$$$ /$$$$| $$| $$
+| $$$$$ | $$__ $$ |____ $$| $$__ $$| $$ /$$__ $$ | $$$$$$$/| $$$$$$ | $$$$$$$/| $$$$$$$$| $$ $$/$$ $$| $$| $$
+| $$__/ | $$ \ $$ /$$$$$$$| $$ \ $$| $$| $$$$$$$$ | $$____/ \____ $$| $$__ $$| $$__ $$| $$ $$$| $$|__/|__/
+| $$ | $$ | $$ /$$__ $$| $$ | $$| $$| $$_____/ | $$ /$$ \ $$| $$ \ $$| $$ | $$| $$\ $ | $$
+| $$$$$$$$| $$ | $$| $$$$$$$| $$$$$$$/| $$| $$$$$$$ | $$ | $$$$$$/| $$ | $$| $$ | $$| $$ \/ | $$ /$$ /$$
+|________/|__/ |__/ \_______/|_______/ |__/ \_______/ |__/ \______/ |__/ |__/|__/ |__/|__/ |__/|__/|__/
+
+
+ */
+#include "config.h"
+
#include
#include
-/* on board led */
-#define LED_PIN 19
-
/*
* Chip is ESP32D0WDQ5 (revision 1)
@@ -58,11 +72,6 @@
*
*/
-/* our samplerate */
-#define SAMPLE_RATE 44100
-
-/* this is used to add a task to core 0 */
-TaskHandle_t Core0TaskHnd ;
/* to avoid the high click when turning on the microphone */
static float click_supp_gain = 0.0f;
@@ -83,19 +92,25 @@ void setup()
click_supp_gain = 0.0f;
+#ifdef BLINK_LED_PIN
Blink_Setup();
-
+#endif
Status_Setup();
+#ifdef ESP32_AUDIO_KIT
#ifdef ES8388_ENABLED
ES8388_Setup();
#else
ac101_setup();
+ /* using mic as default source */
+ ac101_setSourceMic();
+#endif
#endif
setup_i2s();
-
+#ifdef ESP32_AUDIO_KIT
button_setup();
+#endif
/*
* setup midi module / rx port
@@ -108,8 +123,10 @@ void setup()
WiFi.mode(WIFI_OFF);
#endif
+#ifndef ESP8266
btStop();
// esp_wifi_deinit();
+#endif
Delay_Init();
Delay_Reset();
@@ -128,21 +145,53 @@ void setup()
Serial.printf("Total PSRAM: %d\n", ESP.getPsramSize());
Serial.printf("Free PSRAM: %d\n", ESP.getFreePsram());
- /* we need a second task for the terminal output */
- xTaskCreatePinnedToCore(CoreTask0, "terminalTask", 8000, NULL, 999, &Core0TaskHnd, 0);
+#ifdef ESP32
+ Core0TaskInit();
+#else
+#error only supported by ESP32 platform
+#endif
}
-void CoreTask0(void *parameter)
+#ifdef ESP32
+/*
+ * Core 0
+ */
+/* this is used to add a task to core 0 */
+TaskHandle_t Core0TaskHnd ;
+
+inline
+void Core0TaskInit()
{
+ /* we need a second task for the terminal output */
+ xTaskCreatePinnedToCore(Core0Task, "CoreTask0", 8000, NULL, 999, &Core0TaskHnd, 0);
+}
+
+inline
+void Core0TaskSetup()
+{
+
+}
+
+inline
+void Core0TaskLoop()
+{
+ Status_Process();
+}
+
+void Core0Task(void *parameter)
+{
+ Core0TaskSetup();
+
while (true)
{
- Status_Process();
+ Core0TaskLoop();
/* this seems necessary to trigger the watchdog */
delay(1);
yield();
}
}
+#endif
float main_gain = 1.0f;
@@ -232,13 +281,17 @@ void MTLooper_ToggleSource(uint8_t channel, float value)
{
case acSrcLine:
click_supp_gain = 0.0f;
+#ifdef AC101_ENABLED
ac101_setSourceMic();
+#endif
selSource = acSrcMic;
Status_TestMsg("Input: Microphone");
break;
case acSrcMic:
click_supp_gain = 0.0f;
+#ifdef AC101_ENABLED
ac101_setSourceLine();
+#endif
selSource = acSrcLine;
Status_TestMsg("Input: LineIn");
break;
@@ -315,13 +368,10 @@ inline void audio_task()
*/
void loop_1Hz(void)
{
- static uint32_t cycl = ESP.getCycleCount();
- static uint32_t lastCycl;
-
- lastCycl = cycl;
-
button_loop();
+#ifdef BLINK_LED_PIN
Blink_Process();
+#endif
}
static uint32_t midi_pre_scaler = 0;
diff --git a/i2s_interface.ino b/i2s_interface.ino
index f4a47e1..7c589b4 100644
--- a/i2s_interface.ino
+++ b/i2s_interface.ino
@@ -132,12 +132,10 @@ bool i2s_write_stereo_samples(float *fl_sample, float *fr_sample)
} sampleDataU;
#endif
-
sampleDataU.ch[0] = int16_t(*fl_sample * 16383.0f);
sampleDataU.ch[1] = int16_t(*fr_sample * 16383.0f);
static size_t bytes_written = 0;
- static size_t bytes_read = 0;
i2s_write(i2s_num, (const char *)&sampleDataU.sample, 4, &bytes_written, portMAX_DELAY);
@@ -153,10 +151,8 @@ bool i2s_write_stereo_samples(float *fl_sample, float *fr_sample)
void i2s_read_stereo_samples(float *fl_sample, float *fr_sample)
{
- static size_t bytes_written = 0;
static size_t bytes_read = 0;
-
static union
{
uint32_t sample;
diff --git a/loop_module.ino b/loop_module.ino
index e2ea383..a27c928 100644
--- a/loop_module.ino
+++ b/loop_module.ino
@@ -37,9 +37,9 @@
*/
-/*
- * MAX_LOOP can only increased by decreasing TRACK_CNT (track count)
- *
+/*
+ * MAX_LOOP can only increased by decreasing TRACK_CNT (track count)
+ *
* for example using only 2 tracks will allow MAX_LOOP to be set to 1026492
* all PSRAM memory will be used
* if values are set to big the startup of the firmware will fail
@@ -76,7 +76,7 @@ void Loop_init(void)
if (loopLine[n] == NULL)
{
- /* when you see the message the count of TRACK_CNT is too high or MAX_LOOP is too big */
+ /* when you see the message the count of TRACK_CNT is too high or MAX_LOOP is too big */
Serial.printf("not enough memory!\n");
return;
}
@@ -197,7 +197,7 @@ void Loop_Process(float *signal_l, float *signal_r)
for (int n = 0; n < TRACK_CNT; n++)
{
- /* stop erasing when final position has been reached */
+ /* stop erasing when final position has been reached */
if (loopErase[n] == loopIn)
{
loopErase[n] = 0xFFFFFFFFUL;
diff --git a/midi_interface.ino b/midi_interface.ino
index 3a8d3ff..f36c718 100644
--- a/midi_interface.ino
+++ b/midi_interface.ino
@@ -1,6 +1,4 @@
/*
- * The GNU GENERAL PUBLIC LICENSE (GNU GPLv3)
- *
* Copyright (c) 2021 Marcel Licence
*
* This program is free software: you can redistribute it and/or modify
@@ -30,26 +28,83 @@
* Programm erhalten haben. Wenn nicht, siehe .
*/
-/*
- * a simple implementation to use midi
+/**
+ * @file midi_interface.ino
+ * @author Marcel Licence
+ * @date 04.10.2021
*
- * Author: Marcel Licence
+ * @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
*/
-#if 0
-#define RXD2 16 /* U2RRXD */
-#define TXD2 17
-#else
-#define RXD2 22
-#define TXD2 21
+
+#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
@@ -60,98 +115,65 @@ struct midiControllerMapping
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;
};
-/*
- * this mapping is used for the edirol pcr-800
- * this should be changed when using another controller
- */
-struct midiControllerMapping edirolMapping[] =
+struct midiMapping_s
{
- { 0x8, 0x52, "back", NULL, Loop_ResetToStart, 0},
- { 0x8, 0x52, "back", NULL, Click_Reset, 0},
- { 0xD, 0x52, "stop", NULL, Loop_Stop, 0},
- { 0xe, 0x52, "start", NULL, Loop_PlayNormal, 0},
- { 0xe, 0x52, "start", NULL, Loop_StartAll, 0},
- { 0xa, 0x52, "rec", NULL, Loop_SetLength, 0},
+ 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);
- /* upper row of buttons */
- { 0x0, 0x50, "A1", NULL, Loop_SelectTrack, 0},
- { 0x1, 0x50, "A2", NULL, Loop_SelectTrack, 1},
- { 0x2, 0x50, "A3", NULL, Loop_SelectTrack, 2},
- { 0x3, 0x50, "A4", NULL, Loop_SelectTrack, 3},
-
- { 0x4, 0x50, "A5", NULL, Click_ToggleOnOff, 0},
- { 0x5, 0x50, "A6", NULL, Loop_JumpPosQuarter, 1},
- { 0x6, 0x50, "A7", NULL, Loop_JumpPosQuarter, 2},
- { 0x7, 0x50, "A8", NULL, Loop_JumpPosQuarter, 3},
- { 0x5, 0x50, "A6", NULL, Click_JumpPosQuarter, 1},
- { 0x6, 0x50, "A7", NULL, Click_JumpPosQuarter, 2},
- { 0x7, 0x50, "A8", NULL, Click_JumpPosQuarter, 3},
-
- { 0x0, 0x53, "A9", NULL, Click_OnOff, 0},
-
- /* lower row of buttons */
- { 0x0, 0x51, "B1", NULL, Loop_StopChannel, 0},
- { 0x1, 0x51, "B2", NULL, Loop_StopChannel, 1},
- { 0x2, 0x51, "B3", NULL, Loop_StopChannel, 2},
- { 0x3, 0x51, "B4", NULL, Loop_StopChannel, 3},
-
- { 0x4, 0x51, "B5", NULL, Loop_EraseTrack, 0},
- { 0x5, 0x51, "B6", NULL, Loop_EraseTrack, 1},
- { 0x6, 0x51, "B7", NULL, Loop_EraseTrack, 2},
- { 0x7, 0x51, "B8", NULL, Loop_EraseTrack, 3},
-
- { 0x1, 0x53, "B9", NULL, MTLooper_ToggleSource, 0},
-
- /* pedal */
- { 0x0, 0x0b, "VolumePedal", NULL, NULL, 0},
-
- { 0x0, 0x11, "S1", NULL, Loop_SetChannelGainOut, 0},
- { 0x1, 0x11, "S2", NULL, Loop_SetChannelGainOut, 1},
- { 0x2, 0x11, "S3", NULL, Loop_SetChannelGainOut, 2},
- { 0x3, 0x11, "S4", NULL, Loop_SetChannelGainOut, 3},
-
- { 0x4, 0x11, "S5", NULL, NULL, 0},
- { 0x5, 0x11, "S6", NULL, NULL, 0},
- { 0x6, 0x11, "S7", NULL, NULL, 0},
- { 0x7, 0x11, "S8", NULL, NULL, 0},
-
- /* rotary */
- { 0x0, 0x10, "R1", NULL, Loop_SetChannelPan, 0},
- { 0x1, 0x10, "R2", NULL, Loop_SetChannelPan, 1},
- { 0x2, 0x10, "R3", NULL, Loop_SetChannelPan, 2},
- { 0x3, 0x10, "R4", NULL, Loop_SetChannelPan, 3},
-
- { 0x4, 0x10, "R5", NULL, NULL, 0},
- { 0x5, 0x10, "R6", NULL, NULL, 0},
- { 0x6, 0x10, "R7", NULL, Click_SetTempo, 0},
- { 0x7, 0x10, "R8", NULL, Loop_SetSpeed, 0},
-
- { 0x0, 0x12, "R9", NULL, Loop_SetChannelGainIn, 0},
+ struct midiControllerMapping *controlMapping;
+ int mapSize;
};
-
-
-
-
-/* use define to dump midi data */
-//#define DUMP_SERIAL2_TO_SERIAL
+extern struct midiMapping_s midiMapping; /* definition in z_config.ino */
/* constant to normalize midi value to 0.0 - 1.0f */
-#define NORM127MUL 0.007874f
+#define NORM127MUL 0.007874f
-inline void Midi_NoteOn(uint8_t ch, uint8_t note)
+inline void Midi_NoteOn(uint8_t ch, uint8_t note, uint8_t vel)
{
- Loop_NoteOn(ch, note);
- // Synth_NoteOn(note);
+ 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)
{
- // Synth_NoteOff(note);
+ if (midiMapping.noteOff != NULL)
+ {
+ midiMapping.noteOff(ch, note);
+ }
}
/*
@@ -159,56 +181,59 @@ inline void Midi_NoteOff(uint8_t ch, uint8_t note)
*/
inline void Midi_ControlChange(uint8_t channel, uint8_t data1, uint8_t data2)
{
- for (int i = 0; i < (sizeof(edirolMapping) / sizeof(edirolMapping[0])); i++)
+ for (int i = 0; i < midiMapping.mapSize; i++)
{
- if ((edirolMapping[i].channel == channel) && (edirolMapping[i].data1 == data1))
+ if ((midiMapping.controlMapping[i].channel == channel) && (midiMapping.controlMapping[i].data1 == data1))
{
- if (edirolMapping[i].callback_mid != NULL)
+ if (midiMapping.controlMapping[i].callback_mid != NULL)
{
- edirolMapping[i].callback_mid(channel, data1, data2);
+ midiMapping.controlMapping[i].callback_mid(channel, data1, data2);
}
- if (edirolMapping[i].callback_val != NULL)
+ if (midiMapping.controlMapping[i].callback_val != NULL)
{
- edirolMapping[i].callback_val(edirolMapping[i].user_data, (float)data2 * NORM127MUL);
- }
- }
- }
-
- if (data1 == 17)
- {
- if (channel < 10)
- {
- Synth_SetSlider(channel, data2 * NORM127MUL);
- }
- }
-#if 0
- if (data1 == 17)
- {
- if (channel < 10)
- {
- Synth_SetSlider(channel, data2 * NORM127MUL);
- }
- }
- if ((data1 == 18) && (channel == 1))
- {
- Synth_SetSlider(8, data2 * NORM127MUL);
- }
+#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 == 16) && (channel < 9))
- {
- Synth_SetRotary(channel, data2 * NORM127MUL);
-
+ }
+ }
}
- if ((data1 == 18) && (channel == 0))
+
+ if (data1 == 1)
{
- Synth_SetRotary(8, data2 * NORM127MUL);
+ 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 HandleShortMsg(uint8_t *data)
+inline void Midi_HandleShortMsg(uint8_t *data, uint8_t cable __attribute__((unused)))
{
uint8_t ch = data[0] & 0x0F;
@@ -218,7 +243,7 @@ inline void HandleShortMsg(uint8_t *data)
case 0x90:
if (data[2] > 0)
{
- Midi_NoteOn(ch, data[1]);
+ Midi_NoteOn(ch, data[1], data[2]);
}
else
{
@@ -232,77 +257,212 @@ inline void HandleShortMsg(uint8_t *data)
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()
{
- Serial2.begin(31250, SERIAL_8N1, RXD2, TXD2);
- pinMode(RXD2, INPUT_PULLUP); /* 25: GPIO 16, u2_RXD */
+#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 */
}
-/*
- * this function should be called continuously to ensure that incoming messages can be processed
- */
-void Midi_Process()
+void Midi_CheckMidiPort(struct midi_port_s *port)
{
- /*
- * watchdog to avoid getting stuck by receiving incomplete or wrong data
- */
- static uint32_t inMsgWd = 0;
- static uint8_t inMsg[3];
- static uint8_t inMsgIndex = 0;
-
//Choose Serial1 or Serial2 as required
- if (Serial2.available())
+ if (port->serial->available())
{
- uint8_t incomingByte = Serial2.read();
+ uint8_t incomingByte = port->serial->read();
-#ifdef DUMP_SERIAL2_TO_SERIAL
+#ifdef MIDI_DUMP_SERIAL2_TO_SERIAL
Serial.printf("%02x", incomingByte);
#endif
/* ignore live messages */
if ((incomingByte & 0xF0) == 0xF0)
{
+ Midi_RealTimeMessage(incomingByte);
return;
}
- if (inMsgIndex == 0)
+ if (port->inMsgIndex == 0)
{
if ((incomingByte & 0x80) != 0x80)
{
- inMsgIndex = 1;
+ port->inMsgIndex = 1;
}
}
- inMsg[inMsgIndex] = incomingByte;
- inMsgIndex += 1;
+ port->inMsg[port->inMsgIndex] = incomingByte;
+ port->inMsgIndex += 1;
- if (inMsgIndex >= 3)
+ if ((port->inMsgIndex >= 3) ||
+ (
+ (((port->inMsg[0] & 0xF0) == 0xD0)
+ || ((port->inMsg[0] & 0xF0) == 0xC0))
+ && (port->inMsgIndex >= 2))
+ )
{
-#ifdef DUMP_SERIAL2_TO_SERIAL
- Serial.printf(">%02x %02x %02x\n", inMsg[0], inMsg[1], inMsg[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
- HandleShortMsg(inMsg);
- inMsgIndex = 0;
+ Midi_HandleShortMsg(port->inMsg, 0);
+ port->inMsgIndex = 0;
}
/*
* reset watchdog to allow new bytes to be received
*/
- inMsgWd = 0;
+ port->inMsgWd = 0;
}
else
{
- if (inMsgIndex > 0)
+ if (port->inMsgIndex > 0)
{
- inMsgWd++;
- if (inMsgWd == 0xFFF)
+ port->inMsgWd++;
+ if (port->inMsgWd == 0xFFF)
{
- inMsgIndex = 0;
+ 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/status_module.ino b/status_module.ino
index e515f42..93d8e88 100644
--- a/status_module.ino
+++ b/status_module.ino
@@ -40,7 +40,7 @@
*/
-char statusMsg[128] = "\0"; /*!< buffer for top line message */
+char statusMsg[128] = ""; /*!< buffer for top line message */
uint32_t status_cnt = 0; /*!< counter for timeout to reset top line */
uint32_t loopMeterCount = 0; /*!< prescaler to reduce the serial output */
@@ -74,9 +74,9 @@ void Status_Setup(void)
*/
void Status_PrintVu(float *value)
{
- /*
- * first pick a color
- */
+ /*
+ * first pick a color
+ */
if (*value >= 0.7071f) /* -3dB */
{
Serial.printf("\033[0;31m"); /* red */
@@ -226,7 +226,7 @@ void Status_Process(void)
void Status_ValueChangedFloat(const char *descr, float value)
{
status_cnt = 0;
- sprintf(statusMsg, "%s: %0.2f\0", descr, value);
+ sprintf(statusMsg, "%s: %0.2f", descr, value);
}
/*
@@ -235,7 +235,7 @@ void Status_ValueChangedFloat(const char *descr, float value)
void Status_ValueChangedInt(const char *descr, int value)
{
status_cnt = 0;
- sprintf(statusMsg, "%s: %d\0", descr, value);
+ sprintf(statusMsg, "%s: %d", descr, value);
}
/*
@@ -244,5 +244,5 @@ void Status_ValueChangedInt(const char *descr, int value)
void Status_TestMsg(const char *text)
{
status_cnt = 0;
- sprintf(statusMsg, "%s\0", text);
+ sprintf(statusMsg, "%s", text);
}
diff --git a/z_config.ino b/z_config.ino
new file mode 100644
index 0000000..27d639d
--- /dev/null
+++ b/z_config.ino
@@ -0,0 +1,132 @@
+/*
+ * 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 .
+ */
+
+/*
+ * z_config.ino
+ *
+ * Put all your project configuration here (no defines etc)
+ * This file will be included at the and can access all
+ * declarations and type definitions
+ *
+ * Created on: 02.01.2022
+ * Author: Marcel Licence
+ */
+
+/*
+ * this mapping is used for the edirol pcr-800
+ * this should be changed when using another controller
+ */
+struct midiControllerMapping edirolMapping[] =
+{
+ /* transport buttons */
+ { 0x8, 0x52, "back", NULL, Loop_ResetToStart, 0},
+ { 0x8, 0x52, "back", NULL, Click_Reset, 0},
+ { 0xD, 0x52, "stop", NULL, Loop_Stop, 0},
+ { 0xe, 0x52, "start", NULL, Loop_PlayNormal, 0},
+ { 0xe, 0x52, "start", NULL, Loop_StartAll, 0},
+ { 0xa, 0x52, "rec", NULL, Loop_SetLength, 0},
+
+ /* upper row of buttons */
+ { 0x0, 0x50, "A1", NULL, Loop_SelectTrack, 0},
+ { 0x1, 0x50, "A2", NULL, Loop_SelectTrack, 1},
+ { 0x2, 0x50, "A3", NULL, Loop_SelectTrack, 2},
+ { 0x3, 0x50, "A4", NULL, Loop_SelectTrack, 3},
+ { 0x4, 0x50, "A5", NULL, Click_ToggleOnOff, 0},
+
+ { 0x5, 0x50, "A6", NULL, Loop_JumpPosQuarter, 1},
+ { 0x6, 0x50, "A7", NULL, Loop_JumpPosQuarter, 2},
+ { 0x7, 0x50, "A8", NULL, Loop_JumpPosQuarter, 3},
+ { 0x5, 0x50, "A6", NULL, Click_JumpPosQuarter, 1},
+ { 0x6, 0x50, "A7", NULL, Click_JumpPosQuarter, 2},
+ { 0x7, 0x50, "A8", NULL, Click_JumpPosQuarter, 3},
+
+ { 0x0, 0x53, "A9", NULL, Click_OnOff, 0},
+
+ /* lower row of buttons */
+ { 0x0, 0x51, "B1", NULL, Loop_StopChannel, 0},
+ { 0x1, 0x51, "B2", NULL, Loop_StopChannel, 1},
+ { 0x2, 0x51, "B3", NULL, Loop_StopChannel, 2},
+ { 0x3, 0x51, "B4", NULL, Loop_StopChannel, 3},
+
+ { 0x4, 0x51, "B5", NULL, Loop_EraseTrack, 0},
+ { 0x5, 0x51, "B6", NULL, Loop_EraseTrack, 1},
+ { 0x6, 0x51, "B7", NULL, Loop_EraseTrack, 2},
+ { 0x7, 0x51, "B8", NULL, Loop_EraseTrack, 3},
+
+ { 0x1, 0x53, "B9", NULL, MTLooper_ToggleSource, 0},
+
+ /* pedal */
+ { 0x0, 0x0b, "VolumePedal", NULL, NULL, 0},
+
+ { 0x0, 0x11, "S1", NULL, Loop_SetChannelGainOut, 0},
+ { 0x1, 0x11, "S2", NULL, Loop_SetChannelGainOut, 1},
+ { 0x2, 0x11, "S3", NULL, Loop_SetChannelGainOut, 2},
+ { 0x3, 0x11, "S4", NULL, Loop_SetChannelGainOut, 3},
+
+ { 0x4, 0x11, "S5", NULL, NULL, 0},
+ { 0x5, 0x11, "S6", NULL, NULL, 0},
+ { 0x6, 0x11, "S7", NULL, NULL, 0},
+ { 0x7, 0x11, "S8", NULL, NULL, 0},
+
+ /* rotary */
+ { 0x0, 0x10, "R1", NULL, Loop_SetChannelPan, 0},
+ { 0x1, 0x10, "R2", NULL, Loop_SetChannelPan, 1},
+ { 0x2, 0x10, "R3", NULL, Loop_SetChannelPan, 2},
+ { 0x3, 0x10, "R4", NULL, Loop_SetChannelPan, 3},
+
+ { 0x4, 0x10, "R5", NULL, NULL, 0},
+ { 0x5, 0x10, "R6", NULL, NULL, 0},
+ { 0x6, 0x10, "R7", NULL, Click_SetTempo, 0},
+ { 0x7, 0x10, "R8", NULL, Loop_SetSpeed, 0},
+
+ { 0x0, 0x12, "R9", NULL, Loop_SetChannelGainIn, 0},
+
+ /* Central slider */
+#ifndef AS5600_ENABLED
+ // { 0x0, 0x13, "H1", NULL, App_SetBrightness, 0},
+#else
+ { 0x0, 0x13, "H1", NULL, Sampler_ScratchFader, 0},
+#endif
+};
+
+
+struct midiMapping_s midiMapping =
+{
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ edirolMapping,
+ sizeof(edirolMapping) / sizeof(edirolMapping[0]),
+};
+