#define SEQUENCER_MIN_BPM 50 #define SEQUENCER_MAX_BPM 177 // Ui config #define LOCK_POT_SENSTIVITY 3 // hardware setup to fit different kinda of setups and arduino models #define OCTAVE_POT_PIN A3 #define NOTE_POT_PIN A2 #define STEP_LENGTH_POT_PIN A1 #define TEMPO_POT_PIN A0 #define PREVIOUS_STEP_BUTTON_PIN 2 #define NEXT_STEP_BUTTON_PIN 3 #define REST_BUTTON_PIN 4 #define GLIDE_BUTTON_PIN 5 #define ACCENT_BUTTON_PIN 6 #define PLAY_STOP_BUTTON_PIN 7 #define PREVIOUS_STEP_LED_PIN 8 #define NEXT_STEP_LED_PIN 9 #define REST_LED_PIN 10 #define GLIDE_LED_PIN 11 #define ACCENT_LED_PIN 12 #define PLAY_STOP_LED_PIN 13 // User Interface data uint16_t _step_edit = 0; uint8_t _last_octave = 3; uint8_t _last_note = 0; uint8_t _bpm_blink_timer = 1; void configureInterface() { // Buttons config // use internal pullup for buttons pinMode(PREVIOUS_STEP_BUTTON_PIN, INPUT_PULLUP); pinMode(NEXT_STEP_BUTTON_PIN, INPUT_PULLUP); pinMode(REST_BUTTON_PIN, INPUT_PULLUP); pinMode(GLIDE_BUTTON_PIN, INPUT_PULLUP); pinMode(ACCENT_BUTTON_PIN, INPUT_PULLUP); pinMode(PLAY_STOP_BUTTON_PIN, INPUT_PULLUP); // Leds config pinMode(PREVIOUS_STEP_LED_PIN, OUTPUT); pinMode(NEXT_STEP_LED_PIN, OUTPUT); pinMode(REST_LED_PIN, OUTPUT); pinMode(GLIDE_LED_PIN, OUTPUT); pinMode(ACCENT_LED_PIN, OUTPUT); pinMode(PLAY_STOP_LED_PIN, OUTPUT); digitalWrite(PREVIOUS_STEP_LED_PIN, LOW); digitalWrite(NEXT_STEP_LED_PIN, LOW); digitalWrite(REST_LED_PIN, LOW); digitalWrite(GLIDE_LED_PIN, LOW); digitalWrite(ACCENT_LED_PIN, LOW); digitalWrite(PLAY_STOP_LED_PIN, LOW); // getting first value state pressed(PREVIOUS_STEP_BUTTON_PIN); pressed(NEXT_STEP_BUTTON_PIN); pressed(REST_BUTTON_PIN); pressed(GLIDE_BUTTON_PIN); pressed(ACCENT_BUTTON_PIN); pressed(PLAY_STOP_BUTTON_PIN); // getting first values getPotChanges(OCTAVE_POT_PIN, 0, 10); getPotChanges(NOTE_POT_PIN, 0, 11); getPotChanges(STEP_LENGTH_POT_PIN, 1, STEP_MAX_SIZE); getPotChanges(TEMPO_POT_PIN, SEQUENCER_MIN_BPM, SEQUENCER_MAX_BPM); lockPotsState(true); //acidRandomize(); } void processInterface() { processButtons(); processLeds(); processPots(); } void tempoInterface(uint32_t * tick) { // BPM led indicator if ( !(*tick % (96)) || (*tick == 0) ) { // first compass step will flash longer _bpm_blink_timer = 8; digitalWrite(PLAY_STOP_LED_PIN , HIGH); } else if ( !(*tick % (24)) ) { // each quarter led on digitalWrite(PLAY_STOP_LED_PIN , HIGH); } else if ( !(*tick % _bpm_blink_timer) ) { // get led off digitalWrite(PLAY_STOP_LED_PIN , LOW); _bpm_blink_timer = 1; } } void sendPreviewNote(uint16_t step) { unsigned long milliTime, preMilliTime; sendMidiMessage(NOTE_ON, _sequencer[step].note, _sequencer[step].accent ? ACCENT_VELOCITY : NOTE_VELOCITY); // avoid delay() call because of uClock timmer1 usage //delay(200); preMilliTime = millis(); while ( true ) { milliTime = millis(); if (abs(milliTime - preMilliTime) >= 200) { break; } } sendMidiMessage(NOTE_OFF, _sequencer[step].note, 0); } void processPots() { static int8_t octave, note, step_note; static int16_t tempo, step_length; octave = getPotChanges(OCTAVE_POT_PIN, 0, 10); if ( octave != -1 ) { _last_octave = octave; } note = getPotChanges(NOTE_POT_PIN, 0, 11); if ( note != -1 ) { _last_note = note; } // changes on octave or note pot? if ( octave != -1 || note != -1 ) { ATOMIC(_sequencer[_step_edit].note = (_last_octave * 8) + _last_note); if ( _playing == false && _sequencer[_step_edit].rest == false ) { sendPreviewNote(_step_edit); } } step_length = getPotChanges(STEP_LENGTH_POT_PIN, 1, STEP_MAX_SIZE); if ( step_length != -1 ) { ATOMIC(_step_length = step_length); if ( _step_edit >= _step_length ) { _step_edit = _step_length-1; } } tempo = getPotChanges(TEMPO_POT_PIN, SEQUENCER_MIN_BPM, SEQUENCER_MAX_BPM); if ( tempo != -1 ) { //uClock.setTempo(tempo); } } void processButtons() { // play/stop if ( pressed(PLAY_STOP_BUTTON_PIN) ) { if ( _playing == false ) { // Starts the clock, tick-tac-tick-tac... uClock.start(); } else { // stop the clock uClock.stop(); } } // ramdom test //if ( pressed(PREVIOUS_STEP_BUTTON_PIN) && pressed(NEXT_STEP_BUTTON_PIN) ) { //acidRandomize(); //return; //} // previous step edit if ( pressed(PREVIOUS_STEP_BUTTON_PIN) ) { if ( _step_edit != 0 ) { // add a lock here for octave and note to not mess with edit mode when moving steps around lockPotsState(true); --_step_edit; } else { // TODO: just for tests.. take this guy off here and put it on second page acidRandomize(); } if ( _playing == false && _sequencer[_step_edit].rest == false ) { sendPreviewNote(_step_edit); } } // next step edit if ( pressed(NEXT_STEP_BUTTON_PIN) ) { if ( _step_edit < _step_length-1 ) { // add a lock here for octave and note to not mess with edit mode when moving steps around lockPotsState(true); ++_step_edit; } if ( _playing == false && _sequencer[_step_edit].rest == false ) { sendPreviewNote(_step_edit); } } // step rest if ( pressed(REST_BUTTON_PIN) ) { ATOMIC(_sequencer[_step_edit].rest = !_sequencer[_step_edit].rest); if ( _playing == false && _sequencer[_step_edit].rest == false ) { sendPreviewNote(_step_edit); } } // step glide if ( pressed(GLIDE_BUTTON_PIN) ) { ATOMIC(_sequencer[_step_edit].glide = !_sequencer[_step_edit].glide); } // step accent if ( pressed(ACCENT_BUTTON_PIN) ) { ATOMIC(_sequencer[_step_edit].accent = !_sequencer[_step_edit].accent); if ( _playing == false && _sequencer[_step_edit].rest == false ) { sendPreviewNote(_step_edit); } } } void processLeds() { // Editing First Step? if ( _step_edit == 0 ) { digitalWrite(PREVIOUS_STEP_LED_PIN , HIGH); } else { digitalWrite(PREVIOUS_STEP_LED_PIN , LOW); } // Editing Last Step? if ( _step_edit == _step_length-1 ) { digitalWrite(NEXT_STEP_LED_PIN , HIGH); } else { digitalWrite(NEXT_STEP_LED_PIN , LOW); } // Rest if ( _sequencer[_step_edit].rest == true ) { digitalWrite(REST_LED_PIN , HIGH); } else { digitalWrite(REST_LED_PIN , LOW); } // Glide if ( _sequencer[_step_edit].glide == true ) { digitalWrite(GLIDE_LED_PIN , HIGH); } else { digitalWrite(GLIDE_LED_PIN , LOW); } // Accent if ( _sequencer[_step_edit].accent == true ) { digitalWrite(ACCENT_LED_PIN , HIGH); } else { digitalWrite(ACCENT_LED_PIN , LOW); } // shut down play led if we are stoped if ( _playing == false ) { digitalWrite(PLAY_STOP_LED_PIN , LOW); } } void acidRandomize() { // ramdom it all for ( uint16_t i = 0; i < STEP_MAX_SIZE; i++ ) { ATOMIC(_sequencer[i].note = random(36, 70)); // octave 2 to 4. octave 3 to 5 (40 - 83) ATOMIC(_sequencer[i].accent = random(0, 2)); ATOMIC(_sequencer[i].glide = random(0, 2)); ATOMIC(_sequencer[i].rest = random(0, 1)); } }