diff options
Diffstat (limited to 'esp32/lego-piano.ino')
-rw-r--r-- | esp32/lego-piano.ino | 63 |
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) { |