├── .gitignore ├── LICENSE ├── README.md └── ardrando ├── README.md ├── ardrando.fz ├── ardrando.ino ├── panel.png └── schematic.png /.gitignore: -------------------------------------------------------------------------------- 1 | *DS_Store 2 | *~ 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2020 tensiontides 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 4 | 5 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 6 | 7 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | 9 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Eurorack Arduino Modules 2 | 3 | ## License and Contribution 4 | All code is released under the BSD-2-Clause License. As such, I take no responsibility for any objects, expensive modules, or people harmed due to advice given here. 5 | 6 | Please submit Issues if you have any concerns, complaints, or requests. Pull requests are welcome! 7 | 8 | ## Project 1: Ardrando, a quantized random sequence generator 9 | Ardrando uses an Arduino nano and a cheap DAC to create a 3hp random sequence generator. See the `README` for more info. 10 | -------------------------------------------------------------------------------- /ardrando/README.md: -------------------------------------------------------------------------------- 1 | # Ardrando: Simple Arduino Turing-style Quantized Random Sequence Generator 2 | 3 | 4 | ## Parts 5 | ### Electrical Components 6 | - Arduino Nano 7 | - MCP4725 8 | - Optional: Power filtering caps 9 | - 3x 100k pots 10 | - 3x 3mm LEDs 11 | - 1x toggle switch 12 | - 1x momentary button 13 | - 3x 3.5mm mono jacks 14 | - Resistors 15 | - 1x 8.2K 16 | - 1x 5.6K 17 | - 3x 220R 18 | 19 | ### Panel 20 | 3D printed panel from Chris Spitale 21 | - https://www.thingiverse.com/thing:3564365 22 | 23 | 24 | ## Usage 25 | 26 | When the toggle is up, it uses an internal clock. When toggle is down, `CLOCKIN` waits for trigger to emit notes. `v/O` outputs quantized notes CV 0-5V. `GATE` outputs 5V gate signal. 27 | 28 | ### Normal 29 | 30 | - Knob 1: _random_. Full clockwise locks the sequence, full counter-clockwise randomizes the sequence. 31 | - Knob 2: _scale_. Clockwise narrows the range of the sequence, counter-clockwise widens it. 32 | - Knob 3: _sequence length_. Set sequence length 1 - 16. 33 | 34 | ### When Shift button is pressed 35 | 36 | #### Held for 2 seconds 37 | - Knob 1: Set quantization scale 1-8: 1=octaves, 2=octaves and fifths, 3=major, 4=minor, 5=relminor, 6=7th, (default)=all semitones) 38 | - Knob 2: Change BPM (internal mode only) 39 | - Knob 3: Change note length 40 | 41 | #### Held for 4 seconds 42 | Sequence is reset 43 | 44 | #### Held for 8 seconds 45 | Arduino is reset 46 | 47 | ## Schematic and Pictures 48 | 49 | ![Schematic](schematic.png) 50 | ![Panel](panel.png) 51 | -------------------------------------------------------------------------------- /ardrando/ardrando.ino: -------------------------------------------------------------------------------- 1 | /// Title: Ardrando 2 | // VERSION: 3.1 3 | boolean DEBUG = 0; 4 | boolean NOTEDEBUG = 0; 5 | boolean KEYDEBUG = 0 ; // this gives details about all the keys pressed at any given moment 6 | #include 7 | //-------------------- Ins and outs ------------------------- 8 | // ---------------------- ANALOG 9 | 10 | #define clock_in A1 // analog clock input 11 | #define SDA_pin A4 // non-negotiable, see pinout 12 | #define SCL_pin A5 // non-negotiable, see pinout 13 | // analog inputs for pots 1-4 Shift | Normal 14 | // -------------|--------------- 15 | #define pot1 A3 // quant scale | Random lock 16 | #define pot2 A6 // bpm | Random Scale 17 | #define pot3 A7 // note length | Sequence length 18 | 19 | // ---------------------- DIGITAL 20 | #define gateOutPin 5 // uses PWM out 21 | #define led_red 2 22 | #define led_blue 3 23 | #define led_green 4 24 | #define seqPin 6 25 | #define MCP4725 0x60 //MCP4725 address as 0x61 Change yours accordingly; see http://henrysbench.capnfatz.com/henrys-bench/arduino-projects-tips-and-more/arduino-quick-tip-find-your-i2c-address/ 26 | 27 | //These are the valid values for scales 28 | // paste0(sort(c(c((0:8 * 12) + 0), c((0:8 * 12) + 5))), collapse=", ") 29 | uint8_t scale1[9] = {0, 12, 24, 36, 48, 60, 72, 84, 96}; 30 | uint8_t scale2[18] = {0, 7, 12, 19, 24, 31, 36, 43, 48, 31 | 55, 60, 67, 72, 79, 84, 91, 96, 103 32 | }; 33 | uint8_t scale3[27] = {0, 2, 7, 12, 14, 19, 24, 26, 31, 34 | 36, 38, 43, 48, 50, 55, 60, 62, 67, 35 | 72, 74, 79, 84, 86, 91, 96, 98, 103 36 | }; 37 | uint8_t scale4[27] = {0, 5, 7, 12, 17, 19, 24, 29, 31, 38 | 36, 41, 43, 48, 53, 55, 60, 65, 67, 39 | 72, 77, 79, 84, 89, 91, 96, 101, 103 40 | }; 41 | uint8_t scale5[27] = {0, 4, 7, 12, 16, 19, 24, 28, 31, 42 | 36, 40, 43, 48, 52, 55, 60, 64, 67, 43 | 72, 76, 79, 84, 88, 91, 96, 100, 103 44 | }; 45 | uint8_t scale6[36] = {0, 5, 7, 9, 12, 17, 19, 21, 24, 46 | 29, 31, 33, 36, 41, 43, 45, 48, 53, 47 | 55, 57, 60, 65, 67, 69, 72, 77, 79, 48 | 81, 84, 89, 91, 93, 96, 101, 103, 105 49 | }; 50 | uint8_t scale7[36] = {0, 5, 7, 10, 12, 17, 19, 22, 24, 51 | 29, 31, 34, 36, 41, 43, 46, 48, 53, 52 | 55, 58, 60, 65, 67, 70, 72, 77, 79, 53 | 82, 84, 89, 91, 94, 96, 101, 103, 106 54 | }; 55 | uint8_t scale8[128] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 56 | 10, 11, 12, 13, 14, 15, 16, 17, 18, 57 | 19, 20, 21, 22, 23, 24, 25, 26, 27, 58 | 28, 29, 30, 31, 32, 33, 34, 35, 36, 59 | 37, 38, 39, 40, 41, 42, 43, 44, 45, 60 | 46, 47, 48, 49, 50, 51, 52, 53, 54, 61 | 55, 56, 57, 58, 59, 60, 61, 62, 63, 62 | 64, 65, 66, 67, 68, 69, 70, 71, 72, 63 | 73, 74, 75, 76, 77, 78, 79, 80, 81, 64 | 82, 83, 84, 85, 86, 87, 88, 89, 90, 65 | 91, 92, 93, 94, 95, 96, 97, 98, 99, 66 | 100, 101, 102, 103, 104, 105, 106, 107, 108, 67 | 109, 110, 111, 112, 113, 114, 115, 116, 117, 68 | 118, 119, 120, 121, 122, 123, 124, 125, 126, 69 | 127, 128 70 | }; 71 | // digital input for shift button 72 | int shift = 7; 73 | 74 | // needed for toggle cause it is conductive 75 | unsigned long lastDebounceTime = 0; // the last time the output pin was toggled 76 | unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers 77 | 78 | 79 | //-------------------- Midi/key defaults ------------------------- 80 | 81 | int vel = 87; // default velocity 82 | int notes = 128; 83 | 84 | byte buffer[3]; // for dac 85 | 86 | // ------------- Variables for the sequencer ------------------- 87 | uint8_t def_sequencer_steps[16] = {60, 67, 72, 79, 84, 79, 72, 67, 60, 55, 48, 43, 36, 43, 48, 55}; 88 | //uint8_t def_sequencer_steps[16] = {36, 48, 60, 72, 84, 96, 36, 48, 60, 72, 84, 96, 36, 48, 60, 72 }; 89 | uint8_t sequencer_steps[16] ; 90 | float sequencer_lens[16]; 91 | uint8_t seq_counter; 92 | uint8_t seq_length; 93 | boolean seq_running ; 94 | boolean gate_is_high ; 95 | uint8_t thisscale[128]; 96 | uint8_t thisscaleid = 8; 97 | uint8_t thisscalelen = 128; 98 | // you could just take the counter - 1 of the seuqencer to get the last note, but what if the seqeunce changes? 99 | int prev_note; 100 | int base; 101 | 102 | // ------------------ Clock stuff 103 | // These keep track of the toggle state, debounced 104 | int internal_clock ; // int, ext midi, ext cv 105 | int this_clock_state ; 106 | int last_clock_state ; // int, ext midi, ext cv, save this for debouncing 107 | 108 | // internal clock 109 | unsigned long time_next_note; //needs to be unsigned for millis() comparison 110 | unsigned long time_prev_note; 111 | unsigned long time_to_restart; 112 | unsigned long time_to_reset_seq; 113 | unsigned long time_to_reset_bpm; 114 | boolean shift_already = false; 115 | boolean already_reset_seq = false; 116 | boolean already_reset_bpm = false; 117 | int time_between_quarter_notes; 118 | int bpm = 120; 119 | 120 | 121 | 122 | // For Turing Functions 123 | int random_scale; 124 | int random_amt; 125 | int random_rest; 126 | // function declarations 127 | void sequencer_mode(); 128 | void edit_mode(); 129 | void update_key(int i, int val); 130 | void noteOn(int pitch, int velocity); 131 | void noteOff(int pitch, int velocity); 132 | 133 | void process_shift_change(); 134 | void setSequence(); 135 | void toggleSequencer(); 136 | void toggleClock(); 137 | void success_leds(); 138 | void waiting_leds(); 139 | void set_time_between_quarter_notes(float bpm); 140 | void update_param(int button, int param = 0); 141 | 142 | int process_pot(int a_input); 143 | float noteToVolt(int note); 144 | void read_seq_and_params(); 145 | void vpoOut(unsigned int pitch); 146 | void gateOut(unsigned int state); 147 | 148 | void check_pots(); 149 | 150 | // restart function 151 | void(* resetFunc) (void) = 0; 152 | 153 | void setup() { 154 | Wire.begin(); //Begins the I2C communication 155 | time_prev_note = 0; 156 | pinMode(led_red, OUTPUT); 157 | pinMode(led_blue, OUTPUT); 158 | pinMode(led_green, OUTPUT); 159 | pinMode(gateOutPin, OUTPUT); 160 | 161 | pinMode(pot1, INPUT); 162 | pinMode(pot2, INPUT); 163 | pinMode(pot3, INPUT); 164 | pinMode(seqPin, INPUT_PULLUP); 165 | pinMode(shift, INPUT_PULLUP); 166 | 167 | digitalWrite(led_red, LOW); 168 | digitalWrite(led_blue, LOW); 169 | digitalWrite(led_green, LOW); 170 | digitalWrite(gateOutPin, LOW); 171 | internal_clock = digitalRead(seqPin); 172 | last_clock_state = internal_clock ; 173 | 174 | // ------------- Variables for the sequencer ------------------- 175 | // these are in the setup() because we want to be able to reset the seqeunce when the unit is reset 176 | for (int k = 0; k < 16; k++) { 177 | sequencer_steps[k] = def_sequencer_steps[k]; 178 | sequencer_lens[k] = .5; 179 | } 180 | for (int k = 0; k < thisscalelen; k++) { 181 | thisscale[k] = scale8[k]; 182 | } 183 | seq_counter = 0; 184 | seq_length = 16; 185 | seq_running = false; 186 | gate_is_high = false; 187 | // you could just take the counter - 1 of the seuqencer to get the last note, but what if the seqeunce changes? 188 | int prev_note; 189 | 190 | vel = 87; // default velocity 191 | notes = 128; 192 | 193 | delay(50); 194 | 195 | if (DEBUG) { 196 | Serial.begin(9600); 197 | Serial.print("setup done\n"); 198 | } else { 199 | Serial.begin(31250); 200 | } 201 | success_leds(); 202 | 203 | } 204 | 205 | 206 | void loop() { 207 | // base note to start on. 208 | base = (12 * 3); 209 | // check_pots() 210 | // start by checking if the shift key is pressed. If so ignore any note changes 211 | // note shift is connected as a pull up, so activated means 0, deactivated means 1 212 | int this_clock_state = digitalRead(seqPin); 213 | if (this_clock_state != last_clock_state) { 214 | lastDebounceTime = millis(); 215 | } 216 | 217 | if ((millis() - lastDebounceTime) > debounceDelay) { 218 | if (this_clock_state != internal_clock) { // still 219 | if (!internal_clock) { 220 | digitalWrite(led_blue, HIGH); 221 | delay(100); 222 | digitalWrite(led_blue, LOW); 223 | delay(50); 224 | digitalWrite(led_red, HIGH); 225 | delay(100); 226 | digitalWrite(led_red, LOW); 227 | delay(50); 228 | digitalWrite(led_green, HIGH); 229 | delay(100); 230 | digitalWrite(led_green, LOW); 231 | delay(50); 232 | digitalWrite(led_red, HIGH); 233 | delay(100); 234 | digitalWrite(led_red, LOW); 235 | internal_clock = 1; 236 | } else { 237 | internal_clock = 0; 238 | } 239 | } 240 | } 241 | 242 | last_clock_state = this_clock_state; 243 | // pause sequencer if you need to 244 | if (digitalRead(shift) == 0 ) { 245 | digitalWrite(led_green, HIGH); 246 | process_shift_change(); 247 | seq_running = false; 248 | } else { 249 | digitalWrite(led_green, LOW); 250 | seq_running = true; 251 | shift_already = false; 252 | already_reset_bpm = false; 253 | already_reset_seq = false; 254 | } 255 | 256 | if (seq_running) { 257 | sequencer_mode(); 258 | } else { 259 | // otheriwse, if shift key is not pressed, 260 | digitalWrite(led_blue, LOW); 261 | } 262 | } 263 | 264 | /* ------------------------------- Main Logic --------------------------- */ 265 | // one of the three following modes is run each time the main loop executes: 266 | // playing the keyboard, running the sequencer, and editing stuff 267 | 268 | 269 | void check_note_length_int() { 270 | if (gate_is_high) { 271 | if (millis() > (time_prev_note - (sequencer_lens[seq_counter] * time_between_quarter_notes))) { 272 | noteOff(prev_note, 0); 273 | } 274 | } 275 | } 276 | void check_note_length_ext() { 277 | if (gate_is_high) { 278 | if (millis() > (time_prev_note - (sequencer_lens[seq_counter] * time_between_quarter_notes))) { 279 | noteOff(prev_note, 0); 280 | } 281 | } 282 | } 283 | void sequencer_mode() { 284 | 285 | // first, check for BPM changes 286 | // next, checks clock mode 287 | // next, checks if enouggh time has ellapsed between notes 288 | 289 | // Serial.print(bpm); 290 | // Serial.print("bpm; "); 291 | // Serial.print(time_between_quarter_notes); 292 | // Serial.print(" ms between nodes;"); 293 | // Serial.print(time_next_note); 294 | // Serial.print(" "); 295 | // Serial.println(millis()); 296 | 297 | 298 | set_time_between_quarter_notes(bpm); 299 | // internal 300 | if (internal_clock) { 301 | time_prev_note = millis(); 302 | 303 | if (millis() > time_next_note) { 304 | // Serial.print(time_prev_note); 305 | // Serial.print(" "); 306 | // Serial.print(time_between_quarter_notes); 307 | // Serial.print(" "); 308 | // Serial.print(time_next_note); 309 | // Serial.print(" "); 310 | // Serial.println(millis()); 311 | play_sequence(); 312 | time_next_note = time_prev_note + time_between_quarter_notes; 313 | } else { 314 | check_note_length_int(); 315 | } 316 | // external cv 317 | } else { 318 | // check for a CV pulse. USA A VOLTAGE DIVIDER TO ATTENUATE INPUT!!! 319 | // also, ignore long pulses: for instance, STARTUP by music thing modular outputs clock triggers for 10MS 320 | // so for safety lets wait for a 5x that (100) 321 | // Serial.print(analogRead(clock_in)); 322 | // Serial.print("\n"); 323 | if (analogRead(clock_in) > 400) { 324 | // Serial.print(time_prev_note); 325 | // Serial.print(" "); 326 | // Serial.println(millis()); 327 | if ((millis() - time_prev_note) > 100) { 328 | // Serial.print("playing note\n"); 329 | time_prev_note = millis(); 330 | play_sequence(); 331 | } 332 | } else { 333 | check_note_length_ext(); 334 | } 335 | } 336 | } 337 | 338 | 339 | //------------------------------- Functions --------------------------------- 340 | int scale_centered_sequence_note(int thisnote, int scaling, int half_scaling) { 341 | // this scales the seqeunced centered around the middle of the keyboard, key 64 342 | // for instace, scale to 1/3 of total notes(42) and the sequence is 48 60 72 343 | // centered around 1 (really 64) this is 48/64 60/64, 72/64 344 | // .75 .9375 1.125 345 | // scaled to 42's center: 21 .75*21 .9375*21 1.125*21 346 | // 15.75 19.6875 23.625 347 | //but thats not centered around the middle of the keyboard, so 348 | // we add the difference between new middle and old middle: 64 - 21 = 43 349 | // New sequence is 58.75 62.6875 66.625 350 | return (ceil(float(thisnote / 64.0) * half_scaling + (64 - half_scaling))); 351 | 352 | } 353 | 354 | int quantize_to_scale(int thisnote, int thisscalelen) { 355 | //Quantize if neccesary: check if the note is in the selected scale. 356 | // If not, increment or decrement closer to center 357 | int quantized = 0; 358 | for (int q = 0; q < thisscalelen; q++) { 359 | if (abs(thisscale[q] - thisnote) < abs(quantized - thisnote)) { 360 | quantized = thisscale[q]; 361 | } 362 | } 363 | return (quantized); 364 | } 365 | void play_sequence() { 366 | int scaling = map(process_pot(pot2), 0, 1023, 1, 128); 367 | int half_scaling = ceil(float(scaling / 2.0)); 368 | if (DEBUG) { 369 | if (seq_counter == 0) { 370 | for (int i = 0 ; i < seq_length; i++) { 371 | Serial.print(sequencer_steps[i]); 372 | Serial.print(" "); 373 | } 374 | Serial.print(" || "); 375 | for (int i = 0 ; i < seq_length; i++) { 376 | Serial.print(scale_centered_sequence_note(sequencer_steps[i], scaling, half_scaling)); 377 | Serial.print(" "); 378 | } 379 | Serial.print(" || "); 380 | for (int i = 0 ; i < seq_length; i++) { 381 | Serial.print(quantize_to_scale(scale_centered_sequence_note(sequencer_steps[i], scaling, half_scaling), thisscalelen)); 382 | Serial.print(" "); 383 | } 384 | Serial.print(thisscaleid); 385 | Serial.println(" "); 386 | } 387 | } 388 | seq_length = round(map(process_pot(pot3), 0, 1023, 1, 16)); 389 | int thisnote = sequencer_steps[seq_counter]; 390 | int thisscalednote = scale_centered_sequence_note(thisnote, scaling, half_scaling); 391 | int quantized = quantize_to_scale(thisscalednote, thisscalelen); 392 | // kill previous note 393 | if (thisnote == 0) { 394 | // this is how we play rests 395 | gateOut(0); 396 | } else { 397 | noteOff(prev_note, 0); 398 | noteOn(quantized, vel); 399 | } 400 | 401 | // increment, resetting counter if need be 402 | seq_counter = seq_counter + 1 ; 403 | if (seq_counter >= seq_length) { 404 | seq_counter = 0; 405 | } 406 | 407 | // turing bit 408 | random_amt = map(process_pot(pot1), 0, 1023, 100, 0); 409 | // decide change note or not 410 | if ( random_amt > random(100)) { 411 | int base = ceil(scaling / 2.0); 412 | int rscale = random(scaling); 413 | //int new_note = thisnote - half_scaling + rscale; // new note is centered around middle 414 | int new_note = thisnote - base + rscale; 415 | if (DEBUG) { 416 | Serial.print("old step "); 417 | 418 | Serial.print(sequencer_steps[seq_counter]); 419 | Serial.print("; new step "); 420 | Serial.print(new_note); 421 | Serial.print("; base "); 422 | Serial.print(base); 423 | Serial.print("; rand "); 424 | Serial.println(rscale); 425 | } 426 | sequencer_steps[seq_counter] = constrain(new_note, 1, 128); 427 | } 428 | } 429 | 430 | 431 | void set_time_between_quarter_notes(float bpm) { 432 | float bps = 60 / bpm ; // beats per second (2 @120) 433 | time_between_quarter_notes = bps * 1000 ; // milliseconds per beat 434 | } 435 | 436 | 437 | int process_pot(int a_input) { 438 | int thisval = analogRead(a_input); 439 | // if (DEBUG) { 440 | // Serial.print("Analog input:"); 441 | // Serial.println(a_input); 442 | // Serial.print(" "); 443 | // Serial.println(thisval); 444 | // } 445 | // TBD 446 | return (thisval); 447 | } 448 | 449 | 450 | /////////////////////////// Functions for CV ///////////////// 451 | int divider = 38; 452 | float noteToVolt(int note) { 453 | // returns value 0-4096 to sent to DAC 454 | // note to freq 455 | // https://en.wikipedia.org/wiki/Piano_key_frequencies 456 | float freq = pow(2, ((note - 49) / 12.0)) * 440 ; 457 | int constr_note = constrain(note, 36, 97); 458 | int mvolts = map(constr_note, 36, 97, 0, 5000) ; // start at A220 459 | float volts = (mvolts / 1000.0); 460 | // if (DEBUG) { 461 | // Serial.print("Freq: "); 462 | // Serial.print(freq); 463 | // Serial.print(" Note: "); 464 | // Serial.print(note); 465 | // Serial.print(" ConstrNote: "); 466 | // Serial.print(constr_note); 467 | // Serial.print(" mVolts: "); 468 | // Serial.print(mvolts); 469 | // Serial.print(" Volts: "); 470 | // Serial.println(volts); 471 | // } 472 | //return (((note - 60.0) / divider) * 4095.0); 473 | return (volts); 474 | } 475 | 476 | void gateOut(unsigned int state) { 477 | if (state == 1) { 478 | digitalWrite(gateOutPin, HIGH); 479 | } else { 480 | digitalWrite(gateOutPin, LOW); 481 | } 482 | } 483 | 484 | void vpoOut(unsigned int pitch) { 485 | buffer[0] = 0b01000000; //Sets the buffer0 with control byte (010-Sets in Write mode) 486 | //Serial.print("ADC:"); 487 | //Serial.println(adc); 488 | int adc = map(noteToVolt(pitch) * 1000, 0, 5000, 0, 4096); 489 | buffer[1] = adc >> 4; //Puts the most significant bit values 490 | buffer[2] = adc << 4; //Puts the Least significant bit values 491 | Wire.beginTransmission(MCP4725); //Joins I2C bus with MCP4725 with 0x61 address 492 | 493 | Wire.write(buffer[0]); //Sends the control byte to I2C 494 | Wire.write(buffer[1]); //Sends the MSB to I2C 495 | Wire.write(buffer[2]); //Sends the LSB to I2C 496 | 497 | Wire.endTransmission(); //Ends the transmission 498 | } 499 | 500 | /////////////////////////// Functions for MIDI ///////////////// 501 | 502 | 503 | void noteOn(int pitch, int velocity) { 504 | digitalWrite(led_red, HIGH); 505 | vpoOut(pitch); 506 | gateOut( 1 ); 507 | gate_is_high = true; 508 | if (NOTEDEBUG) { 509 | Serial.print("on "); 510 | Serial.print(pitch); 511 | Serial.print("\n"); 512 | } 513 | 514 | prev_note = pitch; 515 | } 516 | 517 | void noteOff(int pitch, int velocity) { 518 | digitalWrite(led_red, LOW); 519 | gateOut(0); 520 | gate_is_high = false; 521 | if (NOTEDEBUG) { 522 | Serial.print("off "); 523 | Serial.print(pitch); 524 | Serial.print("\n"); 525 | } 526 | } 527 | 528 | 529 | /////////////////////////////////// Functions for Sequencer, ETC //////////// 530 | void process_shift_change() { 531 | // After 4 seconds, clear the sequence to all Cs 532 | // After 8, reset the arduino 533 | seq_running = false; 534 | if (!shift_already) { 535 | 536 | shift_already = true; 537 | // restart if held for 8 seconds 538 | time_to_restart = millis() + (8 * 1000) ; 539 | time_to_reset_seq = millis() + (4 * 1000) ; 540 | time_to_reset_bpm = millis() + (2 * 1000) ; 541 | } else { 542 | if (time_to_restart < millis()) { 543 | for (int i = 0; i < 4; i ++) { 544 | digitalWrite(led_red, HIGH); 545 | digitalWrite(led_green, HIGH); 546 | digitalWrite(led_blue, HIGH); 547 | delay(200); 548 | digitalWrite(led_red, LOW); 549 | digitalWrite(led_green, LOW); 550 | digitalWrite(led_blue, LOW); 551 | delay(100); 552 | } 553 | resetFunc(); 554 | } else if (time_to_reset_bpm < millis() and not already_reset_bpm) { 555 | bpm = map(process_pot(pot2), 0, 1023, 10, 400); 556 | already_reset_bpm = true; 557 | digitalWrite(led_blue, HIGH); 558 | delay(100); 559 | digitalWrite(led_blue, LOW); 560 | delay(100); 561 | digitalWrite(led_blue, HIGH); 562 | delay(100); 563 | digitalWrite(led_blue, LOW); 564 | thisscaleid = map(process_pot(pot1), 0, 1023, 1, 8); 565 | if (thisscaleid == 1) { 566 | thisscalelen = 9 ; 567 | for (int s = 0; s < thisscalelen; s++) { 568 | thisscale[s] = scale1[s]; 569 | } 570 | } else if (thisscaleid == 2) { 571 | thisscalelen = 18 ; 572 | for (int s = 0; s < thisscalelen; s++) { 573 | thisscale[s] = scale2[s]; 574 | } 575 | } else if (thisscaleid == 3) { 576 | thisscalelen = 27 ; 577 | for (int s = 0; s < thisscalelen; s++) { 578 | thisscale[s] = scale3[s]; 579 | } 580 | } else if (thisscaleid == 4) { 581 | thisscalelen = 27 ; 582 | for (int s = 0; s < thisscalelen; s++) { 583 | thisscale[s] = scale4[s]; 584 | } 585 | } else if (thisscaleid == 5) { 586 | thisscalelen = 27 ; 587 | for (int s = 0; s < thisscalelen; s++) { 588 | thisscale[s] = scale5[s]; 589 | } 590 | } else if (thisscaleid == 6) { 591 | thisscalelen = 36 ; 592 | for (int s = 0; s < thisscalelen; s++) { 593 | thisscale[s] = scale6[s]; 594 | } 595 | } else if (thisscaleid == 7) { 596 | thisscalelen = 36 ; 597 | for (int s = 0; s < thisscalelen; s++) { 598 | thisscale[s] = scale7[s]; 599 | } 600 | } else { 601 | thisscalelen = 128 ; 602 | for (int s = 0; s < thisscalelen; s++) { 603 | thisscale[s] = scale8[s]; 604 | } 605 | } 606 | } else if (time_to_reset_seq < millis() and not already_reset_seq) { 607 | digitalWrite(led_red, HIGH); 608 | delay(100); 609 | digitalWrite(led_red, LOW); 610 | delay(100); 611 | digitalWrite(led_red, HIGH); 612 | delay(100); 613 | digitalWrite(led_red, LOW); 614 | already_reset_seq = true; 615 | for (int k = 0; k < seq_length; k++ ) { 616 | sequencer_steps[k] = 60; 617 | sequencer_lens[k] = .5; 618 | } 619 | } 620 | } 621 | // if (DEBUG) 622 | // Serial.print(thisscaleid); 623 | // Serial.println(" "); 624 | // Serial.println(thisscalelen); 625 | // for (int k = 0; k < seq_length; k++ ) { 626 | // sequencer_lens[k] = float(process_pot(pot3)) / 1000; 627 | // } 628 | } 629 | 630 | 631 | void success_leds() { 632 | for (int i = 0; i < 4 ; i++) { 633 | digitalWrite(led_green, HIGH); 634 | delay(50); 635 | digitalWrite(led_green, LOW); 636 | delay(100); 637 | } 638 | } 639 | 640 | 641 | 642 | void toggleSequencer() { 643 | seq_running = !seq_running; 644 | } 645 | 646 | 647 | void check_pots() { 648 | Serial.print("1: "); 649 | Serial.print(process_pot(pot1)); 650 | Serial.print("; 2: "); 651 | Serial.print(process_pot(pot2)); 652 | Serial.print(": 3: . "); 653 | Serial.println(process_pot(pot3)); 654 | 655 | } 656 | void check_seq() { 657 | for (int i = 0; i < seq_length; i++ ) { 658 | Serial.print(sequencer_steps[i]); 659 | Serial.print("\t"); 660 | } 661 | Serial.println(); 662 | } 663 | -------------------------------------------------------------------------------- /ardrando/panel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tensiontides/eurorack_arduino/8c68bc2ef4e790f3365e9289b193f4b0d6da3a98/ardrando/panel.png -------------------------------------------------------------------------------- /ardrando/schematic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tensiontides/eurorack_arduino/8c68bc2ef4e790f3365e9289b193f4b0d6da3a98/ardrando/schematic.png --------------------------------------------------------------------------------