Major update to use latest modules developed in the meantime
This commit is contained in:
+4
-4
@@ -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))
|
||||
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @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 <cdt.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* include the board configuration
|
||||
* there you will find the most hardware depending pin settings
|
||||
*/
|
||||
#define BOARD_ESP32_AUDIO_KIT_AC101
|
||||
|
||||
#include <ml_boards.h> /* requires https://github.com/marcel-licence/ML_SynthTools */
|
||||
|
||||
/* our samplerate */
|
||||
#define SAMPLE_RATE 44100
|
||||
|
||||
/* on board led */
|
||||
#define LED_PIN 19
|
||||
|
||||
|
||||
#endif /* CONFIG_H_ */
|
||||
|
||||
+10
-16
@@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 <cdt.h>
|
||||
#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
|
||||
|
||||
+166
-30
@@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 <cdt.h>
|
||||
#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
|
||||
|
||||
|
||||
+71
-21
@@ -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 <cdt.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
*
|
||||
/$$$$$$$$ /$$ /$$ /$$$$$$$ /$$$$$$ /$$$$$$$ /$$$$$$ /$$ /$$ /$$ /$$
|
||||
| $$_____/ | $$ | $$ | $$__ $$ /$$__ $$| $$__ $$ /$$__ $$| $$$ /$$$| $$| $$
|
||||
| $$ /$$$$$$$ /$$$$$$ | $$$$$$$ | $$ /$$$$$$ | $$ \ $$| $$ \__/| $$ \ $$| $$ \ $$| $$$$ /$$$$| $$| $$
|
||||
| $$$$$ | $$__ $$ |____ $$| $$__ $$| $$ /$$__ $$ | $$$$$$$/| $$$$$$ | $$$$$$$/| $$$$$$$$| $$ $$/$$ $$| $$| $$
|
||||
| $$__/ | $$ \ $$ /$$$$$$$| $$ \ $$| $$| $$$$$$$$ | $$____/ \____ $$| $$__ $$| $$__ $$| $$ $$$| $$|__/|__/
|
||||
| $$ | $$ | $$ /$$__ $$| $$ | $$| $$| $$_____/ | $$ /$$ \ $$| $$ \ $$| $$ | $$| $$\ $ | $$
|
||||
| $$$$$$$$| $$ | $$| $$$$$$$| $$$$$$$/| $$| $$$$$$$ | $$ | $$$$$$/| $$ | $$| $$ | $$| $$ \/ | $$ /$$ /$$
|
||||
|________/|__/ |__/ \_______/|_______/ |__/ \_______/ |__/ \______/ |__/ |__/|__/ |__/|__/ |__/|__/|__/
|
||||
|
||||
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <WiFi.h>
|
||||
|
||||
/* 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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
+5
-5
@@ -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;
|
||||
|
||||
+314
-154
@@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 <cdt.h>
|
||||
#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
|
||||
|
||||
|
||||
+7
-7
@@ -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);
|
||||
}
|
||||
|
||||
+132
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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]),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user