From ed8be3aa699d7474d2ad3b1972805ad91742c36a Mon Sep 17 00:00:00 2001 From: Holger Wirtz Date: Thu, 27 Sep 2018 11:28:08 +0200 Subject: [PATCH] Added first steps for a simple UI. --- MicroDexed.ino | 96 ++++++++++++++++++++++++++------------------------ UI.cpp | 75 +++++++++++++++++++++++++++++++++++++++ UI.h | 42 ++++++++++++++++++++++ config.h | 27 ++++++++++---- dexed_sysex.h | 5 +++ 5 files changed, 192 insertions(+), 53 deletions(-) create mode 100644 UI.cpp create mode 100644 UI.h diff --git a/MicroDexed.ino b/MicroDexed.ino index a017e0a..e62522a 100644 --- a/MicroDexed.ino +++ b/MicroDexed.ino @@ -38,26 +38,15 @@ #endif #ifdef I2C_DISPLAY // selecting sounds by encoder, button and display +#include "UI.h" #include #include -#endif -#ifdef I2C_DISPLAY #include -#endif - -#ifdef I2C_DISPLAY -Encoder enc_l(ENC_L_PIN_A, ENC_L_PIN_B); -Bounce but_l = Bounce(BUT_L_PIN, 10); // 10 ms debounce -Encoder enc_r(ENC_R_PIN_A, ENC_R_PIN_B); -Bounce but_r = Bounce(BUT_R_PIN, 10); // 10 ms debounce -#endif - -#ifdef I2C_DISPLAY -// [I2C] SCL: Pin 19, SDA: Pin 18 (https://www.pjrc.com/teensy/td_libs_Wire.html) -#define LCD_I2C_ADDRESS 0x27 -#define LCD_CHARS 16 -#define LCD_LINES 2 LiquidCrystalPlus_I2C lcd(LCD_I2C_ADDRESS, LCD_CHARS, LCD_LINES); +Encoder enc[2] = {Encoder(ENC_L_PIN_A, ENC_L_PIN_B), Encoder(ENC_R_PIN_A, ENC_R_PIN_B)}; +int32_t enc_val[2] = {INITIAL_ENC_L_VALUE, INITIAL_ENC_R_VALUE}; +Bounce but[2] = {Bounce(BUT_L_PIN, BUT_DEBOUNCE_MS), Bounce(BUT_R_PIN, BUT_DEBOUNCE_MS)}; +elapsedMillis master_timer; #endif // GUItool: begin automatically generated code @@ -135,8 +124,8 @@ void setup() lcd.show(0, 0, 16, " MicroDexed"); lcd.show(1, 0, 16, "(c)parasiTstudio"); - enc_l.write(INITIAL_ENC_L_VALUE); - enc_r.write(INITIAL_ENC_R_VALUE); + pinMode(BUT_L_PIN, INPUT_PULLUP); + pinMode(BUT_R_PIN, INPUT_PULLUP); #endif delay(220); @@ -192,8 +181,10 @@ void setup() // load default SYSEX data load_sysex(bank, voice); #ifdef I2C_DISPLAY - enc_l.write(bank); - enc_r.write(voice); + setEncPosition(0,bank); + setEncPosition(1,voice); + but[0].update(); + but[1].update(); #endif } @@ -228,7 +219,6 @@ void setup() #if defined (DEBUG) && defined (SHOW_CPU_LOAD_MSEC) show_cpu_and_mem_usage(); - cpu_mem_millis -= SHOW_CPU_LOAD_MSEC; #endif #ifdef I2C_DISPLAY @@ -262,36 +252,48 @@ void loop() const uint16_t audio_block_time_ms = 1000000 / (SAMPLE_RATE / AUDIO_BLOCK_SAMPLES); #if defined (DEBUG) && defined (SHOW_CPU_LOAD_MSEC) - if (cpu_mem_millis > SHOW_CPU_LOAD_MSEC) - { - show_cpu_and_mem_usage(); - cpu_mem_millis = 0; - } + if (cpu_mem_millis >= SHOW_CPU_LOAD_MSEC) + { + cpu_mem_millis -= SHOW_CPU_LOAD_MSEC; + show_cpu_and_mem_usage(); + } #endif - handle_input(); + // MIDI input handling + handle_input(); - if (queue1.available()) + // Main sound calculation + if (queue1.available()) + { + audio_buffer = queue1.getBuffer(); + + elapsedMicros t1; + dexed->getSamples(AUDIO_BLOCK_SAMPLES, audio_buffer); + if (t1 > audio_block_time_ms) // everything greater 2.9ms is a buffer underrun! + xrun++; + if (t1 > render_time_max) + render_time_max = t1; + if (peak1.available()) { - audio_buffer = queue1.getBuffer(); - - elapsedMicros t1; - dexed->getSamples(AUDIO_BLOCK_SAMPLES, audio_buffer); - if (t1 > audio_block_time_ms) // everything greater 2.9ms is a buffer underrun! - xrun++; - if (t1 > render_time_max) - render_time_max = t1; - if (peak1.available()) - { - if (peak1.read() > 0.99) - peak++; - } + if (peak1.read() > 0.99) + peak++; + } #ifndef TEENSY_AUDIO_BOARD - for (uint8_t i = 0; i < AUDIO_BLOCK_SAMPLES; i++) - audio_buffer[i] *= vol; + for (uint8_t i = 0; i < AUDIO_BLOCK_SAMPLES; i++) + audio_buffer[i] *= vol; +#endif + queue1.playBuffer(); + } + +#ifdef I2C_DISPLAY + // UI + if (master_timer >= TIMER_UI_HANDLING_MS) + { + master_timer -= TIMER_UI_HANDLING_MS; + + handle_ui(); + } #endif - queue1.playBuffer(); - } } void handle_input(void) @@ -757,8 +759,8 @@ void show_cpu_and_mem_usage(void) Serial.print(overload, DEC); Serial.print(F(" PEAK: ")); Serial.print(peak, DEC); - Serial.print(F("Block-size:")); - Serial.print(AUDIO_BLOCK_SAMPLES,DEC); + Serial.print(F(" BLOCKSIZE: ")); + Serial.print(AUDIO_BLOCK_SAMPLES, DEC); Serial.println(); AudioProcessorUsageMaxReset(); AudioMemoryUsageMaxReset(); diff --git a/UI.cpp b/UI.cpp new file mode 100644 index 0000000..11b3eb3 --- /dev/null +++ b/UI.cpp @@ -0,0 +1,75 @@ +/* + MicroDexed + + MicroDexed is a port of the Dexed sound engine + (https://github.com/asb2m10/dexed) for the Teensy-3.5/3.6 with audio shield. + Dexed ist heavily based on https://github.com/google/music-synthesizer-for-android + + (c)2018 H. Wirtz + + 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, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include +#include "config.h" +#include "UI.h" +#include +#include +#include + +#ifdef I2C_DISPLAY // selecting sounds by encoder, button and display + +void handle_ui(void) +{ + for (uint8_t i = 0; i < NUM_ENCODER; i++) + { + but[i].update(); + + if (but[i].risingEdge()) + { + // Button pressed +#ifdef DEBUG + Serial.print(F("Button ")); + Serial.println(i, DEC); +#endif + } + + if ((enc[i].read() / 4) == (enc_val[i] / 4)) + continue; + else + { +#ifdef DEBUG + Serial.print(F("Encoder ")); + Serial.print(i, DEC); + Serial.print(F(": ")); + Serial.println(getEncPosition(i), DEC); +#endif + } + enc_val[i] = enc[i].read(); + } +} + +int32_t getEncPosition(uint8_t encoder_number) +{ + return enc[encoder_number].read() / 4; +} + +void setEncPosition(uint8_t encoder_number, int32_t value) +{ + enc[encoder_number].write(value * 4); + enc_val[encoder_number] = value * 4; +} +#endif diff --git a/UI.h b/UI.h new file mode 100644 index 0000000..dbdd6fc --- /dev/null +++ b/UI.h @@ -0,0 +1,42 @@ +/* + MicroDexed + + MicroDexed is a port of the Dexed sound engine + (https://github.com/asb2m10/dexed) for the Teensy-3.5/3.6 with audio shield. + Dexed ist heavily based on https://github.com/google/music-synthesizer-for-android + + (c)2018 H. Wirtz + + 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, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +#include "config.h" +#include +#include +#include + +#ifndef UI_H_INCLUDED +#define UI_H_INCLUDED + +extern Encoder enc[2]; +extern int32_t enc_val[2]; +extern Bounce but[2]; + +void handle_ui(void); +int32_t getEncPosition(uint8_t encoder_number); +void setEncPosition(uint8_t encoder_number, int32_t value); + +#endif diff --git a/config.h b/config.h index f60e15a..5b937dd 100644 --- a/config.h +++ b/config.h @@ -28,11 +28,14 @@ // ATTENTION! For better latency you have to redefine AUDIO_BLOCK_SAMPLES from // 128 to 64 in /cores/teensy3/AudioStream.h + +#ifndef CONFIG_H_INCLUDED +#define CONFIG_H_INCLUDED + // Initial values #define MIDI_DEVICE Serial1 #define USE_ONBOARD_USB_HOST 1 //#define TEENSY_AUDIO_BOARD 1 -#define I2C_DISPLAY 1 #define VOLUME 0.6 #define DEFAULT_MIDI_CHANNEL MIDI_CHANNEL_OMNI #define DEFAULT_SYSEXBANK 0 @@ -83,15 +86,25 @@ #define SDCARD_MOSI_PIN 11 // not actually used #define SDCARD_SCK_PIN 13 // not actually used +// LCD Display +#define I2C_DISPLAY 1 +// [I2C] SCL: Pin 19, SDA: Pin 18 (https://www.pjrc.com/teensy/td_libs_Wire.html) +#define LCD_I2C_ADDRESS 0x27 +#define LCD_CHARS 16 +#define LCD_LINES 2 + // Encoder with button -#define ENC_L_PIN_A 2 -#define ENC_L_PIN_B 3 +#define TIMER_UI_HANDLING_MS 50 +#define NUM_ENCODER 2 +#define ENC_L_PIN_A 3 +#define ENC_L_PIN_B 2 #define BUT_L_PIN 4 #define INITIAL_ENC_L_VALUE 0 -#define ENC_R_PIN_A 5 -#define ENC_R_PIN_B 24 -#define BUT_R_PIN 25 +#define ENC_R_PIN_A 28 +#define ENC_R_PIN_B 29 +#define BUT_R_PIN 30 #define INITIAL_ENC_R_VALUE 0 +#define BUT_DEBOUNCE_MS 20 // EEPROM address #define EEPROM_OFFSET 0 @@ -103,3 +116,5 @@ #define EEPROM_MASTER_VOLUME_ADDR 2 #define EEPROM_VOLUME_RIGHT_ADDR 3 #define EEPROM_VOLUME_LEFT_ADDR 4 + +#endif diff --git a/dexed_sysex.h b/dexed_sysex.h index 701e57c..aa8b88b 100644 --- a/dexed_sysex.h +++ b/dexed_sysex.h @@ -25,6 +25,9 @@ #include "config.h" +#ifndef DEXED_SYSEX_H_INCLUDED +#define DEXED_SYSEX_H_INCLUDED + extern bool sd_card_available; extern Dexed* dexed; extern uint16_t render_time_max; @@ -36,3 +39,5 @@ extern char voice_name[11]; bool get_bank_name(uint8_t b); bool load_sysex(uint8_t b, uint8_t v); bool get_sysex_voice(char* dir, File sysex, uint8_t voice_number, uint8_t* data); + +#endif