From 609242b8d7334349e9eb8d63447bf63abb4d80bc Mon Sep 17 00:00:00 2001 From: midilab Date: Wed, 7 Mar 2018 15:24:13 -0300 Subject: [PATCH] Roland TB303 StepSequencer clone first draft notes... --- .../AcidStepSequencer/AcidStepSequencer.ino | 140 ++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 examples/AcidStepSequencer/AcidStepSequencer.ino diff --git a/examples/AcidStepSequencer/AcidStepSequencer.ino b/examples/AcidStepSequencer/AcidStepSequencer.ino new file mode 100644 index 0000000..2d43907 --- /dev/null +++ b/examples/AcidStepSequencer/AcidStepSequencer.ino @@ -0,0 +1,140 @@ +#include "Arduino.h" +#include + +// Sequencer config +#define STEP_MAX_SIZE 16 +#define SEQUENCER_MIN_BPM 50 +#define SEQUENCER_MAX_BPM 178 +#define NOTE_VELOCITY 90 +#define ACCENT_VELOCITY 110 + +// Choose only 1 mode and comment the other. +// OLD_SCHOOL_ACID_ACCENTED +// a button/led extra hardware to control steps velocity using accent only +// NEW_SCHOOL_VELOCITY_CONTROLLED +// a 10k potentiomer extra hardware to freely control steps velocity +#define OLD_SCHOOL_ACID_ACCENTED +#define NEW_SCHOOL_FREE_VELOCITY + +typedef struct +{ + uint8_t note; + uint8_t velocity; + bool accent; + bool glide; + bool rest; +} SEQUENCER_STEP_DATA; + +SEQUENCER_STEP_DATA _sequencer[STEP_MAX_SIZE]; +uint16_t _last_step = 0; + +// MIDI clock, start, stop, note on and note off byte definitions - based on MIDI 1.0 Standards. +#define MIDI_CLOCK 0xF8 +#define MIDI_START 0xFA +#define MIDI_STOP 0xFC +#define NOTE_ON 0x90 +#define NOTE_OFF 0x80 + +void sendMidiMessage(uint8_t command, uint8_t byte1, uint8_t byte2) +{ + // send midi message + Serial.write(command); + Serial.write(byte1); + Serial.write(byte2); +} + +// The callback function wich will be called by uClock each Pulse of 16PPQN clock resolution. +// At this resolution each call represents exactly one step. +void ClockOut16PPQN(uint32_t * tick) +{ + uint16_t step; + + // get actual step. + step = *tick % STEP_MAX_SIZE; + + // send note off for the last step note on if we had send it on last ClockOut16PPQN() call and if this step are not in glide mode also. + if ( _sequencer[_last_step].rest == false && _sequencer[_last_step].glide == false ) { + sendMidiMessage(NOTE_OFF, _sequencer[_last_step].note, 0); + } + + // send note on only if this step are not in rest mode + if ( _sequencer[step].rest == false ) { + sendMidiMessage(NOTE_ON, _sequencer[step].note, _sequencer[step].velocity); + } + + // time to let glide go away? be shure to send glided note off before the _last_step send his note off + // same note? do not send note off + if ( _sequencer[_last_step].glide == true && _sequencer[step].note != _sequencer[_last_step].note ) { + sendMidiMessage(NOTE_OFF, _sequencer[_last_step].note, 0); + } + + _last_step = step; +} + +// The callback function wich will be called by uClock each Pulse of 96PPQN clock resolution. +void ClockOut96PPQN(uint32_t * tick) +{ + // Send MIDI_CLOCK to external gears + Serial.write(MIDI_CLOCK); +} + +// The callback function wich will be called when clock starts by using Clock.start() method. +void onClockStart() +{ + Serial.write(MIDI_START); +} + +// The callback function wich will be called when clock stops by using Clock.stop() method. +void onClockStop() +{ + Serial.write(MIDI_STOP); +} + +void setup() +{ + // Initialize serial communication at 31250 bits per second, the default MIDI serial speed communication: + Serial.begin(31250); + + // Inits the clock + uClock.init(); + + // Set the callback function for the clock output to send MIDI Sync message. + uClock.setClock96PPQNOutput(ClockOut96PPQN); + + // Set the callback function for the step sequencer on 16ppqn + uClock.setClock16PPQNOutput(ClockOut16PPQN); + + // Set the callback function for MIDI Start and Stop messages. + uClock.setOnClockStartOutput(onClockStart); + uClock.setOnClockStopOutput(onClockStop); + + // Set the clock BPM to 126 BPM + uClock.setTempo(126); + + // initing sequencer data + for ( uint16_t i = 0; i < STEP_MAX_SIZE; i++ ) { + _sequencer[i].note = 36; + _sequencer[i].velocity = NOTE_VELOCITY; + _sequencer[i].accent = false; + _sequencer[i].glide = false; + _sequencer[i].rest = false; + } + + // Starts the clock, tick-tac-tick-tac... + uClock.start(); +} + +// User interaction goes here +void loop() +{ + // octave pot + // note pot + // tempo pot + // pattern step init pot + // pattern step size pot + // previous step button + // next step button + // rest button/led + // glide button/led + // accent button/led +}