├── Build Guide ├── Build Guide.pdf └── build_incomplete.pdf ├── DODECA_MOUSER_BOM.xlsx ├── Hardware ├── 1203 - Dodeca.pdf ├── 1213 - dubldecav2.pdf └── Panels.pdf ├── README.md └── Software └── Octatrack 2x Setup ├── dubldecca_left ├── MIDI_CLOCK_handlers.ino ├── MIDI_Note_CC_handlers.ino └── dubldecca_left.ino └── dubldecca_right ├── MIDI_CLOCK_handlers.ino ├── MIDI_Note_CC_handlers.ino └── dubldecca_right.ino /Build Guide/Build Guide.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MagpieModular/Dodeca/4205b8b02d7f34e922357a7c2c27ab05f4d2114a/Build Guide/Build Guide.pdf -------------------------------------------------------------------------------- /Build Guide/build_incomplete.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MagpieModular/Dodeca/4205b8b02d7f34e922357a7c2c27ab05f4d2114a/Build Guide/build_incomplete.pdf -------------------------------------------------------------------------------- /DODECA_MOUSER_BOM.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MagpieModular/Dodeca/4205b8b02d7f34e922357a7c2c27ab05f4d2114a/DODECA_MOUSER_BOM.xlsx -------------------------------------------------------------------------------- /Hardware/1203 - Dodeca.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MagpieModular/Dodeca/4205b8b02d7f34e922357a7c2c27ab05f4d2114a/Hardware/1203 - Dodeca.pdf -------------------------------------------------------------------------------- /Hardware/1213 - dubldecav2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MagpieModular/Dodeca/4205b8b02d7f34e922357a7c2c27ab05f4d2114a/Hardware/1213 - dubldecav2.pdf -------------------------------------------------------------------------------- /Hardware/Panels.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MagpieModular/Dodeca/4205b8b02d7f34e922357a7c2c27ab05f4d2114a/Hardware/Panels.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dodeca 2 | An Open Hardware, DIY Eurorack extensible platform allowing the configuration of custom MIDI outputs. 3 | 4 | The Dodeca can be chained together with other Dodeca boards. The 5 | typical configuration is the Dubldeca, which is two Dodeca boards 6 | configured in a left and right arrangement, as used by the 7 | [Octatrack 2x Setup Firmware](Octatrack 2x Setup). 8 | 9 | # PCBs and panels 10 | 11 | Available from Magpie Modular: 12 | - [Dodeca PCB](https://magpie-modular.myshopify.com/products/dodeca) 13 | - [Dubldeca PCBs](https://magpie-modular.myshopify.com/products/dodecca-dubldeca-pcbs) 14 | - [Dubldeca Panel](https://magpie-modular.myshopify.com/products/magpie-modular-dubledeca) 15 | 16 | # Build resources 17 | 18 | This repository contains the [Build Guide](Build Guide/Build Guide.pdf) and [Hardware Resources](Hardware) 19 | 20 | Components for the Dodeca can be ordered from Mouser using [this cart](https://ca.mouser.com/ProjectManager/ProjectDetail.aspx?State=EDIT&ProjectGUID=0082110f-d597-4c76-925b-8146d7b16813) 21 | 22 | There is also a [Muffwiggler Build Thread](https://www.muffwiggler.com/forum/viewtopic.php?t=188619&highlight=). 23 | -------------------------------------------------------------------------------- /Software/Octatrack 2x Setup/dubldecca_left/MIDI_CLOCK_handlers.ino: -------------------------------------------------------------------------------- 1 | //void HandleClock(void){ 2 | // if (playing){ 3 | // pulses ++; 4 | // if (pulses > 5){ 5 | // pulses = 0; 6 | // sixteenthnotes ++; 7 | // } 8 | // if (pulses < 3){ 9 | // analogWrite(out2pin[11],127); 10 | // } 11 | // else analogWrite(out2pin[11],0); 12 | //} 13 | //} 14 | // 15 | // void HandleStart(){ 16 | // pulses = 0; 17 | // sixteenthnotes = 0; 18 | // playing = 1; 19 | // } 20 | // 21 | // void HandleStop(){ 22 | // playing = 0; //remove this to have continuous clock pulses on dodeca after sequencer is stopped 23 | // digitalWriteFast(out2pin[11],LOW); //turn pulse off when stopped even if it is in the middle of "on" cycle 24 | // } 25 | // 26 | // 27 | // void HandleContinue(){ 28 | // //maybe only needed for song position pointer 29 | // } 30 | 31 | -------------------------------------------------------------------------------- /Software/Octatrack 2x Setup/dubldecca_left/MIDI_Note_CC_handlers.ino: -------------------------------------------------------------------------------- 1 | void HandleNoteOn(byte channel, byte pitch, byte velocity) { 2 | if (channel == CHANA) { 3 | int modNote = (whitekeys[pitch % 12] ) ; 4 | if (velocity != 0) { 5 | if (modNote) { 6 | analogWrite(out2pin[modNote], velocity); 7 | } 8 | } 9 | else bothNoteOff(channel, pitch, velocity); 10 | } 11 | if (channel == CHANB) { 12 | 13 | if (velocity != 0) { 14 | 15 | analogWrite(out2pin[0], velocity); 16 | analogWrite(A14, pitch); 17 | analogWrite(out2pin[2], 127); 18 | } 19 | else bothNoteOff(channel, pitch, velocity); 20 | } 21 | } 22 | 23 | void HandleNoteOff(byte channel, byte pitch, byte velocity) { 24 | bothNoteOff(channel, pitch, velocity); 25 | } 26 | 27 | void bothNoteOff(byte channel, byte pitch, byte velocity) { //this is called by handle noteoff and note on when velocity = 0 28 | if (channel == CHANA) { 29 | int modNote = (whitekeys[pitch % 12] ) ; 30 | if (modNote) { 31 | analogWrite(out2pin[modNote], 0); 32 | } 33 | } 34 | if (channel == CHANB) { 35 | //analogWrite(out2pin[0], 0); 36 | analogWrite(out2pin[2], 0); 37 | } 38 | } 39 | 40 | 41 | void HandleControlChange (byte channel, byte number, byte value) { 42 | if (channel == CHANA) { 43 | 44 | for (int i = 0; i < 6; i ++) { 45 | if ( number == cc2active[i]) { //ignore wrong channel or CC numbers 46 | analogWrite(out2pin[cc2out[i]], value); 47 | } 48 | } 49 | } 50 | } 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /Software/Octatrack 2x Setup/dubldecca_left/dubldecca_left.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Neutron magpie dodeca: 3 | 4 | LEFT SIDE 5 | 6 | 1) Velocity (synth voice) Midi Channel 3 7 | 2) Note out (synth voice) Midi Channel 3 8 | 3) Gate (synth voice) Midi Channel 3 9 | 4) CC# 71 MIDI Channel 1 10 | 5) Note to Gate/Trig - C Midi Channel 1 11 | 6) CC #72 MIDI Channel 1 12 | 7) Note to Gate/Trig - D Midi Channel 1 13 | 😎 CC #73 MIDI Channel 1 14 | 9) Note to Gate/Trig - E Midi Channel 1 15 | 10) CC #74 MIDI Channel 1 16 | 11) CC #75 MIDI Channel 1 17 | 12) CC #76 MIDI Channel 1 18 | 19 | 20 | * */ 21 | 22 | #include 23 | 24 | const uint8_t CHANA = 1;//set the MIDI channel here! 25 | const uint8_t CHANB = 3; 26 | 27 | uint8_t out2pin[] = {23, 0, 22, 25, 20, 6, 21, 5, 9, 4, 10, 3};//output number to actual teensy pin, dont change. 28 | uint8_t whitekeys[] = {4, 0, 6, 0, 8, 0, 0, 0, 0, 0, 0, 0};//non zero keys sent to output number. 29 | uint8_t pulses; 30 | uint8_t sixteenthnotes; 31 | uint8_t quartertoggle; 32 | uint8_t wholetoggle; 33 | bool playing; 34 | 35 | 36 | 37 | uint8_t cc2active[] = {71, 72, 73, 74, 75, 76 }; 38 | uint8_t cc2out[] = {3, 5, 7, 9, 10, 11}; 39 | 40 | 41 | 42 | void setup() { 43 | // Initiate MIDI communications, listen to all channels 44 | 45 | for (int i = 0; i < 12; i ++) { 46 | if (out2pin[i]) { 47 | pinMode(out2pin[i], OUTPUT); 48 | analogWriteFrequency(out2pin[i], 200000); 49 | } 50 | } 51 | 52 | analogWriteResolution(7); 53 | 54 | for (int i = 0; i < 12; i ++) {//start up LED animation 55 | for (int j = 0; j < 128; j ++) { 56 | if (out2pin[i] == 0) analogWrite(A14, (j )); 57 | else analogWrite(out2pin[i], j ); 58 | delay(1); 59 | } 60 | if (out2pin[i] == 0) analogWrite(A14, 0); 61 | analogWrite(out2pin[i], 0); 62 | }//end of start up animantion 63 | 64 | MIDI.begin(MIDI_CHANNEL_OMNI); 65 | // Connect the Handlers to the library, so it is called upon reception. 66 | MIDI.setHandleNoteOn(HandleNoteOn); // Put only the name of the function 67 | MIDI.setHandleControlChange(HandleControlChange); 68 | MIDI.setHandleNoteOff(HandleNoteOff); 69 | // MIDI.setHandleClock(HandleClock); 70 | // MIDI.setHandleStart(HandleStart); 71 | // MIDI.setHandleStop(HandleStop); 72 | // MIDI.setHandleContinue(HandleContinue); 73 | 74 | Serial.begin(9600); 75 | } 76 | 77 | void loop() { 78 | // Call MIDI.read the fastest you can for real-time performance. 79 | MIDI.read(); 80 | 81 | // There is no need to check if there are messages incoming if they are bound to a Callback function. 82 | } 83 | -------------------------------------------------------------------------------- /Software/Octatrack 2x Setup/dubldecca_right/MIDI_CLOCK_handlers.ino: -------------------------------------------------------------------------------- 1 | void HandleClock(void){ 2 | if (playing){ 3 | pulses ++; 4 | if (pulses > 5){ 5 | pulses = 0; 6 | sixteenthnotes ++; 7 | } 8 | if (pulses < 3){ 9 | analogWrite(out2pin[3],127); 10 | } 11 | else analogWrite(out2pin[3],0); 12 | } 13 | } 14 | 15 | void HandleStart(){ 16 | pulses = 0; 17 | sixteenthnotes = 0; 18 | playing = 1; 19 | } 20 | 21 | void HandleStop(){ 22 | playing = 0; //remove this to have continuous clock pulses on dodeca after sequencer is stopped 23 | digitalWriteFast(out2pin[3],LOW); //turn pulse off when stopped even if it is in the middle of "on" cycle 24 | } 25 | 26 | 27 | void HandleContinue(){ 28 | //maybe only needed for song position pointer 29 | } 30 | 31 | -------------------------------------------------------------------------------- /Software/Octatrack 2x Setup/dubldecca_right/MIDI_Note_CC_handlers.ino: -------------------------------------------------------------------------------- 1 | void HandleNoteOn(byte channel, byte pitch, byte velocity) { 2 | if (channel == CHANA) { 3 | int modNote = (whitekeys[pitch % 12] ) ; 4 | if (velocity != 0) { 5 | if (modNote) { 6 | analogWrite(out2pin[modNote], velocity); 7 | } 8 | 9 | } 10 | else bothNoteOff(channel, pitch, velocity); 11 | } 12 | if (channel == CHANB) { 13 | 14 | if (velocity != 0) { 15 | 16 | analogWrite(out2pin[0], velocity); 17 | analogWrite(A14, pitch); 18 | analogWrite(out2pin[2], 127); 19 | } 20 | else bothNoteOff(channel, pitch, velocity); 21 | } 22 | } 23 | 24 | void HandleNoteOff(byte channel, byte pitch, byte velocity) { 25 | bothNoteOff(channel, pitch, velocity); 26 | } 27 | 28 | void bothNoteOff(byte channel, byte pitch, byte velocity) { //this is called by handle noteoff and note on when velocity = 0 29 | if (channel == CHANA) { 30 | int modNote = (whitekeys[pitch % 12] ) ; 31 | if (modNote) { 32 | analogWrite(out2pin[modNote], 0); 33 | } 34 | } 35 | if (channel == CHANB) { 36 | //analogWrite(out2pin[0], 0); 37 | analogWrite(out2pin[2], 0); 38 | } 39 | } 40 | 41 | 42 | void HandleControlChange (byte channel, byte number, byte value) { 43 | if (channel == CHANA) { 44 | 45 | for (int i = 0; i < 5; i ++) { 46 | if ( number == cc2active[i]) { //ignore wrong channel or CC numbers 47 | analogWrite(out2pin[cc2out[i]], value); 48 | } 49 | } 50 | } 51 | } 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /Software/Octatrack 2x Setup/dubldecca_right/dubldecca_right.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Neutron magpie dodeca: 3 | 4 | Right Side Dodceca - DUBDECA layout 5 | 6 | 1) Velocity (synth voice) Midi Channel 4 7 | 2) Note out (synth voice) Midi Channel 4 8 | 3) Gate (synth voice) Midi Channel 4 9 | 4) 12) MIDI Clock out 10 | 5) Note to Gate/Trig - C Midi Channel 2 11 | 6) CC #72 MIDI Channel 2 12 | 7) Note to Gate/Trig - D Midi Channel 2 13 | 😎 CC #73 MIDI Channel 2 14 | 9) Note to Gate/Trig - E Midi Channel 2 15 | 10) CC #74 MIDI Channel 2 16 | 11) CC #75 MIDI Channel 2 17 | 12) CC #76 MIDI Channel 2 18 | 19 | 20 | * */ 21 | 22 | #include 23 | 24 | const uint8_t CHANA = 2;//set the MIDI channel here! 25 | const uint8_t CHANB = 4; 26 | 27 | uint8_t out2pin[] = {23, 0, 22, 25, 20, 6, 21, 5, 9, 4, 10, 3};//output number to actual teensy pin, dont change. 28 | uint8_t whitekeys[] = {4, 0, 6, 0, 8, 0, 0, 0, 0, 0, 0, 0};//non zero keys sent to output number. 29 | uint8_t pulses; 30 | uint8_t sixteenthnotes; 31 | uint8_t quartertoggle; 32 | uint8_t wholetoggle; 33 | bool playing; 34 | 35 | 36 | 37 | uint8_t cc2active[] = {72, 73, 74, 75, 76 }; 38 | uint8_t cc2out[] = {5, 7, 9, 10, 11}; 39 | 40 | 41 | 42 | void setup() { 43 | // Initiate MIDI communications, listen to all channels 44 | 45 | for (int i = 0; i < 12; i ++) { 46 | if (out2pin[i]) { 47 | pinMode(out2pin[i], OUTPUT); 48 | analogWriteFrequency(out2pin[i], 200000); 49 | } 50 | } 51 | 52 | analogWriteResolution(7); 53 | 54 | for (int i = 0; i < 12; i ++) {//start up LED animation 55 | for (int j = 0; j < 128; j ++) { 56 | if (out2pin[i] == 0) analogWrite(A14, (j )); 57 | else analogWrite(out2pin[i], j ); 58 | delay(1); 59 | } 60 | if (out2pin[i] == 0) analogWrite(A14, 0); 61 | analogWrite(out2pin[i], 0); 62 | }//end of start up animantion 63 | 64 | MIDI.begin(MIDI_CHANNEL_OMNI); 65 | // Connect the Handlers to the library, so it is called upon reception. 66 | MIDI.setHandleNoteOn(HandleNoteOn); // Put only the name of the function 67 | MIDI.setHandleControlChange(HandleControlChange); 68 | MIDI.setHandleNoteOff(HandleNoteOff); 69 | MIDI.setHandleClock(HandleClock); 70 | MIDI.setHandleStart(HandleStart); 71 | MIDI.setHandleStop(HandleStop); 72 | MIDI.setHandleContinue(HandleContinue); 73 | 74 | Serial.begin(9600); 75 | } 76 | 77 | void loop() { 78 | // Call MIDI.read the fastest you can for real-time performance. 79 | MIDI.read(); 80 | 81 | // There is no need to check if there are messages incoming if they are bound to a Callback function. 82 | } 83 | --------------------------------------------------------------------------------