From aabcb40f230803803f8c2faa82b82cc696b6bb1a Mon Sep 17 00:00:00 2001 From: Dirk Niggemann Date: Tue, 15 Oct 2019 19:33:34 +0100 Subject: [PATCH] Initial commit of SSD1322/u8x8 support --- MicroDexed.ino | 86 ++++++++++++++++++--------------------- SSD1322_Plus.h | 98 ++++++++++++++++++++++++++++++++++++++++++++ UI.hpp | 107 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 244 insertions(+), 47 deletions(-) create mode 100644 SSD1322_Plus.h diff --git a/MicroDexed.ino b/MicroDexed.ino index 32476c9..66b67a1 100644 --- a/MicroDexed.ino +++ b/MicroDexed.ino @@ -42,7 +42,8 @@ AudioPlayQueue dexed1; AudioAnalyzePeak peak1; AudioEffectDelay delay_r; AudioEffectDelay delay_l; -AudioEffectFreeverbStereo freeverbs1; +AudioEffectFreeverb freeverb_r; +AudioEffectFreeverb freeverb_l; AudioEffectModulatedDelay modchorus_r; AudioEffectModulatedDelay modchorus_l; #if MOD_FILTER_OUTPUT != MOD_NO_FILTER_OUTPUT @@ -61,7 +62,7 @@ AudioMixer4 reverb_mixer_r; AudioMixer4 reverb_mixer_l; AudioAmplifier volume_r; AudioAmplifier volume_l; -#ifdef MIDI_DEVICE_USB +#if defined(AUDIO_DEVICE_USB) AudioOutputUSB usb1; #endif AudioConnection patchCord0(dexed1, peak1); @@ -97,30 +98,30 @@ AudioConnection patchCord24(delay_r, 0, delay_mixer_r, 2); AudioConnection patchCord25(delay_l, 0, delay_mixer_l, 2); AudioConnection patchCord26(delay_fb_mixer_r, delay_r); AudioConnection patchCord27(delay_fb_mixer_l, delay_l); -AudioConnection patchCord28(delay_mixer_r, 0, freeverbs1, 1); -AudioConnection patchCord29(delay_mixer_l, 0, freeverbs1, 1); -AudioConnection patchCord30(freeverbs1, 0, reverb_mixer_r, 1); -AudioConnection patchCord31(freeverbs1, 1, reverb_mixer_l, 1); -AudioConnection patchCord32(reverb_mixer_r, volume_r); -AudioConnection patchCord33(reverb_mixer_l, volume_l); -#ifdef MIDI_DEVICE_USB -AudioConnection patchCord34(volume_r, 0, usb1, 0); -AudioConnection patchCord35(volume_l, 0, usb1, 1); +AudioConnection patchCord28(freeverb_r, 0, reverb_mixer_r, 1); +AudioConnection patchCord29(freeverb_l, 0, reverb_mixer_l, 1); +AudioConnection patchCord30(reverb_mixer_r, volume_r); +AudioConnection patchCord31(reverb_mixer_l, volume_l); +#if defined(AUDIO_DEVICE_USB) +AudioConnection patchCord32(volume_r, 0, usb1, 0); +AudioConnection patchCord33(volume_l, 0, usb1, 1); #endif -#if defined(TEENSY_AUDIO_BOARD) +#if defined(TEENSY_AUDIO_BOARD) || defined (I2S_AUDIO_ONLY) AudioOutputI2S i2s1; -AudioConnection patchCord36(volume_r, 0, i2s1, 0); -AudioConnection patchCord37(volume_l, 0, i2s1, 1); +AudioConnection patchCord34(volume_r, 0, i2s1, 0); +AudioConnection patchCord35(volume_l, 0, i2s1, 1); +#endif +#if defined(TEENSY_AUDIO_BOARD) AudioControlSGTL5000 sgtl5000_1; #elif defined(TGA_AUDIO_BOARD) AudioOutputI2S i2s1; -AudioConnection patchCord36(volume_r, 0, i2s1, 0); -AudioConnection patchCord37(volume_l, 0, i2s1, 1); +AudioConnection patchCord34(volume_r, 0, i2s1, 0); +AudioConnection patchCord35(volume_l, 0, i2s1, 1); AudioControlWM8731master wm8731_1; -#else +#elif !defined(I2S_AUDIO_ONLY) AudioOutputPT8211 pt8211_1; -AudioConnection patchCord36(volume_r, 0, pt8211_1, 0); -AudioConnection patchCord37(volume_l, 0, pt8211_1, 1); +AudioConnection patchCord34(volume_r, 0, pt8211_1, 0); +AudioConnection patchCord35(volume_l, 0, pt8211_1, 1); #endif Dexed* dexed = new Dexed(SAMPLE_RATE); @@ -165,42 +166,25 @@ short r_delayline[MOD_DELAY_SAMPLE_BUFFER]; /*********************************************************************** LCDMenuLib2 ***********************************************************************/ -extern LiquidCrystalPlus_I2C lcd; extern LCDMenuLib2 LCDML; extern uint8_t menu_state; #endif +void change_disp_sd(bool disp) +{ + digitalWrite(SDCARD_CS_PIN, disp); + digitalWrite(U8X8_CS_PIN, !disp); +} + void setup() { //while (!Serial) ; // wait for Arduino Serial Monitor Serial.begin(SERIAL_SPEED); - + pinMode(SDCARD_CS_PIN, OUTPUT); + pinMode(U8X8_CS_PIN, OUTPUT); + #ifdef ENABLE_LCD_UI - // LCD Begin - lcd.init(); - lcd.backlight(); - lcd.clear(); - lcd.blink_off(); - lcd.cursor_off(); - lcd.backlight(); - lcd.setCursor(1, 0); - lcd.print("MicroDexed"); - lcd.setCursor(0, 1); - lcd.print("(c)parasiTstudio"); - - // set special chars for scrollbar - lcd.createChar(0, (uint8_t*)scroll_bar[0]); - lcd.createChar(1, (uint8_t*)scroll_bar[1]); - lcd.createChar(2, (uint8_t*)scroll_bar[2]); - lcd.createChar(3, (uint8_t*)scroll_bar[3]); - lcd.createChar(4, (uint8_t*)scroll_bar[4]); - - // LCDMenuLib Setup - LCDML_setup(_LCDML_DISP_cnt); - // Enable Menu Rollover - //LCDML.MENU_enRollover(); - // Enable Screensaver (screensaver menu function, time to activate in ms) - //LCDML.SCREEN_enable(UI_func_voice_selection, VOICE_SELECTION_MS); // set to 10 seconds + setup_ui(); #else Serial.println(F("NO LCD DISPLAY ENABLED!")); #endif @@ -255,13 +239,18 @@ void setup() wm8731_1.enable(); wm8731_1.volume(1.0); Serial.println(F("TGA board enabled.")); +#elif defined(I2S_AUDIO_ONLY) + Serial.println(F("I2S enabled.")); #else Serial.println(F("PT8211 enabled.")); #endif // start SD card +#ifndef __IMXRT1062__ SPI.setMOSI(SDCARD_MOSI_PIN); SPI.setSCK(SDCARD_SCK_PIN); +#endif + change_disp_sd(false); if (!SD.begin(SDCARD_CS_PIN)) { Serial.println(F("SD card not accessable.")); @@ -300,7 +289,7 @@ void setup() // load default SYSEX data load_sysex(configuration.bank, configuration.voice); } - + change_disp_sd(true); // Init effects if (!modchorus_r.begin(r_delayline, MOD_DELAY_SAMPLE_BUFFER)) { Serial.println(F("AudioEffectModulatedDelay - right channel begin failed")); @@ -443,6 +432,7 @@ void loop() { #ifdef ENABLE_LCD_UI // LCD Menu + delay(1); LCDML.loop(); // initial starts voice selection menu as default @@ -637,7 +627,9 @@ void handleProgramChange(byte inChannel, byte inProgram) { if (inProgram < MAX_VOICES) { + change_disp_sd(false); load_sysex(configuration.bank, inProgram); + change_disp_sd(true); } } diff --git a/SSD1322_Plus.h b/SSD1322_Plus.h new file mode 100644 index 0000000..2e20160 --- /dev/null +++ b/SSD1322_Plus.h @@ -0,0 +1,98 @@ +/* + 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 + + +#ifndef SSD1322_PLUS_H_INCLUDED +#define SSD1322_PLUS_H_INCLUDED + +#ifdef U8X8_HAVE_HW_SPI +#include +#endif +#ifdef U8X8_HAVE_HW_I2C +#include +#endif + + +#define STRING_BUF_SIZE 21 + +class SSD1322_Plus : public U8X8_SSD1322_NHD_256X64_4W_HW_SPI +{ + public: + + using U8X8_SSD1322_NHD_256X64_4W_HW_SPI::U8X8_SSD1322_NHD_256X64_4W_HW_SPI; + + void show(uint8_t y, uint8_t x, uint8_t fs, char *str) + { + _show(y, x, fs, str, false, false); + } + + void show(uint8_t y, uint8_t x, uint8_t fs, long num) + { + char _buf10[STRING_BUF_SIZE]; + + _show(y, x, fs, itoa(num, _buf10, 10), true, true); + } + + private: + void _show(uint8_t pos_y, uint8_t pos_x, uint8_t field_size, char *str, bool justify_right, bool fill_zero) + { + { + char tmp[STRING_BUF_SIZE]; + char *s = tmp; + uint8_t l = strlen(str); + + memset(tmp, 0, sizeof(tmp)); + if (fill_zero == true) + memset(tmp, '0', field_size); + else + memset(tmp, 0x20, field_size - 1); // blank + + if (l > field_size) + l = field_size; + + if (justify_right == true) + s += field_size - l; + + strncpy(s, str, l); + + //setCursor(pos_x * getMaxCharWidth(), pos_y * getMaxCharHeight()); + setCursor(pos_x, pos_y ); + print(tmp); + +#ifdef DEBUG + Serial.print(pos_y, DEC); + Serial.print(F("/")); + Serial.print(pos_x, DEC); + Serial.print(F(": [")); + Serial.print(tmp); + Serial.println(F("]")); +#endif + } + } +}; + +#endif diff --git a/UI.hpp b/UI.hpp index 11cbef7..bda5f9e 100644 --- a/UI.hpp +++ b/UI.hpp @@ -27,14 +27,23 @@ #define _UI_HPP_ #include "config.h" +#ifdef I2C_DISPLAY #include "LiquidCrystalPlus_I2C.h" +#endif +#ifdef U8X8_DISPLAY +#include "SSD1322_Plus.h" +#endif #include #include #define _LCDML_DISP_cols LCD_cols #define _LCDML_DISP_rows LCD_rows +#ifdef I2C_DISPLAY #define _LCDML_DISP_cfg_cursor 0x7E // cursor Symbol +#else +#define _LCDML_DISP_cfg_cursor 0x8d // cursor Symbol +#endif #define _LCDML_DISP_cfg_scrollbar 1 // enable a scrollbar extern config_t configuration; @@ -47,6 +56,7 @@ extern void strip_extension(char* s, char *target); extern void eeprom_write(void); extern bool get_voice_names_from_bank(uint8_t b); extern bool load_sysex(uint8_t b, uint8_t v); +extern void change_disp_sd(bool d); extern value_change_t soften_volume; extern value_change_t soften_filter_res; extern value_change_t soften_filter_cut; @@ -56,7 +66,13 @@ extern value_change_t soften_filter_cut; ************************************************************************/ elapsedMillis back_from_volume; +#ifdef I2C_DISPLAY LiquidCrystalPlus_I2C lcd(LCD_I2C_ADDRESS, _LCDML_DISP_cols, _LCDML_DISP_rows); +#endif + +#ifdef U8X8_DISPLAY +SSD1322_Plus lcd(/* cs=*/ U8X8_CS_PIN, /* dc=*/ U8X8_DC_PIN, /* reset=*/ U8X8_RESET_PIN); +#endif const uint8_t scroll_bar[5][8] = { {B10001, B10001, B10001, B10001, B10001, B10001, B10001, B10001}, // scrollbar top @@ -109,6 +125,7 @@ void UI_func_volume(uint8_t param); void UI_func_back(uint8_t param); void UI_func_goToRootMenu(uint8_t param); + // normal menu LCDMenuLib2_menu LCDML_0(255, 0, 0, NULL, NULL); // normal root menu element (do not change) LCDMenuLib2 LCDML(LCDML_0, _LCDML_DISP_rows, _LCDML_DISP_cols, lcdml_menu_display, lcdml_menu_clear, lcdml_menu_control); @@ -158,6 +175,63 @@ long g_LCDML_CONTROL_button_press_time[NUM_ENCODER] = {0, 0}; bool g_LCDML_CONTROL_button_prev[NUM_ENCODER] = {HIGH, HIGH}; uint8_t g_LCDML_CONTROL_prev[NUM_ENCODER] = {0, 0}; +#ifdef U8X8_DISPLAY +const uint8_t * flipped_scroll_bar[5]; + +uint8_t * rotTile(const uint8_t * tile) { + uint8_t * newt = new uint8_t[8]; + for (int x = 0; x < 8; x++) { + uint8_t newb = 0; + for (int y = 0 ; y < 8; y++){ + newb |= (tile[y] << x) & 0x80; + newb >>= 1; + } + newt[x] = newb; + } + return newt; +} +#endif + +void setup_ui(void){ + // LCD Begin +#ifdef I2C_DISPLAY + lcd.init(); + lcd.backlight(); + lcd.clear(); + lcd.blink_off(); + lcd.cursor_off(); + lcd.backlight(); +#else + lcd.begin(); + lcd.clear(); + lcd.setFont(u8x8_font_amstrad_cpc_extended_f); +#endif + lcd.setCursor(1, 0); + lcd.print("MicroDexed"); + lcd.setCursor(0, 1); + lcd.print("(c)parasiTstudio"); + +#ifdef I2C_DISPLAY + // set special chars for scrollbar + lcd.createChar(0, (uint8_t*)scroll_bar[0]); + lcd.createChar(1, (uint8_t*)scroll_bar[1]); + lcd.createChar(2, (uint8_t*)scroll_bar[2]); + lcd.createChar(3, (uint8_t*)scroll_bar[3]); + lcd.createChar(4, (uint8_t*)scroll_bar[4]); +#else + for (int x=0; x < 5; x++) { + flipped_scroll_bar[x] = rotTile(scroll_bar[x]); + } +#endif + +// LCDMenuLib Setup + LCDML_setup(_LCDML_DISP_cnt); + // Enable Menu Rollover + //LCDML.MENU_enRollover(); + // Enable Screensaver (screensaver menu function, time to activate in ms) + //LCDML.SCREEN_enable(UI_func_voice_selection, VOICE_SELECTION_MS); // set to 10 seconds +} + void lcdml_menu_control(void) { // If something must init, put in in the setup condition @@ -326,8 +400,11 @@ void encoder_right_up(void) if (configuration.bank < MAX_BANKS) { configuration.bank++; + change_disp_sd(false); load_sysex(configuration.bank, configuration.voice); get_voice_names_from_bank(configuration.bank); + change_disp_sd(true); + } break; case MENU_VOICE_SOUND: @@ -341,9 +418,12 @@ void encoder_right_up(void) configuration.voice = 0; } } + change_disp_sd(false); load_sysex(configuration.bank, configuration.voice); get_voice_names_from_bank(configuration.bank); + change_disp_sd(true); eeprom_write(); + } UI_func_voice_selection(0); break; @@ -369,8 +449,12 @@ void encoder_right_down(void) if (configuration.bank > 0) { configuration.bank--; + change_disp_sd(false); + load_sysex(configuration.bank, configuration.voice); get_voice_names_from_bank(configuration.bank); + change_disp_sd(true); + } break; case MENU_VOICE_SOUND: @@ -384,8 +468,11 @@ void encoder_right_down(void) configuration.voice = 31; } } + change_disp_sd(false); load_sysex(configuration.bank, configuration.voice); get_voice_names_from_bank(configuration.bank); + change_disp_sd(true); + eeprom_write(); } UI_func_voice_selection(0); @@ -567,8 +654,13 @@ void lcdml_menu_display(void) // delete or reset scrollbar if (_LCDML_DISP_cfg_scrollbar == 1) { if (scrollbar_max > n_max) { +#ifdef I2C_DISPLAY lcd.setCursor((_LCDML_DISP_cols - 1), n); lcd.write((uint8_t)0); +#else + lcd.drawTile((_LCDML_DISP_cols - 1), n, 1, flipped_scroll_bar[0]); + lcd.setCursor((_LCDML_DISP_cols), n+1); +#endif } else { lcd.setCursor((_LCDML_DISP_cols - 1), n); @@ -583,16 +675,31 @@ void lcdml_menu_display(void) //set scroll position if (scrollbar_cur_pos == scrollbar_min) { // min pos +#ifdef I2C_DISPLAY lcd.setCursor((_LCDML_DISP_cols - 1), 0); lcd.write((uint8_t)1); +#else + lcd.drawTile((_LCDML_DISP_cols - 1), 0, 1, flipped_scroll_bar[1]); + lcd.setCursor((_LCDML_DISP_cols), 1); +#endif } else if (scrollbar_cur_pos == (scrollbar_max - 1)) { // max pos +#ifdef I2C_DISPLAY lcd.setCursor((_LCDML_DISP_cols - 1), (n_max - 1)); lcd.write((uint8_t)4); +#else + lcd.drawTile((_LCDML_DISP_cols - 1), (n_max - 1), 1, flipped_scroll_bar[4]); + lcd.setCursor((_LCDML_DISP_cols), (n_max)); +#endif } else { // between +#ifdef I2C_DISPLAY lcd.setCursor((_LCDML_DISP_cols - 1), scroll_pos / n_max); lcd.write((uint8_t)(scroll_pos % n_max) + 1); +#else + lcd.drawTile((_LCDML_DISP_cols - 1), scroll_pos / n_max, 1, flipped_scroll_bar[(scroll_pos % n_max) + 1]); + lcd.setCursor((_LCDML_DISP_cols), (scroll_pos / n_max)+1); +#endif } } }