Use centralized modules

This commit is contained in:
Marcel Licence
2023-04-02 20:45:47 +02:00
parent ce666eb334
commit e48348e223
11 changed files with 251 additions and 2200 deletions
-444
View File
@@ -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 <http://www.gnu.org/licenses/>.
*
* Dieses Programm ist Freie Software: Sie knnen 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
* verffentlichten Version, weiter verteilen und/oder modifizieren.
*
* Dieses Programm wird in der Hoffnung bereitgestellt, dass es ntzlich sein wird, jedoch
* OHNE JEDE GEWHR,; sogar ohne die implizite
* Gewhr der MARKTFHIGKEIT oder EIGNUNG FR EINEN BESTIMMTEN ZWECK.
* Siehe die GNU General Public License fr 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 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 <cdt.h>
#endif
#ifdef ESP8266
#include <ESP8266WiFi.h>
#include <I2S.h>
#include <i2s_reg.h>
#endif
#ifdef ESP32
#include <WiFi.h>
#endif
#ifdef TEENSYDUINO
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#endif
#ifdef ARDUINO_DAISY_SEED
#include "DaisyDuino.h"
#endif
#ifdef ARDUINO_RASPBERRY_PI_PICO
#include <I2S.h>
#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) */
-57
View File
@@ -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 <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/>.
*/
/*
* 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;
}
+5 -2
View File
@@ -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 <ml_boards.h> /* requires https://github.com/marcel-licence/ML_SynthTools */
#include <ml_boards.h> /* 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_ */
+236
View File
@@ -0,0 +1,236 @@
<h1>Board Build Variants</h1>
Below you will find a list of build which can be configured and should compile without any problems
<hr>
<a name="espressif_esp32_2_0_2_esp32"></a><b>Core:</b> <a h_ref="https://github.com/espressif/arduino-esp32">ESP32 Arduino </a><br />
<b>Version:</b> 2.0.0<br />
<b>Board:</b> ESP32 Dev Module<br />
<br />
<b>Program storage space:</b> 725241 bytes<br />
<b>Dynamic memory:</b> 48892 bytes<br />
<br />
<b>PSRAM:</b> Enabled<br />
<b>Partition Scheme:</b> Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS)<br />
<b>CPU Frequency:</b> 240MHz (WiFi/BT)<br />
<b>Flash Mode:</b> QIO<br />
<b>Flash Frequency:</b> 80MHz<br />
<b>Flash Size:</b> 4MB (32Mb)<br />
<b>Upload Speed:</b> 921600<br />
<b>Arduino Runs On:</b> Core 1<br />
<b>Events Run On:</b> Core 1<br />
<b>Core Debug Level:</b> None<br />
<br />
<b>Used libraries:</b><br />
<table>
<tr>
<td>Name</td>
<td>Version</td>
<td>Url</td>
<td>Git</td>
<td>Core library</td>
</tr>
<tr>
<td>ML SynthTools</td>
<td>1.0.1</td>
<td>https://github.com/marcel-licence/ML_SynthTools</td>
<td>https://github.com/marcel-licence/ML_SynthTools.git</td>
<td>False</td>
</tr>
<tr>
<td>WiFi</td>
<td>2.0.0</td>
<td></td>
<td></td>
<td>True</td>
</tr>
<tr>
<td>Wire</td>
<td>2.0.0</td>
<td>http://arduino.cc/en/Reference/Wire</td>
<td></td>
<td>True</td>
</tr>
<tr>
<td>Adafruit GFX Library</td>
<td>1.10.10</td>
<td>https://github.com/adafruit/Adafruit-GFX-Library</td>
<td></td>
<td>False</td>
</tr>
<tr>
<td>Adafruit SSD1306</td>
<td>2.4.5</td>
<td>https://github.com/adafruit/Adafruit_SSD1306</td>
<td></td>
<td>False</td>
</tr>
<tr>
<td>SPI</td>
<td>2.0.0</td>
<td>http://arduino.cc/en/Reference/SPI</td>
<td></td>
<td>True</td>
</tr>
<tr>
<td>Adafruit BusIO</td>
<td>1.14.1</td>
<td>https://github.com/adafruit/Adafruit_BusIO</td>
<td>https://github.com/adafruit/Adafruit_BusIO</td>
<td>False</td>
</tr>
</table><hr>
<a name="espressif_2.0.7_esp32_esp32"></a><b>Core:</b> <a h_ref="https://github.com/espressif/arduino-esp32">ESP32 Arduino </a><br />
<b>Version:</b> 2.0.7<br />
<b>Board:</b> ESP32 Dev Module<br />
<br />
<b>Program storage space:</b> 789277 bytes<br />
<b>Dynamic memory:</b> 53536 bytes<br />
<br />
<b>JTAG Adapter:</b> Disabled<br />
<b>PSRAM:</b> Enabled<br />
<b>Partition Scheme:</b> Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS)<br />
<b>CPU Frequency:</b> 240MHz (WiFi/BT)<br />
<b>Flash Mode:</b> QIO<br />
<b>Flash Frequency:</b> 80MHz<br />
<b>Flash Size:</b> 4MB (32Mb)<br />
<b>Upload Speed:</b> 921600<br />
<b>Arduino Runs On:</b> Core 1<br />
<b>Events Run On:</b> Core 1<br />
<b>Core Debug Level:</b> None<br />
<b>Erase All Flash Before Sketch Upload:</b> Disabled<br />
<br />
<b>Used libraries:</b><br />
<table>
<tr>
<td>Name</td>
<td>Version</td>
<td>Url</td>
<td>Git</td>
<td>Core library</td>
</tr>
<tr>
<td>ML SynthTools</td>
<td>1.0.1</td>
<td>https://github.com/marcel-licence/ML_SynthTools</td>
<td>https://github.com/marcel-licence/ML_SynthTools.git</td>
<td>False</td>
</tr>
<tr>
<td>WiFi</td>
<td>2.0.0</td>
<td></td>
<td>https://github.com/espressif/arduino-esp32.git</td>
<td>True</td>
</tr>
<tr>
<td>Wire</td>
<td>2.0.0</td>
<td>http://arduino.cc/en/Reference/Wire</td>
<td>https://github.com/espressif/arduino-esp32.git</td>
<td>True</td>
</tr>
<tr>
<td>Adafruit GFX Library</td>
<td>1.10.10</td>
<td>https://github.com/adafruit/Adafruit-GFX-Library</td>
<td></td>
<td>False</td>
</tr>
<tr>
<td>Adafruit SSD1306</td>
<td>2.4.5</td>
<td>https://github.com/adafruit/Adafruit_SSD1306</td>
<td></td>
<td>False</td>
</tr>
<tr>
<td>SPI</td>
<td>2.0.0</td>
<td>http://arduino.cc/en/Reference/SPI</td>
<td>https://github.com/espressif/arduino-esp32.git</td>
<td>True</td>
</tr>
<tr>
<td>Adafruit BusIO</td>
<td>1.14.1</td>
<td>https://github.com/adafruit/Adafruit_BusIO</td>
<td>https://github.com/adafruit/Adafruit_BusIO</td>
<td>False</td>
</tr>
</table><hr>
<a name="esp32_esp32_esp32"></a><b>Core:</b> <a h_ref="N/A">ESP32 Arduino</a><br />
<b>Version:</b> 1.0.6<br />
<b>Board:</b> ESP32 Dev Module<br />
<br />
<b>Program storage space:</b> 769954 bytes<br />
<b>Dynamic memory:</b> 49272 bytes<br />
<br />
<b>PSRAM:</b> Enabled<br />
<b>Partition Scheme:</b> Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS)<br />
<b>CPU Frequency:</b> 240MHz (WiFi/BT)<br />
<b>Flash Mode:</b> QIO<br />
<b>Flash Frequency:</b> 80MHz<br />
<b>Flash Size:</b> 4MB (32Mb)<br />
<b>Upload Speed:</b> 921600<br />
<b>Core Debug Level:</b> None<br />
<br />
<b>Used libraries:</b><br />
<table>
<tr>
<td>Name</td>
<td>Version</td>
<td>Url</td>
<td>Git</td>
<td>Core library</td>
</tr>
<tr>
<td>ML SynthTools</td>
<td>1.0.1</td>
<td>https://github.com/marcel-licence/ML_SynthTools</td>
<td>https://github.com/marcel-licence/ML_SynthTools.git</td>
<td>False</td>
</tr>
<tr>
<td>WiFi</td>
<td>1.0</td>
<td></td>
<td></td>
<td>True</td>
</tr>
<tr>
<td>Wire</td>
<td>1.0.1</td>
<td>http://arduino.cc/en/Reference/Wire</td>
<td></td>
<td>True</td>
</tr>
<tr>
<td>Adafruit GFX Library</td>
<td>1.10.10</td>
<td>https://github.com/adafruit/Adafruit-GFX-Library</td>
<td></td>
<td>False</td>
</tr>
<tr>
<td>Adafruit SSD1306</td>
<td>2.4.5</td>
<td>https://github.com/adafruit/Adafruit_SSD1306</td>
<td></td>
<td>False</td>
</tr>
<tr>
<td>SPI</td>
<td>1.0</td>
<td>http://arduino.cc/en/Reference/SPI</td>
<td></td>
<td>True</td>
</tr>
<tr>
<td>Adafruit BusIO</td>
<td>1.14.1</td>
<td>https://github.com/adafruit/Adafruit_BusIO</td>
<td>https://github.com/adafruit/Adafruit_BusIO</td>
<td>False</td>
</tr>
</table>
-531
View File
@@ -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 <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 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 <cdt.h>
#endif
#ifdef ES8388_ENABLED
/*
* http://www.everest-semi.com/pdf/ES8388%20DS.pdf
*/
#include <Wire.h>
/* 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
-327
View File
@@ -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 <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 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 <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
//#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
+5
View File
@@ -83,6 +83,11 @@
#endif
#define ML_SYNTH_INLINE_DECLARATION
#include <ml_inline.h>
#undef ML_SYNTH_INLINE_DECLARATION
/* to avoid the high click when turning on the microphone */
static float click_supp_gain = 0.0f;
-371
View File
@@ -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 <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 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 <cdt.h>
#endif
#include <driver/i2s.h>
/*
* 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
}
-468
View File
@@ -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 <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 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 <cdt.h>
#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
+4
View File
@@ -0,0 +1,4 @@
#define ML_SYNTH_INLINE_DEFINITION
#include <ml_inline.h>
#undef ML_SYNTH_INLINE_DEFINITION
+1
View File
@@ -128,6 +128,7 @@ struct midiMapping_s midiMapping =
NULL,
NULL,
NULL,
NULL,
edirolMapping,
sizeof(edirolMapping) / sizeof(edirolMapping[0]),
};