#include <M5Unified.h>
#include "M5UnitSynth.h"
M5UnitSynth synth;
static const uint8_t MELODY_CHANNEL = 0;
static const uint8_t DRUM_CHANNEL = 9;
void showStatus(const char* stage, const char* detail = nullptr) {
M5.Display.fillScreen(TFT_BLACK);
M5.Display.setTextColor(TFT_WHITE, TFT_BLACK);
M5.Display.setTextSize(2);
M5.Display.setCursor(8, 8);
M5.Display.println("Unit Synth Test");
M5.Display.drawFastHLine(8, 32, M5.Display.width() - 16, TFT_DARKGREY);
M5.Display.setCursor(8, 48);
M5.Display.setTextColor(TFT_CYAN, TFT_BLACK);
M5.Display.println(stage);
if (detail != nullptr) {
M5.Display.setCursor(8, 82);
M5.Display.setTextColor(TFT_WHITE, TFT_BLACK);
M5.Display.println(detail);
}
}
void playNote(uint8_t channel, uint8_t pitch, uint8_t velocity,
uint16_t durationMs) {
if (pitch == REST) {
delay(durationMs);
return;
}
synth.setNoteOn(channel, pitch, velocity);
delay(durationMs);
synth.setNoteOff(channel, pitch, 0);
}
void playScale() {
const uint8_t scale[] = {NOTE_C4, NOTE_D4, NOTE_E4, NOTE_F4,
NOTE_G4, NOTE_A4, NOTE_B4, NOTE_C5};
for (uint8_t i = 0; i < sizeof(scale); ++i) {
playNote(MELODY_CHANNEL, scale[i], 100, 180);
}
}
void playChord() {
synth.setNoteOn(MELODY_CHANNEL, NOTE_C4, 90);
synth.setNoteOn(MELODY_CHANNEL, NOTE_E4, 90);
synth.setNoteOn(MELODY_CHANNEL, NOTE_G4, 90);
delay(600);
synth.setNoteOff(MELODY_CHANNEL, NOTE_C4, 0);
synth.setNoteOff(MELODY_CHANNEL, NOTE_E4, 0);
synth.setNoteOff(MELODY_CHANNEL, NOTE_G4, 0);
}
void playDrumPattern() {
synth.setInstrument(0, DRUM_CHANNEL, SynthDrum);
for (uint8_t beat = 0; beat < 8; ++beat) {
synth.setNoteOn(DRUM_CHANNEL, 36, 120);
synth.setNoteOn(DRUM_CHANNEL, 42, 90);
if ((beat & 0x03) == 2) {
synth.setNoteOn(DRUM_CHANNEL, 38, 110);
}
delay(180);
}
synth.setAllNotesOff(DRUM_CHANNEL);
}
void configureVoice() {
synth.setInstrument(0, MELODY_CHANNEL, ElGrdPiano_3);
synth.setVolume(MELODY_CHANNEL, 105);
synth.setPan(MELODY_CHANNEL, 64);
synth.setReverb(MELODY_CHANNEL, 1, 55, 20);
synth.setChorus(MELODY_CHANNEL, 1, 35, 18, 12);
synth.setEqualizer(MELODY_CHANNEL,
64,
60,
68,
64,
45,
55,
70,
80);
synth.setTuning(MELODY_CHANNEL, 64, 64);
synth.setVibrate(MELODY_CHANNEL, 45, 30, 10);
synth.setTvf(MELODY_CHANNEL, 90, 35);
synth.setEnvelope(MELODY_CHANNEL, 20, 75, 45);
synth.setPitchBendRange(MELODY_CHANNEL, 2);
synth.setMasterVolume(110);
}
void demonstrateVoiceShape() {
synth.setInstrument(0, MELODY_CHANNEL, Lead2Sawtooth);
synth.setVolume(MELODY_CHANNEL, 110);
synth.setPan(MELODY_CHANNEL, 64);
synth.setTvf(MELODY_CHANNEL, 48, 100);
synth.setEnvelope(MELODY_CHANNEL, 70, 45, 90);
synth.setVibrate(MELODY_CHANNEL, 80, 85, 8);
playNote(MELODY_CHANNEL, NOTE_C4, 105, 850);
playNote(MELODY_CHANNEL, NOTE_G4, 105, 850);
synth.setTvf(MELODY_CHANNEL, 115, 35);
synth.setEnvelope(MELODY_CHANNEL, 10, 85, 35);
playNote(MELODY_CHANNEL, NOTE_C5, 105, 850);
}
void demonstrateEffects() {
synth.setInstrument(0, MELODY_CHANNEL, StringEnsemble1);
synth.setVolume(MELODY_CHANNEL, 115);
synth.setReverb(MELODY_CHANNEL, 1, 110, 70);
synth.setChorus(MELODY_CHANNEL, 1, 100, 70, 50);
synth.setEqualizer(MELODY_CHANNEL, 95, 45, 75, 90, 35, 55, 80, 100);
synth.setNoteOn(MELODY_CHANNEL, NOTE_C4, 95);
synth.setNoteOn(MELODY_CHANNEL, NOTE_E4, 95);
synth.setNoteOn(MELODY_CHANNEL, NOTE_G4, 95);
delay(900);
synth.setNoteOff(MELODY_CHANNEL, NOTE_C4, 0);
synth.setNoteOff(MELODY_CHANNEL, NOTE_E4, 0);
synth.setNoteOff(MELODY_CHANNEL, NOTE_G4, 0);
delay(1200);
synth.setTuning(MELODY_CHANNEL, 64, 72);
playNote(MELODY_CHANNEL, NOTE_A4, 105, 650);
synth.setTuning(MELODY_CHANNEL, 64, 64);
}
void demonstratePitchBend() {
synth.setNoteOn(MELODY_CHANNEL, NOTE_C4, 110);
synth.setPitchBend(MELODY_CHANNEL, 0);
delay(250);
synth.setPitchBend(MELODY_CHANNEL, 512);
delay(250);
synth.setPitchBend(MELODY_CHANNEL, 1023);
delay(250);
synth.setPitchBend(MELODY_CHANNEL, 512);
synth.setNoteOff(MELODY_CHANNEL, NOTE_C4, 0);
}
void demonstrateModWheel() {
synth.setModWheel(MELODY_CHANNEL,
20,
30,
40,
50,
25,
35,
45);
}
void setup() {
M5.begin();
M5.Display.setTextWrap(true);
showStatus("Starting", "MIDI 31250 baud");
Serial.begin(115200);
Serial.println("M5UnitSynth comprehensive example");
synth.begin(&Serial2, UNIT_SYNTH_BAUD, 18, 17);
}
void loop() {
Serial.printf("\n--- M5UnitSynth demo cycle ---\n");
showStatus("Reset", "Reapply voice settings");
synth.reset();
delay(100);
configureVoice();
demonstrateModWheel();
showStatus("Scale + chord", "Channel 1");
Serial.println("Scale and chord");
playScale();
playChord();
showStatus("Pitch bend", "C4: low -> high");
Serial.println("Pitch bend");
demonstratePitchBend();
showStatus("Voice shaping", "Filter/envelope/vibrato");
Serial.println("Filter, envelope and vibrato");
demonstrateVoiceShape();
showStatus("Effects", "Reverb/chorus/EQ");
Serial.println("Reverb, chorus, equalizer and tuning");
demonstrateEffects();
showStatus("Drums", "Channel 10");
Serial.println("Drums");
synth.setAllInstrumentDrums();
playDrumPattern();
synth.setAllNotesOff(MELODY_CHANNEL);
synth.setAllNotesOff(DRUM_CHANNEL);
showStatus("Complete", "Next cycle in 1.5 s");
delay(1500);
}