aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordakkar <dakkar@thenautilus.net>2020-08-28 19:42:12 +0100
committerdakkar <dakkar@thenautilus.net>2020-08-28 19:42:12 +0100
commitc9584b9b3c8c83decfda3712ad61ca13eb04d94f (patch)
tree902b4ffd0dcf93dd5ce0f310e1a826969c619fc9
parentmove sound rendering inside delay waiting for sensor (diff)
downloadlego-piano-c9584b9b3c8c83decfda3712ad61ca13eb04d94f.tar.gz
lego-piano-c9584b9b3c8c83decfda3712ad61ca13eb04d94f.tar.bz2
lego-piano-c9584b9b3c8c83decfda3712ad61ca13eb04d94f.zip
using the i2c-to-internal-dac functions, it sounds a bit better
-rw-r--r--esp32/lego-piano.ino63
1 files changed, 33 insertions, 30 deletions
diff --git a/esp32/lego-piano.ino b/esp32/lego-piano.ino
index 7901279..8991f07 100644
--- a/esp32/lego-piano.ino
+++ b/esp32/lego-piano.ino
@@ -17,6 +17,7 @@
*/
#include <driver/dac.h>
+#include <driver/i2s.h>
#define TSF_IMPLEMENTATION
#define TSF_NO_STDIO
@@ -39,27 +40,12 @@ const int ampEnable = 32;
const int octave_shift = 2;
+const int sampleRate = 8000;
+
char pressed[row_count*col_count] = { 0 };
-hw_timer_t * timer = NULL;
-portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
tsf* g_TinySoundFont = 0;
-bool playing = false;
-
-RingBuf<short, 500> buffer;
-
-void IRAM_ATTR onTimer() {
- if (!g_TinySoundFont) return;
-
- portENTER_CRITICAL_ISR(&timerMux);
-
- short sample;
- if (buffer.pop(sample)) {
- dac_output_voltage(DAC_CHANNEL_1, sample >> 8);
- }
-
- portEXIT_CRITICAL_ISR(&timerMux);
-}
+const i2s_port_t i2sPort = I2S_NUM_0;
void setup() {
Serial.begin(115200);
@@ -67,9 +53,24 @@ void setup() {
pinMode(ampEnable, OUTPUT);
digitalWrite(ampEnable, LOW);
- dac_i2s_disable();
+ dac_i2s_enable();
dac_output_enable(DAC_CHANNEL_1);
+ static const i2s_config_t i2s_config = {
+ .mode = (i2s_mode_t)( I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN ),
+ .sample_rate = sampleRate,
+ .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
+ .channel_format = I2S_CHANNEL_FMT_ALL_RIGHT,
+ .intr_alloc_flags = 0, // default interrupt priority
+ .dma_buf_count = 8,
+ .dma_buf_len = 64,
+ .use_apll = false
+ };
+
+ i2s_driver_install(i2sPort, &i2s_config, 0, NULL);
+ i2s_set_dac_mode(I2S_DAC_CHANNEL_RIGHT_EN); // only dac1
+ i2s_set_sample_rates(i2sPort, sampleRate); // ??
+
for (int i=0;i<row_count;++i) {
pinMode(rows[i], OUTPUT|PULLUP);
pinMode(adc[i], INPUT);
@@ -79,19 +80,11 @@ void setup() {
}
currentLed = 0;
- playing = false;
g_TinySoundFont = tsf_load_memory(SoundFont, sizeof(SoundFont));
if (g_TinySoundFont) {
// render at 5kHz
- tsf_set_output(g_TinySoundFont, TSF_MONO, 5000, 0);
-
- // pre-scaling a 40MHz clock by 4k, then calling on every 2 tick,
- // should give us 5kHz
- timer = timerBegin(0, 4000, true);
- timerAttachInterrupt(timer, &onTimer, true);
- timerAlarmWrite(timer, 2, true);
- timerAlarmEnable(timer);
+ tsf_set_output(g_TinySoundFont, TSF_MONO, sampleRate, 0);
}
else {
Serial.println("failed to start tsf");
@@ -149,6 +142,7 @@ int sense(int led) {
return value < 500;
}
+RingBuf<short, 500> buffer;
short intermediateBuffer[5000];
void loop() {
@@ -159,15 +153,24 @@ void loop() {
enableLed(currentLed);
unsigned long t = millis();
+ size_t written=100;
+ short value;
+ // fill the I2S buffer
+ while (written > 0) {
+ // we don't want to drop an element from the buffer if we then
+ // can't write it! so we peek at the buffer, try to write, and pop
+ // if successful
+ value=buffer[0];
+ i2s_write(i2sPort, &value, sizeof(value), &written, 0);
+ if (written > 0) buffer.pop(value);
+ }
int toFill = buffer.maxSize() - buffer.size();
if (toFill > 100) {
tsf_render_short(g_TinySoundFont, intermediateBuffer, toFill, 0);
- noInterrupts();
for (int i=0;i<toFill;++i) {
buffer.push(intermediateBuffer[i]);
}
- interrupts();
}
while (millis() == t) {