├── README.md ├── firmware └── i2c2midi_firmware │ ├── i2c.ino │ ├── i2c2midi_firmware.ino │ ├── leds.ino │ ├── midiBuffer.ino │ ├── midiCCs.ino │ ├── midiChord.ino │ ├── midiMisc.ino │ ├── midiNotes.ino │ ├── nrpns.ino │ ├── ops.ino │ └── test.ino └── hardware ├── hardware-MK1 ├── BUILD-GUIDE.md ├── README.md ├── gerber │ ├── board_2021-04-26_board.zip │ ├── board_2021-04-26_board │ │ ├── GerberJob │ │ │ └── gerber_job.gbrjob │ │ ├── board.GBL │ │ ├── board.GBO │ │ ├── board.GBP │ │ ├── board.GBS │ │ ├── board.GKO │ │ ├── board.GTL │ │ ├── board.GTO │ │ ├── board.GTP │ │ ├── board.GTS │ │ └── board.XLN │ ├── panel_2021-04-05_panel.zip │ └── panel_2021-04-05_panel │ │ ├── GerberJob │ │ └── gerber_job.gbrjob │ │ ├── panel.GBL │ │ ├── panel.GBO │ │ ├── panel.GBP │ │ ├── panel.GBS │ │ ├── panel.GKO │ │ ├── panel.GTL │ │ ├── panel.GTO │ │ ├── panel.GTP │ │ ├── panel.GTS │ │ └── panel.XLN ├── i2c2midi_board.brd ├── i2c2midi_board.sch ├── i2c2midi_panel.brd ├── i2c2midi_panel.sch ├── i2c2midi_schematic.pdf ├── i2c2midi_schematic.png └── pictures │ ├── i2c2midi_diagram.png │ ├── i2c2midi_v_1_0_side.jpg │ ├── i2c2midi_v_1_0_top.jpg │ ├── i2c2midi_v_2_0.jpg │ ├── i2c2midi_v_2_0_build_1.jpg │ ├── i2c2midi_v_2_0_build_2.jpg │ ├── i2c2midi_v_2_0_build_3.jpg │ ├── i2c2midi_v_2_0_build_4.jpg │ ├── i2c2midi_v_2_0_build_5.jpg │ ├── i2c2midi_v_2_0_build_6.jpg │ ├── i2c2midi_v_2_0_build_7.jpg │ ├── i2c2midi_v_2_0_build_8.jpg │ ├── i2c2midi_v_2_0_build_9.jpg │ ├── i2c2midi_v_2_0_kit.jpg │ └── i2c2midi_v_2_0_side.jpg └── hardware-MK2 ├── BUILD-GUIDE.md ├── eagle ├── board-A.brd ├── board-B.brd ├── board.brd ├── board.sch ├── panel.brd └── panel.sch ├── gerber ├── board-A.zip ├── board-B.zip └── panel.zip ├── i2c2midi_schematic.png └── pictures ├── i2c2midi_MK2_build_01.JPG ├── i2c2midi_MK2_build_02.JPG ├── i2c2midi_MK2_build_03.JPG ├── i2c2midi_MK2_build_04.JPG ├── i2c2midi_MK2_build_05.JPG ├── i2c2midi_MK2_build_06.JPG ├── i2c2midi_MK2_build_07.JPG ├── i2c2midi_MK2_build_08.JPG ├── i2c2midi_MK2_build_10.JPG ├── i2c2midi_MK2_build_11.JPG ├── i2c2midi_MK2_build_12.JPG ├── i2c2midi_MK2_build_13.JPG ├── i2c2midi_MK2_build_14.JPG ├── i2c2midi_MK2_build_15.JPG ├── i2c2midi_MK2_build_15b.jpg ├── i2c2midi_MK2_build_16.JPG ├── i2c2midi_MK2_build_17.JPG ├── i2c2midi_MK2_build_18.JPG ├── i2c2midi_MK2_build_outline.png ├── i2c2midi_MK2_diagram.png └── i2c2midi_MK2_shot.jpg /firmware/i2c2midi_firmware/i2c.ino: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------------------- 2 | // I2C receive and request events 3 | // ------------------------------------------------------------------------------------------- 4 | 5 | 6 | #ifdef TEENSY3X 7 | 8 | // handler for receiving I2C messages 9 | void i2cReceiveEvent(size_t count) { 10 | if(count < MEM_LEN) { 11 | Wire.read(i2cData, count); 12 | received = count; // this triggers function in loop 13 | } 14 | } 15 | 16 | // hanlder for receiving I2C request messages 17 | void i2cRequestEvent(void) { 18 | opFunctions(true, i2cData); // call the respective OP with isRequest = true 19 | } 20 | 21 | #endif 22 | 23 | 24 | // ------------------------------------------------------------------------------------------- 25 | 26 | 27 | #ifdef TEENSY41 28 | 29 | // handler for receiving I2C messages 30 | void i2cReceiveEvent(int count) { 31 | for(int i=0; i < count; i++) { 32 | i2cData[i] = Wire.read(); 33 | } 34 | received = count; 35 | } 36 | 37 | // hanlder for receiving I2C request messages 38 | void i2cRequestEvent() { 39 | opFunctions(true, i2cData); 40 | } 41 | 42 | #endif -------------------------------------------------------------------------------- /firmware/i2c2midi_firmware/i2c2midi_firmware.ino: -------------------------------------------------------------------------------- 1 | /* 2 | ------------------------------------------------------------------------------------------- 3 | 4 | 5 | I2C2MIDI MK2 6 | – Firmware v5_0_2 7 | 8 | https://github.com/attowatt/i2c2midi 9 | 10 | ------------------------------------------------------------------------------------------- 11 | 12 | Copyright (c) 2023 attowatt (http://www.attowatt.com) 13 | 14 | MIT License 15 | 16 | Permission is hereby granted, free of charge, to any person obtaining a copy of this 17 | software and associated documentation files (the "Software"), to deal in the Software 18 | without restriction, including without limitation the rights to use, copy, modify, merge, 19 | publish, distribute, sublicense, and/or sell copies of the Software, and to permit 20 | persons to whom the Software is furnished to do so, subject to the following conditions: 21 | 22 | The above copyright notice and this permission notice shall be included in all copies or 23 | substantial portions of the Software. 24 | 25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 26 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 27 | PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 28 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT 29 | OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 30 | OTHER DEALINGS IN THE SOFTWARE. 31 | 32 | ------------------------------------------------------------------------------------------- 33 | */ 34 | 35 | 36 | // Turn on MK2 features 37 | #define MK2 38 | 39 | // Set Teensy model (Teensy 3.x vs. Teensy 4.1) 40 | //#define TEENSY3X 41 | #define TEENSY41 42 | 43 | // USB Device 44 | // i2c2midi can also act as a USB device and send MIDI data over the Teensy Micro USB jack to a host (e.g. a computer). 45 | // Please note: Do not connect Teensy USB and Euro Power at the same time! Please cut the 5V pads on the Teensy! 46 | // Select Tools -> USB Type "MIDI" in Teensyduino, and uncomment the next line to turn the MIDI device feature on: 47 | // #define USB_DEVICE 48 | 49 | // Debug Mode 50 | // Turn on debug mode to plot some debug message to the Serial Monitor 51 | //#define DEBUG 52 | 53 | // Turn on testing mode 54 | // Sending: channel 1, random note between 50 and 70, velocity 127 55 | //#define TEST 56 | 57 | // Experimental feature enabling multiple devices for USB MIDI out 58 | //#define MULTIPLEUSBOUT 59 | 60 | 61 | // ------------------------------------------------------------------------------------------- 62 | 63 | 64 | #include 65 | // MIT License – Copyright (c) 2016 Francois Best 66 | // https://github.com/FortySevenEffects/arduino_midi_library 67 | // Used for MIDI communication 68 | 69 | #ifdef TEENSY3X 70 | #include 71 | // MIT License – Copyright (c) 2013-2018, Brian (nox771 at gmail.com) 72 | // https://github.com/nox771/i2c_t3 73 | // Used for I2C communication on Teensy 3.x 74 | #endif 75 | #ifdef TEENSY41 76 | #include 77 | #include 78 | // MIT License – Copyright © 2019-2020 Richard Gemmell 79 | // https://github.com/Richard-Gemmell/teensy4_i2c 80 | // Used for I2C communication on Teensy 4.1 81 | #endif 82 | 83 | #ifdef MK2 84 | #include 85 | // MIT License – Copyright 2017 Paul Stoffregen (paul@pjrc.com) 86 | // https://github.com/PaulStoffregen/USBHost_t36 87 | // Used for USB MIDI Host 88 | #endif 89 | 90 | #include 91 | // GPL-3.0 License – Sylvain GARNAVAULT - 2016/08/07 92 | // https://github.com/siteswapjuggler/RAMP 93 | // Used for ramping CC values 94 | 95 | 96 | // ------------------------------------------------------------------------------------------- 97 | 98 | 99 | // USB Host 100 | // The front panel USB jack ... 101 | // ... receives data from MIDI controllers (MIDI in) 102 | // ... sends out MIDI data to devices (MIDI out) 103 | #ifdef MK2 104 | USBHost myusb; 105 | USBHub hub1(myusb); // USB host: MIDI in 106 | MIDIDevice_BigBuffer midiDevice(myusb); // USB host: MIDI out 107 | #ifdef MULTIPLEUSBOUT 108 | USBHub hub2(myusb); 109 | MIDIDevice_BigBuffer midiDevice2(myusb); 110 | MIDIDevice_BigBuffer* midiDeviceList[2] = { 0 }; 111 | #endif 112 | #endif 113 | 114 | // I2C 115 | #define MEM_LEN 256 // save I2C data in 8 bit chunks 116 | uint8_t i2cData[MEM_LEN]; // save I2C data in variable "i2cData" 117 | volatile uint8_t received; // variable to store if there are received I2C messages 118 | void i2cReceiveEvent(size_t count); // function for receiving I2C messages, count = number of bites 119 | void i2cRequestEvent(void); // function for receiving I2C messages, count = number of bites 120 | 121 | // I2C Address 122 | // i2c2midi acts as a I2C follower and listens to messages on address 0x3F (63). 123 | const uint8_t i2cAddress = 0x3F; // official I2C address for Teletype I2M OPs 124 | 125 | // MIDI TRS 126 | MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI); 127 | 128 | 129 | // ------------------------------------------------------------------------------------------- 130 | 131 | 132 | // channels 133 | #ifdef MK2 134 | const byte channelsOut = 32; // number of MIDI channels OUT (1-16 for TRS out, 17-32 for USB out) 135 | const byte channelsIn = 16; // number of MIDI channels IN (16 for USB in) 136 | #else 137 | const byte channelsOut = 16; // number of MIDI channels OUT 138 | const byte channelsIn = 0; // number of MIDI channels IN 139 | #endif 140 | 141 | // channels 142 | int channelMute[channelsOut]; // mute state for each MIDI out channel 143 | int channelSolo[channelsOut]; // solo state for each MIDI out channel 144 | 145 | // notes 146 | const byte maxNotes = 8; 147 | unsigned long notes[channelsOut][maxNotes][7]; 148 | // array to store notes: 149 | // 0 : note number 150 | // 1 : start time 151 | // 2 : duration 152 | // 3 : currently on/off 153 | // 4 : velocity 154 | // 5 : ratchet count 155 | // 6 : repeat count 156 | int noteCount[channelsOut]; // total note count, per channel 157 | int currentNote[channelsOut]; // current note number between 0 and maxNotes, per channel 158 | int currentNoteDuration[channelsOut]; // setting for note duration per channel 159 | int8_t currentNoteShift[channelsOut]; // setting for note shift per channel 160 | byte currentRepetition[channelsOut]; // setting for note repetition per channel 161 | byte currentRatcheting[channelsOut]; // setting for note ratcheting per channel 162 | const int ratchetingLength = 75; // in percent: 75 means 75% of original note length for racheted notes 163 | byte noteUpperLimit[channelsOut]; // setting for highest allowed midi note per channel 164 | byte noteLowerLimit[channelsOut]; // setting for lowest allowed midi note per channel 165 | byte noteLimitMode[channelsOut]; // setting for limit mode per channel 166 | 167 | // CCs 168 | int CCs[channelsOut][127][3]; 169 | // array to store CC values: 170 | // 1 : current value 171 | // 2 : slew time in ms 172 | // 3 : offset 173 | 174 | // NRPNs 175 | const byte maxNRPNs = 8; 176 | int NRPNs[maxNRPNs][4]; 177 | // array to store NRPN settings 178 | // 0 : channel 179 | // 1 : controller 180 | // 2 : offset 181 | // 3 : slew time 182 | byte nrpnCount = 0; 183 | 184 | // Chords 185 | const byte maxChords = 8; // number of chords 186 | const byte chordMaxLength = 8; // maximum allowed length of chords 187 | int chord[maxChords][chordMaxLength]; // array to store chords 188 | byte chordNoteCount[maxChords]; // number of added notes per chord 189 | byte chordLength[maxChords]; // size of chord that should be played 190 | int chordScaled[2][chordMaxLength]; // store current chord w transformations; 0 scaled notes, 1 deltas 191 | byte currentChordLength; // length of current chord 192 | byte currentChordNoteCount; // number of added notes in current chord 193 | int chordReverse[maxChords]; // reverse transformation setting per chord 194 | bool chordReversedQ = 0; // keeping track of wether the chord is reversed or not 195 | int chordRotate[maxChords]; // rotate transformation setting per chord 196 | int chordInversion[maxChords]; // inversion transformation setting per chord 197 | int chordStrumming[maxChords]; // strumming transformation setting per chord 198 | int chordShift[maxChords]; // shift transformation setting per chord 199 | int chordStretch[maxChords][2]; // stretch transformation setting per chord; 0 value, 1 anchor point 200 | int chordReflection[maxChords][2]; // reflection setting per chord; 0 refl value, 1 refl point 201 | int currentScaleChord[maxChords]; // storing the chord number which is set as the scale for each chord 202 | int currentScale[maxChords][12]; // storing the current scale for each chord 203 | int currentScaleLength[maxChords]; // storing the length of the current scale for each chord 204 | int curveVelocity[maxChords][3]; // type of curve, start percent, end percent 205 | int curveTime[maxChords][3]; // type of curve, start percent, end percent 206 | byte chordDirection[maxChords]; // play direction for chord 207 | int chordNotePlayCount[maxChords]; // count how often a note of a chord has been played 208 | int chordRandomIndices[maxChords][chordMaxLength*2]; 209 | 210 | // Scheduled notes 211 | const byte maxNotesScheduled = 42; // maximum allowed notes for scheduling 212 | unsigned long scheduledNotes[maxNotesScheduled][7]; 213 | // array to store scheduled notes: 214 | // 0 : note number 215 | // 1 : start time scheduled 216 | // 2 : duration 217 | // 3 : velocity 218 | // 4 : channel 219 | // 5 : chord number 220 | // 6 : note index 221 | byte scheduledNoteCount = 0; // total count of scheduled notes 222 | 223 | // MIDI buffer 224 | const uint8_t maxBuffer = 64; 225 | unsigned long buffer[maxBuffer][10]; 226 | // 0 : channel 227 | // 1 : note number 228 | // 2 : velocity 229 | // 3 : start time 230 | // 4 : duration 231 | // 5 : buffer round 232 | // 6 : original velocity 233 | // 7 : chord number 234 | // 8 : note index 235 | // 9 : note index original 236 | // internal values 237 | uint8_t bufferCount = 0; // the current splot position in the buffer array 238 | uint8_t bufferRoundCount = 0; // keeping track of rounds 239 | int bufferOffset = 0; // time when play direction was changed 240 | bool bufferReverse = 0; // play direction 241 | unsigned long bufferFrame = 0; 242 | elapsedMicros bufferElapsedMicros; 243 | // parameters set by OPs 244 | byte bufferRecord = 0; // if notes should be recorded to buffer or not 245 | int bufferLength = 1000; // length of the buffer in ms 246 | int bufferStartOffset = 0; // offset added to the start in ms 247 | int bufferEndOffset = 0; // negative offset added to the end in ms 248 | byte bufferDirection = 0; // direction of buffer, 0 = forward, 1 = backward, 2 = ping pong 249 | int bufferSpeed = 100; // buffer speed, 100 = normal speed, 50 = double speed, 200 = half speed 250 | byte bufferFeedback = 8; // how many rounds the note should survive (affects note velocity) 251 | int bufferPitchShift = 0; // pitch added to note with each round 252 | int bufferDurationShift = 0; // duration added to note with each round 253 | int bufferVelocityShift = 0; 254 | int bufferNoteOffset = 0; // pitch offset added to all notes, fixed for all rounds 255 | int bufferVelocityOffset = 0; // velocity offset added to all notes, fixed for all rounds 256 | int bufferDurationOffset = 0; // duration offset added to all notes, fixed for all rounds 257 | byte bufferMode = 0; // buffer mode, 0 = "digital", 1 = "tape" (pitch/duration fixed to speed) 258 | 259 | // Ramp (slew) 260 | const byte maxRamps = 8; // maximum allowed ramps 261 | rampInt* myRamps = new rampInt[maxRamps]; // intialize 8 ramps 262 | int lastRampValues[maxRamps]; // store the latest ramp values (used for comparison with new values) 263 | int rampsAssignedCCs[maxRamps][3]; // which CC was assigned to each ramp: channel, controller, NRPN? 264 | const byte maxRampSpeed = 30; // shortest intervall between outgoing MIDI CC messages when ramping 265 | byte rampCount; // total ramp count 266 | byte currentRamp; // current ramp number between 0 and maxRamps 267 | 268 | // USB MIDI in 269 | byte CCsIn[channelsIn][127]; // array to store MIDI CCs values received via USB MIDI in 270 | byte noteHistoryIn[channelsIn][16][2]; // array to store the last 8 received MIDI notes: note number, velocity 271 | const byte noteHistoryInLength = 16; // length of the note history per channel 272 | bool latch = true; // latch setting for note history 273 | byte lastChannelIn = 1; // the last channel received via MIDI in 274 | byte lastNoteIn = 0; // the last note number of Note On message received via MIDI in 275 | byte lastVelocityIn = 0; // the last note velocity of Note On messagereceived via MIDI in 276 | byte lastNoteOffIn = 0; // the last note number of Note Off message received via MIDI in 277 | byte lastCIn = 0; // the last controller number received via MIDI in 278 | byte lastCCIn = 0; // the last CC value received via MIDI in 279 | 280 | // LEDs 281 | const byte led1 = 3; // pin definition for led 1 282 | const byte led2 = 2; // pin definition for led 2 283 | unsigned long lastLEDMillis1 = 0; // last time LED 1 turned on 284 | unsigned long lastLEDMillis2 = 0; // last time LED 2 turned on 285 | const byte animationSpeed = 100; // start up animation speed 286 | 287 | 288 | // ------------------------------------------------------------------------------------------- 289 | // SETUP 290 | // ------------------------------------------------------------------------------------------- 291 | 292 | 293 | void setup() { 294 | 295 | // LEDs 296 | pinMode(led1,OUTPUT); 297 | pinMode(led2,OUTPUT); 298 | 299 | // I2C 300 | #ifdef TEENSY3X 301 | // setup for slave mode, address, pins 18/19, external pullups, 400kHz 302 | Wire.begin(I2C_SLAVE, i2cAddress, I2C_PINS_18_19, I2C_PULLUP_EXT, 400000); 303 | #endif 304 | #ifdef TEENSY41 305 | Wire.begin(i2cAddress); 306 | #endif 307 | received = 0; // i2c data initalize 308 | memset(i2cData, 0, sizeof(i2cData)); // save I2C data in memory 309 | Wire.onReceive(i2cReceiveEvent); // register i2c events 310 | Wire.onRequest(i2cRequestEvent); 311 | 312 | // Serial 313 | Serial.begin(115200); 314 | 315 | // MIDI & USB MIDI 316 | MIDI.begin(); 317 | #ifdef MK2 318 | #ifdef MULTIPLEUSBOUT 319 | midiDeviceList[0] = &midiDevice; 320 | midiDeviceList[1] = &midiDevice2; 321 | #endif 322 | myusb.begin(); 323 | #endif 324 | 325 | // setup up ramps 326 | for (int i = 0; i < maxRamps; i++) { 327 | myRamps[i].setGrain(maxRampSpeed); 328 | } 329 | 330 | // setup up default scales 331 | for (int i = 0; i < maxChords; i++) { 332 | currentScaleChord[i] = 0; 333 | currentScaleLength[i] = 12; 334 | for (int j = 0; j < 12; j++) { 335 | currentScale[i][j] = j; 336 | } 337 | } 338 | 339 | // setup default note duration & note shift 340 | for (int i = 0; i < channelsOut; i++) { 341 | currentNoteDuration[i] = 100; 342 | currentNoteShift[i] = 0; 343 | currentRepetition[i] = 1; 344 | currentRatcheting[i] = 1; 345 | noteUpperLimit[i] = 127; 346 | noteLowerLimit[i] = 0; 347 | noteLowerLimit[i] = 0; 348 | noteLimitMode[i] = 0; 349 | channelMute[i] = 0; 350 | channelSolo[i] = 0; 351 | } 352 | 353 | // start up animation 354 | for (int i = 0; i < 4; i++) { 355 | digitalWrite(led2,HIGH); delay(animationSpeed); 356 | digitalWrite(led1,HIGH); delay(animationSpeed); 357 | digitalWrite(led2,LOW); delay(animationSpeed); 358 | digitalWrite(led1,LOW); delay(animationSpeed); 359 | } 360 | 361 | #ifdef DEBUG 362 | Serial.println("started"); 363 | #endif 364 | 365 | } 366 | 367 | 368 | // ------------------------------------------------------------------------------------------- 369 | // LOOP 370 | // ------------------------------------------------------------------------------------------- 371 | 372 | 373 | void loop() { 374 | 375 | // I2C 376 | if(received) { 377 | #ifdef DEBUG 378 | Serial.print(received); 379 | Serial.print(" bytes received: "); 380 | for (int i = 0; i < received; i++) { 381 | Serial.print(i2cData[i]); 382 | Serial.print(" "); 383 | } 384 | Serial.println(""); 385 | #endif 386 | 387 | opFunctions(false, i2cData); // call the respective OP with isRequest = false 388 | received = 0; // reset back to 0 389 | } 390 | 391 | #ifdef MK2 392 | // USB MIDI 393 | if (midiDevice.read()) { 394 | 395 | uint8_t type = midiDevice.getType(); 396 | uint8_t channel = midiDevice.getChannel(); 397 | uint8_t data1 = midiDevice.getData1(); 398 | uint8_t data2 = midiDevice.getData2(); 399 | 400 | //const uint8_t *sys = midiDevice.getSysExArray(); // not used at the moment 401 | 402 | #ifdef DEBUG 403 | Serial.print("USB received"); 404 | Serial.print("Type: "); Serial.println(type); 405 | Serial.print("channel: "); Serial.println(channel); 406 | Serial.print("data1: "); Serial.println(data1); 407 | Serial.print("data2: "); Serial.println(data2); 408 | #endif 409 | 410 | if (channel < 1 || channel > 16) return; 411 | 412 | // NOTE ON (status 144-159) 413 | if (type >= 144 && type <= 159) { 414 | int noteNumber = data1; 415 | if (noteNumber < 0 || noteNumber > 127) return; 416 | int velocity = data2; 417 | if (velocity < 0) { // velocity = 0 is treated as Note Off 418 | if (!latch) { 419 | removeFromNoteHistoryIn(channel-1, noteNumber); 420 | } 421 | }; 422 | if (velocity > 127) velocity = 127; 423 | addToNoteHistoryIn(channel-1, noteNumber, velocity); // store the note number to the history 424 | lastNoteIn = noteNumber; // store note number as last received 425 | lastVelocityIn = velocity; 426 | } 427 | 428 | // NOTE OFF (status 128-143) 429 | else if (type >= 128 && type <= 143) { 430 | int noteNumber = data1; 431 | if (noteNumber < 0 || noteNumber > 127) return; 432 | if (!latch) { 433 | removeFromNoteHistoryIn(channel-1, noteNumber); // remove the note number from the history if latch = 0 434 | } 435 | lastNoteOffIn = noteNumber; // store note number as last received 436 | } 437 | 438 | // CC (status 176-191) 439 | else if (type >= 176 && type <= 191) { 440 | int controller = data1; 441 | if (controller < 0 || controller > 127) return; 442 | int value = data2; 443 | if (value < 0) value = 0; 444 | if (value > 127) value = 127; 445 | CCsIn[channel-1][controller] = value; // store CC value 446 | lastCIn = controller; // store controller number as last received 447 | lastCCIn = value; // store CC value as last received 448 | } 449 | 450 | lastChannelIn = channel; // store the channel as last used channel 451 | 452 | blinkLED(2); 453 | 454 | } 455 | #endif 456 | 457 | checkNoteDurations(); // check if there are notes to turn off 458 | checkScheduledNotes(); // check scheduled notes 459 | checkBuffer(); 460 | updateRamps(); // update all ramps for MIDI CC 461 | checkLEDs(); // check if the LEDs should be turned off 462 | 463 | #ifdef TEST 464 | TESTFunction(); // function for testing 465 | #endif 466 | 467 | } -------------------------------------------------------------------------------- /firmware/i2c2midi_firmware/leds.ino: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------------------- 2 | // LEDs 3 | // ------------------------------------------------------------------------------------------- 4 | 5 | 6 | // function for turning on the LEDs 7 | void blinkLED(int led) { 8 | if (led == 1) { 9 | digitalWrite(led1,HIGH); 10 | lastLEDMillis1 = millis(); 11 | } 12 | if (led == 2) { 13 | digitalWrite(led2,HIGH); 14 | lastLEDMillis2 = millis(); 15 | } 16 | } 17 | 18 | 19 | // function for turning off the LEDs 20 | void checkLEDs() { 21 | unsigned long currentMillis = millis(); 22 | uint8_t LEDBlinkLength = 10; 23 | if (currentMillis - lastLEDMillis1 >= LEDBlinkLength) { 24 | digitalWrite(led1, LOW); 25 | } 26 | if (currentMillis - lastLEDMillis2 >= LEDBlinkLength) { 27 | digitalWrite(led2, LOW); 28 | } 29 | } -------------------------------------------------------------------------------- /firmware/i2c2midi_firmware/midiBuffer.ino: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------------------- 2 | // MIDI Buffer 3 | // ------------------------------------------------------------------------------------------- 4 | 5 | 6 | void recordToBuffer(int channel, int noteNumber, int velocity, int startTime, int noteDuration, int chordNumber, int noteIndex) { 7 | 8 | int c = bufferCount % maxBuffer; // get slot in the buffer to store note data 9 | 10 | buffer[c][0] = channel; 11 | buffer[c][1] = noteNumber; 12 | buffer[c][2] = velocity; // new velocity, gets changed per iteration 13 | buffer[c][3] = bufferFrame; // store position of note in the buffer (bufferframe) 14 | buffer[c][4] = noteDuration; 15 | buffer[c][5] = bufferRoundCount; // store the unique buffer round, so it is played once per round 16 | buffer[c][6] = velocity; // original velocity, do not change 17 | buffer[c][7] = chordNumber; // the chord number, if the note came from a chord 18 | buffer[c][8] = noteIndex; // the original note index in the chord scale, do not change 19 | buffer[c][9] = noteIndex; // new note index, gets changed per iteration 20 | bufferCount += 1; // advance to the next slot in the buffer 21 | } 22 | 23 | 24 | 25 | void checkBuffer() { 26 | 27 | // fixed offset, used if bufferMode = 1 (pitch/duration offset linked to speed) 28 | float fixedOffset1 = 1; // used when bufferSpeed is faster 29 | float fixedOffset2 = 1; // used when bufferSpeed is slower 30 | if (bufferMode == 1) { 31 | if (bufferSpeed <= 100) { // faster 32 | fixedOffset1 = 100. / bufferSpeed; 33 | fixedOffset2 = 1; 34 | } 35 | else { // slower 36 | fixedOffset1 = 1; 37 | fixedOffset2 = bufferSpeed / 100.; 38 | } 39 | } 40 | 41 | if (bufferElapsedMicros >= static_cast(bufferSpeed * 10)) { // default bufferSpeed of 100 * 10 = 1000, so 1 bufferframe per millisecond 42 | 43 | if (!bufferReverse) { 44 | bufferFrame += 1; 45 | if (bufferFrame >= static_cast(bufferLength - bufferEndOffset)) { // when reaching the end of the buffer... 46 | if (bufferDirection == 2) { // ...if direction 2 = ping pong: reverse the direction 47 | reverseBuffer(1); 48 | } else { 49 | bufferFrame = 0 + bufferStartOffset; // ...otherwise go back to start 50 | bufferRoundCount += 1; 51 | clearBufferNotes(0 + bufferStartOffset); 52 | } 53 | } 54 | } 55 | else { 56 | bufferFrame -= 1; 57 | if (bufferFrame <= static_cast(0 + bufferStartOffset)) { // when reaching the start of the buffer... 58 | if (bufferDirection == 2) { // ...if direction 2 = ping pong: re-reverse the direction 59 | reverseBuffer(0); 60 | } else { 61 | bufferFrame = bufferLength - bufferEndOffset; // ...otherwise go back to end 62 | bufferRoundCount += 1; 63 | clearBufferNotes(bufferLength - bufferEndOffset); // clear notes, because buffer length might have changed 64 | } 65 | } 66 | } 67 | bufferElapsedMicros = bufferElapsedMicros - bufferSpeed * 10; // reset the timer 68 | } 69 | 70 | for (int i = 0; i < maxBuffer; i++) { // go through the MIDI buffer 71 | if (buffer[i][2]) { // check if there is a note to be played 72 | if (bufferRoundCount != buffer[i][5]) { // check if note has been played already in this round 73 | 74 | if ( (!bufferReverse && bufferFrame > buffer[i][3] ) || 75 | ( bufferReverse && bufferFrame < buffer[i][3] ) ) { 76 | 77 | // calculate new velocity 78 | int newVelocity1 = buffer[i][2] - (buffer[i][6] / bufferFeedback); // add shift via I2M.B.FB 79 | if (newVelocity1 < 0) newVelocity1 = 0; // keep in bounds 80 | int newVelocity2 = newVelocity1 + bufferVelocityShift; // add shift via I2M.B.VSHIFT 81 | if (newVelocity2 < 0) newVelocity2 = 0; // keep in bounds 82 | buffer[i][2] = newVelocity2; // save for next round 83 | int newVelocity3 = newVelocity2 + bufferVelocityOffset; // add offset 84 | if (newVelocity3 < 0) newVelocity3 = 0; // keep in bounds 85 | 86 | // calculate new duration 87 | int newDuration1 = buffer[i][4] + bufferDurationShift; // add shift 88 | if (newDuration1 < 0) newDuration1 = 0; // keep in bounds 89 | buffer[i][4] = newDuration1; // save for next round 90 | int newDuration2 = (newDuration1 + bufferDurationOffset) / fixedOffset1 * fixedOffset2; // add offset 91 | if (newDuration2 < 0) newDuration2 = 0; // keep in bounds 92 | 93 | // calculate new note 94 | byte newNote1; 95 | byte newNote2; 96 | byte newIndex1; 97 | byte newIndex2; 98 | if (buffer[i][7] == 99) { 99 | newNote1 = buffer[i][1] + bufferPitchShift; // add shift 100 | if (newNote1 < 0) newNote1 = 0; // keep in bounds 101 | buffer[i][1] = newNote1; // save for next round 102 | newNote2 = newNote1 + bufferNoteOffset + (12 * fixedOffset1) - (12 * fixedOffset2); // add offset 103 | if (newNote2 < 0) newNote2 = 0; // keep in bounds 104 | } 105 | else { 106 | const byte index_ = buffer[i][8]; // the original index 107 | const byte note_ = buffer[i][1]; // the original note 108 | newIndex1 = buffer[i][9] + bufferPitchShift; 109 | buffer[i][9] = newIndex1; 110 | newIndex2 = newIndex1 + bufferNoteOffset + (7 * fixedOffset1) - (7 * fixedOffset2); // add offset 111 | newNote2 = note_ + getNoteFromIndexBuffer(buffer[i][7], newIndex2) - getNoteFromIndexBuffer(buffer[i][7], index_); 112 | if (newNote2 < 0) newNote2 = 0; 113 | } 114 | // if any of the values reached out of bound, clear the entry 115 | if (newVelocity3 <= 0 || newDuration2 <= 0 || newNote2 <= 0 || newNote2 > 127) { 116 | buffer[i][2] = 0; 117 | } 118 | // otherwise play the note 119 | else { 120 | buffer[i][5] = bufferRoundCount; // store round so note is note is not played again in this round 121 | midiNoteOn(buffer[i][0], newNote2, newVelocity3, newDuration2, 0, 99, 0); 122 | } 123 | } 124 | } 125 | } 126 | } 127 | 128 | } 129 | 130 | 131 | void clearBuffer() { 132 | for (int i = 0; i < maxBuffer; i++) { 133 | buffer[i][2] = 0; 134 | } 135 | } 136 | 137 | 138 | void reverseBuffer(bool reverse) { 139 | bufferOffset = bufferFrame; 140 | bufferReverse = reverse; 141 | bufferRoundCount += 1; 142 | 143 | clearBufferNotes(bufferOffset); 144 | } 145 | 146 | 147 | 148 | void clearBufferNotes(unsigned long position) { 149 | for (int i = 0; i < maxBuffer; i++) { 150 | if (buffer[i][2]) { 151 | if ( ( bufferReverse && buffer[i][3] > position ) || // for reverse, exclude notes after offset 152 | (!bufferReverse && buffer[i][3] < position ) ) { // for forward, exclude notes before offset 153 | buffer[i][5] = bufferRoundCount; 154 | } 155 | } 156 | } 157 | } -------------------------------------------------------------------------------- /firmware/i2c2midi_firmware/midiCCs.ino: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------------------- 2 | // MIDI CCs 3 | // ------------------------------------------------------------------------------------------- 4 | 5 | 6 | // function for handling MIDI CCs 7 | void midiCC(int channel, int controller, int value_, bool useRamp) { 8 | 9 | // keep values in range 10 | if (channel < 0 || channel >= channelsOut) return; 11 | if (controller < 0 || controller > 127) return; 12 | 13 | int offset = CCs[channel][controller][2]; 14 | int value = value_ + offset; 15 | if (value < 0) value = 0; 16 | if (value > 16383) value = 16383; 17 | 18 | int slewTime = CCs[channel][controller][1]; // get the set slew time for controller 19 | 20 | // if ramp is allowed and slew time higher than zero: use a ramp 21 | if (useRamp == true && slewTime != 0) { 22 | handleRamp(channel, controller, value, slewTime, 0); 23 | } 24 | // if ramp is not allowed and slew time higher than zero: 25 | // CC.SET, use a ramp with slew time = 1 to set it to new value immediately but using a ramp 26 | else if (useRamp == false && slewTime != 0) { 27 | handleRamp(channel, controller, value, 1, 0); 28 | } 29 | // if slewTime is zero, don't use a ramp 30 | else if (slewTime == 0) { 31 | sendMidiCC(channel, controller, scaleDown(value)); 32 | } 33 | CCs[channel][controller][0] = value; // store the new CC value in the CC array 34 | } 35 | 36 | 37 | // ------------------------------------------------------------------------------------------- 38 | 39 | 40 | // function for handling ramps 41 | void handleRamp(int channel, int controller, int value, int slewTime, bool type) { 42 | int oldValue = CCs[channel][controller][0]; // get the old CC value temporarily 43 | int rampToUse = 0; // set to zero, because no ramp is yet chosen 44 | // check if this controller is already assigned to a ramp, if yes: use the same ramp, if no: get a new ramp to use 45 | for (int i = 0; i < maxRamps; i++) { 46 | if (rampsAssignedCCs[i][0] == channel && rampsAssignedCCs[i][1] == controller) { 47 | rampToUse = i; // use the ramp to which this controller is already assigned 48 | break; 49 | } 50 | } 51 | if (!rampToUse) { // if there's not yet a ramp assigned ... 52 | rampToUse = getNextFreeRamp(); // check which new ramp to use 53 | rampsAssignedCCs[rampToUse][0] = channel; // assign channel to this ramp 54 | rampsAssignedCCs[rampToUse][1] = controller; // assign controller to this ramp 55 | rampsAssignedCCs[rampToUse][2] = type; // Type: 0 = CC, 1 = NRPN 56 | myRamps[rampToUse].go(oldValue, 1); // set the new ramp to the old value before using it 57 | } 58 | // start the ramp 59 | myRamps[rampToUse].go(value, slewTime); 60 | } 61 | 62 | 63 | // ------------------------------------------------------------------------------------------- 64 | 65 | 66 | // function for updating ramps 67 | void updateRamps() { 68 | for (int i = 0; i < maxRamps; i++) { // go through all ramps 69 | if (myRamps[i].isRunning()) { // check if the ramp is running 70 | int currentValue = myRamps[i].update(); // update the ramp 71 | //int currentValueScaled = scaleDown(currentValue); // scale the value down from 14 bit to 0..127 72 | if (scaleDown(currentValue) != lastRampValues[i]) { // if the updated ramp value is different... 73 | int channel = rampsAssignedCCs[i][0]; // get the channel of the ramp 74 | int controller = rampsAssignedCCs[i][1]; // get the controller of the ramp 75 | int type = rampsAssignedCCs[i][2]; // get the type: 0 = CC, 1 = NRPN 76 | if (type == 1) { 77 | sendNRPN(channel, controller, currentValue); // send NRPN 78 | } else { 79 | sendMidiCC(channel, controller, scaleDown(currentValue)); // send MIDI CC with new ramp value 80 | } 81 | } 82 | lastRampValues[i] = scaleDown(currentValue); // store the new value for comparison 83 | } 84 | } 85 | } 86 | 87 | 88 | // ------------------------------------------------------------------------------------------- 89 | 90 | 91 | // function for getting next free ramp to use 92 | int getNextFreeRamp() { 93 | rampCount += 1; // count one ramp up 94 | currentRamp = rampCount % maxRamps; // determine the current ramp number 95 | // check if next ramp number is still running; if yes, skip to next ramp number; 96 | // if there's no more space available, replace the ramp 97 | for (int i = 0; i < maxRamps; i++) { 98 | if (myRamps[currentRamp].isRunning()) { 99 | rampCount += 1; 100 | currentRamp = rampCount % maxRamps; 101 | } 102 | else { 103 | break; 104 | } 105 | } 106 | return currentRamp; 107 | } 108 | 109 | 110 | // ------------------------------------------------------------------------------------------- 111 | 112 | 113 | // functions to scale up/down between 0..127 and 14 bit range 114 | int scaleUp (int value) { 115 | return value * 129; // 129 == 16383 / 127 116 | } 117 | int scaleDown (int value) { 118 | int result = (value << 1) / 129; // multiply by 2 so we can round below 119 | return (result >> 1) + (result & 1); // divide by 2 and round 120 | } 121 | 122 | 123 | // ------------------------------------------------------------------------------------------- 124 | 125 | 126 | // function for sending MIDI CC 127 | void sendMidiCC(int channel, int controller, int value) { 128 | 129 | // check channel mute 130 | if (channelMute[channel] == 1 && channelSolo[channel] != 1) return; 131 | 132 | // check channel solo 133 | int solo = 0; 134 | for(int i = 0; i < channelsOut; i++) 135 | { 136 | solo = solo + channelSolo[i]; 137 | } 138 | if (solo > 0 && channelSolo[channel] != 1) return; 139 | 140 | 141 | if (isTRS(channel)) { 142 | MIDI.sendControlChange(controller, value, channel+1); 143 | #ifdef USB_DEVICE 144 | usbMIDI.sendControlChange(controller, value, channel+1); 145 | #endif 146 | } else { 147 | #ifdef MK2 148 | #ifdef MULTIPLEUSBOUT 149 | for (int i = 0; i < 2; i++) { 150 | if (* midiDeviceList[i] && channel == i+16) { 151 | midiDeviceList[i]->sendControlChange(controller, value, i+1); 152 | } 153 | } 154 | #else 155 | midiDevice.sendControlChange(controller, value, channel+1-16); 156 | #endif 157 | #endif 158 | } 159 | blinkLED(1); 160 | #ifdef DEBUG 161 | Serial.print("Sending MIDI CC: "); 162 | Serial.print(controller); Serial.print(", "); 163 | Serial.print("Ch: "); Serial.print(channel+1); Serial.print(", "); 164 | Serial.print("Val: "); Serial.println(value); 165 | #endif 166 | } -------------------------------------------------------------------------------- /firmware/i2c2midi_firmware/midiChord.ino: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------------------- 2 | // Chord 3 | // ------------------------------------------------------------------------------------------- 4 | 5 | // order of chord transformations: 6 | // REVERSE > ROTATE > TRANSPOSE > DISTORT > REFLECT > INVERT > STRUMMING 7 | 8 | 9 | // function for playing chord or getting chord note/velocity 10 | int playChord(int channel, int noteNumber, int velocity, int noteDuration, int chordNumber, bool getNote, bool getVelocity, byte index) { 11 | 12 | // keep values in range 13 | if (channel < 0 || channel >= channelsOut) return 0; 14 | if (noteNumber < 0 || noteNumber > 127) return 0; 15 | if (noteDuration < 0) return 0; 16 | if (chordNumber < 0 || chordNumber >= maxChords) return 0; 17 | 18 | currentChordLength = chordLength[chordNumber]; 19 | currentChordNoteCount = chordNoteCount[chordNumber]; 20 | 21 | // if no notes are defined for the chord, don't do anything 22 | if (currentChordLength == 0) return 0 ; 23 | 24 | // create a scaled chord (chordScaled) based on original chord and currentScale 25 | createChordScaled(chordNumber); 26 | 27 | // apply chord transformations to scaledChord 28 | applyTransformations(chordNumber); 29 | 30 | // calculate new chord length based on play direction 31 | int currentChordLength2 = calculateChordLengthByDirection(chordNumber); 32 | 33 | // randomize the note order if direction is random (4) 34 | if (chordDirection[chordNumber] == 4) { 35 | randomizeChordIndices(chordNumber, currentChordLength2); 36 | } 37 | 38 | int delay = 0; 39 | 40 | // if the chord should be played, go through all the chord notes 41 | int j_start = 0; 42 | int j_max = currentChordLength2; 43 | // if note or velocity is requested, calculate note and velocity only for given index 44 | if (getNote || getVelocity) { 45 | j_start = mod(index, currentChordLength2); 46 | j_max = index + 1; 47 | } 48 | 49 | // go through the chord notes 50 | for (int j = j_start; j < j_max; j++) { 51 | 52 | // get next note based on play direction 53 | int i = getNextChordNoteIndex(chordNumber, currentChordLength, currentChordLength2, j); 54 | 55 | const int chordNote = noteNumber + getNoteFromIndex(chordNumber, i); 56 | 57 | // Transformation: VELOCITY CURVE 58 | const int velocityCurved = getCurveValue(curveVelocity[chordNumber][0], j, currentChordLength2, velocity, curveVelocity[chordNumber][1], curveVelocity[chordNumber][2]); 59 | 60 | // if note or velocity is requested, return the values and stop the function 61 | if (getNote) return chordNote; 62 | if (getVelocity) return velocityCurved; 63 | 64 | if (j == 0) { 65 | midiNoteOn(channel, chordNote, velocityCurved, noteDuration, 1, chordNumber, chordScaled[0][i]); 66 | } 67 | else { 68 | // Transformation: STRUMMING 69 | int currentStrumming = chordStrumming[chordNumber]; 70 | 71 | // Transformation: TIME CURVE 72 | const int timeCurved = getCurveValue(curveTime[chordNumber][0], j, currentChordLength2, currentStrumming, curveTime[chordNumber][1], curveTime[chordNumber][2]) - currentStrumming; 73 | delay += currentStrumming + timeCurved; 74 | 75 | if (currentStrumming == 0) { 76 | midiNoteOn(channel, chordNote, velocityCurved, noteDuration, 1, chordNumber, chordScaled[0][i]); 77 | } else { 78 | scheduleNote(channel, chordNote, velocityCurved, noteDuration, delay, chordNumber, chordScaled[0][i]); 79 | } 80 | } 81 | } 82 | return 0; 83 | } 84 | 85 | 86 | // ------------------------------------------------------------------------------------------- 87 | 88 | 89 | // function to remove a note from the chord based on noteNumber 90 | void removeFromChord(int chordNumber, int noteNumber) { 91 | if (chordNumber < 0 || chordNumber >= maxChords) return; 92 | if (noteNumber < -127 || noteNumber > 127) return; 93 | int c = chordNumber; 94 | int position = -1; 95 | for(int j = 0; j < chordMaxLength; j++){ 96 | if(chord[c][j] == noteNumber){ // find the position of the note 97 | position = j; // store the position 98 | break; // stop the for loop 99 | } 100 | } 101 | if (position >= 0) { 102 | deleteFromChord(chordNumber, position); 103 | } 104 | } 105 | 106 | 107 | // function to insert a note into chord at a specific index 108 | void insertIntoChord(int8_t chordNumber, int8_t index, int8_t noteNumber) { 109 | if (chordNumber < 0 || chordNumber >= maxChords) return; 110 | int c = chordNumber; 111 | if (index < 0 || index > chordNoteCount[c]) return; 112 | if (noteNumber < -127 || noteNumber > 127) return; 113 | 114 | for (int i = chordMaxLength - 1; i > index; i--) { 115 | chord[c][i] = chord[c][i-1]; // shift note number values to the right by 1 index 116 | } 117 | chord[c][index] = noteNumber; // store new note number 118 | 119 | // set chord length automatically when new note is pushed 120 | int newChordNoteCount = chordNoteCount[c] + 1; 121 | if (newChordNoteCount > 8) newChordNoteCount = 8; 122 | chordNoteCount[c] = newChordNoteCount; 123 | chordLength[c] = newChordNoteCount; 124 | } 125 | 126 | 127 | // function to delete a note at specific index from chord 128 | void deleteFromChord(int8_t chordNumber, int8_t index) { 129 | if (chordNumber < 0 || chordNumber >= maxChords) return; 130 | int c = chordNumber; 131 | if (index < 0 || index > chordNoteCount[c]) return; 132 | int position = index; 133 | 134 | for (int i = position; i < chordMaxLength; i++) { // go through all elements right to the found position 135 | if (i == chordMaxLength) { 136 | chord[c][i] = 0; 137 | } else { 138 | chord[c][i] = chord[c][i+1]; // shift note number values to the left by 1 index 139 | } 140 | } 141 | 142 | // set chord length automatically when a note is removed 143 | int newChordNoteCount = chordNoteCount[c] - 1; 144 | if (newChordNoteCount < 0) newChordNoteCount = 0; 145 | chordNoteCount[c] = newChordNoteCount; 146 | chordLength[c] = newChordNoteCount; 147 | } 148 | 149 | 150 | // function to set specific index in chord 151 | void setChord(int8_t chordNumber, int8_t index, int8_t noteNumber) { 152 | if (chordNumber < 0 || chordNumber >= maxChords) return; 153 | int c = chordNumber; 154 | if (index < 0 || index > chordNoteCount[c]) return; 155 | if (noteNumber < 0 || noteNumber > 127) return; 156 | 157 | chord[c][index] = noteNumber; 158 | } 159 | 160 | 161 | // function to clear chord 162 | void clearChord(int chordNumber) { 163 | if (chordNumber < 0 || chordNumber >= maxChords) return; 164 | int c = chordNumber; 165 | for (int i = 0; i < chordMaxLength; i++) { 166 | chord[c][i] = 0; 167 | } 168 | chordNoteCount[c] = 0; 169 | chordLength[c] = 0; 170 | } 171 | 172 | 173 | // ------------------------------------------------------------------------------------------- 174 | 175 | 176 | // function to reverse chord 177 | void reverseChord() { 178 | 179 | int reversedChord[2][currentChordNoteCount]; 180 | for(int i = currentChordNoteCount-1; i >= 0; i--){ 181 | reversedChord[0][currentChordNoteCount-1-i] = chordScaled[0][i]; 182 | reversedChord[1][currentChordNoteCount-1-i] = chordScaled[1][i]; 183 | } 184 | for (int i = 0; i < currentChordNoteCount; i++) { 185 | chordScaled[0][i] = reversedChord[0][i]; 186 | chordScaled[1][i] = reversedChord[1][i]; 187 | } 188 | } 189 | 190 | 191 | // ------------------------------------------------------------------------------------------- 192 | 193 | 194 | // function to rotate chord left 195 | void rotateChordLeft(int amount) { 196 | if (amount < -127 || amount > 127 || amount == 0) return; 197 | 198 | for (int i = 0; i < amount; i++) { 199 | int firstElement0 = chordScaled[0][0]; 200 | int firstElement1 = chordScaled[1][0]; 201 | for (int i = 0; i < currentChordNoteCount-1; i++) { 202 | chordScaled[0][i] = chordScaled[0][i+1]; // shift left 203 | chordScaled[1][i] = chordScaled[1][i+1]; // shift left 204 | } 205 | chordScaled[0][currentChordNoteCount-1] = firstElement0; 206 | chordScaled[1][currentChordNoteCount-1] = firstElement1; 207 | } 208 | } 209 | 210 | 211 | // function to rotate chord right 212 | void rotateChordRight(int amount) { 213 | if (amount < -127 || amount > 127 || amount == 0) return; 214 | for (int i = 0; i < amount; i++) { 215 | int lastElement0 = chordScaled[0][currentChordNoteCount-1]; 216 | int lastElement1 = chordScaled[1][currentChordNoteCount-1]; 217 | for (int i = currentChordNoteCount-1; i > 0; i--) { 218 | chordScaled[0][i] = chordScaled[0][i-1]; // shift right 219 | chordScaled[1][i] = chordScaled[1][i-1]; // shift right 220 | } 221 | chordScaled[0][0] = lastElement0; 222 | chordScaled[1][0] = lastElement1; 223 | } 224 | } 225 | 226 | 227 | // ------------------------------------------------------------------------------------------- 228 | 229 | 230 | int getStretchedNote(int i, int value, int position, int inbetween) { 231 | 232 | int note = 0; 233 | 234 | if (i <= position) { 235 | note = chordScaled[0][i] + (value * (i-position-inbetween)); 236 | } else { 237 | note = chordScaled[0][i] + (value * (i-position)); 238 | } 239 | return note; 240 | } 241 | 242 | 243 | 244 | 245 | 246 | // ------------------------------------------------------------------------------------------- 247 | 248 | 249 | // function to calculate notes for chord reflection 250 | int getReflectedNote(int noteIndex, int chordNumber) { 251 | int reflectionValue = chordReflection[chordNumber][0]; 252 | int reflectionPoint = chordReflection[chordNumber][1]; 253 | int note; 254 | int reflectionValue2 = 0; 255 | if (mod(reflectionValue, 2) != 0 ) { // if odd number 256 | chordReversedQ = !chordReversedQ; 257 | int distance = reflectionPoint - noteIndex; 258 | note = reflectionPoint + distance; 259 | if (reflectionValue > 1) { 260 | reflectionValue2 = reflectionValue - 1; 261 | } 262 | } else { 263 | note = noteIndex; 264 | reflectionValue2 = reflectionValue; 265 | } 266 | 267 | int addon = (reflectionPoint + (reflectionPoint - chordScaled[0][currentChordNoteCount-1])) * reflectionValue2; 268 | int finalNote = note + addon; 269 | return finalNote; 270 | } 271 | 272 | 273 | // ------------------------------------------------------------------------------------------- 274 | 275 | 276 | // function to get inversion addon for a chord note 277 | int getInversionAddon(int noteIndex_, int chordNumber) { 278 | int currentInversion = chordInversion[chordNumber]; 279 | int inversionAddon = 0; 280 | int noteIndex = noteIndex_; 281 | int octaveMultiplier = 12; 282 | 283 | if (currentScaleChord[chordNumber] != 0) octaveMultiplier = 7; 284 | if (!chordReversedQ) { 285 | noteIndex = mod(noteIndex_ + currentInversion, currentChordNoteCount); 286 | } else { 287 | noteIndex = mod(noteIndex_ , currentChordNoteCount); 288 | } 289 | if (currentInversion > 0) { 290 | inversionAddon = floor((currentInversion + ((currentChordNoteCount-1) - noteIndex)) / currentChordNoteCount) * octaveMultiplier; 291 | } else if (currentInversion < 0) { 292 | inversionAddon = floor((currentInversion + (0 - noteIndex)) / currentChordNoteCount) * octaveMultiplier; 293 | } 294 | return inversionAddon; 295 | } 296 | 297 | 298 | // ------------------------------------------------------------------------------------------- 299 | 300 | 301 | // function to set current scale based on a chord 302 | void setCurrentScale(int chordNumber) { 303 | 304 | // scale is set in three steps: 305 | // 1: notes from original chord are stored unchanged in chordScaled 306 | // 2: chord transformations are applied to chordScaled 307 | // 3: final notes are calculated from chordScaled and added to currentScale 308 | const int scaleChordNumber = currentScaleChord[chordNumber]; 309 | 310 | if (scaleChordNumber >= 0) { 311 | 312 | currentChordLength = chordLength[scaleChordNumber]; 313 | currentChordNoteCount = chordNoteCount[scaleChordNumber]; 314 | currentScaleLength[chordNumber] = chordNoteCount[scaleChordNumber]; 315 | 316 | // 1: add notes in chord to chordScaled (notes as indexes; deltas are all zero) 317 | for (int i = 0; i < currentChordNoteCount; i++) { 318 | chordScaled[0][i] = chord[scaleChordNumber][currentScaleLength[chordNumber] - 1 - i]; // indexes 319 | chordScaled[1][i] = 0; // deltas 320 | } 321 | 322 | // 2: apply transformations to chordScaled 323 | applyTransformations(scaleChordNumber); 324 | 325 | // 3: calculate notes from indexes in chordScaled and add them to currentScale 326 | for (int i = 0; i < currentScaleLength[chordNumber]; i++) { 327 | const int scaleLengthChromatic = 12; 328 | const int noteIndex = chordScaled[0][i]; 329 | int octave = 0; 330 | if (noteIndex >= 0) { 331 | octave = (noteIndex / scaleLengthChromatic) * 12; // calc octave from shifted index 332 | } else { 333 | octave = (((noteIndex+1) / scaleLengthChromatic) * 12) - 12; // calc octave from shifted index 334 | } 335 | const int finalNote = noteIndex + octave; // final note incl octave and delta 336 | currentScale[chordNumber][i] = finalNote; 337 | } 338 | 339 | } 340 | } 341 | 342 | 343 | // ------------------------------------------------------------------------------------------- 344 | 345 | 346 | // function to store the current chord as scale indexes and their deltas 347 | void createChordScaled(int chordNumber) { 348 | for (int i = 0; i < chordNoteCount[chordNumber]; i++) { 349 | const int noteChord = chord[chordNumber][i]; // get the note of the original chord 350 | const int noteChordIndex = getNearest(chordNumber, mod(noteChord, 12)); // calc the note's nearest index in the scale 351 | const int delta = noteChord - currentScale[chordNumber][mod(noteChordIndex, currentScaleLength[chordNumber])]; // calc delta betw orgiginal note and note in scale 352 | chordScaled[0][i] = noteChordIndex; 353 | chordScaled[1][i] = delta; 354 | } 355 | reverseChord(); 356 | } 357 | 358 | 359 | int getNearest(int chordNumber, int x) { 360 | for (int i = 0; i < currentScaleLength[chordNumber]; i++) { 361 | if (x == currentScale[chordNumber][i]) { 362 | return i; 363 | } 364 | } 365 | for (int i = 0; i < currentScaleLength[chordNumber]-1; i++) { 366 | if ( 367 | (x > currentScale[chordNumber][i] && x < currentScale[chordNumber][i+1]) 368 | || 369 | (x < currentScale[chordNumber][i] && x > currentScale[chordNumber][i+1]) 370 | ) { 371 | return i; 372 | } 373 | } 374 | return 0; 375 | } 376 | 377 | 378 | // ------------------------------------------------------------------------------------------- 379 | 380 | 381 | // function to calculate the final note from the current scaled chord and an index 382 | int getNoteFromIndex(int chordNumber, int noteIndex_) { 383 | const int noteIndex = chordScaled[0][noteIndex_]; 384 | const int delta = chordScaled[1][noteIndex_]; 385 | const int noteScaled = currentScale[chordNumber][mod(noteIndex, currentScaleLength[chordNumber])]; // get the note in scale from shifted index 386 | int octave = 0; 387 | if (noteIndex >= 0) { 388 | octave = (noteIndex / currentScaleLength[chordNumber]) * 12; // calc octave from shifted index 389 | } else { 390 | octave = (((noteIndex+1) / currentScaleLength[chordNumber]) * 12) - 12; // calc octave from shifted index 391 | } 392 | const int finalNote = noteScaled + octave + delta; // final note incl octave and delta 393 | 394 | return finalNote; 395 | } 396 | 397 | // function to calculate the final note from the current scaled chord and an index 398 | int getNoteFromIndexBuffer(int chordNumber, int noteIndex) { 399 | //const int noteIndex = chordScaled[0][noteIndex_]; 400 | //const int delta = chordScaled[1][noteIndex_]; 401 | const int noteScaled = currentScale[chordNumber][mod(noteIndex, currentScaleLength[chordNumber])]; // get the note in scale from shifted index 402 | int octave = 0; 403 | if (noteIndex >= 0) { 404 | octave = (noteIndex / currentScaleLength[chordNumber]) * 12; // calc octave from shifted index 405 | } else { 406 | octave = (((noteIndex+1) / currentScaleLength[chordNumber]) * 12) - 12; // calc octave from shifted index 407 | } 408 | //const int finalNote = noteScaled + octave + delta; // final note incl octave and delta 409 | const int finalNote = noteScaled + octave; // final note incl octave and delta 410 | 411 | return finalNote; 412 | } 413 | 414 | 415 | // ------------------------------------------------------------------------------------------- 416 | 417 | 418 | // modulo helper function (that handles negative values correctly) 419 | int mod(int a, int b) { 420 | int c = a % b; 421 | return (c < 0) ? c + b : c; 422 | } 423 | 424 | 425 | // ------------------------------------------------------------------------------------------- 426 | 427 | 428 | void applyTransformations(int chordNumber) { 429 | 430 | // Transformation: REVERSE 431 | if (chordReverse[chordNumber]) { 432 | reverseChord(); 433 | chordReversedQ = 1; 434 | } else { 435 | chordReversedQ = 0; 436 | } 437 | 438 | // Transformation: ROTATE 439 | int currentRotate = chordRotate[chordNumber]; 440 | if (currentRotate != 0) { 441 | if (currentRotate > 0) rotateChordRight(currentRotate); 442 | else if (currentRotate < 0) rotateChordLeft(abs(currentRotate)); 443 | } 444 | 445 | // Transformation: STRETCH (distort) 446 | int stretchValue = chordStretch[chordNumber][0]; 447 | int stretchAnchorPoint = chordStretch[chordNumber][1]; 448 | int stretchPosition = 0; 449 | bool stretchInbetween = 0; 450 | // calculate where the anchor point is in the chord 451 | for (int c = 0; c < currentChordNoteCount; c++) { 452 | if (chordScaled[0][0] > stretchAnchorPoint) { 453 | stretchPosition = -1; break; 454 | } 455 | if (chordScaled[0][c] == stretchAnchorPoint) { 456 | stretchPosition = c; break; 457 | } 458 | if (chordScaled[0][c] < stretchAnchorPoint && chordScaled[0][c+1] > stretchAnchorPoint) { 459 | stretchPosition = c; 460 | stretchInbetween = 1; break; 461 | } 462 | else { 463 | stretchPosition = currentChordNoteCount; 464 | } 465 | } 466 | // get the note based on stretch value and anchor point position 467 | for (int i = 0; i < currentChordNoteCount; i++) { 468 | chordScaled[0][i] = getStretchedNote(i, stretchValue, stretchPosition, stretchInbetween); 469 | } 470 | 471 | // Transformation: SHIFT (transpose) 472 | for (int i = 0; i < currentChordNoteCount; i++) { 473 | const int noteIndex = chordScaled[0][i] + chordShift[chordNumber]; // add shift 474 | chordScaled[0][i] = noteIndex; 475 | } 476 | 477 | // Transformation: REFLECT 478 | for (int i = 0; i < currentChordNoteCount; i++) { 479 | chordScaled[0][i] = getReflectedNote(chordScaled[0][i], chordNumber); 480 | } 481 | 482 | // Transformation: INVERT 483 | if (chordInversion[chordNumber] > 0) { 484 | if (!chordReversedQ) { 485 | rotateChordLeft(chordInversion[chordNumber]); 486 | } else { 487 | rotateChordRight(chordInversion[chordNumber]); 488 | } 489 | } 490 | else if (chordInversion[chordNumber] < 0) { 491 | if (!chordReversedQ) { rotateChordRight(abs(chordInversion[chordNumber])); 492 | } else { 493 | rotateChordLeft(abs(chordInversion[chordNumber])); 494 | } 495 | } 496 | for (int i = 0; i < currentChordNoteCount; i++) { 497 | int inversionAddon = getInversionAddon(i, chordNumber); 498 | chordScaled[0][i] = chordScaled[0][i] + inversionAddon; 499 | } 500 | 501 | } 502 | 503 | 504 | // ------------------------------------------------------------------------------------------- 505 | 506 | 507 | int getCurveValue(byte curveType, int step, int numberOfSteps, int originalValue, float percStart, float percEnd){ 508 | float valueStart = (originalValue / 100.) * percStart; 509 | float valueEnd = (originalValue / 100.) * percEnd; 510 | 511 | if (curveType == 0) { 512 | return originalValue; 513 | } 514 | 515 | // linear 516 | else if (curveType == 1) { 517 | return valueStart + ((valueEnd - valueStart) / (numberOfSteps - 1) * step); 518 | } 519 | 520 | // exponential 521 | else if (curveType == 2) { 522 | return valueStart + ((valueEnd - valueStart) * pow((1. / (numberOfSteps - 1)) * step, 3)); 523 | } 524 | 525 | // triangle 526 | else if (curveType == 3) { 527 | int period = numberOfSteps/2; 528 | return valueStart + (((valueEnd - valueStart) / period) * (period - abs(step % (2 * period) - period))); 529 | } 530 | 531 | // alternating 532 | else if (curveType == 4) { 533 | if (step % 2) return valueEnd; 534 | else return valueStart; 535 | } 536 | 537 | // random 538 | else if (curveType == 5) { 539 | if (valueStart > valueEnd) { 540 | return random(valueEnd + 1, valueStart); 541 | } else { 542 | return random(valueStart, int(valueEnd) + 1); 543 | } 544 | } 545 | 546 | return originalValue; 547 | 548 | } 549 | 550 | 551 | // ------------------------------------------------------------------------------------------- 552 | 553 | 554 | byte calculateChordLengthByDirection(int chordNumber) { 555 | // calculate chord length based on play direction 556 | int currentChordLength2 = currentChordLength; // forward, backward, inside out, outside in, random 557 | if (chordDirection[chordNumber] == 7) currentChordLength2 = (currentChordLength * 2) - 1; // pingpong 558 | else if (chordDirection[chordNumber] == 8) currentChordLength2 = (currentChordLength * 2); // ping & pong 559 | else if (chordDirection[chordNumber] == 5 || chordDirection[chordNumber] == 6) currentChordLength2 = currentChordLength + (currentChordLength - 2); // bottom repeat or top repeat 560 | return currentChordLength2; 561 | } 562 | 563 | 564 | // ------------------------------------------------------------------------------------------- 565 | 566 | 567 | byte getNextChordNoteIndex(int chordNumber, int chordLength, int chordLength2, int index) { 568 | int i = 0; 569 | int j = index; 570 | 571 | // forward 572 | if (chordDirection[chordNumber] == 0) i = j; 573 | 574 | // backward 575 | else if (chordDirection[chordNumber] == 1) i = (chordLength - 1) - j; 576 | 577 | // inside out 578 | else if (chordDirection[chordNumber] == 2) { 579 | int start = (chordLength - 1) / 2; 580 | if (chordLength % 2) { // odd chord length 581 | i = start; 582 | for (int k = 0; k <= j; k++) { 583 | if (k % 2) i -= k; 584 | else i += k; 585 | } 586 | } 587 | else { // even chord length 588 | i = start; 589 | for (int k = 0; k <= j; k++) { 590 | if (k % 2) i += k; 591 | else i -= k; 592 | } 593 | } 594 | } 595 | 596 | // outside in 597 | else if (chordDirection[chordNumber] == 3) { 598 | i = 0; 599 | if (j != 0) { 600 | for (int k = 1; k <= j; k++) { 601 | if (k % 2) i = i + chordLength - k; 602 | else i = i - chordLength + k; 603 | } 604 | } 605 | } 606 | 607 | // random 608 | else if (chordDirection[chordNumber] == 4) { 609 | i = chordRandomIndices[chordNumber][j]; 610 | } 611 | 612 | // bottom repeat 613 | else if (chordDirection[chordNumber] == 5) { 614 | if (j % 2) i = j / 2 + 1; 615 | else i = 0; 616 | } 617 | 618 | // top repeat 619 | else if (chordDirection[chordNumber] == 6) { 620 | if (j % 2) i = chordLength - 1; 621 | else i = j - (j / 2); 622 | } 623 | 624 | // pingpong 625 | else if (chordDirection[chordNumber] == 7) { 626 | i = (chordLength - 1) - abs(j - (chordLength - 1)); 627 | } 628 | // ping & pong 629 | else if (chordDirection[chordNumber] == 8) { 630 | if (j < chordLength2 / 2) i = j; 631 | else i = (chordLength2 - 1) - j; 632 | } 633 | 634 | return i; 635 | } 636 | 637 | 638 | // ------------------------------------------------------------------------------------------- 639 | 640 | 641 | void randomizeChordIndices(int chordNumber, int chordLength) { 642 | 643 | // fill it with 0,1,2,... 644 | for(int i = 0; i < chordLength; i++) { 645 | chordRandomIndices[chordNumber][i] = i; 646 | } 647 | 648 | // shuffle it 649 | for(int i = 0; i < chordLength; i++) { 650 | int j = random(i, chordLength); 651 | int t = chordRandomIndices[chordNumber][i]; 652 | chordRandomIndices[chordNumber][i] = chordRandomIndices[chordNumber][j]; 653 | chordRandomIndices[chordNumber][j] = t; 654 | } 655 | 656 | } -------------------------------------------------------------------------------- /firmware/i2c2midi_firmware/midiMisc.ino: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------------------- 2 | // MIDI misc 3 | // ------------------------------------------------------------------------------------------- 4 | 5 | 6 | // function for sending MIDI Program Change 7 | void sendMidiProgramChange(int channel, int programNumber) { 8 | 9 | // keep values in range 10 | if (channel < 0 || channel >= channelsOut) return; 11 | if (programNumber < 0 || programNumber > 127) return; 12 | 13 | // check channel mute 14 | if (channelMute[channel] == 1 && channelSolo[channel] != 1) return; 15 | 16 | // check channel solo 17 | int solo = 0; 18 | for(int i = 0; i < channelsOut; i++) 19 | { 20 | solo = solo + channelSolo[i]; 21 | } 22 | if (solo > 0 && channelSolo[channel] != 1) return; 23 | 24 | if (isTRS(channel)) { 25 | MIDI.sendProgramChange(programNumber, channel+1); 26 | #ifdef USB_DEVICE 27 | usbMIDI.sendProgramChange(programNumber, channel+1); 28 | #endif 29 | } else { 30 | #ifdef MK2 31 | midiDevice.sendProgramChange(programNumber, channel+1-16); 32 | #endif 33 | } 34 | blinkLED(1); 35 | } 36 | 37 | 38 | // ------------------------------------------------------------------------------------------- 39 | 40 | 41 | // function for sending MIDI Pitch Bend 42 | void sendMidiPitchBend(int channel, int value) { 43 | 44 | // keep values in range 45 | if (channel < 0 || channel >= channelsOut) return; 46 | if (value < -8192) value = -8192; 47 | else if (value > 8191) value = 8191; 48 | 49 | // check channel mute 50 | if (channelMute[channel] == 1 && channelSolo[channel] != 1) return; 51 | 52 | // check channel solo 53 | int solo = 0; 54 | for(int i = 0; i < channelsOut; i++) 55 | { 56 | solo = solo + channelSolo[i]; 57 | } 58 | if (solo > 0 && channelSolo[channel] != 1) return; 59 | 60 | if (isTRS(channel)) { 61 | MIDI.sendPitchBend(value, channel+1); 62 | #ifdef USB_DEVICE 63 | usbMIDI.sendPitchBend(value, channel+1); 64 | #endif 65 | } else { 66 | #ifdef MK2 67 | midiDevice.sendPitchBend(value, channel+1-16); 68 | #endif 69 | } 70 | blinkLED(1); 71 | } 72 | 73 | 74 | // ------------------------------------------------------------------------------------------- 75 | 76 | 77 | // function for sending MIDI Aftertouch 78 | void sendMidiAftertouch(int channel, int value) { 79 | 80 | // keep values in range 81 | if (channel < 0 || channel >= channelsOut) return; 82 | if (value < 0) value = 0; 83 | if (value > 127) value = 127; 84 | 85 | // check channel mute 86 | if (channelMute[channel] == 1 && channelSolo[channel] != 1) return; 87 | 88 | // check channel solo 89 | int solo = 0; 90 | for(int i = 0; i < channelsOut; i++) 91 | { 92 | solo = solo + channelSolo[i]; 93 | } 94 | if (solo > 0 && channelSolo[channel] != 1) return; 95 | 96 | if (isTRS(channel)) { 97 | MIDI.sendAfterTouch(value, channel+1); 98 | #ifdef USB_DEVICE 99 | usbMIDI.sendAfterTouch(value, channel+1); 100 | #endif 101 | } else { 102 | #ifdef MK2 103 | midiDevice.sendAfterTouch(value, channel+1-16); 104 | #endif 105 | } 106 | blinkLED(1); 107 | } 108 | 109 | 110 | // ------------------------------------------------------------------------------------------- 111 | 112 | 113 | // function for sending MIDI Clock 114 | void sendMidiClock() { 115 | MIDI.sendRealTime(midi::Clock); 116 | #ifdef USB_DEVICE 117 | usbMIDI.sendRealTime(usbMIDI.Clock); 118 | #endif 119 | #ifdef MK2 120 | midiDevice.sendRealTime(midiDevice.Clock); 121 | #endif 122 | } 123 | 124 | 125 | // ------------------------------------------------------------------------------------------- 126 | 127 | 128 | // function for sending MIDI Clock Start 129 | void sendMidiClockStart() { 130 | MIDI.sendRealTime(midi::Start); 131 | #ifdef USB_DEVICE 132 | usbMIDI.sendRealTime(usbMIDI.Start); 133 | #endif 134 | #ifdef MK2 135 | midiDevice.sendRealTime(midiDevice.Start); 136 | #endif 137 | } 138 | 139 | 140 | // ------------------------------------------------------------------------------------------- 141 | 142 | 143 | // function for sending MIDI Clock Stop 144 | void sendMidiClockStop() { 145 | MIDI.sendRealTime(midi::Stop); 146 | #ifdef USB_DEVICE 147 | usbMIDI.sendRealTime(usbMIDI.Stop); 148 | #endif 149 | #ifdef MK2 150 | midiDevice.sendRealTime(midiDevice.Stop); 151 | #endif 152 | } 153 | 154 | 155 | // ------------------------------------------------------------------------------------------- 156 | 157 | 158 | // function for sending MIDI Clock Continue 159 | void sendMidiClockContinue() { 160 | MIDI.sendRealTime(midi::Continue); 161 | #ifdef USB_DEVICE 162 | usbMIDI.sendRealTime(usbMIDI.Continue); 163 | #endif 164 | #ifdef MK2 165 | midiDevice.sendRealTime(midiDevice.Continue); 166 | #endif 167 | } 168 | 169 | 170 | // ------------------------------------------------------------------------------------------- 171 | 172 | 173 | // MIDI panic 174 | void panic() { 175 | 176 | sendMidiClockStop(); 177 | 178 | // send note offs and reset ratchets and repeats 179 | for (int j=0; j < 16; j++) { 180 | for (int i=0; i <= 127; i++) { 181 | midiNoteOff(j, i); 182 | } 183 | } 184 | 185 | setDefaults(); 186 | 187 | } 188 | 189 | 190 | // ------------------------------------------------------------------------------------------- 191 | 192 | 193 | void setDefaults() { 194 | 195 | for (int i = 0; i < channelsOut; i++) { 196 | channelMute[i] = 0; 197 | channelSolo[i] = 0; 198 | currentNoteDuration[i] = 100; 199 | currentNoteShift[i] = 0; 200 | currentRepetition[i] = 1; 201 | currentRatcheting[i] = 1; 202 | noteUpperLimit[i] = 127; 203 | noteLowerLimit[i] = 0; 204 | noteLimitMode[i] = 0; 205 | for (int j = 0; j < 127; j++) { 206 | CCs[i][j][0] = 0; 207 | CCs[i][j][1] = 0; 208 | CCs[i][j][2] = 0; 209 | } 210 | } 211 | 212 | // reset NRPNs 213 | for (int j = 0; j < maxNRPNs; j++) { 214 | NRPNs[j][2] = 0; 215 | NRPNs[j][3] = 0; 216 | } 217 | 218 | // reset ratchets and repeats 219 | for (int j=0; j < channelsOut; j++) { 220 | for (int i=0; i < maxNotes; i++) { 221 | notes[j][i][5] = 0; // reset ratchet count 222 | notes[j][i][6] = 0; // reset repeat count 223 | } 224 | } 225 | 226 | // reset scheduled notes 227 | for (int i = 0; i < maxNotesScheduled; i++) { 228 | for (int j = 0; j < 5; j++) { 229 | scheduledNotes[i][j] = 0; 230 | } 231 | scheduledNoteCount -= 1; 232 | } 233 | 234 | // reset chords 235 | for (int i = 0; i < maxChords; i++) { 236 | clearChord(i); 237 | chordReverse[i] = 0; 238 | chordRotate[i] = 0; 239 | chordInversion[i] = 0; 240 | chordStrumming[i] = 0; 241 | chordShift[i] = 0; 242 | chordStretch[i][0] = 0; 243 | chordStretch[i][1] = 0; 244 | chordReflection[i][0] = 0; 245 | chordReflection[i][1] = 0; 246 | currentScaleChord[i] = 0; 247 | currentScaleLength[i] = 12; 248 | for (int j = 0; j < 12; j++) { 249 | currentScale[i][j] = j; 250 | } 251 | curveVelocity[i][0] = 0; 252 | curveVelocity[i][1] = 100; 253 | curveVelocity[i][2] = 100; 254 | curveTime[i][0] = 0; 255 | curveTime[i][1] = 100; 256 | curveTime[i][2] = 100; 257 | chordDirection[i] = 0; 258 | 259 | } 260 | 261 | // reset USB MIDI in 262 | latch = true; 263 | lastChannelIn = 1; 264 | lastNoteIn = 0; 265 | lastVelocityIn = 0; 266 | lastNoteOffIn = 0; 267 | lastCIn = 0; 268 | lastCCIn = 0; 269 | 270 | // reset buffer 271 | bufferRecord = 0; 272 | bufferLength = 10; 273 | bufferStartOffset = 0; 274 | bufferEndOffset = 0; 275 | bufferDirection = 0; 276 | bufferSpeed = 100; 277 | bufferFeedback = 8; 278 | bufferPitchShift = 0; 279 | bufferDurationShift = 0; 280 | bufferVelocityShift = 0; 281 | bufferNoteOffset = 0; 282 | bufferVelocityOffset = 0; 283 | bufferDurationOffset = 0; 284 | bufferMode = 0; 285 | bufferReverse = 0; 286 | 287 | 288 | 289 | } -------------------------------------------------------------------------------- /firmware/i2c2midi_firmware/midiNotes.ino: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------------------- 2 | // Notes 3 | // ------------------------------------------------------------------------------------------- 4 | 5 | 6 | // function for getting output type (TRS or USB) for channel number 7 | bool isTRS(int channel) { 8 | if (channel < 0 || channel >= channelsOut) return 1; 9 | return channel >= 0 && channel < 16; // if channel is 0..15 -> true -> TRS 10 | } 11 | 12 | 13 | // ------------------------------------------------------------------------------------------- 14 | 15 | 16 | // function for handling MIDI Note Ons 17 | void midiNoteOn(int channel, int noteNumber_, int velocity, int noteDuration, bool toBuffer, int chordNumber, int noteIndex) { 18 | 19 | // check channel mute 20 | if (channelMute[channel] == 1 && channelSolo[channel] != 1) return; 21 | 22 | // check channel solo 23 | int solo = 0; 24 | for(int i = 0; i < channelsOut; i++) 25 | { 26 | solo = solo + channelSolo[i]; 27 | } 28 | if (solo > 0 && channelSolo[channel] != 1) return; 29 | 30 | // keep values in range 31 | if (channel < 0 || channel >= channelsOut) return; 32 | int noteNumberUnlimited = noteNumber_ + currentNoteShift[channel]; 33 | byte noteNumber = getLimitedNote(channel, noteNumberUnlimited); 34 | 35 | if (noteNumber < 0 || noteNumber > 127) return; 36 | if (noteDuration < 1) return; 37 | if (velocity < 1) { 38 | sendMidiNoteOff(channel, noteNumber); // velocity = 0 is treated as Note Off 39 | return; 40 | } 41 | if (velocity > 127) velocity = 127; 42 | 43 | // check if this note is already playing; if yes, send note off first 44 | for (int i=0; i < maxNotes; i++) { 45 | if (notes[channel][i][0] == noteNumber && notes[channel][i][3] == 1) { 46 | sendMidiNoteOff(channel, notes[channel][i][0]); 47 | notes[channel][i][3] = 0; 48 | } 49 | } 50 | noteCount[channel] += 1; // count one note up 51 | currentNote[channel] = noteCount[channel] % maxNotes; // determine the current note slot 52 | // check if next note slot is free; if no, skip to next note slot; 53 | for (int i=0; i < maxNotes; i++) { 54 | if (notes[channel][currentNote[channel]][3] == 1) { // slot not free ... 55 | noteCount[channel] += 1; // ... so skip to the next 56 | currentNote[channel] = noteCount[channel] % maxNotes; 57 | } 58 | else { 59 | break; // slot is free, we can stop the for loop 60 | } 61 | } 62 | // if no slot was empty, and the note in the oldest slot is still playing, send a note off 63 | if (notes[channel][currentNote[channel]][3] == 1) { 64 | sendMidiNoteOff(channel, notes[channel][currentNote[channel]][0]); 65 | } 66 | 67 | int newNoteDuration = noteDuration; 68 | 69 | if (currentRepetition[channel] > 1 || currentRatcheting[channel] > 1) { 70 | newNoteDuration = noteDuration / currentRatcheting[channel] * ratchetingLength / 100; 71 | if (newNoteDuration <= 0) return; 72 | notes[channel][currentNote[channel]][5] = currentRepetition[channel] * currentRatcheting[channel]; 73 | } 74 | 75 | // store the values for the note in the notes array 76 | notes[channel][currentNote[channel]][0] = noteNumber; // note number 77 | notes[channel][currentNote[channel]][1] = millis(); // note start time 78 | notes[channel][currentNote[channel]][2] = newNoteDuration; // note duration 79 | notes[channel][currentNote[channel]][3] = 1; // note is on 80 | notes[channel][currentNote[channel]][4] = velocity; // note is on 81 | 82 | sendMidiNoteOn(channel, noteNumber, velocity); 83 | 84 | // record outoing notes to MIDI buffer: 85 | // only "inital" notes are recorded to the buffer; 86 | // notes that are triggered from the buffer itself are not recorded to the buffer 87 | if (toBuffer) { 88 | // notes are only recorded, if recording is on 89 | if (bufferRecord) { 90 | recordToBuffer(channel, noteNumber - currentNoteShift[channel], velocity, millis(), newNoteDuration, chordNumber, noteIndex); 91 | } 92 | } 93 | 94 | } 95 | 96 | 97 | // ------------------------------------------------------------------------------------------- 98 | 99 | 100 | // function for checking note duration 101 | void checkNoteDurations() { 102 | unsigned long currentTime = millis(); // get current time 103 | for (int j=0; j < channelsOut; j++) { // go through all channels 104 | for (int i=0; i < maxNotes; i++) { // go through all notes 105 | 106 | if (notes[j][i][3] != 0 && notes[j][i][2] != 0) { // check if note is currently playing and duration is not 0 107 | if (currentTime - notes[j][i][1] > notes[j][i][2]) { // if yes, check if the note duration has been reached 108 | sendMidiNoteOff(j, notes[j][i][0]); // if yes, send MIDI Note off 109 | notes[j][i][3] = 0; // set note on/off to off 110 | } 111 | } 112 | 113 | // note repetition & ratcheting 114 | if (currentRepetition[j] > 1 || currentRatcheting[j] > 1) { // if racheting or repetition is set than 1 115 | if (notes[j][i][5] > 1) { // index 5 is ratchet/rep count, do if higher than 1 116 | if (currentTime - notes[j][i][1] > notes[j][i][2] * 100 / ratchetingLength) { 117 | notes[j][i][1] = millis(); // note start time 118 | notes[j][i][3] = 1; // set note is on 119 | sendMidiNoteOn(j, notes[j][i][0], notes[j][i][4]); // send same note with same velocity 120 | notes[j][i][5] -= 1; // update ratchet count 121 | } 122 | } 123 | } 124 | 125 | } 126 | } 127 | } 128 | 129 | 130 | // ------------------------------------------------------------------------------------------- 131 | 132 | 133 | // function for handling MIDI Note Offs 134 | void midiNoteOff(int channel, int noteNumber) { 135 | if (channel < 0 || channel >= channelsOut) return; 136 | if (noteNumber < 0 || noteNumber > 127) return; 137 | sendMidiNoteOff(channel, noteNumber); 138 | } 139 | 140 | 141 | // ------------------------------------------------------------------------------------------- 142 | // Note History 143 | 144 | 145 | // function for adding a received note number and velocity to the note history 146 | void addToNoteHistoryIn(int channel, int noteNumber, int velocity) { 147 | if (channel < 0 || channel >= channelsOut) return; 148 | if (noteNumber < 0 || noteNumber > 127) return; 149 | if (velocity < 0) return; 150 | if (velocity > 127) velocity = 127; 151 | for (int i = noteHistoryInLength; i > 0; i--) { 152 | noteHistoryIn[channel][i][0] = noteHistoryIn[channel][i-1][0]; // shift note number values to the right by 1 index 153 | noteHistoryIn[channel][i][1] = noteHistoryIn[channel][i-1][1]; // shift note velocity values to the right by 1 index 154 | } 155 | noteHistoryIn[channel][0][0] = noteNumber; // store new note number at index 0 156 | noteHistoryIn[channel][0][1] = velocity; // store new note velocity at index 0 157 | } 158 | 159 | 160 | // ------------------------------------------------------------------------------------------- 161 | 162 | 163 | // function for removing a received note number and velocity from the note history 164 | void removeFromNoteHistoryIn(int channel, int noteNumber) { 165 | if (channel < 0 || channel >= channelsOut) return; 166 | if (noteNumber < 0 || noteNumber > 127) return; 167 | int position = -1; 168 | for(int j = 0; j < noteHistoryInLength; j++){ 169 | if(noteHistoryIn[channel][j][0] == noteNumber){ // find the position of the note 170 | position = j; // store the position 171 | break; // stop the for loop 172 | } 173 | } 174 | if (position >= 0) { 175 | for (int i = position; i < noteHistoryInLength; i++) { // go through all elements right to the found position 176 | if (i == 7) { 177 | noteHistoryIn[channel][i][0] = 0; 178 | noteHistoryIn[channel][i][1] = 0; 179 | } else { 180 | noteHistoryIn[channel][i][0] = noteHistoryIn[channel][i+1][0]; // shift note number values to the left by 1 index 181 | noteHistoryIn[channel][i][1] = noteHistoryIn[channel][i+1][1]; // shift note velocity values to the left by 1 index 182 | } 183 | } 184 | } 185 | } 186 | 187 | 188 | // ------------------------------------------------------------------------------------------- 189 | 190 | 191 | // function for latch setting 192 | void setLatch(int value) { 193 | if (value < 0 || value > 1) return; 194 | value ? latch = true : latch = false; 195 | 196 | // clear the note history when changing the latch setting 197 | for (int j = 0; j < channelsIn; j++) { 198 | for (int i = 0; i < noteHistoryInLength; i++) { 199 | noteHistoryIn[j][i][0] = 0; 200 | noteHistoryIn[j][i][1] = 0; 201 | } 202 | } 203 | } 204 | 205 | 206 | // ------------------------------------------------------------------------------------------- 207 | 208 | 209 | #ifdef DEBUG 210 | void printNoteHistory(int channel) { 211 | for (int i = 0; i < noteHistoryInLength; i++) { 212 | Serial.print(noteHistoryIn[channel][i][0]); 213 | Serial.print(","); 214 | } 215 | Serial.println(" "); 216 | } 217 | #endif 218 | 219 | 220 | // ------------------------------------------------------------------------------------------- 221 | // Schedule Notes 222 | 223 | 224 | void scheduleNote(int channel, int noteNumber, int velocity, int noteDuration, int delay, int chordNumber, int noteIndex) { 225 | scheduledNotes[scheduledNoteCount][0] = noteNumber; 226 | scheduledNotes[scheduledNoteCount][1] = millis() + delay; 227 | scheduledNotes[scheduledNoteCount][2] = noteDuration; 228 | scheduledNotes[scheduledNoteCount][3] = velocity; 229 | scheduledNotes[scheduledNoteCount][4] = channel; 230 | scheduledNotes[scheduledNoteCount][5] = chordNumber; 231 | scheduledNotes[scheduledNoteCount][6] = noteIndex; 232 | scheduledNoteCount = (scheduledNoteCount + 1) % maxNotesScheduled; 233 | } 234 | 235 | 236 | // ------------------------------------------------------------------------------------------- 237 | 238 | 239 | void checkScheduledNotes() { 240 | unsigned long currentTime = millis(); // get current time 241 | for (int i = 0; i < maxNotesScheduled; i++) { // go through all scheduled notes 242 | if (scheduledNotes[i][1]) { // check if the entry is not empty 243 | if (currentTime > scheduledNotes[i][1]) { // check if the scheduled time has been reached 244 | midiNoteOn(scheduledNotes[i][4], scheduledNotes[i][0], scheduledNotes[i][3], scheduledNotes[i][2], 1, scheduledNotes[i][5], scheduledNotes[i][6]); 245 | for (int j = 0; j < 5; j++) { 246 | scheduledNotes[i][j] = 0; 247 | } 248 | scheduledNoteCount -= 1; 249 | } 250 | } 251 | } 252 | } 253 | 254 | 255 | // ------------------------------------------------------------------------------------------- 256 | 257 | 258 | // function for different ways of handling min max note limit 259 | byte getLimitedNote(int channel, int noteNumber) { 260 | 261 | byte lowerLimit = noteLowerLimit[channel]; 262 | byte upperLimit = noteUpperLimit[channel]; 263 | byte mode = noteLimitMode[channel]; 264 | 265 | // mode 0: ignore notes 266 | if (mode == 0) { 267 | if (noteNumber < lowerLimit || noteNumber > upperLimit) return -1; 268 | else return noteNumber; 269 | } 270 | 271 | // mode 1: clamp notes 272 | else if (mode == 1) { 273 | if (noteNumber < lowerLimit) return lowerLimit; 274 | if (noteNumber > upperLimit) return upperLimit; 275 | else return noteNumber; 276 | } 277 | 278 | // mode 2: fold back notes by 1 octave 279 | else if (mode == 2) { 280 | if (noteNumber < lowerLimit) { 281 | return lowerLimit + 12 - mod(lowerLimit - noteNumber, 12); 282 | } 283 | else if (noteNumber > upperLimit) { 284 | return upperLimit - 12 + mod(noteNumber - upperLimit, 12); 285 | } 286 | else { 287 | return noteNumber; 288 | } 289 | } 290 | 291 | // mode 3: fold back notes by multiple octaves 292 | else if (mode == 3) { 293 | if (noteNumber < lowerLimit) { 294 | const int octave = ((lowerLimit - noteNumber) / 12 ) + 1; 295 | const int finalNote = lowerLimit + (octave * 12) - mod(lowerLimit - noteNumber, 12); 296 | return finalNote; 297 | } 298 | else if (noteNumber > upperLimit) { 299 | const int octave = ((noteNumber - upperLimit) / 12) + 1; 300 | const int finalNote = upperLimit - (octave * 12) + mod(noteNumber - upperLimit, 12); 301 | return finalNote; 302 | 303 | } 304 | else { 305 | return noteNumber; 306 | } 307 | } else { 308 | return noteNumber; 309 | } 310 | 311 | } 312 | 313 | 314 | // ------------------------------------------------------------------------------------------- 315 | 316 | 317 | // function for sending MIDI Note On 318 | void sendMidiNoteOn(int channel, int noteNumber, int velocity) { 319 | 320 | if (isTRS(channel)) { 321 | MIDI.sendNoteOn(noteNumber, velocity, channel+1); 322 | blinkLED(1); 323 | #ifdef USB_DEVICE 324 | usbMIDI.sendNoteOn(noteNumber, velocity, channel+1); 325 | #endif 326 | } else { 327 | #ifdef MK2 328 | #ifdef MULTIPLEUSBOUT 329 | for (int i = 0; i < 2; i++) { 330 | if (* midiDeviceList[i] && channel == i+16) { 331 | midiDeviceList[i]->sendNoteOn(noteNumber, velocity, i+1); 332 | } 333 | } 334 | #else 335 | midiDevice.sendNoteOn(noteNumber, velocity, channel+1-16); 336 | #endif 337 | #endif 338 | } 339 | 340 | 341 | #ifdef DEBUG 342 | Serial.print("Sending MIDI Note On: "); 343 | Serial.print(noteNumber); Serial.print(", "); 344 | Serial.print("Vel: "); Serial.print(velocity); Serial.print(", "); 345 | Serial.print("Ch: "); Serial.println(channel+1); 346 | #endif 347 | } 348 | 349 | 350 | // ------------------------------------------------------------------------------------------- 351 | 352 | 353 | // function for sending MIDI Note Off 354 | void sendMidiNoteOff(int channel, int noteNumber) { 355 | 356 | if (isTRS(channel)) { 357 | MIDI.sendNoteOff(noteNumber, 0, channel+1); 358 | blinkLED(1); 359 | #ifdef USB_DEVICE 360 | usbMIDI.sendNoteOff(noteNumber, 0, channel+1); 361 | #endif 362 | } else { 363 | #ifdef MK2 364 | #ifdef MULTIPLEUSBOUT 365 | for (int i = 0; i < 2; i++) { 366 | if (* midiDeviceList[i] && channel == i+16) { 367 | midiDeviceList[i]->sendNoteOff(noteNumber, 0, i+1); 368 | } 369 | } 370 | #else 371 | midiDevice.sendNoteOff(noteNumber, 0, channel+1-16); 372 | #endif 373 | #endif 374 | } 375 | 376 | 377 | #ifdef DEBUG 378 | Serial.print("Sending MIDI Note Off: "); 379 | Serial.print(noteNumber); Serial.print(", "); 380 | Serial.print("Ch: "); Serial.println(channel+1); 381 | #endif 382 | } -------------------------------------------------------------------------------- /firmware/i2c2midi_firmware/nrpns.ino: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------------------- 2 | // NRPNs 3 | // ------------------------------------------------------------------------------------------- 4 | 5 | 6 | // function for handling NRPN 7 | void NRPN(int channel, int controller, int value_, bool useRamp) { 8 | 9 | // keep values in range 10 | if (channel < 0 || channel >= channelsOut) return; 11 | 12 | int offset = 0; 13 | int slewTime = 0; 14 | 15 | // find the position of the NRPN controller in the NRPN array 16 | for (int i=0; i < maxNRPNs; i++) { 17 | if (NRPNs[i][1] == controller) { 18 | offset = NRPNs[i][2]; 19 | slewTime = NRPNs[i][3]; 20 | break; 21 | } 22 | } 23 | 24 | // keep values in range 25 | int value = value_ + offset; 26 | if (value < 0) value = 0; 27 | if (value > 16384) value = 16384; 28 | 29 | // if the slew time is higher than zero, a ramp is used to slew the value ... 30 | if (useRamp == true && slewTime != 0) { 31 | handleRamp(channel, controller, value, slewTime, 1); 32 | } else { 33 | sendNRPN(channel, controller, value); 34 | } 35 | 36 | } 37 | 38 | 39 | // ------------------------------------------------------------------------------------------- 40 | 41 | 42 | // function for sending NRPN 43 | void sendNRPN(int channel, int controller, int value) { 44 | uint8_t controller_MSB = controller >> 7; 45 | uint8_t controller_LSB = controller & 0x7F; 46 | uint8_t value_MSB = value >> 7; 47 | uint8_t value_LSB = value & 0x7F; 48 | 49 | if (controller_MSB < 0 || controller_MSB > 127) return; 50 | if (controller_LSB < 0 || controller_LSB > 127) return; 51 | if (value_MSB < 0 || value_MSB > 127) return; 52 | if (value_LSB < 0 || value_LSB > 127) return; 53 | 54 | sendMidiCC(channel, 99, controller_MSB); 55 | sendMidiCC(channel, 98, controller_LSB); 56 | sendMidiCC(channel, 6, value_MSB); 57 | sendMidiCC(channel, 38, value_LSB); 58 | } 59 | 60 | 61 | // ------------------------------------------------------------------------------------------- 62 | 63 | 64 | // function for getting next free slot to store NRPN data 65 | int8_t getNextFreeNRPN(int channel, int controller) { 66 | // check if controller is already stored in a slot 67 | for (int i=0; i < maxNRPNs; i++) { 68 | if (NRPNs[i][0] == channel && NRPNs[i][1] == controller) { 69 | //Serial.println("already stored in NRPN array"); 70 | return i; 71 | } 72 | } 73 | // if that did not find anything ... 74 | nrpnCount += 1; // count one slot up 75 | byte currentNRPN = nrpnCount % maxNRPNs; // determine the current slot 76 | // check if next slot is occupied; if yes, skip to next slot; 77 | // if there's no more space available, replace the slot 78 | for (int i=0; i < maxNRPNs; i++) { 79 | if (NRPNs[currentNRPN][1] != 0) { 80 | nrpnCount += 1; 81 | currentNRPN = nrpnCount % maxNRPNs; 82 | } 83 | else { 84 | break; 85 | } 86 | } 87 | return currentNRPN; 88 | } 89 | 90 | 91 | // ------------------------------------------------------------------------------------------- 92 | 93 | 94 | int getNRPNvalue(int channel, int controller, int index) { 95 | for (int i=0; i < maxNRPNs; i++) { // go through the list of stored NRPN settings 96 | if (NRPNs[i][0] == channel && NRPNs[i][1] == controller) { // check if there's data for requested CH & NRPN controller 97 | return NRPNs[i][index]; // if yes, return the requested data 98 | } 99 | } 100 | return 0; // if no, return 0 101 | } -------------------------------------------------------------------------------- /firmware/i2c2midi_firmware/test.ino: -------------------------------------------------------------------------------- 1 | #ifdef TEST 2 | 3 | // ------------------------------------------------------------------------------------------- 4 | // Testing 5 | // ------------------------------------------------------------------------------------------- 6 | 7 | 8 | unsigned long lastTEST; 9 | int TESTinterval = 500; 10 | 11 | void TESTFunction() { 12 | unsigned long currentMillis = millis(); 13 | 14 | if (currentMillis - lastTEST >= TESTinterval) { 15 | //blinkLED(1); 16 | i2cReceiveEventTEST(20, 0, random(50,70), 120, 0, 0); 17 | lastTEST = millis(); 18 | } 19 | } 20 | 21 | 22 | void i2cReceiveEventTEST(uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint8_t e, uint8_t f) { 23 | i2cData[0] = a; // OP 24 | i2cData[1] = b; // channel 25 | i2cData[2] = c; // value 1 26 | i2cData[3] = d; // value 2 27 | i2cData[4] = e; // value 3 28 | i2cData[5] = f; // value 4 29 | received += 1; 30 | } 31 | 32 | 33 | #endif -------------------------------------------------------------------------------- /hardware/hardware-MK1/BUILD-GUIDE.md: -------------------------------------------------------------------------------- 1 | # Build Guide MKI 2 | 3 | 4 | ## I 5 | Get the parts. Here's the [BOM](https://github.com/attowatt/i2c2midi/tree/main/hardware/i2c2midi_hardware_MK1#BOM). 6 | 7 | ![](pictures/i2c2midi_v_2_0_build_1.jpg) 8 | 9 | ## II 10 | - Solder the following parts: 11 | - Resistors (R1, R2, R3, R4, R5) 12 | - Voltage regulator: Bend the legs before soldering. 13 | - Power header: Please check the orientation – the opening of the header should be on the right, when -12V is on the bottom. 14 | - Capacitors: C1 (0.33 uF) negative side (white line, short leg) should be facing away from the power header. Orientation of C2 (0.1 uF) capacitor does not matter. 15 | - I2C header 16 | - Teensy header: I prefer to solder a few pins with the Teensy board attached (to make sure it will fit later), then remove the Teensy and solder the rest of the pins. 17 | - Cut the legs of the parts. 18 | 19 | ![](pictures/i2c2midi_v_2_0_build_2.jpg) 20 | ![](pictures/i2c2midi_v_2_0_build_3.jpg) 21 | ![](pictures/i2c2midi_v_2_0_build_4.jpg) 22 | ![](pictures/i2c2midi_v_2_0_build_5.jpg) 23 | 24 | 25 | ## III 26 | - Mount the spacer to the PCB with one of the two M3 screws. 27 | - Place the stereo jack (U1) and leds into their positions, but don't solder them yet. 28 | - Place the panel on top of the stereo jack and spacer. Mount it to the jack with the nut and to the spacer with the second M3 screw. 29 | 30 | ## IV 31 | - Carefully place the LEDs into position, so they look nice on the panel. Then solder them. 32 | - Solder the stereo jack. 33 | 34 | ![](pictures/i2c2midi_v_2_0_build_6.jpg) 35 | ![](pictures/i2c2midi_v_2_0_build_7.jpg) 36 | 37 | 38 | ## V 39 | Flash the firmware to the Teensy. 40 | Don't connect the module to Euro power and USB at the same time! 41 | 42 | **Via Teensyduino** 43 | - Download the firmware and open it with [Teensyduino](https://www.pjrc.com/teensy/td_download.html). 44 | - Connect the Teensy to your computer with a USB cable. 45 | - Under `Tools`, set `Board` to `Teensy 3.2`, `USB Type` to `Serial`, and select the `Port` that shows the Teensy. 46 | - Upload the firmware to your Teensy via `Sketch` → `Upload`. 47 | - If the upload was successfull, i2c2midi lights up with both LEDs turning on and off four times. 48 | 49 | **Via Teensy Loader** (not tested) 50 | - Download and open the [Teensy Loader App](https://www.pjrc.com/teensy/loader.html). 51 | - Connect the Teensy to your computer with a USB cable. 52 | - Select `File` → `Open HEX File` and load the [HEX file of the firmware](../firmware/i2c2midi_firmware_v2_3/i2c2midi_firmware_v2_3.ino.hex). 53 | - Select `Program`. 54 | - If the upload was successfull, i2c2midi lights up with both LEDs turning on and off four times. 55 | 56 | 57 | ## Disclaimer: 58 | After building the module, please test it very carefully in a separate case. This is a DIY module. I am not responsible for any damage to your gear. 59 | 60 | 61 | ![](pictures/i2c2midi_v_2_0_build_8.jpg) 62 | ![](pictures/i2c2midi_v_2_0_build_9.jpg) 63 | -------------------------------------------------------------------------------- /hardware/hardware-MK1/README.md: -------------------------------------------------------------------------------- 1 | # i2c2midi 2 | 3 | **i2c2midi is a simple DIY 4 hp eurorack module that speaks I2C and MIDI.** 4 | It's primarily build to be used together with [monome Teletype](https://monome.org/docs/teletype/). It receives I2C messages from Teletype and converts them to MIDI notes, MIDI CC messages and other MIDI messages to control external devices like synths and effects. 5 | 6 | - handles MIDI note off messages automatically 7 | - variable note duration 8 | - 8 voice polyphony per MIDI channel 9 | - 16 MIDI channels simultaneously 10 | 11 | i2c2midi lines community thread: 12 | https://llllllll.co/t/i2c2midi-a-diy-module-that-translates-i2c-to-midi/ 13 | 14 | 15 | ![](/pictures/i2c2midi_diagram.png) 16 | 17 | ## Table of content 18 | [Details](#Details) 19 | [Usage](#usage) 20 | [About the firmware](#about-the-firmware) 21 | [Schematic](#schematic) 22 | [BOM](#BOM) 23 | [Build Guide](#Build-Guide) 24 | [Changelog](#Changelog) 25 | [Thanks](#thanks) 26 | 27 | 28 | 29 | ## Details 30 | - DIY eurorack module (early stage) 31 | - 4 hp 32 | - Inputs: I2C 3 pin 33 | - Outputs: MIDI TRS (Type A) 34 | - Based on Teensy 3.2 35 | 36 | 37 | ![](pictures/i2c2midi_v_2_0_side.jpg) 38 | 39 | 40 | ## Usage 41 | The following commands are currently available: 42 | 43 | ``` 44 | EX 2 // tells Teletype that following code in the script is meant for i2c2midi 45 | EX2: // tells Teletype that following line is meant for i2c2midi 46 | EX.M.CH channel // set the MIDI channel 47 | ``` 48 | ``` 49 | EX.M.N note velocity // send MIDI Note 50 | EX.M.CC controller value // send MIDI CC 51 | EX.M.PB value // sent MIDI Pitch Bend (-8192 - 8191); affects all notes per channel 52 | EX.M.PRG number // sent MIDI Program Change 53 | ``` 54 | ``` 55 | EX.M.CLK // send MIDI clock pulse 56 | EX.M.START // start MIDI transport start 57 | EX.M.STOP // stop MIDI transport stop 58 | EX.M.CONT // continue MIDI transport 59 | ``` 60 | ``` 61 | EX.P 1 value // set note duration in milliseconds 62 | EX.P 2 value // send MIDI Aftertouch value (0 - 127); affects all notes of last used channel 63 | EX.P 99 value // set I2C address of i2c2midi (65 for EX 1, 66 for EX 2, 67 for EX 3, 68 for EX 4) 64 | ``` 65 | 66 | **Note off messages** 67 | 68 | The firmware takes care of Note off messages automatically, depending on the current note duration value (EX.P 1). 69 | 70 | **LEDs** 71 | 72 | The left LED lights up when I2C messages are incoming. 73 | The right LED lights up when MIDI messages are outgoing. 74 | 75 | 76 | 77 | 78 | ## About the firmware 79 | 80 | The firmware is written specifically for I2C messages sent from [monome Teletype](https://monome.org/docs/teletype/) using the [disting Ex MIDI OPs](https://github.com/scanner-darkly/teletype/wiki/DISTING-EX-INTEGRATION) by [scanner-darkly](https://github.com/scanner-darkly). The i2c2midi module “poses” as a second disting. 81 | Based on that setup, there are a few things to note and hardcoded within the firmware: 82 | 83 | - The following addresses are specifically reserved for the disting EX within the Teletype firmware: `0x41`, `0x42`, `0x43`, `0x44` (65, 66, 67, 68). Since the module should act like a second disting EX, it is set up to listen to I2C messages on address `0x42` (66). This could be changed to act as the first (65), third (67) or fourth (68) disting EX instead. 84 | 85 | - The I2C messages for the disting Ex are constructed as `
`. See [here](https://github.com/scanner-darkly/teletype/wiki/DISTING-EX-I2C-SPECIFICATION) or [here](https://www.expert-sleepers.co.uk/distingEXfirmwareupdates.html) for further details. 86 | 87 | - The “send MIDI message” command of the disting Ex is `0x4F`(79) and is constructed as `
0x4F `. 88 | 89 | - ``refers to the [MIDI status](https://www.midimountain.com/midi/midi_status.htm). MIDI note on messages have the status 144-159 for channels 1-16. MIDI CC messages have the status 176-191 for channels 1-16. 90 | 91 | - Sending a MIDI note on (e.g. note 48, velocity 127, channel 1) therefore looks like this: `0x42 0x4F 144 48 127`. 92 | 93 | - Sending a MIDI CC (e.g. controller 1, value 60, channel 1) therefore looks like this: `0x42 0x4F 176 1 60`. 94 | 95 | - Same applies to MIDI Pitch Bend and Program Change messages. 96 | 97 | - There is also a general I2C message used to control parameters of a disting Ex algorithm. This message is hijacked for additional parameters of the i2c2midi module. E.g. parameter 1 is hardcoded for note duration, parameter 2 for Aftertouch, etc. 98 | 99 | **USB MIDI** 100 | 101 | If you want to to modify the module and use Teensy’s USB port for MIDI out: USB MIDI can be activated in the firmware by uncommenting `#define USB_MIDI` in the source code. All MIDI messages will then be sent to the USB port of the Teensy, as well as the TRS output of the module. Please make sure to select `Tools` → `USB Type: Serial + MIDI` when uploading the firmware to the Teensy. 102 | 103 | Caution: Do not connect power from the modular and USB at the same time, unless you have separated the 5V pads on the Teensy!! Otherwise you will damage your Teensy. For more info, please follow [this link](https://www.pjrc.com/teensy/external_power.html). 104 | 105 | **Libraries used** 106 | 107 | The firmware uses the [i2c_t3 Library](https://github.com/nox771/i2c_t3) for reading I2C and [Arduino MIDI library](https://github.com/FortySevenEffects/arduino_midi_library/) for sending MIDI. 108 | 109 | 110 | 111 | 112 | ## Schematic 113 | 114 | ![](i2c2midi_schematic.png) 115 | 116 | **MIDI TRS Type A Wiring:** 117 | 118 | Teensy | TRS | MIDI 119 | --- | --- | --- 120 | Teensy Pin 1 | → Tip | → MIDI Pin 5 121 | Teensy 3V3 | → Ring | → MIDI Pin 4 122 | Ground | → Sleeve | → MIDI Pin 2 123 | 124 | 125 | ## BOM 126 | 127 | Number | Part | Value 128 | --- | --- | --- 129 | 1 | T32 | Teensy 3.2 (with pins) 130 | 2 | C1 | 0.33 uF capacitor 131 | 3 | C2 | 0.1 uF capacitor 132 | 4 | D1 | LED 3 mm 133 | 5 | D2 | LED 3 mm 134 | 6 | I2C | 3x2 pin header (male) 135 | 7 | IC1 | 7805 5V regulator 136 | 8 | R1 | 2.2k Ω resistor 137 | 9 | R2 | 2.2k Ω resistor 138 | 10 | R3 | 47 Ω resistor 139 | 11 | R4 | 47 Ω resistor 140 | 12 | R5 | 220 Ω resistor 141 | 13 | R6 | 220 Ω resistor 142 | 14 | POW | 2x5 power header (male) 143 | 15 | U1 | Green Thonkiconn Stereo 3.5mm Audio Jack (PJ366ST) 144 | 16 | | Nut for Thonkiconn 145 | 17 | | 1x14 pin header for Teensy (female) 146 | 18 | | 1x14 pin header for Teensy (female) 147 | 19 | | 10 mm M3 Hex standoff 148 | 20 | | 10 mm M3 screw 149 | 21 | | 10 mm M3 screw 150 | 151 | Starting point for sourcing parts: 152 | - https://octopart.com/bom-tool/pmHTMfR9 153 | - https://eu.mouser.com/ProjectManager/ProjectDetail.aspx?AccessID=09d13b7d7e 154 | 155 | Here are the [Gerber files](/gerber/) for the PCB and panel. 156 | 157 | Here are some [more details](https://llllllll.co/t/i2c2midi-a-diy-module-that-translates-i2c-to-midi/40950/56) about ordering the PCB and Pancel from a manufacturer. 158 | 159 | 160 | ![](/pictures/i2c2midi_v_2_0_kit.jpg) 161 | 162 | ## Build Guide 163 | 164 | Please find a Build Guide [here](/BUILD-GUIDE.md). 165 | 166 | ## Changelog 167 | 168 | **Version 2.6** 169 | - added MIDI clock implementation (not tested) 170 | 171 | **Version 2.5** 172 | - added optional USB MIDI support (for one's own modifications involving USB MIDI) 173 | 174 | **Version 2.4.4** 175 | - updated firmware 176 | - added MIDI clock, via EX.M.CLK 177 | - added MIDI transport start, stop and continue, via EX.M.START, EX.M.STOP and EX.M.CONT 178 | - I2C address can be set via EX.P 99 179 | 180 | **Version 2.3.0** 181 | - new firmware 182 | - added 8-voice polyphony for 16 channels 183 | - note duration can be set in ms via EX.P 1 value 184 | - added MIDI Pitch Bend, via EX.M.PB value (min: -8192, max: 8191) 185 | - added MIDI Program Change, via EX.M.PRG program 186 | 187 | **Version 2.0** 188 | - Proper PCB 189 | - Proper panel 190 | - Added two LEDs 191 | 192 | **Version 1.1** 193 | - Added a voltage regulator, so the module can be powered from the case with a normal eurorack power ribbon cable. 194 | 195 | **Version 1.0** 196 | - Initial version using a protoboard and LEGO 2x16 plate as front panel. 197 | 198 | 199 | 200 | ## Thanks 201 | 202 | - To [scanner-darkly](https://github.com/scanner-darkly) – for developing the disting EX Teletype OPs and helping out on several occasions during the making of this module. 203 | - To [Ansome](https://www.instagram.com/ansomeuk/) – for helping me out on multiple occasions trying to learn Eagle CAD. 204 | 205 | 206 | ## Sources 207 | 208 | - https://www.pjrc.com/teensy/external_power.html 209 | - https://www.pjrc.com/teensy/td_libs_MIDI.html 210 | - https://github.com/nox771/i2c_t3 211 | - https://github.com/TomWhitwell/MTM-Parts-Library 212 | -------------------------------------------------------------------------------- /hardware/hardware-MK1/gerber/board_2021-04-26_board.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK1/gerber/board_2021-04-26_board.zip -------------------------------------------------------------------------------- /hardware/hardware-MK1/gerber/board_2021-04-26_board/GerberJob/gerber_job.gbrjob: -------------------------------------------------------------------------------- 1 | { 2 | "Header": { 3 | "Comment": "All values are metric (mm)", 4 | "CreationDate": "2021-04-26T18:43:46Z", 5 | "GenerationSoftware": { 6 | "Application": "EAGLE", 7 | "Vendor": "Autodesk", 8 | "Version": "9.6.2" 9 | }, 10 | "Part": "Single" 11 | }, 12 | "Overall": { 13 | "BoardThickness": 1.57, 14 | "LayerNumber": 2, 15 | "Name": { 16 | "ProjectId": "board" 17 | }, 18 | "Owner": "mail mail ", 19 | "Size": { 20 | "X": 109.525, 21 | "Y": 19.04 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /hardware/hardware-MK1/gerber/board_2021-04-26_board/board.GBL: -------------------------------------------------------------------------------- 1 | G04 EAGLE Gerber RS-274X export* 2 | G75* 3 | %MOMM*% 4 | %FSLAX34Y34*% 5 | %LPD*% 6 | %INBottom Copper*% 7 | %IPPOS*% 8 | %AMOC8* 9 | 5,1,8,0,0,1.08239X$1,22.5*% 10 | G01* 11 | %ADD10P,1.429621X8X202.500000*% 12 | %ADD11P,1.429621X8X22.500000*% 13 | %ADD12P,1.814519X8X292.500000*% 14 | %ADD13C,1.676400*% 15 | %ADD14P,1.429621X8X292.500000*% 16 | %ADD15P,1.429621X8X112.500000*% 17 | %ADD16C,1.473200*% 18 | %ADD17C,1.650000*% 19 | %ADD18P,2.034460X8X112.500000*% 20 | %ADD19C,1.524000*% 21 | %ADD20P,1.649562X8X22.500000*% 22 | %ADD21P,1.814519X8X112.500000*% 23 | %ADD22C,0.812800*% 24 | %ADD23C,0.609600*% 25 | %ADD24C,0.406400*% 26 | %ADD25C,0.304800*% 27 | 28 | G36* 29 | X469908Y12194D02* 30 | X469908Y12194D01* 31 | X469915Y12193D01* 32 | X470005Y12214D01* 33 | X470097Y12232D01* 34 | X470103Y12237D01* 35 | X470111Y12239D01* 36 | X470259Y12341D01* 37 | X495510Y37593D01* 38 | X500425Y37593D01* 39 | X475891Y13059D01* 40 | X475890Y13056D01* 41 | X475888Y13055D01* 42 | X475835Y12974D01* 43 | X475780Y12892D01* 44 | X475780Y12889D01* 45 | X475778Y12887D01* 46 | X475761Y12791D01* 47 | X475743Y12695D01* 48 | X475743Y12692D01* 49 | X475743Y12690D01* 50 | X475764Y12593D01* 51 | X475784Y12499D01* 52 | X475786Y12497D01* 53 | X475786Y12494D01* 54 | X475843Y12414D01* 55 | X475899Y12334D01* 56 | X475901Y12333D01* 57 | X475902Y12331D01* 58 | X475985Y12279D01* 59 | X476068Y12227D01* 60 | X476070Y12226D01* 61 | X476073Y12225D01* 62 | X476250Y12193D01* 63 | X482600Y12193D01* 64 | X482608Y12194D01* 65 | X482615Y12193D01* 66 | X482705Y12214D01* 67 | X482797Y12232D01* 68 | X482803Y12237D01* 69 | X482811Y12239D01* 70 | X482959Y12341D01* 71 | X508210Y37593D01* 72 | X513125Y37593D01* 73 | X488591Y13059D01* 74 | X488590Y13056D01* 75 | X488588Y13055D01* 76 | X488535Y12974D01* 77 | X488480Y12892D01* 78 | X488480Y12889D01* 79 | X488478Y12887D01* 80 | X488461Y12791D01* 81 | X488443Y12695D01* 82 | X488443Y12692D01* 83 | X488443Y12690D01* 84 | X488464Y12593D01* 85 | X488484Y12499D01* 86 | X488486Y12497D01* 87 | X488486Y12494D01* 88 | X488543Y12414D01* 89 | X488599Y12334D01* 90 | X488601Y12333D01* 91 | X488602Y12331D01* 92 | X488685Y12279D01* 93 | X488768Y12227D01* 94 | X488770Y12226D01* 95 | X488773Y12225D01* 96 | X488950Y12193D01* 97 | X495300Y12193D01* 98 | X495308Y12194D01* 99 | X495315Y12193D01* 100 | X495405Y12214D01* 101 | X495497Y12232D01* 102 | X495503Y12237D01* 103 | X495511Y12239D01* 104 | X495659Y12341D01* 105 | X520910Y37593D01* 106 | X525825Y37593D01* 107 | X501291Y13059D01* 108 | X501290Y13056D01* 109 | X501288Y13055D01* 110 | X501235Y12974D01* 111 | X501180Y12892D01* 112 | X501180Y12889D01* 113 | X501178Y12887D01* 114 | X501161Y12791D01* 115 | X501143Y12695D01* 116 | X501143Y12692D01* 117 | X501143Y12690D01* 118 | X501164Y12593D01* 119 | X501184Y12499D01* 120 | X501186Y12497D01* 121 | X501186Y12494D01* 122 | X501243Y12414D01* 123 | X501299Y12334D01* 124 | X501301Y12333D01* 125 | X501302Y12331D01* 126 | X501385Y12279D01* 127 | X501468Y12227D01* 128 | X501470Y12226D01* 129 | X501473Y12225D01* 130 | X501650Y12193D01* 131 | X508000Y12193D01* 132 | X508008Y12194D01* 133 | X508015Y12193D01* 134 | X508105Y12214D01* 135 | X508197Y12232D01* 136 | X508203Y12237D01* 137 | X508211Y12239D01* 138 | X508359Y12341D01* 139 | X533610Y37593D01* 140 | X538525Y37593D01* 141 | X513991Y13059D01* 142 | X513990Y13056D01* 143 | X513988Y13055D01* 144 | X513935Y12974D01* 145 | X513880Y12892D01* 146 | X513880Y12889D01* 147 | X513878Y12887D01* 148 | X513861Y12791D01* 149 | X513843Y12695D01* 150 | X513843Y12692D01* 151 | X513843Y12690D01* 152 | X513864Y12593D01* 153 | X513884Y12499D01* 154 | X513886Y12497D01* 155 | X513886Y12494D01* 156 | X513943Y12414D01* 157 | X513999Y12334D01* 158 | X514001Y12333D01* 159 | X514002Y12331D01* 160 | X514085Y12279D01* 161 | X514168Y12227D01* 162 | X514170Y12226D01* 163 | X514173Y12225D01* 164 | X514350Y12193D01* 165 | X520700Y12193D01* 166 | X520708Y12194D01* 167 | X520715Y12193D01* 168 | X520805Y12214D01* 169 | X520897Y12232D01* 170 | X520903Y12237D01* 171 | X520911Y12239D01* 172 | X521059Y12341D01* 173 | X546310Y37593D01* 174 | X551225Y37593D01* 175 | X526691Y13059D01* 176 | X526690Y13056D01* 177 | X526688Y13055D01* 178 | X526635Y12974D01* 179 | X526580Y12892D01* 180 | X526580Y12889D01* 181 | X526578Y12887D01* 182 | X526561Y12791D01* 183 | X526543Y12695D01* 184 | X526543Y12692D01* 185 | X526543Y12690D01* 186 | X526564Y12593D01* 187 | X526584Y12499D01* 188 | X526586Y12497D01* 189 | X526586Y12494D01* 190 | X526643Y12414D01* 191 | X526699Y12334D01* 192 | X526701Y12333D01* 193 | X526702Y12331D01* 194 | X526785Y12279D01* 195 | X526868Y12227D01* 196 | X526870Y12226D01* 197 | X526873Y12225D01* 198 | X527050Y12193D01* 199 | X533400Y12193D01* 200 | X533408Y12194D01* 201 | X533415Y12193D01* 202 | X533505Y12214D01* 203 | X533597Y12232D01* 204 | X533603Y12237D01* 205 | X533611Y12239D01* 206 | X533759Y12341D01* 207 | X559010Y37593D01* 208 | X563925Y37593D01* 209 | X539391Y13059D01* 210 | X539390Y13056D01* 211 | X539388Y13055D01* 212 | X539335Y12974D01* 213 | X539280Y12892D01* 214 | X539280Y12889D01* 215 | X539278Y12887D01* 216 | X539261Y12791D01* 217 | X539243Y12695D01* 218 | X539243Y12692D01* 219 | X539243Y12690D01* 220 | X539264Y12593D01* 221 | X539284Y12499D01* 222 | X539286Y12497D01* 223 | X539286Y12494D01* 224 | X539343Y12414D01* 225 | X539399Y12334D01* 226 | X539401Y12333D01* 227 | X539402Y12331D01* 228 | X539485Y12279D01* 229 | X539568Y12227D01* 230 | X539570Y12226D01* 231 | X539573Y12225D01* 232 | X539750Y12193D01* 233 | X546100Y12193D01* 234 | X546108Y12194D01* 235 | X546115Y12193D01* 236 | X546205Y12214D01* 237 | X546297Y12232D01* 238 | X546303Y12237D01* 239 | X546311Y12239D01* 240 | X546459Y12341D01* 241 | X571710Y37593D01* 242 | X576625Y37593D01* 243 | X552091Y13059D01* 244 | X552090Y13056D01* 245 | X552088Y13055D01* 246 | X552035Y12974D01* 247 | X551980Y12892D01* 248 | X551980Y12889D01* 249 | X551978Y12887D01* 250 | X551961Y12791D01* 251 | X551943Y12695D01* 252 | X551943Y12692D01* 253 | X551943Y12690D01* 254 | X551964Y12593D01* 255 | X551984Y12499D01* 256 | X551986Y12497D01* 257 | X551986Y12494D01* 258 | X552043Y12414D01* 259 | X552099Y12334D01* 260 | X552101Y12333D01* 261 | X552102Y12331D01* 262 | X552185Y12279D01* 263 | X552268Y12227D01* 264 | X552270Y12226D01* 265 | X552273Y12225D01* 266 | X552450Y12193D01* 267 | X558800Y12193D01* 268 | X558808Y12194D01* 269 | X558815Y12193D01* 270 | X558905Y12214D01* 271 | X558997Y12232D01* 272 | X559003Y12237D01* 273 | X559011Y12239D01* 274 | X559159Y12341D01* 275 | X584410Y37593D01* 276 | X589325Y37593D01* 277 | X564791Y13059D01* 278 | X564790Y13056D01* 279 | X564788Y13055D01* 280 | X564735Y12974D01* 281 | X564680Y12892D01* 282 | X564680Y12889D01* 283 | X564678Y12887D01* 284 | X564661Y12791D01* 285 | X564643Y12695D01* 286 | X564643Y12692D01* 287 | X564643Y12690D01* 288 | X564664Y12593D01* 289 | X564684Y12499D01* 290 | X564686Y12497D01* 291 | X564686Y12494D01* 292 | X564743Y12414D01* 293 | X564799Y12334D01* 294 | X564801Y12333D01* 295 | X564802Y12331D01* 296 | X564885Y12279D01* 297 | X564968Y12227D01* 298 | X564970Y12226D01* 299 | X564973Y12225D01* 300 | X565150Y12193D01* 301 | X571500Y12193D01* 302 | X571508Y12194D01* 303 | X571515Y12193D01* 304 | X571605Y12214D01* 305 | X571697Y12232D01* 306 | X571703Y12237D01* 307 | X571711Y12239D01* 308 | X571859Y12341D01* 309 | X597110Y37593D01* 310 | X602025Y37593D01* 311 | X577491Y13059D01* 312 | X577490Y13056D01* 313 | X577488Y13055D01* 314 | X577435Y12974D01* 315 | X577380Y12892D01* 316 | X577380Y12889D01* 317 | X577378Y12887D01* 318 | X577361Y12791D01* 319 | X577343Y12695D01* 320 | X577343Y12692D01* 321 | X577343Y12690D01* 322 | X577364Y12593D01* 323 | X577384Y12499D01* 324 | X577386Y12497D01* 325 | X577386Y12494D01* 326 | X577443Y12414D01* 327 | X577499Y12334D01* 328 | X577501Y12333D01* 329 | X577502Y12331D01* 330 | X577585Y12279D01* 331 | X577668Y12227D01* 332 | X577670Y12226D01* 333 | X577673Y12225D01* 334 | X577850Y12193D01* 335 | X584200Y12193D01* 336 | X584208Y12194D01* 337 | X584215Y12193D01* 338 | X584305Y12214D01* 339 | X584397Y12232D01* 340 | X584403Y12237D01* 341 | X584411Y12239D01* 342 | X584559Y12341D01* 343 | X609810Y37593D01* 344 | X614725Y37593D01* 345 | X590191Y13059D01* 346 | X590190Y13056D01* 347 | X590188Y13055D01* 348 | X590135Y12974D01* 349 | X590080Y12892D01* 350 | X590080Y12889D01* 351 | X590078Y12887D01* 352 | X590061Y12791D01* 353 | X590043Y12695D01* 354 | X590043Y12692D01* 355 | X590043Y12690D01* 356 | X590064Y12593D01* 357 | X590084Y12499D01* 358 | X590086Y12497D01* 359 | X590086Y12494D01* 360 | X590143Y12414D01* 361 | X590199Y12334D01* 362 | X590201Y12333D01* 363 | X590202Y12331D01* 364 | X590285Y12279D01* 365 | X590368Y12227D01* 366 | X590370Y12226D01* 367 | X590373Y12225D01* 368 | X590550Y12193D01* 369 | X596900Y12193D01* 370 | X596908Y12194D01* 371 | X596915Y12193D01* 372 | X597005Y12214D01* 373 | X597097Y12232D01* 374 | X597103Y12237D01* 375 | X597111Y12239D01* 376 | X597259Y12341D01* 377 | X622510Y37593D01* 378 | X627425Y37593D01* 379 | X602891Y13059D01* 380 | X602890Y13056D01* 381 | X602888Y13055D01* 382 | X602835Y12974D01* 383 | X602780Y12892D01* 384 | X602780Y12889D01* 385 | X602778Y12887D01* 386 | X602761Y12791D01* 387 | X602743Y12695D01* 388 | X602743Y12692D01* 389 | X602743Y12690D01* 390 | X602764Y12593D01* 391 | X602784Y12499D01* 392 | X602786Y12497D01* 393 | X602786Y12494D01* 394 | X602843Y12414D01* 395 | X602899Y12334D01* 396 | X602901Y12333D01* 397 | X602902Y12331D01* 398 | X602985Y12279D01* 399 | X603068Y12227D01* 400 | X603070Y12226D01* 401 | X603073Y12225D01* 402 | X603250Y12193D01* 403 | X609600Y12193D01* 404 | X609608Y12194D01* 405 | X609615Y12193D01* 406 | X609705Y12214D01* 407 | X609797Y12232D01* 408 | X609803Y12237D01* 409 | X609811Y12239D01* 410 | X609959Y12341D01* 411 | X635210Y37593D01* 412 | X640125Y37593D01* 413 | X615591Y13059D01* 414 | X615590Y13056D01* 415 | X615588Y13055D01* 416 | X615535Y12974D01* 417 | X615480Y12892D01* 418 | X615480Y12889D01* 419 | X615478Y12887D01* 420 | X615461Y12791D01* 421 | X615443Y12695D01* 422 | X615443Y12692D01* 423 | X615443Y12690D01* 424 | X615464Y12593D01* 425 | X615484Y12499D01* 426 | X615486Y12497D01* 427 | X615486Y12494D01* 428 | X615543Y12414D01* 429 | X615599Y12334D01* 430 | X615601Y12333D01* 431 | X615602Y12331D01* 432 | X615685Y12279D01* 433 | X615768Y12227D01* 434 | X615770Y12226D01* 435 | X615773Y12225D01* 436 | X615950Y12193D01* 437 | X622300Y12193D01* 438 | X622308Y12194D01* 439 | X622315Y12193D01* 440 | X622405Y12214D01* 441 | X622497Y12232D01* 442 | X622503Y12237D01* 443 | X622511Y12239D01* 444 | X622659Y12341D01* 445 | X673459Y63141D01* 446 | X673463Y63148D01* 447 | X673469Y63152D01* 448 | X673518Y63231D01* 449 | X673570Y63308D01* 450 | X673571Y63316D01* 451 | X673575Y63323D01* 452 | X673607Y63500D01* 453 | X673607Y120650D01* 454 | X673606Y120658D01* 455 | X673607Y120665D01* 456 | X673586Y120755D01* 457 | X673568Y120847D01* 458 | X673563Y120853D01* 459 | X673561Y120861D01* 460 | X673459Y121009D01* 461 | X641709Y152759D01* 462 | X641702Y152763D01* 463 | X641698Y152769D01* 464 | X641619Y152818D01* 465 | X641542Y152870D01* 466 | X641534Y152871D01* 467 | X641527Y152875D01* 468 | X641350Y152907D01* 469 | X482600Y152907D01* 470 | X482595Y152906D01* 471 | X482590Y152907D01* 472 | X482497Y152886D01* 473 | X482404Y152868D01* 474 | X482399Y152865D01* 475 | X482394Y152864D01* 476 | X482316Y152808D01* 477 | X482238Y152755D01* 478 | X482235Y152751D01* 479 | X482231Y152748D01* 480 | X482180Y152666D01* 481 | X482128Y152587D01* 482 | X482128Y152582D01* 483 | X482125Y152577D01* 484 | X482093Y152400D01* 485 | X482093Y114300D01* 486 | X482094Y114292D01* 487 | X482093Y114285D01* 488 | X482114Y114195D01* 489 | X482132Y114104D01* 490 | X482137Y114097D01* 491 | X482139Y114089D01* 492 | X482241Y113941D01* 493 | X501143Y95040D01* 494 | X501143Y51010D01* 495 | X463191Y13059D01* 496 | X463190Y13056D01* 497 | X463188Y13055D01* 498 | X463135Y12974D01* 499 | X463080Y12892D01* 500 | X463080Y12889D01* 501 | X463078Y12887D01* 502 | X463061Y12791D01* 503 | X463043Y12695D01* 504 | X463043Y12692D01* 505 | X463043Y12690D01* 506 | X463064Y12593D01* 507 | X463084Y12499D01* 508 | X463086Y12497D01* 509 | X463086Y12494D01* 510 | X463143Y12414D01* 511 | X463199Y12334D01* 512 | X463201Y12333D01* 513 | X463202Y12331D01* 514 | X463285Y12279D01* 515 | X463368Y12227D01* 516 | X463370Y12226D01* 517 | X463373Y12225D01* 518 | X463550Y12193D01* 519 | X469900Y12193D01* 520 | X469908Y12194D01* 521 | G37* 522 | %LPC*% 523 | G36* 524 | X551479Y68579D02* 525 | X551479Y68579D01* 526 | X544695Y70397D01* 527 | X538614Y73908D01* 528 | X533648Y78874D01* 529 | X530137Y84955D01* 530 | X528319Y91739D01* 531 | X528319Y98761D01* 532 | X530137Y105545D01* 533 | X533648Y111626D01* 534 | X538614Y116592D01* 535 | X544695Y120103D01* 536 | X551479Y121921D01* 537 | X558501Y121921D01* 538 | X565285Y120103D01* 539 | X571366Y116592D01* 540 | X576332Y111626D01* 541 | X579843Y105545D01* 542 | X581661Y98761D01* 543 | X581661Y91739D01* 544 | X579843Y84955D01* 545 | X576332Y78874D01* 546 | X571366Y73908D01* 547 | X565285Y70397D01* 548 | X558501Y68579D01* 549 | X551479Y68579D01* 550 | G37* 551 | %LPD*% 552 | D10* 553 | X717550Y158750D03* 554 | X666750Y158750D03* 555 | D11* 556 | X666750Y25400D03* 557 | X717550Y25400D03* 558 | D12* 559 | X939800Y139700D03* 560 | X939800Y114300D03* 561 | D13* 562 | X713232Y120650D02* 563 | X696468Y120650D01* 564 | X696468Y95250D02* 565 | X713232Y95250D01* 566 | X713232Y69850D02* 567 | X696468Y69850D01* 568 | D11* 569 | X381000Y82550D03* 570 | X482600Y82550D03* 571 | X381000Y57150D03* 572 | X482600Y57150D03* 573 | D14* 574 | X882650Y146050D03* 575 | X882650Y44450D03* 576 | D15* 577 | X857250Y44450D03* 578 | X857250Y146050D03* 579 | D14* 580 | X908050Y146050D03* 581 | X908050Y44450D03* 582 | D16* 583 | X19050Y171450D03* 584 | X44450Y171450D03* 585 | X69850Y171450D03* 586 | X95250Y171450D03* 587 | X120650Y171450D03* 588 | X146050Y171450D03* 589 | X171450Y171450D03* 590 | X196850Y171450D03* 591 | X222250Y171450D03* 592 | X247650Y171450D03* 593 | X273050Y171450D03* 594 | X298450Y171450D03* 595 | X323850Y171450D03* 596 | X349250Y171450D03* 597 | X349250Y19050D03* 598 | X323850Y19050D03* 599 | X298450Y19050D03* 600 | X273050Y19050D03* 601 | X247650Y19050D03* 602 | X222250Y19050D03* 603 | X196850Y19050D03* 604 | X171450Y19050D03* 605 | X146050Y19050D03* 606 | X120650Y19050D03* 607 | X95250Y19050D03* 608 | X69850Y19050D03* 609 | X44450Y19050D03* 610 | X19050Y19050D03* 611 | D17* 612 | X1041400Y145250D03* 613 | X1041400Y60250D03* 614 | X1041400Y30250D03* 615 | D18* 616 | X775970Y44450D03* 617 | X773430Y69850D03* 618 | X775970Y95250D03* 619 | X773430Y120650D03* 620 | X775970Y146050D03* 621 | X801370Y44450D03* 622 | X798830Y69850D03* 623 | X801370Y95250D03* 624 | X798830Y120650D03* 625 | X801370Y146050D03* 626 | D19* 627 | X406400Y146050D03* 628 | D20* 629 | X431800Y146050D03* 630 | X457200Y146050D03* 631 | X406400Y120650D03* 632 | X431800Y120650D03* 633 | X457200Y120650D03* 634 | D21* 635 | X939800Y50800D03* 636 | X939800Y76200D03* 637 | D14* 638 | X971550Y146050D03* 639 | X971550Y44450D03* 640 | D22* 641 | X775970Y95250D02* 642 | X704850Y95250D01* 643 | X762000Y69850D02* 644 | X773430Y69850D01* 645 | X685800Y139700D02* 646 | X666750Y158750D01* 647 | X754380Y120650D02* 648 | X773430Y120650D01* 649 | X754380Y120650D02* 650 | X735330Y139700D01* 651 | X685800Y139700D01* 652 | X406400Y120650D02* 653 | X381000Y120650D01* 654 | X69850Y120650D01* 655 | X19050Y171450D01* 656 | X381000Y120650D02* 657 | X406400Y146050D01* 658 | X773430Y120650D02* 659 | X798830Y120650D01* 660 | X775970Y118110D02* 661 | X773430Y120650D01* 662 | X775970Y118110D02* 663 | X775970Y95250D01* 664 | X801370Y95250D01* 665 | X775970Y95250D02* 666 | X775970Y72390D01* 667 | X773430Y69850D01* 668 | X798830Y69850D01* 669 | X801370Y95250D02* 670 | X857250Y95250D01* 671 | X908050Y146050D01* 672 | X762000Y69850D02* 673 | X717550Y25400D01* 674 | X1041400Y30250D02* 675 | X1041400Y31750D01* 676 | X1079500Y69850D01* 677 | X1079500Y152400D01* 678 | X1055724Y176176D01* 679 | X1001676Y176176D02* 680 | X971550Y146050D01* 681 | X1001676Y176176D02* 682 | X1055724Y176176D01* 683 | X381000Y57150D02* 684 | X355600Y82550D01* 685 | X133350Y82550D01* 686 | X69850Y19050D01* 687 | X355600Y82550D02* 688 | X381000Y82550D01* 689 | D23* 690 | X914400Y114300D02* 691 | X939800Y114300D01* 692 | X914400Y114300D02* 693 | X895350Y95250D01* 694 | X895350Y57150D01* 695 | X908050Y44450D01* 696 | D24* 697 | X127000Y139700D02* 698 | X95250Y171450D01* 699 | X368300Y139700D02* 700 | X393700Y165100D01* 701 | X368300Y139700D02* 702 | X127000Y139700D01* 703 | X393700Y165100D02* 704 | X647700Y165100D01* 705 | D25* 706 | X654050Y171450D01* 707 | X730250Y171450D01* 708 | X736600Y165100D01* 709 | D24* 710 | X933450Y165100D01* 711 | X939800Y158750D02* 712 | X939800Y139700D01* 713 | X939800Y158750D02* 714 | X933450Y165100D01* 715 | D22* 716 | X704850Y63500D02* 717 | X666750Y25400D01* 718 | X704850Y63500D02* 719 | X704850Y69850D01* 720 | D24* 721 | X438150Y12700D02* 722 | X374650Y12700D01* 723 | X438150Y12700D02* 724 | X482600Y57150D01* 725 | X254000Y50800D02* 726 | X222250Y19050D01* 727 | X254000Y50800D02* 728 | X336550Y50800D01* 729 | X374650Y12700D01* 730 | X241300Y63500D02* 731 | X196850Y19050D01* 732 | X349250Y63500D02* 733 | X387350Y25400D01* 734 | X412750Y25400D01* 735 | X469900Y82550D01* 736 | X482600Y82550D01* 737 | X349250Y63500D02* 738 | X241300Y63500D01* 739 | X469900Y95250D02* 740 | X482600Y82550D01* 741 | X469900Y95250D02* 742 | X457200Y95250D01* 743 | X431800Y120650D01* 744 | X431800Y146050D01* 745 | D22* 746 | X857250Y44450D02* 747 | X882650Y19050D01* 748 | X1003300Y19050D01* 749 | X1041400Y57150D01* 750 | X1041400Y60250D01* 751 | D23* 752 | X971550Y44450D02* 753 | X939800Y76200D01* 754 | D24* 755 | X139700Y152400D02* 756 | X120650Y171450D01* 757 | X139700Y152400D02* 758 | X361950Y152400D01* 759 | X387350Y177800D01* 760 | X946150Y177800D01* 761 | X958850Y165100D01* 762 | X958850Y101600D01* 763 | X952500Y95250D01* 764 | X927100Y95250D01* 765 | X920750Y69850D02* 766 | X939800Y50800D01* 767 | X920750Y88900D02* 768 | X927100Y95250D01* 769 | X920750Y88900D02* 770 | X920750Y69850D01* 771 | M02* 772 | -------------------------------------------------------------------------------- /hardware/hardware-MK1/gerber/board_2021-04-26_board/board.GBP: -------------------------------------------------------------------------------- 1 | G04 EAGLE Gerber RS-274X export* 2 | G75* 3 | %MOMM*% 4 | %FSLAX34Y34*% 5 | %LPD*% 6 | %INSolderpaste Bottom*% 7 | %IPPOS*% 8 | %AMOC8* 9 | 5,1,8,0,0,1.08239X$1,22.5*% 10 | G01* 11 | 12 | 13 | M02* 14 | -------------------------------------------------------------------------------- /hardware/hardware-MK1/gerber/board_2021-04-26_board/board.GBS: -------------------------------------------------------------------------------- 1 | G04 EAGLE Gerber RS-274X export* 2 | G75* 3 | %MOMM*% 4 | %FSLAX34Y34*% 5 | %LPD*% 6 | %INSoldermask Bottom*% 7 | %IPPOS*% 8 | %AMOC8* 9 | 5,1,8,0,0,1.08239X$1,22.5*% 10 | G01* 11 | %ADD10C,3.403200*% 12 | %ADD11P,1.649562X8X202.500000*% 13 | %ADD12P,1.649562X8X22.500000*% 14 | %ADD13P,2.034460X8X292.500000*% 15 | %ADD14C,1.879600*% 16 | %ADD15C,3.505200*% 17 | %ADD16P,1.649562X8X292.500000*% 18 | %ADD17P,1.649562X8X112.500000*% 19 | %ADD18C,1.676400*% 20 | %ADD19C,1.853200*% 21 | %ADD20P,2.254402X8X112.500000*% 22 | %ADD21C,1.727200*% 23 | %ADD22P,1.869504X8X22.500000*% 24 | %ADD23P,2.034460X8X112.500000*% 25 | 26 | G36* 27 | X469990Y11954D02* 28 | X469990Y11954D01* 29 | X470081Y11961D01* 30 | X470111Y11973D01* 31 | X470143Y11979D01* 32 | X470223Y12021D01* 33 | X470307Y12057D01* 34 | X470339Y12083D01* 35 | X470360Y12094D01* 36 | X470382Y12117D01* 37 | X470438Y12162D01* 38 | X495615Y37339D01* 39 | X499812Y37339D01* 40 | X475712Y13238D01* 41 | X475670Y13180D01* 42 | X475621Y13128D01* 43 | X475599Y13081D01* 44 | X475568Y13039D01* 45 | X475547Y12970D01* 46 | X475517Y12905D01* 47 | X475511Y12853D01* 48 | X475496Y12803D01* 49 | X475498Y12732D01* 50 | X475490Y12661D01* 51 | X475501Y12610D01* 52 | X475502Y12558D01* 53 | X475527Y12490D01* 54 | X475542Y12420D01* 55 | X475569Y12376D01* 56 | X475587Y12327D01* 57 | X475632Y12271D01* 58 | X475668Y12209D01* 59 | X475708Y12175D01* 60 | X475740Y12135D01* 61 | X475801Y12096D01* 62 | X475855Y12049D01* 63 | X475903Y12030D01* 64 | X475947Y12002D01* 65 | X476017Y11984D01* 66 | X476083Y11957D01* 67 | X476155Y11949D01* 68 | X476186Y11941D01* 69 | X476209Y11943D01* 70 | X476250Y11939D01* 71 | X482600Y11939D01* 72 | X482690Y11954D01* 73 | X482781Y11961D01* 74 | X482811Y11973D01* 75 | X482843Y11979D01* 76 | X482923Y12021D01* 77 | X483007Y12057D01* 78 | X483039Y12083D01* 79 | X483060Y12094D01* 80 | X483082Y12117D01* 81 | X483138Y12162D01* 82 | X508315Y37339D01* 83 | X512512Y37339D01* 84 | X488412Y13238D01* 85 | X488370Y13180D01* 86 | X488321Y13128D01* 87 | X488299Y13081D01* 88 | X488268Y13039D01* 89 | X488247Y12970D01* 90 | X488217Y12905D01* 91 | X488211Y12853D01* 92 | X488196Y12803D01* 93 | X488198Y12732D01* 94 | X488190Y12661D01* 95 | X488201Y12610D01* 96 | X488202Y12558D01* 97 | X488227Y12490D01* 98 | X488242Y12420D01* 99 | X488269Y12376D01* 100 | X488287Y12327D01* 101 | X488332Y12271D01* 102 | X488368Y12209D01* 103 | X488408Y12175D01* 104 | X488440Y12135D01* 105 | X488501Y12096D01* 106 | X488555Y12049D01* 107 | X488603Y12030D01* 108 | X488647Y12002D01* 109 | X488717Y11984D01* 110 | X488783Y11957D01* 111 | X488855Y11949D01* 112 | X488886Y11941D01* 113 | X488909Y11943D01* 114 | X488950Y11939D01* 115 | X495300Y11939D01* 116 | X495390Y11954D01* 117 | X495481Y11961D01* 118 | X495511Y11973D01* 119 | X495543Y11979D01* 120 | X495623Y12021D01* 121 | X495707Y12057D01* 122 | X495739Y12083D01* 123 | X495760Y12094D01* 124 | X495782Y12117D01* 125 | X495838Y12162D01* 126 | X521015Y37339D01* 127 | X525212Y37339D01* 128 | X501112Y13238D01* 129 | X501070Y13180D01* 130 | X501021Y13128D01* 131 | X500999Y13081D01* 132 | X500968Y13039D01* 133 | X500947Y12970D01* 134 | X500917Y12905D01* 135 | X500911Y12853D01* 136 | X500896Y12803D01* 137 | X500898Y12732D01* 138 | X500890Y12661D01* 139 | X500901Y12610D01* 140 | X500902Y12558D01* 141 | X500927Y12490D01* 142 | X500942Y12420D01* 143 | X500969Y12376D01* 144 | X500987Y12327D01* 145 | X501032Y12271D01* 146 | X501068Y12209D01* 147 | X501108Y12175D01* 148 | X501140Y12135D01* 149 | X501201Y12096D01* 150 | X501255Y12049D01* 151 | X501303Y12030D01* 152 | X501347Y12002D01* 153 | X501417Y11984D01* 154 | X501483Y11957D01* 155 | X501555Y11949D01* 156 | X501586Y11941D01* 157 | X501609Y11943D01* 158 | X501650Y11939D01* 159 | X508000Y11939D01* 160 | X508090Y11954D01* 161 | X508181Y11961D01* 162 | X508211Y11973D01* 163 | X508243Y11979D01* 164 | X508323Y12021D01* 165 | X508407Y12057D01* 166 | X508439Y12083D01* 167 | X508460Y12094D01* 168 | X508482Y12117D01* 169 | X508538Y12162D01* 170 | X533715Y37339D01* 171 | X537912Y37339D01* 172 | X513812Y13238D01* 173 | X513770Y13180D01* 174 | X513721Y13128D01* 175 | X513699Y13081D01* 176 | X513668Y13039D01* 177 | X513647Y12970D01* 178 | X513617Y12905D01* 179 | X513611Y12853D01* 180 | X513596Y12803D01* 181 | X513598Y12732D01* 182 | X513590Y12661D01* 183 | X513601Y12610D01* 184 | X513602Y12558D01* 185 | X513627Y12490D01* 186 | X513642Y12420D01* 187 | X513669Y12376D01* 188 | X513687Y12327D01* 189 | X513732Y12271D01* 190 | X513768Y12209D01* 191 | X513808Y12175D01* 192 | X513840Y12135D01* 193 | X513901Y12096D01* 194 | X513955Y12049D01* 195 | X514003Y12030D01* 196 | X514047Y12002D01* 197 | X514117Y11984D01* 198 | X514183Y11957D01* 199 | X514255Y11949D01* 200 | X514286Y11941D01* 201 | X514309Y11943D01* 202 | X514350Y11939D01* 203 | X520700Y11939D01* 204 | X520790Y11954D01* 205 | X520881Y11961D01* 206 | X520911Y11973D01* 207 | X520943Y11979D01* 208 | X521023Y12021D01* 209 | X521107Y12057D01* 210 | X521139Y12083D01* 211 | X521160Y12094D01* 212 | X521182Y12117D01* 213 | X521238Y12162D01* 214 | X546415Y37339D01* 215 | X550612Y37339D01* 216 | X526512Y13238D01* 217 | X526470Y13180D01* 218 | X526421Y13128D01* 219 | X526399Y13081D01* 220 | X526368Y13039D01* 221 | X526347Y12970D01* 222 | X526317Y12905D01* 223 | X526311Y12853D01* 224 | X526296Y12803D01* 225 | X526298Y12732D01* 226 | X526290Y12661D01* 227 | X526301Y12610D01* 228 | X526302Y12558D01* 229 | X526327Y12490D01* 230 | X526342Y12420D01* 231 | X526369Y12376D01* 232 | X526387Y12327D01* 233 | X526432Y12271D01* 234 | X526468Y12209D01* 235 | X526508Y12175D01* 236 | X526540Y12135D01* 237 | X526601Y12096D01* 238 | X526655Y12049D01* 239 | X526703Y12030D01* 240 | X526747Y12002D01* 241 | X526817Y11984D01* 242 | X526883Y11957D01* 243 | X526955Y11949D01* 244 | X526986Y11941D01* 245 | X527009Y11943D01* 246 | X527050Y11939D01* 247 | X533400Y11939D01* 248 | X533490Y11954D01* 249 | X533581Y11961D01* 250 | X533611Y11973D01* 251 | X533643Y11979D01* 252 | X533723Y12021D01* 253 | X533807Y12057D01* 254 | X533839Y12083D01* 255 | X533860Y12094D01* 256 | X533882Y12117D01* 257 | X533938Y12162D01* 258 | X559115Y37339D01* 259 | X563312Y37339D01* 260 | X539212Y13238D01* 261 | X539170Y13180D01* 262 | X539121Y13128D01* 263 | X539099Y13081D01* 264 | X539068Y13039D01* 265 | X539047Y12970D01* 266 | X539017Y12905D01* 267 | X539011Y12853D01* 268 | X538996Y12803D01* 269 | X538998Y12732D01* 270 | X538990Y12661D01* 271 | X539001Y12610D01* 272 | X539002Y12558D01* 273 | X539027Y12490D01* 274 | X539042Y12420D01* 275 | X539069Y12376D01* 276 | X539087Y12327D01* 277 | X539132Y12271D01* 278 | X539168Y12209D01* 279 | X539208Y12175D01* 280 | X539240Y12135D01* 281 | X539301Y12096D01* 282 | X539355Y12049D01* 283 | X539403Y12030D01* 284 | X539447Y12002D01* 285 | X539517Y11984D01* 286 | X539583Y11957D01* 287 | X539655Y11949D01* 288 | X539686Y11941D01* 289 | X539709Y11943D01* 290 | X539750Y11939D01* 291 | X546100Y11939D01* 292 | X546190Y11954D01* 293 | X546281Y11961D01* 294 | X546311Y11973D01* 295 | X546343Y11979D01* 296 | X546423Y12021D01* 297 | X546507Y12057D01* 298 | X546539Y12083D01* 299 | X546560Y12094D01* 300 | X546582Y12117D01* 301 | X546638Y12162D01* 302 | X571815Y37339D01* 303 | X576012Y37339D01* 304 | X551912Y13238D01* 305 | X551870Y13180D01* 306 | X551821Y13128D01* 307 | X551799Y13081D01* 308 | X551768Y13039D01* 309 | X551747Y12970D01* 310 | X551717Y12905D01* 311 | X551711Y12853D01* 312 | X551696Y12803D01* 313 | X551698Y12732D01* 314 | X551690Y12661D01* 315 | X551701Y12610D01* 316 | X551702Y12558D01* 317 | X551727Y12490D01* 318 | X551742Y12420D01* 319 | X551769Y12376D01* 320 | X551787Y12327D01* 321 | X551832Y12271D01* 322 | X551868Y12209D01* 323 | X551908Y12175D01* 324 | X551940Y12135D01* 325 | X552001Y12096D01* 326 | X552055Y12049D01* 327 | X552103Y12030D01* 328 | X552147Y12002D01* 329 | X552217Y11984D01* 330 | X552283Y11957D01* 331 | X552355Y11949D01* 332 | X552386Y11941D01* 333 | X552409Y11943D01* 334 | X552450Y11939D01* 335 | X558800Y11939D01* 336 | X558890Y11954D01* 337 | X558981Y11961D01* 338 | X559011Y11973D01* 339 | X559043Y11979D01* 340 | X559123Y12021D01* 341 | X559207Y12057D01* 342 | X559239Y12083D01* 343 | X559260Y12094D01* 344 | X559282Y12117D01* 345 | X559338Y12162D01* 346 | X584515Y37339D01* 347 | X588712Y37339D01* 348 | X564612Y13238D01* 349 | X564570Y13180D01* 350 | X564521Y13128D01* 351 | X564499Y13081D01* 352 | X564468Y13039D01* 353 | X564447Y12970D01* 354 | X564417Y12905D01* 355 | X564411Y12853D01* 356 | X564396Y12803D01* 357 | X564398Y12732D01* 358 | X564390Y12661D01* 359 | X564401Y12610D01* 360 | X564402Y12558D01* 361 | X564427Y12490D01* 362 | X564442Y12420D01* 363 | X564469Y12376D01* 364 | X564487Y12327D01* 365 | X564532Y12271D01* 366 | X564568Y12209D01* 367 | X564608Y12175D01* 368 | X564640Y12135D01* 369 | X564701Y12096D01* 370 | X564755Y12049D01* 371 | X564803Y12030D01* 372 | X564847Y12002D01* 373 | X564917Y11984D01* 374 | X564983Y11957D01* 375 | X565055Y11949D01* 376 | X565086Y11941D01* 377 | X565109Y11943D01* 378 | X565150Y11939D01* 379 | X571500Y11939D01* 380 | X571590Y11954D01* 381 | X571681Y11961D01* 382 | X571711Y11973D01* 383 | X571743Y11979D01* 384 | X571823Y12021D01* 385 | X571907Y12057D01* 386 | X571939Y12083D01* 387 | X571960Y12094D01* 388 | X571982Y12117D01* 389 | X572038Y12162D01* 390 | X597215Y37339D01* 391 | X601412Y37339D01* 392 | X577312Y13238D01* 393 | X577270Y13180D01* 394 | X577221Y13128D01* 395 | X577199Y13081D01* 396 | X577168Y13039D01* 397 | X577147Y12970D01* 398 | X577117Y12905D01* 399 | X577111Y12853D01* 400 | X577096Y12803D01* 401 | X577098Y12732D01* 402 | X577090Y12661D01* 403 | X577101Y12610D01* 404 | X577102Y12558D01* 405 | X577127Y12490D01* 406 | X577142Y12420D01* 407 | X577169Y12376D01* 408 | X577187Y12327D01* 409 | X577232Y12271D01* 410 | X577268Y12209D01* 411 | X577308Y12175D01* 412 | X577340Y12135D01* 413 | X577401Y12096D01* 414 | X577455Y12049D01* 415 | X577503Y12030D01* 416 | X577547Y12002D01* 417 | X577617Y11984D01* 418 | X577683Y11957D01* 419 | X577755Y11949D01* 420 | X577786Y11941D01* 421 | X577809Y11943D01* 422 | X577850Y11939D01* 423 | X584200Y11939D01* 424 | X584290Y11954D01* 425 | X584381Y11961D01* 426 | X584411Y11973D01* 427 | X584443Y11979D01* 428 | X584523Y12021D01* 429 | X584607Y12057D01* 430 | X584639Y12083D01* 431 | X584660Y12094D01* 432 | X584682Y12117D01* 433 | X584738Y12162D01* 434 | X609915Y37339D01* 435 | X614112Y37339D01* 436 | X590012Y13238D01* 437 | X589970Y13180D01* 438 | X589921Y13128D01* 439 | X589899Y13081D01* 440 | X589868Y13039D01* 441 | X589847Y12970D01* 442 | X589817Y12905D01* 443 | X589811Y12853D01* 444 | X589796Y12803D01* 445 | X589798Y12732D01* 446 | X589790Y12661D01* 447 | X589801Y12610D01* 448 | X589802Y12558D01* 449 | X589827Y12490D01* 450 | X589842Y12420D01* 451 | X589869Y12376D01* 452 | X589887Y12327D01* 453 | X589932Y12271D01* 454 | X589968Y12209D01* 455 | X590008Y12175D01* 456 | X590040Y12135D01* 457 | X590101Y12096D01* 458 | X590155Y12049D01* 459 | X590203Y12030D01* 460 | X590247Y12002D01* 461 | X590317Y11984D01* 462 | X590383Y11957D01* 463 | X590455Y11949D01* 464 | X590486Y11941D01* 465 | X590509Y11943D01* 466 | X590550Y11939D01* 467 | X596900Y11939D01* 468 | X596990Y11954D01* 469 | X597081Y11961D01* 470 | X597111Y11973D01* 471 | X597143Y11979D01* 472 | X597223Y12021D01* 473 | X597307Y12057D01* 474 | X597339Y12083D01* 475 | X597360Y12094D01* 476 | X597382Y12117D01* 477 | X597438Y12162D01* 478 | X622615Y37339D01* 479 | X626812Y37339D01* 480 | X602712Y13238D01* 481 | X602670Y13180D01* 482 | X602621Y13128D01* 483 | X602599Y13081D01* 484 | X602568Y13039D01* 485 | X602547Y12970D01* 486 | X602517Y12905D01* 487 | X602511Y12853D01* 488 | X602496Y12803D01* 489 | X602498Y12732D01* 490 | X602490Y12661D01* 491 | X602501Y12610D01* 492 | X602502Y12558D01* 493 | X602527Y12490D01* 494 | X602542Y12420D01* 495 | X602569Y12376D01* 496 | X602587Y12327D01* 497 | X602632Y12271D01* 498 | X602668Y12209D01* 499 | X602708Y12175D01* 500 | X602740Y12135D01* 501 | X602801Y12096D01* 502 | X602855Y12049D01* 503 | X602903Y12030D01* 504 | X602947Y12002D01* 505 | X603017Y11984D01* 506 | X603083Y11957D01* 507 | X603155Y11949D01* 508 | X603186Y11941D01* 509 | X603209Y11943D01* 510 | X603250Y11939D01* 511 | X609600Y11939D01* 512 | X609690Y11954D01* 513 | X609781Y11961D01* 514 | X609811Y11973D01* 515 | X609843Y11979D01* 516 | X609923Y12021D01* 517 | X610007Y12057D01* 518 | X610039Y12083D01* 519 | X610060Y12094D01* 520 | X610082Y12117D01* 521 | X610138Y12162D01* 522 | X635315Y37339D01* 523 | X639512Y37339D01* 524 | X615412Y13238D01* 525 | X615370Y13180D01* 526 | X615321Y13128D01* 527 | X615299Y13081D01* 528 | X615268Y13039D01* 529 | X615247Y12970D01* 530 | X615217Y12905D01* 531 | X615211Y12853D01* 532 | X615196Y12803D01* 533 | X615198Y12732D01* 534 | X615190Y12661D01* 535 | X615201Y12610D01* 536 | X615202Y12558D01* 537 | X615227Y12490D01* 538 | X615242Y12420D01* 539 | X615269Y12376D01* 540 | X615287Y12327D01* 541 | X615332Y12271D01* 542 | X615368Y12209D01* 543 | X615408Y12175D01* 544 | X615440Y12135D01* 545 | X615501Y12096D01* 546 | X615555Y12049D01* 547 | X615603Y12030D01* 548 | X615647Y12002D01* 549 | X615717Y11984D01* 550 | X615783Y11957D01* 551 | X615855Y11949D01* 552 | X615886Y11941D01* 553 | X615909Y11943D01* 554 | X615950Y11939D01* 555 | X622300Y11939D01* 556 | X622390Y11954D01* 557 | X622481Y11961D01* 558 | X622511Y11973D01* 559 | X622543Y11979D01* 560 | X622623Y12021D01* 561 | X622707Y12057D01* 562 | X622739Y12083D01* 563 | X622760Y12094D01* 564 | X622782Y12117D01* 565 | X622838Y12162D01* 566 | X673638Y62962D01* 567 | X673691Y63036D01* 568 | X673751Y63105D01* 569 | X673763Y63135D01* 570 | X673782Y63161D01* 571 | X673809Y63248D01* 572 | X673843Y63333D01* 573 | X673847Y63374D01* 574 | X673854Y63397D01* 575 | X673853Y63429D01* 576 | X673861Y63500D01* 577 | X673861Y120650D01* 578 | X673847Y120740D01* 579 | X673839Y120831D01* 580 | X673827Y120861D01* 581 | X673822Y120893D01* 582 | X673779Y120973D01* 583 | X673743Y121057D01* 584 | X673717Y121089D01* 585 | X673706Y121110D01* 586 | X673683Y121132D01* 587 | X673638Y121188D01* 588 | X641888Y152938D01* 589 | X641814Y152991D01* 590 | X641745Y153051D01* 591 | X641715Y153063D01* 592 | X641689Y153082D01* 593 | X641602Y153109D01* 594 | X641517Y153143D01* 595 | X641476Y153147D01* 596 | X641453Y153154D01* 597 | X641421Y153153D01* 598 | X641350Y153161D01* 599 | X482600Y153161D01* 600 | X482580Y153158D01* 601 | X482561Y153160D01* 602 | X482459Y153138D01* 603 | X482357Y153122D01* 604 | X482340Y153112D01* 605 | X482320Y153108D01* 606 | X482231Y153055D01* 607 | X482140Y153006D01* 608 | X482126Y152992D01* 609 | X482109Y152982D01* 610 | X482042Y152903D01* 611 | X481971Y152828D01* 612 | X481962Y152810D01* 613 | X481949Y152795D01* 614 | X481910Y152699D01* 615 | X481867Y152605D01* 616 | X481865Y152585D01* 617 | X481857Y152567D01* 618 | X481839Y152400D01* 619 | X481839Y114300D01* 620 | X481854Y114210D01* 621 | X481861Y114119D01* 622 | X481873Y114089D01* 623 | X481879Y114057D01* 624 | X481921Y113977D01* 625 | X481957Y113893D01* 626 | X481983Y113861D01* 627 | X481994Y113840D01* 628 | X482017Y113818D01* 629 | X482062Y113762D01* 630 | X500889Y94935D01* 631 | X500889Y51115D01* 632 | X463012Y13238D01* 633 | X462970Y13180D01* 634 | X462921Y13128D01* 635 | X462899Y13081D01* 636 | X462868Y13039D01* 637 | X462847Y12970D01* 638 | X462817Y12905D01* 639 | X462811Y12853D01* 640 | X462796Y12803D01* 641 | X462798Y12732D01* 642 | X462790Y12661D01* 643 | X462801Y12610D01* 644 | X462802Y12558D01* 645 | X462827Y12490D01* 646 | X462842Y12420D01* 647 | X462869Y12376D01* 648 | X462887Y12327D01* 649 | X462932Y12271D01* 650 | X462968Y12209D01* 651 | X463008Y12175D01* 652 | X463040Y12135D01* 653 | X463101Y12096D01* 654 | X463155Y12049D01* 655 | X463203Y12030D01* 656 | X463247Y12002D01* 657 | X463317Y11984D01* 658 | X463383Y11957D01* 659 | X463455Y11949D01* 660 | X463486Y11941D01* 661 | X463509Y11943D01* 662 | X463550Y11939D01* 663 | X469900Y11939D01* 664 | X469990Y11954D01* 665 | G37* 666 | D10* 667 | X44450Y95250D03* 668 | D11* 669 | X717550Y158750D03* 670 | X666750Y158750D03* 671 | D12* 672 | X666750Y25400D03* 673 | X717550Y25400D03* 674 | D13* 675 | X939800Y139700D03* 676 | X939800Y114300D03* 677 | D14* 678 | X713232Y120650D02* 679 | X696468Y120650D01* 680 | X696468Y95250D02* 681 | X713232Y95250D01* 682 | X713232Y69850D02* 683 | X696468Y69850D01* 684 | D15* 685 | X554990Y95250D03* 686 | D12* 687 | X381000Y82550D03* 688 | X482600Y82550D03* 689 | X381000Y57150D03* 690 | X482600Y57150D03* 691 | D16* 692 | X882650Y146050D03* 693 | X882650Y44450D03* 694 | D17* 695 | X857250Y44450D03* 696 | X857250Y146050D03* 697 | D16* 698 | X908050Y146050D03* 699 | X908050Y44450D03* 700 | D18* 701 | X19050Y171450D03* 702 | X44450Y171450D03* 703 | X69850Y171450D03* 704 | X95250Y171450D03* 705 | X120650Y171450D03* 706 | X146050Y171450D03* 707 | X171450Y171450D03* 708 | X196850Y171450D03* 709 | X222250Y171450D03* 710 | X247650Y171450D03* 711 | X273050Y171450D03* 712 | X298450Y171450D03* 713 | X323850Y171450D03* 714 | X349250Y171450D03* 715 | X349250Y19050D03* 716 | X323850Y19050D03* 717 | X298450Y19050D03* 718 | X273050Y19050D03* 719 | X247650Y19050D03* 720 | X222250Y19050D03* 721 | X196850Y19050D03* 722 | X171450Y19050D03* 723 | X146050Y19050D03* 724 | X120650Y19050D03* 725 | X95250Y19050D03* 726 | X69850Y19050D03* 727 | X44450Y19050D03* 728 | X19050Y19050D03* 729 | D19* 730 | X1041400Y145250D03* 731 | X1041400Y60250D03* 732 | X1041400Y30250D03* 733 | D20* 734 | X775970Y44450D03* 735 | X773430Y69850D03* 736 | X775970Y95250D03* 737 | X773430Y120650D03* 738 | X775970Y146050D03* 739 | X801370Y44450D03* 740 | X798830Y69850D03* 741 | X801370Y95250D03* 742 | X798830Y120650D03* 743 | X801370Y146050D03* 744 | D21* 745 | X406400Y146050D03* 746 | D22* 747 | X431800Y146050D03* 748 | X457200Y146050D03* 749 | X406400Y120650D03* 750 | X431800Y120650D03* 751 | X457200Y120650D03* 752 | D23* 753 | X939800Y50800D03* 754 | X939800Y76200D03* 755 | D16* 756 | X971550Y146050D03* 757 | X971550Y44450D03* 758 | M02* 759 | -------------------------------------------------------------------------------- /hardware/hardware-MK1/gerber/board_2021-04-26_board/board.GKO: -------------------------------------------------------------------------------- 1 | G04 EAGLE Gerber RS-274X export* 2 | G75* 3 | %MOMM*% 4 | %FSLAX34Y34*% 5 | %LPD*% 6 | %INBoard Outline*% 7 | %IPPOS*% 8 | %AMOC8* 9 | 5,1,8,0,0,1.08239X$1,22.5*% 10 | G01* 11 | %ADD10C,0.000000*% 12 | %ADD11C,0.254000*% 13 | 14 | 15 | D10* 16 | X0Y0D02* 17 | X1095250Y0D01* 18 | X1095250Y190400D01* 19 | X0Y190400D01* 20 | X0Y0D01* 21 | X28450Y95250D02* 22 | X28455Y95643D01* 23 | X28469Y96035D01* 24 | X28493Y96427D01* 25 | X28527Y96818D01* 26 | X28570Y97209D01* 27 | X28623Y97598D01* 28 | X28686Y97985D01* 29 | X28757Y98371D01* 30 | X28839Y98756D01* 31 | X28929Y99138D01* 32 | X29030Y99517D01* 33 | X29139Y99895D01* 34 | X29258Y100269D01* 35 | X29385Y100640D01* 36 | X29522Y101008D01* 37 | X29668Y101373D01* 38 | X29823Y101734D01* 39 | X29986Y102091D01* 40 | X30158Y102444D01* 41 | X30339Y102792D01* 42 | X30529Y103136D01* 43 | X30726Y103476D01* 44 | X30932Y103810D01* 45 | X31146Y104139D01* 46 | X31369Y104463D01* 47 | X31599Y104781D01* 48 | X31836Y105094D01* 49 | X32082Y105400D01* 50 | X32335Y105701D01* 51 | X32595Y105995D01* 52 | X32862Y106283D01* 53 | X33136Y106564D01* 54 | X33417Y106838D01* 55 | X33705Y107105D01* 56 | X33999Y107365D01* 57 | X34300Y107618D01* 58 | X34606Y107864D01* 59 | X34919Y108101D01* 60 | X35237Y108331D01* 61 | X35561Y108554D01* 62 | X35890Y108768D01* 63 | X36224Y108974D01* 64 | X36564Y109171D01* 65 | X36908Y109361D01* 66 | X37256Y109542D01* 67 | X37609Y109714D01* 68 | X37966Y109877D01* 69 | X38327Y110032D01* 70 | X38692Y110178D01* 71 | X39060Y110315D01* 72 | X39431Y110442D01* 73 | X39805Y110561D01* 74 | X40183Y110670D01* 75 | X40562Y110771D01* 76 | X40944Y110861D01* 77 | X41329Y110943D01* 78 | X41715Y111014D01* 79 | X42102Y111077D01* 80 | X42491Y111130D01* 81 | X42882Y111173D01* 82 | X43273Y111207D01* 83 | X43665Y111231D01* 84 | X44057Y111245D01* 85 | X44450Y111250D01* 86 | X44843Y111245D01* 87 | X45235Y111231D01* 88 | X45627Y111207D01* 89 | X46018Y111173D01* 90 | X46409Y111130D01* 91 | X46798Y111077D01* 92 | X47185Y111014D01* 93 | X47571Y110943D01* 94 | X47956Y110861D01* 95 | X48338Y110771D01* 96 | X48717Y110670D01* 97 | X49095Y110561D01* 98 | X49469Y110442D01* 99 | X49840Y110315D01* 100 | X50208Y110178D01* 101 | X50573Y110032D01* 102 | X50934Y109877D01* 103 | X51291Y109714D01* 104 | X51644Y109542D01* 105 | X51992Y109361D01* 106 | X52336Y109171D01* 107 | X52676Y108974D01* 108 | X53010Y108768D01* 109 | X53339Y108554D01* 110 | X53663Y108331D01* 111 | X53981Y108101D01* 112 | X54294Y107864D01* 113 | X54600Y107618D01* 114 | X54901Y107365D01* 115 | X55195Y107105D01* 116 | X55483Y106838D01* 117 | X55764Y106564D01* 118 | X56038Y106283D01* 119 | X56305Y105995D01* 120 | X56565Y105701D01* 121 | X56818Y105400D01* 122 | X57064Y105094D01* 123 | X57301Y104781D01* 124 | X57531Y104463D01* 125 | X57754Y104139D01* 126 | X57968Y103810D01* 127 | X58174Y103476D01* 128 | X58371Y103136D01* 129 | X58561Y102792D01* 130 | X58742Y102444D01* 131 | X58914Y102091D01* 132 | X59077Y101734D01* 133 | X59232Y101373D01* 134 | X59378Y101008D01* 135 | X59515Y100640D01* 136 | X59642Y100269D01* 137 | X59761Y99895D01* 138 | X59870Y99517D01* 139 | X59971Y99138D01* 140 | X60061Y98756D01* 141 | X60143Y98371D01* 142 | X60214Y97985D01* 143 | X60277Y97598D01* 144 | X60330Y97209D01* 145 | X60373Y96818D01* 146 | X60407Y96427D01* 147 | X60431Y96035D01* 148 | X60445Y95643D01* 149 | X60450Y95250D01* 150 | X60445Y94857D01* 151 | X60431Y94465D01* 152 | X60407Y94073D01* 153 | X60373Y93682D01* 154 | X60330Y93291D01* 155 | X60277Y92902D01* 156 | X60214Y92515D01* 157 | X60143Y92129D01* 158 | X60061Y91744D01* 159 | X59971Y91362D01* 160 | X59870Y90983D01* 161 | X59761Y90605D01* 162 | X59642Y90231D01* 163 | X59515Y89860D01* 164 | X59378Y89492D01* 165 | X59232Y89127D01* 166 | X59077Y88766D01* 167 | X58914Y88409D01* 168 | X58742Y88056D01* 169 | X58561Y87708D01* 170 | X58371Y87364D01* 171 | X58174Y87024D01* 172 | X57968Y86690D01* 173 | X57754Y86361D01* 174 | X57531Y86037D01* 175 | X57301Y85719D01* 176 | X57064Y85406D01* 177 | X56818Y85100D01* 178 | X56565Y84799D01* 179 | X56305Y84505D01* 180 | X56038Y84217D01* 181 | X55764Y83936D01* 182 | X55483Y83662D01* 183 | X55195Y83395D01* 184 | X54901Y83135D01* 185 | X54600Y82882D01* 186 | X54294Y82636D01* 187 | X53981Y82399D01* 188 | X53663Y82169D01* 189 | X53339Y81946D01* 190 | X53010Y81732D01* 191 | X52676Y81526D01* 192 | X52336Y81329D01* 193 | X51992Y81139D01* 194 | X51644Y80958D01* 195 | X51291Y80786D01* 196 | X50934Y80623D01* 197 | X50573Y80468D01* 198 | X50208Y80322D01* 199 | X49840Y80185D01* 200 | X49469Y80058D01* 201 | X49095Y79939D01* 202 | X48717Y79830D01* 203 | X48338Y79729D01* 204 | X47956Y79639D01* 205 | X47571Y79557D01* 206 | X47185Y79486D01* 207 | X46798Y79423D01* 208 | X46409Y79370D01* 209 | X46018Y79327D01* 210 | X45627Y79293D01* 211 | X45235Y79269D01* 212 | X44843Y79255D01* 213 | X44450Y79250D01* 214 | X44057Y79255D01* 215 | X43665Y79269D01* 216 | X43273Y79293D01* 217 | X42882Y79327D01* 218 | X42491Y79370D01* 219 | X42102Y79423D01* 220 | X41715Y79486D01* 221 | X41329Y79557D01* 222 | X40944Y79639D01* 223 | X40562Y79729D01* 224 | X40183Y79830D01* 225 | X39805Y79939D01* 226 | X39431Y80058D01* 227 | X39060Y80185D01* 228 | X38692Y80322D01* 229 | X38327Y80468D01* 230 | X37966Y80623D01* 231 | X37609Y80786D01* 232 | X37256Y80958D01* 233 | X36908Y81139D01* 234 | X36564Y81329D01* 235 | X36224Y81526D01* 236 | X35890Y81732D01* 237 | X35561Y81946D01* 238 | X35237Y82169D01* 239 | X34919Y82399D01* 240 | X34606Y82636D01* 241 | X34300Y82882D01* 242 | X33999Y83135D01* 243 | X33705Y83395D01* 244 | X33417Y83662D01* 245 | X33136Y83936D01* 246 | X32862Y84217D01* 247 | X32595Y84505D01* 248 | X32335Y84799D01* 249 | X32082Y85100D01* 250 | X31836Y85406D01* 251 | X31599Y85719D01* 252 | X31369Y86037D01* 253 | X31146Y86361D01* 254 | X30932Y86690D01* 255 | X30726Y87024D01* 256 | X30529Y87364D01* 257 | X30339Y87708D01* 258 | X30158Y88056D01* 259 | X29986Y88409D01* 260 | X29823Y88766D01* 261 | X29668Y89127D01* 262 | X29522Y89492D01* 263 | X29385Y89860D01* 264 | X29258Y90231D01* 265 | X29139Y90605D01* 266 | X29030Y90983D01* 267 | X28929Y91362D01* 268 | X28839Y91744D01* 269 | X28757Y92129D01* 270 | X28686Y92515D01* 271 | X28623Y92902D01* 272 | X28570Y93291D01* 273 | X28527Y93682D01* 274 | X28493Y94073D01* 275 | X28469Y94465D01* 276 | X28455Y94857D01* 277 | X28450Y95250D01* 278 | X538480Y95250D02* 279 | X538485Y95655D01* 280 | X538500Y96060D01* 281 | X538525Y96465D01* 282 | X538560Y96868D01* 283 | X538604Y97271D01* 284 | X538659Y97673D01* 285 | X538723Y98073D01* 286 | X538797Y98471D01* 287 | X538881Y98867D01* 288 | X538975Y99262D01* 289 | X539078Y99653D01* 290 | X539191Y100043D01* 291 | X539313Y100429D01* 292 | X539445Y100812D01* 293 | X539586Y101192D01* 294 | X539737Y101568D01* 295 | X539896Y101941D01* 296 | X540065Y102309D01* 297 | X540243Y102673D01* 298 | X540429Y103033D01* 299 | X540625Y103388D01* 300 | X540829Y103738D01* 301 | X541041Y104083D01* 302 | X541262Y104422D01* 303 | X541492Y104757D01* 304 | X541729Y105085D01* 305 | X541974Y105407D01* 306 | X542228Y105724D01* 307 | X542488Y106034D01* 308 | X542757Y106337D01* 309 | X543033Y106634D01* 310 | X543316Y106924D01* 311 | X543606Y107207D01* 312 | X543903Y107483D01* 313 | X544206Y107752D01* 314 | X544516Y108012D01* 315 | X544833Y108266D01* 316 | X545155Y108511D01* 317 | X545483Y108748D01* 318 | X545818Y108978D01* 319 | X546157Y109199D01* 320 | X546502Y109411D01* 321 | X546852Y109615D01* 322 | X547207Y109811D01* 323 | X547567Y109997D01* 324 | X547931Y110175D01* 325 | X548299Y110344D01* 326 | X548672Y110503D01* 327 | X549048Y110654D01* 328 | X549428Y110795D01* 329 | X549811Y110927D01* 330 | X550197Y111049D01* 331 | X550587Y111162D01* 332 | X550978Y111265D01* 333 | X551373Y111359D01* 334 | X551769Y111443D01* 335 | X552167Y111517D01* 336 | X552567Y111581D01* 337 | X552969Y111636D01* 338 | X553372Y111680D01* 339 | X553775Y111715D01* 340 | X554180Y111740D01* 341 | X554585Y111755D01* 342 | X554990Y111760D01* 343 | X555395Y111755D01* 344 | X555800Y111740D01* 345 | X556205Y111715D01* 346 | X556608Y111680D01* 347 | X557011Y111636D01* 348 | X557413Y111581D01* 349 | X557813Y111517D01* 350 | X558211Y111443D01* 351 | X558607Y111359D01* 352 | X559002Y111265D01* 353 | X559393Y111162D01* 354 | X559783Y111049D01* 355 | X560169Y110927D01* 356 | X560552Y110795D01* 357 | X560932Y110654D01* 358 | X561308Y110503D01* 359 | X561681Y110344D01* 360 | X562049Y110175D01* 361 | X562413Y109997D01* 362 | X562773Y109811D01* 363 | X563128Y109615D01* 364 | X563478Y109411D01* 365 | X563823Y109199D01* 366 | X564162Y108978D01* 367 | X564497Y108748D01* 368 | X564825Y108511D01* 369 | X565147Y108266D01* 370 | X565464Y108012D01* 371 | X565774Y107752D01* 372 | X566077Y107483D01* 373 | X566374Y107207D01* 374 | X566664Y106924D01* 375 | X566947Y106634D01* 376 | X567223Y106337D01* 377 | X567492Y106034D01* 378 | X567752Y105724D01* 379 | X568006Y105407D01* 380 | X568251Y105085D01* 381 | X568488Y104757D01* 382 | X568718Y104422D01* 383 | X568939Y104083D01* 384 | X569151Y103738D01* 385 | X569355Y103388D01* 386 | X569551Y103033D01* 387 | X569737Y102673D01* 388 | X569915Y102309D01* 389 | X570084Y101941D01* 390 | X570243Y101568D01* 391 | X570394Y101192D01* 392 | X570535Y100812D01* 393 | X570667Y100429D01* 394 | X570789Y100043D01* 395 | X570902Y99653D01* 396 | X571005Y99262D01* 397 | X571099Y98867D01* 398 | X571183Y98471D01* 399 | X571257Y98073D01* 400 | X571321Y97673D01* 401 | X571376Y97271D01* 402 | X571420Y96868D01* 403 | X571455Y96465D01* 404 | X571480Y96060D01* 405 | X571495Y95655D01* 406 | X571500Y95250D01* 407 | X571495Y94845D01* 408 | X571480Y94440D01* 409 | X571455Y94035D01* 410 | X571420Y93632D01* 411 | X571376Y93229D01* 412 | X571321Y92827D01* 413 | X571257Y92427D01* 414 | X571183Y92029D01* 415 | X571099Y91633D01* 416 | X571005Y91238D01* 417 | X570902Y90847D01* 418 | X570789Y90457D01* 419 | X570667Y90071D01* 420 | X570535Y89688D01* 421 | X570394Y89308D01* 422 | X570243Y88932D01* 423 | X570084Y88559D01* 424 | X569915Y88191D01* 425 | X569737Y87827D01* 426 | X569551Y87467D01* 427 | X569355Y87112D01* 428 | X569151Y86762D01* 429 | X568939Y86417D01* 430 | X568718Y86078D01* 431 | X568488Y85743D01* 432 | X568251Y85415D01* 433 | X568006Y85093D01* 434 | X567752Y84776D01* 435 | X567492Y84466D01* 436 | X567223Y84163D01* 437 | X566947Y83866D01* 438 | X566664Y83576D01* 439 | X566374Y83293D01* 440 | X566077Y83017D01* 441 | X565774Y82748D01* 442 | X565464Y82488D01* 443 | X565147Y82234D01* 444 | X564825Y81989D01* 445 | X564497Y81752D01* 446 | X564162Y81522D01* 447 | X563823Y81301D01* 448 | X563478Y81089D01* 449 | X563128Y80885D01* 450 | X562773Y80689D01* 451 | X562413Y80503D01* 452 | X562049Y80325D01* 453 | X561681Y80156D01* 454 | X561308Y79997D01* 455 | X560932Y79846D01* 456 | X560552Y79705D01* 457 | X560169Y79573D01* 458 | X559783Y79451D01* 459 | X559393Y79338D01* 460 | X559002Y79235D01* 461 | X558607Y79141D01* 462 | X558211Y79057D01* 463 | X557813Y78983D01* 464 | X557413Y78919D01* 465 | X557011Y78864D01* 466 | X556608Y78820D01* 467 | X556205Y78785D01* 468 | X555800Y78760D01* 469 | X555395Y78745D01* 470 | X554990Y78740D01* 471 | X554585Y78745D01* 472 | X554180Y78760D01* 473 | X553775Y78785D01* 474 | X553372Y78820D01* 475 | X552969Y78864D01* 476 | X552567Y78919D01* 477 | X552167Y78983D01* 478 | X551769Y79057D01* 479 | X551373Y79141D01* 480 | X550978Y79235D01* 481 | X550587Y79338D01* 482 | X550197Y79451D01* 483 | X549811Y79573D01* 484 | X549428Y79705D01* 485 | X549048Y79846D01* 486 | X548672Y79997D01* 487 | X548299Y80156D01* 488 | X547931Y80325D01* 489 | X547567Y80503D01* 490 | X547207Y80689D01* 491 | X546852Y80885D01* 492 | X546502Y81089D01* 493 | X546157Y81301D01* 494 | X545818Y81522D01* 495 | X545483Y81752D01* 496 | X545155Y81989D01* 497 | X544833Y82234D01* 498 | X544516Y82488D01* 499 | X544206Y82748D01* 500 | X543903Y83017D01* 501 | X543606Y83293D01* 502 | X543316Y83576D01* 503 | X543033Y83866D01* 504 | X542757Y84163D01* 505 | X542488Y84466D01* 506 | X542228Y84776D01* 507 | X541974Y85093D01* 508 | X541729Y85415D01* 509 | X541492Y85743D01* 510 | X541262Y86078D01* 511 | X541041Y86417D01* 512 | X540829Y86762D01* 513 | X540625Y87112D01* 514 | X540429Y87467D01* 515 | X540243Y87827D01* 516 | X540065Y88191D01* 517 | X539896Y88559D01* 518 | X539737Y88932D01* 519 | X539586Y89308D01* 520 | X539445Y89688D01* 521 | X539313Y90071D01* 522 | X539191Y90457D01* 523 | X539078Y90847D01* 524 | X538975Y91238D01* 525 | X538881Y91633D01* 526 | X538797Y92029D01* 527 | X538723Y92427D01* 528 | X538659Y92827D01* 529 | X538604Y93229D01* 530 | X538560Y93632D01* 531 | X538525Y94035D01* 532 | X538500Y94440D01* 533 | X538485Y94845D01* 534 | X538480Y95250D01* 535 | D11* 536 | X0Y0D02* 537 | X1095250Y0D01* 538 | X1095250Y190400D01* 539 | X0Y190400D01* 540 | X0Y0D01* 541 | X60450Y94726D02* 542 | X60382Y93681D01* 543 | X60245Y92642D01* 544 | X60040Y91615D01* 545 | X59769Y90603D01* 546 | X59433Y89611D01* 547 | X59032Y88643D01* 548 | X58568Y87704D01* 549 | X58045Y86796D01* 550 | X57463Y85925D01* 551 | X56825Y85094D01* 552 | X56134Y84307D01* 553 | X55393Y83566D01* 554 | X54606Y82875D01* 555 | X53775Y82238D01* 556 | X52904Y81656D01* 557 | X51996Y81132D01* 558 | X51057Y80668D01* 559 | X50089Y80267D01* 560 | X49097Y79931D01* 561 | X48085Y79660D01* 562 | X47058Y79455D01* 563 | X46019Y79319D01* 564 | X44974Y79250D01* 565 | X43926Y79250D01* 566 | X42881Y79319D01* 567 | X41842Y79455D01* 568 | X40815Y79660D01* 569 | X39803Y79931D01* 570 | X38811Y80267D01* 571 | X37843Y80668D01* 572 | X36904Y81132D01* 573 | X35996Y81656D01* 574 | X35125Y82238D01* 575 | X34294Y82875D01* 576 | X33507Y83566D01* 577 | X32766Y84307D01* 578 | X32075Y85094D01* 579 | X31438Y85925D01* 580 | X30856Y86796D01* 581 | X30332Y87704D01* 582 | X29868Y88643D01* 583 | X29467Y89611D01* 584 | X29131Y90603D01* 585 | X28860Y91615D01* 586 | X28655Y92642D01* 587 | X28519Y93681D01* 588 | X28450Y94726D01* 589 | X28450Y95774D01* 590 | X28519Y96819D01* 591 | X28655Y97858D01* 592 | X28860Y98885D01* 593 | X29131Y99897D01* 594 | X29467Y100889D01* 595 | X29868Y101857D01* 596 | X30332Y102796D01* 597 | X30856Y103704D01* 598 | X31438Y104575D01* 599 | X32075Y105406D01* 600 | X32766Y106193D01* 601 | X33507Y106934D01* 602 | X34294Y107625D01* 603 | X35125Y108263D01* 604 | X35996Y108845D01* 605 | X36904Y109368D01* 606 | X37843Y109832D01* 607 | X38811Y110233D01* 608 | X39803Y110569D01* 609 | X40815Y110840D01* 610 | X41842Y111045D01* 611 | X42881Y111182D01* 612 | X43926Y111250D01* 613 | X44974Y111250D01* 614 | X46019Y111182D01* 615 | X47058Y111045D01* 616 | X48085Y110840D01* 617 | X49097Y110569D01* 618 | X50089Y110233D01* 619 | X51057Y109832D01* 620 | X51996Y109368D01* 621 | X52904Y108845D01* 622 | X53775Y108263D01* 623 | X54606Y107625D01* 624 | X55393Y106934D01* 625 | X56134Y106193D01* 626 | X56825Y105406D01* 627 | X57463Y104575D01* 628 | X58045Y103704D01* 629 | X58568Y102796D01* 630 | X59032Y101857D01* 631 | X59433Y100889D01* 632 | X59769Y99897D01* 633 | X60040Y98885D01* 634 | X60245Y97858D01* 635 | X60382Y96819D01* 636 | X60450Y95774D01* 637 | X60450Y94726D01* 638 | X555530Y78740D02* 639 | X556609Y78811D01* 640 | X557681Y78952D01* 641 | X558741Y79163D01* 642 | X559785Y79442D01* 643 | X560809Y79790D01* 644 | X561807Y80204D01* 645 | X562777Y80682D01* 646 | X563713Y81222D01* 647 | X564612Y81823D01* 648 | X565469Y82481D01* 649 | X566282Y83194D01* 650 | X567047Y83958D01* 651 | X567759Y84771D01* 652 | X568417Y85628D01* 653 | X569018Y86527D01* 654 | X569558Y87463D01* 655 | X570036Y88433D01* 656 | X570450Y89431D01* 657 | X570798Y90455D01* 658 | X571077Y91499D01* 659 | X571288Y92559D01* 660 | X571429Y93631D01* 661 | X571500Y94710D01* 662 | X571500Y95790D01* 663 | X571429Y96869D01* 664 | X571288Y97941D01* 665 | X571077Y99001D01* 666 | X570798Y100045D01* 667 | X570450Y101069D01* 668 | X570036Y102067D01* 669 | X569558Y103037D01* 670 | X569018Y103973D01* 671 | X568417Y104872D01* 672 | X567759Y105729D01* 673 | X567047Y106542D01* 674 | X566282Y107307D01* 675 | X565469Y108019D01* 676 | X564612Y108677D01* 677 | X563713Y109278D01* 678 | X562777Y109818D01* 679 | X561807Y110296D01* 680 | X560809Y110710D01* 681 | X559785Y111058D01* 682 | X558741Y111337D01* 683 | X557681Y111548D01* 684 | X556609Y111689D01* 685 | X555530Y111760D01* 686 | X554450Y111760D01* 687 | X553371Y111689D01* 688 | X552299Y111548D01* 689 | X551239Y111337D01* 690 | X550195Y111058D01* 691 | X549171Y110710D01* 692 | X548173Y110296D01* 693 | X547203Y109818D01* 694 | X546267Y109278D01* 695 | X545368Y108677D01* 696 | X544511Y108019D01* 697 | X543698Y107307D01* 698 | X542934Y106542D01* 699 | X542221Y105729D01* 700 | X541563Y104872D01* 701 | X540962Y103973D01* 702 | X540422Y103037D01* 703 | X539944Y102067D01* 704 | X539530Y101069D01* 705 | X539182Y100045D01* 706 | X538903Y99001D01* 707 | X538692Y97941D01* 708 | X538551Y96869D01* 709 | X538480Y95790D01* 710 | X538480Y94710D01* 711 | X538551Y93631D01* 712 | X538692Y92559D01* 713 | X538903Y91499D01* 714 | X539182Y90455D01* 715 | X539530Y89431D01* 716 | X539944Y88433D01* 717 | X540422Y87463D01* 718 | X540962Y86527D01* 719 | X541563Y85628D01* 720 | X542221Y84771D01* 721 | X542934Y83958D01* 722 | X543698Y83194D01* 723 | X544511Y82481D01* 724 | X545368Y81823D01* 725 | X546267Y81222D01* 726 | X547203Y80682D01* 727 | X548173Y80204D01* 728 | X549171Y79790D01* 729 | X550195Y79442D01* 730 | X551239Y79163D01* 731 | X552299Y78952D01* 732 | X553371Y78811D01* 733 | X554450Y78740D01* 734 | X555530Y78740D01* 735 | M02* 736 | -------------------------------------------------------------------------------- /hardware/hardware-MK1/gerber/board_2021-04-26_board/board.GTL: -------------------------------------------------------------------------------- 1 | G04 EAGLE Gerber RS-274X export* 2 | G75* 3 | %MOMM*% 4 | %FSLAX34Y34*% 5 | %LPD*% 6 | %INTop Copper*% 7 | %IPPOS*% 8 | %AMOC8* 9 | 5,1,8,0,0,1.08239X$1,22.5*% 10 | G01* 11 | %ADD10P,1.429621X8X202.500000*% 12 | %ADD11P,1.429621X8X22.500000*% 13 | %ADD12P,1.814519X8X292.500000*% 14 | %ADD13C,1.676400*% 15 | %ADD14P,1.429621X8X292.500000*% 16 | %ADD15P,1.429621X8X112.500000*% 17 | %ADD16C,1.473200*% 18 | %ADD17C,1.650000*% 19 | %ADD18P,2.034460X8X112.500000*% 20 | %ADD19C,1.524000*% 21 | %ADD20P,1.649562X8X22.500000*% 22 | %ADD21P,1.814519X8X112.500000*% 23 | %ADD22C,0.812800*% 24 | %ADD23C,0.406400*% 25 | %ADD24C,0.609600*% 26 | 27 | 28 | D10* 29 | X717550Y158750D03* 30 | X666750Y158750D03* 31 | D11* 32 | X666750Y25400D03* 33 | X717550Y25400D03* 34 | D12* 35 | X939800Y139700D03* 36 | X939800Y114300D03* 37 | D13* 38 | X713232Y120650D02* 39 | X696468Y120650D01* 40 | X696468Y95250D02* 41 | X713232Y95250D01* 42 | X713232Y69850D02* 43 | X696468Y69850D01* 44 | D11* 45 | X381000Y82550D03* 46 | X482600Y82550D03* 47 | X381000Y57150D03* 48 | X482600Y57150D03* 49 | D14* 50 | X882650Y146050D03* 51 | X882650Y44450D03* 52 | D15* 53 | X857250Y44450D03* 54 | X857250Y146050D03* 55 | D14* 56 | X908050Y146050D03* 57 | X908050Y44450D03* 58 | D16* 59 | X19050Y171450D03* 60 | X44450Y171450D03* 61 | X69850Y171450D03* 62 | X95250Y171450D03* 63 | X120650Y171450D03* 64 | X146050Y171450D03* 65 | X171450Y171450D03* 66 | X196850Y171450D03* 67 | X222250Y171450D03* 68 | X247650Y171450D03* 69 | X273050Y171450D03* 70 | X298450Y171450D03* 71 | X323850Y171450D03* 72 | X349250Y171450D03* 73 | X349250Y19050D03* 74 | X323850Y19050D03* 75 | X298450Y19050D03* 76 | X273050Y19050D03* 77 | X247650Y19050D03* 78 | X222250Y19050D03* 79 | X196850Y19050D03* 80 | X171450Y19050D03* 81 | X146050Y19050D03* 82 | X120650Y19050D03* 83 | X95250Y19050D03* 84 | X69850Y19050D03* 85 | X44450Y19050D03* 86 | X19050Y19050D03* 87 | D17* 88 | X1041400Y145250D03* 89 | X1041400Y60250D03* 90 | X1041400Y30250D03* 91 | D18* 92 | X775970Y44450D03* 93 | X773430Y69850D03* 94 | X775970Y95250D03* 95 | X773430Y120650D03* 96 | X775970Y146050D03* 97 | X801370Y44450D03* 98 | X798830Y69850D03* 99 | X801370Y95250D03* 100 | X798830Y120650D03* 101 | X801370Y146050D03* 102 | D19* 103 | X406400Y146050D03* 104 | D20* 105 | X431800Y146050D03* 106 | X457200Y146050D03* 107 | X406400Y120650D03* 108 | X431800Y120650D03* 109 | X457200Y120650D03* 110 | D21* 111 | X939800Y50800D03* 112 | X939800Y76200D03* 113 | D14* 114 | X971550Y146050D03* 115 | X971550Y44450D03* 116 | D22* 117 | X1017500Y30250D02* 118 | X1041400Y30250D01* 119 | X1017500Y30250D02* 120 | X996950Y50800D01* 121 | X996950Y152400D01* 122 | X984250Y165100D01* 123 | X927100Y165100D01* 124 | X908050Y146050D01* 125 | X666750Y158750D02* 126 | X660400Y165100D01* 127 | X425450Y165100D01* 128 | X406400Y146050D01* 129 | X728869Y44958D02* 130 | X754777Y19050D01* 131 | X812800Y19050D01* 132 | X831850Y120650D02* 133 | X857250Y146050D01* 134 | X831850Y120650D02* 135 | X831850Y38100D01* 136 | X812800Y19050D01* 137 | X400558Y38608D02* 138 | X400050Y38100D01* 139 | X381000Y57150D01* 140 | X654558Y44958D02* 141 | X728869Y44958D01* 142 | X647700Y38100D02* 143 | X400050Y38100D01* 144 | X647700Y38100D02* 145 | X654558Y44958D01* 146 | D23* 147 | X406400Y177800D02* 148 | X371475Y142875D01* 149 | X863600Y177800D02* 150 | X869950Y171450D01* 151 | X869950Y57150D01* 152 | X882650Y44450D01* 153 | X863600Y177800D02* 154 | X406400Y177800D01* 155 | X101600Y139700D02* 156 | X69850Y171450D01* 157 | X101600Y139700D02* 158 | X368300Y139700D01* 159 | X371475Y142875D01* 160 | X882650Y146050D02* 161 | X914400Y177800D01* 162 | X1009650Y177800D01* 163 | X1041400Y146050D01* 164 | D24* 165 | X1041400Y145250D01* 166 | D22* 167 | X381000Y19050D02* 168 | X361950Y38100D01* 169 | X38100Y38100D01* 170 | X19050Y19050D01* 171 | X381000Y19050D02* 172 | X660400Y19050D01* 173 | X666750Y25400D01* 174 | X775970Y146050D02* 175 | X801370Y146050D01* 176 | X730250Y146050D02* 177 | X704850Y120650D01* 178 | X730250Y146050D02* 179 | X775970Y146050D01* 180 | X730250Y146050D02* 181 | X717550Y158750D01* 182 | D23* 183 | X495300Y69850D02* 184 | X482600Y57150D01* 185 | X495300Y69850D02* 186 | X495300Y95250D01* 187 | X482600Y107950D01* 188 | X469900Y107950D01* 189 | X457200Y120650D01* 190 | X457200Y146050D01* 191 | M02* 192 | -------------------------------------------------------------------------------- /hardware/hardware-MK1/gerber/board_2021-04-26_board/board.GTP: -------------------------------------------------------------------------------- 1 | G04 EAGLE Gerber RS-274X export* 2 | G75* 3 | %MOMM*% 4 | %FSLAX34Y34*% 5 | %LPD*% 6 | %INSolderpaste Top*% 7 | %IPPOS*% 8 | %AMOC8* 9 | 5,1,8,0,0,1.08239X$1,22.5*% 10 | G01* 11 | 12 | 13 | M02* 14 | -------------------------------------------------------------------------------- /hardware/hardware-MK1/gerber/board_2021-04-26_board/board.GTS: -------------------------------------------------------------------------------- 1 | G04 EAGLE Gerber RS-274X export* 2 | G75* 3 | %MOMM*% 4 | %FSLAX34Y34*% 5 | %LPD*% 6 | %INSoldermask Top*% 7 | %IPPOS*% 8 | %AMOC8* 9 | 5,1,8,0,0,1.08239X$1,22.5*% 10 | G01* 11 | %ADD10C,3.403200*% 12 | %ADD11P,1.649562X8X202.500000*% 13 | %ADD12P,1.649562X8X22.500000*% 14 | %ADD13P,2.034460X8X292.500000*% 15 | %ADD14C,1.879600*% 16 | %ADD15C,3.505200*% 17 | %ADD16P,1.649562X8X292.500000*% 18 | %ADD17P,1.649562X8X112.500000*% 19 | %ADD18C,1.676400*% 20 | %ADD19C,1.853200*% 21 | %ADD20P,2.254402X8X112.500000*% 22 | %ADD21C,1.727200*% 23 | %ADD22P,1.869504X8X22.500000*% 24 | %ADD23P,2.034460X8X112.500000*% 25 | 26 | 27 | D10* 28 | X44450Y95250D03* 29 | D11* 30 | X717550Y158750D03* 31 | X666750Y158750D03* 32 | D12* 33 | X666750Y25400D03* 34 | X717550Y25400D03* 35 | D13* 36 | X939800Y139700D03* 37 | X939800Y114300D03* 38 | D14* 39 | X713232Y120650D02* 40 | X696468Y120650D01* 41 | X696468Y95250D02* 42 | X713232Y95250D01* 43 | X713232Y69850D02* 44 | X696468Y69850D01* 45 | D15* 46 | X554990Y95250D03* 47 | D12* 48 | X381000Y82550D03* 49 | X482600Y82550D03* 50 | X381000Y57150D03* 51 | X482600Y57150D03* 52 | D16* 53 | X882650Y146050D03* 54 | X882650Y44450D03* 55 | D17* 56 | X857250Y44450D03* 57 | X857250Y146050D03* 58 | D16* 59 | X908050Y146050D03* 60 | X908050Y44450D03* 61 | D18* 62 | X19050Y171450D03* 63 | X44450Y171450D03* 64 | X69850Y171450D03* 65 | X95250Y171450D03* 66 | X120650Y171450D03* 67 | X146050Y171450D03* 68 | X171450Y171450D03* 69 | X196850Y171450D03* 70 | X222250Y171450D03* 71 | X247650Y171450D03* 72 | X273050Y171450D03* 73 | X298450Y171450D03* 74 | X323850Y171450D03* 75 | X349250Y171450D03* 76 | X349250Y19050D03* 77 | X323850Y19050D03* 78 | X298450Y19050D03* 79 | X273050Y19050D03* 80 | X247650Y19050D03* 81 | X222250Y19050D03* 82 | X196850Y19050D03* 83 | X171450Y19050D03* 84 | X146050Y19050D03* 85 | X120650Y19050D03* 86 | X95250Y19050D03* 87 | X69850Y19050D03* 88 | X44450Y19050D03* 89 | X19050Y19050D03* 90 | D19* 91 | X1041400Y145250D03* 92 | X1041400Y60250D03* 93 | X1041400Y30250D03* 94 | D20* 95 | X775970Y44450D03* 96 | X773430Y69850D03* 97 | X775970Y95250D03* 98 | X773430Y120650D03* 99 | X775970Y146050D03* 100 | X801370Y44450D03* 101 | X798830Y69850D03* 102 | X801370Y95250D03* 103 | X798830Y120650D03* 104 | X801370Y146050D03* 105 | D21* 106 | X406400Y146050D03* 107 | D22* 108 | X431800Y146050D03* 109 | X457200Y146050D03* 110 | X406400Y120650D03* 111 | X431800Y120650D03* 112 | X457200Y120650D03* 113 | D23* 114 | X939800Y50800D03* 115 | X939800Y76200D03* 116 | D16* 117 | X971550Y146050D03* 118 | X971550Y44450D03* 119 | M02* 120 | -------------------------------------------------------------------------------- /hardware/hardware-MK1/gerber/board_2021-04-26_board/board.XLN: -------------------------------------------------------------------------------- 1 | M48 2 | ;GenerationSoftware,Autodesk,EAGLE,9.6.2*% 3 | ;CreationDate,2021-04-26T18:43:46Z*% 4 | FMAT,2 5 | ICI,OFF 6 | METRIC,TZ,000.000 7 | T7C0.813 8 | T6C0.965 9 | T5C1.016 10 | T4C1.100 11 | T3C1.118 12 | T2C3.200 13 | T1C3.302 14 | % 15 | G90 16 | M71 17 | T1 18 | X55499Y9525 19 | T2 20 | X4445Y9525 21 | T3 22 | X70485Y12065 23 | X70485Y9525 24 | X70485Y6985 25 | T4 26 | X104140Y3025 27 | X104140Y6025 28 | X104140Y14525 29 | T5 30 | X45720Y12065 31 | X43180Y12065 32 | X40640Y12065 33 | X45720Y14605 34 | X43180Y14605 35 | X40640Y14605 36 | X80137Y14605 37 | X79883Y12065 38 | X80137Y9525 39 | X79883Y6985 40 | X80137Y4445 41 | X77597Y14605 42 | X77343Y12065 43 | X77597Y9525 44 | X77343Y6985 45 | X77597Y4445 46 | T6 47 | X9525Y17145 48 | X12065Y17145 49 | X14605Y17145 50 | X17145Y17145 51 | X19685Y17145 52 | X22225Y17145 53 | X24765Y17145 54 | X27305Y17145 55 | X29845Y17145 56 | X32385Y17145 57 | X34925Y17145 58 | X34925Y1905 59 | X32385Y1905 60 | X29845Y1905 61 | X27305Y1905 62 | X24765Y1905 63 | X22225Y1905 64 | X19685Y1905 65 | X17145Y1905 66 | X14605Y1905 67 | X12065Y1905 68 | X9525Y1905 69 | X6985Y1905 70 | X4445Y1905 71 | X1905Y1905 72 | X6985Y17145 73 | X4445Y17145 74 | X1905Y17145 75 | T7 76 | X90805Y4445 77 | X90805Y14605 78 | X85725Y14605 79 | X85725Y4445 80 | X88265Y4445 81 | X88265Y14605 82 | X48260Y5715 83 | X38100Y5715 84 | X48260Y8255 85 | X38100Y8255 86 | X93980Y11430 87 | X93980Y13970 88 | X71755Y2540 89 | X66675Y2540 90 | X66675Y15875 91 | X71755Y15875 92 | X93980Y5080 93 | X93980Y7620 94 | X97155Y14605 95 | X97155Y4445 96 | M30 -------------------------------------------------------------------------------- /hardware/hardware-MK1/gerber/panel_2021-04-05_panel.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK1/gerber/panel_2021-04-05_panel.zip -------------------------------------------------------------------------------- /hardware/hardware-MK1/gerber/panel_2021-04-05_panel/GerberJob/gerber_job.gbrjob: -------------------------------------------------------------------------------- 1 | { 2 | "Header": { 3 | "Comment": "All values are metric (mm)", 4 | "CreationDate": "2021-04-05T22:39:01Z", 5 | "GenerationSoftware": { 6 | "Application": "EAGLE", 7 | "Vendor": "Autodesk", 8 | "Version": "9.6.2" 9 | }, 10 | "Part": "Single" 11 | }, 12 | "Overall": { 13 | "BoardThickness": 1.57, 14 | "LayerNumber": 2, 15 | "Name": { 16 | "ProjectId": "panel" 17 | }, 18 | "Owner": "mail mail ", 19 | "Size": { 20 | "X": 128.5, 21 | "Y": 20 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /hardware/hardware-MK1/gerber/panel_2021-04-05_panel/panel.GBL: -------------------------------------------------------------------------------- 1 | G04 EAGLE Gerber RS-274X export* 2 | G75* 3 | %MOMM*% 4 | %FSLAX34Y34*% 5 | %LPD*% 6 | %INBottom Copper*% 7 | %IPPOS*% 8 | %AMOC8* 9 | 5,1,8,0,0,1.08239X$1,22.5*% 10 | G01* 11 | %ADD10C,7.116000*% 12 | 13 | G36* 14 | X1282701Y-126D02* 15 | X1282701Y-126D01* 16 | X1282703Y-126D01* 17 | X1282746Y-107D01* 18 | X1282791Y-88D01* 19 | X1282791Y-87D01* 20 | X1282792Y-86D01* 21 | X1282826Y-1D01* 22 | X1285126Y199999D01* 23 | X1285125Y200001D01* 24 | X1285126Y200004D01* 25 | X1285107Y200046D01* 26 | X1285089Y200090D01* 27 | X1285086Y200091D01* 28 | X1285085Y200093D01* 29 | X1285000Y200126D01* 30 | X0Y200126D01* 31 | X-2Y200125D01* 32 | X-4Y200126D01* 33 | X-47Y200106D01* 34 | X-91Y200088D01* 35 | X-91Y200086D01* 36 | X-93Y200085D01* 37 | X-126Y200000D01* 38 | X-126Y0D01* 39 | X-125Y-2D01* 40 | X-126Y-4D01* 41 | X-106Y-47D01* 42 | X-88Y-91D01* 43 | X-86Y-91D01* 44 | X-85Y-93D01* 45 | X0Y-126D01* 46 | X1282700Y-126D01* 47 | X1282701Y-126D01* 48 | G37* 49 | D10* 50 | X1136400Y100250D03* 51 | M02* 52 | -------------------------------------------------------------------------------- /hardware/hardware-MK1/gerber/panel_2021-04-05_panel/panel.GBO: -------------------------------------------------------------------------------- 1 | G04 EAGLE Gerber RS-274X export* 2 | G75* 3 | %MOMM*% 4 | %FSLAX34Y34*% 5 | %LPD*% 6 | %INSilkscreen Bottom*% 7 | %IPPOS*% 8 | %AMOC8* 9 | 5,1,8,0,0,1.08239X$1,22.5*% 10 | G01* 11 | 12 | 13 | M02* 14 | -------------------------------------------------------------------------------- /hardware/hardware-MK1/gerber/panel_2021-04-05_panel/panel.GBP: -------------------------------------------------------------------------------- 1 | G04 EAGLE Gerber RS-274X export* 2 | G75* 3 | %MOMM*% 4 | %FSLAX34Y34*% 5 | %LPD*% 6 | %INSolderpaste Bottom*% 7 | %IPPOS*% 8 | %AMOC8* 9 | 5,1,8,0,0,1.08239X$1,22.5*% 10 | G01* 11 | 12 | 13 | M02* 14 | -------------------------------------------------------------------------------- /hardware/hardware-MK1/gerber/panel_2021-04-05_panel/panel.GBS: -------------------------------------------------------------------------------- 1 | G04 EAGLE Gerber RS-274X export* 2 | G75* 3 | %MOMM*% 4 | %FSLAX34Y34*% 5 | %LPD*% 6 | %INSoldermask Bottom*% 7 | %IPPOS*% 8 | %AMOC8* 9 | 5,1,8,0,0,1.08239X$1,22.5*% 10 | G01* 11 | %ADD10C,3.403200*% 12 | %ADD11C,3.203200*% 13 | %ADD12R,10.000000X20.000000*% 14 | %ADD13C,7.319200*% 15 | 16 | 17 | D10* 18 | X139450Y100250D03* 19 | D11* 20 | X1034800Y132000D03* 21 | X1034800Y68500D03* 22 | D12* 23 | X50000Y100000D03* 24 | X1235000Y100000D03* 25 | D13* 26 | X1136400Y100250D03* 27 | M02* 28 | -------------------------------------------------------------------------------- /hardware/hardware-MK1/gerber/panel_2021-04-05_panel/panel.GTL: -------------------------------------------------------------------------------- 1 | G04 EAGLE Gerber RS-274X export* 2 | G75* 3 | %MOMM*% 4 | %FSLAX34Y34*% 5 | %LPD*% 6 | %INTop Copper*% 7 | %IPPOS*% 8 | %AMOC8* 9 | 5,1,8,0,0,1.08239X$1,22.5*% 10 | G01* 11 | %ADD10C,7.116000*% 12 | 13 | 14 | D10* 15 | X1136400Y100250D03* 16 | M02* 17 | -------------------------------------------------------------------------------- /hardware/hardware-MK1/gerber/panel_2021-04-05_panel/panel.GTP: -------------------------------------------------------------------------------- 1 | G04 EAGLE Gerber RS-274X export* 2 | G75* 3 | %MOMM*% 4 | %FSLAX34Y34*% 5 | %LPD*% 6 | %INSolderpaste Top*% 7 | %IPPOS*% 8 | %AMOC8* 9 | 5,1,8,0,0,1.08239X$1,22.5*% 10 | G01* 11 | 12 | 13 | M02* 14 | -------------------------------------------------------------------------------- /hardware/hardware-MK1/gerber/panel_2021-04-05_panel/panel.GTS: -------------------------------------------------------------------------------- 1 | G04 EAGLE Gerber RS-274X export* 2 | G75* 3 | %MOMM*% 4 | %FSLAX34Y34*% 5 | %LPD*% 6 | %INSoldermask Top*% 7 | %IPPOS*% 8 | %AMOC8* 9 | 5,1,8,0,0,1.08239X$1,22.5*% 10 | G01* 11 | %ADD10C,3.403200*% 12 | %ADD11C,3.203200*% 13 | %ADD12C,7.319200*% 14 | 15 | 16 | D10* 17 | X139450Y100250D03* 18 | D11* 19 | X1034800Y132000D03* 20 | X1034800Y68500D03* 21 | D12* 22 | X1136400Y100250D03* 23 | M02* 24 | -------------------------------------------------------------------------------- /hardware/hardware-MK1/gerber/panel_2021-04-05_panel/panel.XLN: -------------------------------------------------------------------------------- 1 | M48 2 | ;GenerationSoftware,Autodesk,EAGLE,9.6.2*% 3 | ;CreationDate,2021-04-05T22:39:01Z*% 4 | FMAT,2 5 | ICI,OFF 6 | METRIC,TZ,000.000 7 | T3C3.000 8 | T2C3.200 9 | T1C6.100 10 | % 11 | G90 12 | M71 13 | T1 14 | X113640Y10025 15 | T2 16 | X13945Y10025 17 | T3 18 | X103480Y13200 19 | X103480Y6850 20 | M30 -------------------------------------------------------------------------------- /hardware/hardware-MK1/i2c2midi_schematic.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK1/i2c2midi_schematic.pdf -------------------------------------------------------------------------------- /hardware/hardware-MK1/i2c2midi_schematic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK1/i2c2midi_schematic.png -------------------------------------------------------------------------------- /hardware/hardware-MK1/pictures/i2c2midi_diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK1/pictures/i2c2midi_diagram.png -------------------------------------------------------------------------------- /hardware/hardware-MK1/pictures/i2c2midi_v_1_0_side.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK1/pictures/i2c2midi_v_1_0_side.jpg -------------------------------------------------------------------------------- /hardware/hardware-MK1/pictures/i2c2midi_v_1_0_top.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK1/pictures/i2c2midi_v_1_0_top.jpg -------------------------------------------------------------------------------- /hardware/hardware-MK1/pictures/i2c2midi_v_2_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK1/pictures/i2c2midi_v_2_0.jpg -------------------------------------------------------------------------------- /hardware/hardware-MK1/pictures/i2c2midi_v_2_0_build_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK1/pictures/i2c2midi_v_2_0_build_1.jpg -------------------------------------------------------------------------------- /hardware/hardware-MK1/pictures/i2c2midi_v_2_0_build_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK1/pictures/i2c2midi_v_2_0_build_2.jpg -------------------------------------------------------------------------------- /hardware/hardware-MK1/pictures/i2c2midi_v_2_0_build_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK1/pictures/i2c2midi_v_2_0_build_3.jpg -------------------------------------------------------------------------------- /hardware/hardware-MK1/pictures/i2c2midi_v_2_0_build_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK1/pictures/i2c2midi_v_2_0_build_4.jpg -------------------------------------------------------------------------------- /hardware/hardware-MK1/pictures/i2c2midi_v_2_0_build_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK1/pictures/i2c2midi_v_2_0_build_5.jpg -------------------------------------------------------------------------------- /hardware/hardware-MK1/pictures/i2c2midi_v_2_0_build_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK1/pictures/i2c2midi_v_2_0_build_6.jpg -------------------------------------------------------------------------------- /hardware/hardware-MK1/pictures/i2c2midi_v_2_0_build_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK1/pictures/i2c2midi_v_2_0_build_7.jpg -------------------------------------------------------------------------------- /hardware/hardware-MK1/pictures/i2c2midi_v_2_0_build_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK1/pictures/i2c2midi_v_2_0_build_8.jpg -------------------------------------------------------------------------------- /hardware/hardware-MK1/pictures/i2c2midi_v_2_0_build_9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK1/pictures/i2c2midi_v_2_0_build_9.jpg -------------------------------------------------------------------------------- /hardware/hardware-MK1/pictures/i2c2midi_v_2_0_kit.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK1/pictures/i2c2midi_v_2_0_kit.jpg -------------------------------------------------------------------------------- /hardware/hardware-MK1/pictures/i2c2midi_v_2_0_side.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK1/pictures/i2c2midi_v_2_0_side.jpg -------------------------------------------------------------------------------- /hardware/hardware-MK2/BUILD-GUIDE.md: -------------------------------------------------------------------------------- 1 | # Build Guide MKII 2 | 3 | 4 | ## I 5 | Get the parts. Here's the [BOM](https://github.com/attowatt/i2c2midi#BOM). 6 | 7 | ![](pictures/i2c2midi_MK2_build_01.JPG) 8 | 9 | Let's start with PCB a. 10 | 11 | ## II 12 | - Solder the following parts to PCB a, in this order: 13 | - Voltage regulator (IC1) 14 | - Resistors: 47 Ω (R1, R2), 2.2k Ω (R3, R4), 220 Ω (R5, R6) 15 | - 2x5 angled pin header (Power connection) & 2x3 angled pin header (I2C connection) 16 | - Capacitors (C1, C2) 17 | - Cut the legs of the parts as short as possible. 18 | 19 | ![](pictures/i2c2midi_MK2_build_02.JPG) 20 | ![](pictures/i2c2midi_MK2_build_03.JPG) 21 | ![](pictures/i2c2midi_MK2_build_04.JPG) 22 | ![](pictures/i2c2midi_MK2_build_05.JPG) 23 | ![](pictures/i2c2midi_MK2_build_06.JPG) 24 | ![](pictures/i2c2midi_MK2_build_07.JPG) 25 | 26 | ## III 27 | *A quick note before we continue with the Teensy: If you plan to use the Micro USB jack of the Teensy for sending MIDI device data to a host (e.g. a compouter) alongside the USB host connection on the i2c2midi front panel: Please cut the "5V pad" on the Teensy before soldering! More information please see: https://www.pjrc.com/teensy/external_power.html 28 | Be aware, that if you cut the pads, powering i2c2midi will then only be possible via eurorack, so flashing the firmware has to be done while connected to your eurorack case.* 29 | 30 | - If your Teensy 3.6 comes with pins: Place the 1x5 pin header for USB Host on the PCB, with the shorter legs facing up. Then place the Teensy on top. 31 | - If your Teensy 3.6 comes without pins: Place the two 1x24 pin headers on the PCB, with the shorter legs facing up. Same with the 1x5 pin header for USB Host. Then place the Teensy on top. You can also use shorter pin headers if you don't have 1x24s, since not all Teensy Pins are needed (as seen in the picture). Please refer to the following graphic for which pins need to be soldered. 32 | - I prefer to secure the Teensy with a rubber band to the PCB, then solder the four pins in each corner of the Teensy first. 33 | - Afterwards, I solder the remaining pins, on PCB and Teensy respectively. 34 | 35 | ![](pictures/i2c2midi_MK2_build_08.JPG) 36 | ![](pictures/i2c2midi_MK2_build_10.JPG) 37 | ![](pictures/i2c2midi_MK2_build_outline.png) 38 | 39 | PCB a done. Let's continue with PCB b. 40 | 41 | ## IV 42 | 43 | - Solder the 1x10 angled pin header to PCB b. Note the orientation: If the LEDs are on the bottom, the pins point to the right. 44 | - Make sure it sits straight on the PCB. I prefer to secure the header in place with an excess spacer (1x1 or 1x2 with metal pins removed), and solder the two outer pins. I then remove the extra spacer and solder the remaining pins. 45 | 46 | ![](pictures/i2c2midi_MK2_build_11.JPG) 47 | ![](pictures/i2c2midi_MK2_build_12.JPG) 48 | ![](pictures/i2c2midi_MK2_build_13.JPG) 49 | 50 | ## V 51 | 52 | - Mount the spacer to PCB b with one of the two M3 screws. 53 | - Place the Thonkiconn stereo jack and LEDs into their positions, but don't solder them yet. Mind the orientation of the LEDs: The longer leg is `+`. 54 | - Grab the Panel and place the USB jack through the panel. 55 | - Place the panel on top of the stereo jack and spacer, and place the USB jack into the PCB. Secure the panel to the jack with the nut and to the spacer with the second M3 screw. 56 | 57 | ![](pictures/i2c2midi_MK2_build_14.JPG) 58 | ![](pictures/i2c2midi_MK2_build_15.JPG) 59 | 60 | 61 | ## VI 62 | - Solder Thonkiconn and USB jack to the PCB. Make sure to use enough solder to secure the USB jack in place. 63 | - Carefully place the LEDs into position, so they look nice on the panel. You can position them flush with the panel or let them stick out – your choice :) If you double-checked the LEDs are in position, solder them. 64 | 65 | 66 | ## VII 67 | - Place PCB a into the angled header of PCB b. Make sure everything is aligned nicely and PCB a is perpendicular to PCB b. It should work by just placing both PCBs flat on the table. 68 | - Solder. 69 | - Finally, trim all the legs on PCB a as short as possible. I prefer to trim down *all* legs (including power header, I2C header, 1x10 angled pin header) – making sure, that the width of the module is as less as possible. 70 | 71 | ![](pictures/i2c2midi_MK2_build_15b.jpg) 72 | ![](pictures/i2c2midi_MK2_build_16.JPG) 73 | ![](pictures/i2c2midi_MK2_build_17.JPG) 74 | 75 | Ok, done with soldering! 76 | 77 | ## VIII 78 | [Flash the firmware to the Teensy](https://github.com/attowatt/i2c2midi#firmware-update). 79 | 80 | 81 | 82 | All done – Have fun! 83 | 84 | ## Disclaimer 85 | After building the module, please test it very carefully in a separate case. This is a DIY module. I am not responsible for any damage to your gear. 86 | 87 | ![](pictures/i2c2midi_MK2_build_18.JPG) 88 | 89 | -------------------------------------------------------------------------------- /hardware/hardware-MK2/eagle/panel.sch: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | Eurorack Power 162 | MIDI Out 163 | I2C In 164 | LED 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /hardware/hardware-MK2/gerber/board-A.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK2/gerber/board-A.zip -------------------------------------------------------------------------------- /hardware/hardware-MK2/gerber/board-B.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK2/gerber/board-B.zip -------------------------------------------------------------------------------- /hardware/hardware-MK2/gerber/panel.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK2/gerber/panel.zip -------------------------------------------------------------------------------- /hardware/hardware-MK2/i2c2midi_schematic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK2/i2c2midi_schematic.png -------------------------------------------------------------------------------- /hardware/hardware-MK2/pictures/i2c2midi_MK2_build_01.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK2/pictures/i2c2midi_MK2_build_01.JPG -------------------------------------------------------------------------------- /hardware/hardware-MK2/pictures/i2c2midi_MK2_build_02.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK2/pictures/i2c2midi_MK2_build_02.JPG -------------------------------------------------------------------------------- /hardware/hardware-MK2/pictures/i2c2midi_MK2_build_03.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK2/pictures/i2c2midi_MK2_build_03.JPG -------------------------------------------------------------------------------- /hardware/hardware-MK2/pictures/i2c2midi_MK2_build_04.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK2/pictures/i2c2midi_MK2_build_04.JPG -------------------------------------------------------------------------------- /hardware/hardware-MK2/pictures/i2c2midi_MK2_build_05.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK2/pictures/i2c2midi_MK2_build_05.JPG -------------------------------------------------------------------------------- /hardware/hardware-MK2/pictures/i2c2midi_MK2_build_06.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK2/pictures/i2c2midi_MK2_build_06.JPG -------------------------------------------------------------------------------- /hardware/hardware-MK2/pictures/i2c2midi_MK2_build_07.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK2/pictures/i2c2midi_MK2_build_07.JPG -------------------------------------------------------------------------------- /hardware/hardware-MK2/pictures/i2c2midi_MK2_build_08.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK2/pictures/i2c2midi_MK2_build_08.JPG -------------------------------------------------------------------------------- /hardware/hardware-MK2/pictures/i2c2midi_MK2_build_10.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK2/pictures/i2c2midi_MK2_build_10.JPG -------------------------------------------------------------------------------- /hardware/hardware-MK2/pictures/i2c2midi_MK2_build_11.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK2/pictures/i2c2midi_MK2_build_11.JPG -------------------------------------------------------------------------------- /hardware/hardware-MK2/pictures/i2c2midi_MK2_build_12.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK2/pictures/i2c2midi_MK2_build_12.JPG -------------------------------------------------------------------------------- /hardware/hardware-MK2/pictures/i2c2midi_MK2_build_13.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK2/pictures/i2c2midi_MK2_build_13.JPG -------------------------------------------------------------------------------- /hardware/hardware-MK2/pictures/i2c2midi_MK2_build_14.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK2/pictures/i2c2midi_MK2_build_14.JPG -------------------------------------------------------------------------------- /hardware/hardware-MK2/pictures/i2c2midi_MK2_build_15.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK2/pictures/i2c2midi_MK2_build_15.JPG -------------------------------------------------------------------------------- /hardware/hardware-MK2/pictures/i2c2midi_MK2_build_15b.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK2/pictures/i2c2midi_MK2_build_15b.jpg -------------------------------------------------------------------------------- /hardware/hardware-MK2/pictures/i2c2midi_MK2_build_16.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK2/pictures/i2c2midi_MK2_build_16.JPG -------------------------------------------------------------------------------- /hardware/hardware-MK2/pictures/i2c2midi_MK2_build_17.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK2/pictures/i2c2midi_MK2_build_17.JPG -------------------------------------------------------------------------------- /hardware/hardware-MK2/pictures/i2c2midi_MK2_build_18.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK2/pictures/i2c2midi_MK2_build_18.JPG -------------------------------------------------------------------------------- /hardware/hardware-MK2/pictures/i2c2midi_MK2_build_outline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK2/pictures/i2c2midi_MK2_build_outline.png -------------------------------------------------------------------------------- /hardware/hardware-MK2/pictures/i2c2midi_MK2_diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK2/pictures/i2c2midi_MK2_diagram.png -------------------------------------------------------------------------------- /hardware/hardware-MK2/pictures/i2c2midi_MK2_shot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/attowatt/i2c2midi/59aa60bfd8d50dcbfa96af07be3dc8e2f924f547/hardware/hardware-MK2/pictures/i2c2midi_MK2_shot.jpg --------------------------------------------------------------------------------