thousandparadox

MIDI Monstrosity

Jul 14th, 2021 (edited)
472
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Arduino 24.94 KB | None | 0 0
  1. // MIDI MACHINE by Gabriel Maria
  2. // More info at gabrielmaria.com
  3.  
  4. // This code is for a Teensy 3.5
  5.  
  6. // What this code does:
  7. // Takes USB midi notes AND midi CC values and applys them to 4 different types of devices
  8. // Solonoids, Servos, Stepper Motors and Floppy Drives.
  9. // Solonoids and Servos are on MIDI channel 10.
  10. // Stepper Motors 0,1,2,3 are collectivly on MIDI channel 1, and are polyphonic.
  11. // The Floppy Drive (Stepper Motor 4) is on MIDI channel 2.
  12. // each Solonoid has a pulse width setting via MIDI CC.
  13. // each Servo has a start-angle and end-angle, both can be set via MIDI CC.
  14. // Stepper Motors collectivly have one octive shift setting via MIDI CC.
  15. // Every so often the current midi CC values are saved to EEPROM
  16.    
  17.  
  18. #include <PWMServo.h>
  19. #include <IntervalTimer.h>
  20. #include <MIDI.h>
  21. #include <EEPROM.h>
  22.  
  23. MIDI_CREATE_DEFAULT_INSTANCE();
  24.  
  25. #define p Serial.print
  26. #define pl Serial.println
  27. #define debugGraphing 1
  28.  
  29. //--pinMux-------------------
  30. #define ledR     28
  31. #define ledG     3
  32.  
  33. uint32_t deviceOnTime = 0;
  34.  
  35. volatile uint32_t TIMEmicros = 0;
  36.  
  37.  
  38. struct solenoidStruct{
  39.   bool      en = 0;
  40.   uint8_t   pin = 100;
  41.   uint8_t   midiNote = 255;
  42.   uint8_t   midiCC = 255;
  43.   bool      polarity = 1; //1 normal
  44.   bool      bidirectional = 0;
  45.   //
  46.   bool      gate = 0;
  47.   bool      stayOnMode = 0; //set by baseOnTime midi knob being 0
  48.   bool      forceStayOnMode = 0; //set by midi velocity being 0
  49.   uint32_t  trigTime = 0;
  50.   uint32_t  releaseTime = 0;
  51.   uint32_t  baseOnTime = 10000; // set by midi knobs
  52.   float     velocityMultiplyer = 1; //(1)midi = 1%, (100)midi = 100%, (127)midi = 200%, (0)midi = 9999999%
  53.   uint32_t  onTimeSet = 10000; // result
  54. };
  55. volatile struct solenoidStruct sol[30];
  56. volatile uint32_t numberOfSols = 30;
  57.  
  58. struct stepperStruct{
  59.   bool      en = 0;
  60.   uint8_t   enPin = 100;
  61.   uint8_t   stepPin = 100;
  62.   uint8_t   directionPin = 100;
  63.   uint32_t  stepsBeforeReverse = 0;
  64.   //
  65.   bool      gate = 0;
  66.   uint32_t  stepCount = 0;
  67.   float     speedSet = 0;
  68.   uint32_t  periodSet = 0;
  69.   bool      dir = 0;
  70.   bool      stepPinState = 0;
  71.   float     freqOut = 0;
  72.   uint32_t  fCount = 0;
  73.   uint32_t  fFlip = 0;
  74.  
  75. };
  76. volatile struct stepperStruct stepp[6];
  77. volatile uint32_t numberOfSteppers = 6;
  78. uint8_t voices[4];
  79. uint8_t numVoices = 4;
  80. uint8_t floppyVoice[1];
  81. uint8_t notes[2][129];
  82. uint8_t numNotes[2];
  83.  
  84. struct servoStruct{
  85.   bool      en = 0;
  86.   uint8_t   pwmPin = 100;
  87.   uint8_t   midiNote = 0;
  88.   uint8_t   midiCC1 = 0;
  89.   uint8_t   midiCC2 = 0;
  90.   uint8_t   position1 = 0; //home position, also can be modulated for analog control
  91.   uint8_t   position2 = 180; //second position when the MIDI note is enaged
  92.   bool      gate = 0;
  93. };
  94. volatile struct servoStruct serv[10];
  95. volatile uint32_t numberOfServos = 10;
  96.  
  97. volatile bool updateEEPROMflag = 0;
  98. volatile uint32_t updateEEPROMflagTime = 0;
  99.  
  100. volatile int32_t sysFrequency = 10000;
  101. IntervalTimer timer10k;
  102. IntervalTimer timerStepper;
  103. volatile int32_t stepperPeriod = 7; //142857.1428
  104. volatile float masterTuning = 440;//442.9132;
  105.  
  106. PWMServo servo0;
  107. PWMServo servo1;
  108. PWMServo servo2;
  109. PWMServo servo3;
  110. PWMServo servo4;
  111. PWMServo servo5;
  112. PWMServo servo6;
  113.  
  114. uint32_t lastmillis = 0;
  115. uint32_t MILLIS = 0;
  116.  
  117. bool noteIndicator[128];
  118. uint32_t NAnoteTime = 0;
  119.  
  120.  
  121. uint8_t StepperMIDICC = 0;
  122. int SteppOctaveShift = 0;
  123.  
  124. void setup() {
  125.   setupNotes();
  126.   deviceSetup();
  127.   readEEPROM();
  128.  
  129.   Serial.begin(115200);
  130.   pinMode(13, OUTPUT); digitalWrite(13, 0);
  131.   pinMode(ledR, OUTPUT); digitalWrite(ledR, 1);
  132.   pinMode(ledG, OUTPUT); digitalWrite(ledG, 1);
  133.   memset(noteIndicator,0,sizeof(noteIndicator));
  134.   pl("hi");
  135.  
  136.  
  137.  
  138.   timer10k.begin(ISR10k,1000000/sysFrequency);
  139.   timerStepper.begin(ISRStepper,stepperPeriod);
  140.   //timerStepper0.begin(ISRStepper0,1000000/100);
  141.   //timerStepper1.begin(ISRStepper1,1000000/100);
  142.   //timerStepper2.begin(ISRStepper2,1000000/100);
  143.  
  144.   midiSetup();
  145.  
  146. }
  147.  
  148. void loop() {  
  149.   usbMIDI.read();
  150.  
  151.   //MIDI.read();
  152.  
  153.   if(updateEEPROMflag){
  154.     if(updateEEPROMflagTime < millis()){
  155.       updateEEPROMflag = 0;
  156.       updateEEPROMflagTime = 4294967294;
  157.       writeEEPROM();
  158.     }
  159.   }
  160.  
  161.  
  162.  
  163.   MILLIS = millis();
  164.   if((MILLIS> lastmillis + 1000)){
  165.     lastmillis = MILLIS;
  166.     p("["); p(MILLIS/1000); pl("]");
  167.     printNotes(0);
  168.     digitalWrite(13, 1);
  169.   }
  170.   if((MILLIS> lastmillis)){
  171.     digitalWrite(13, 0);
  172.   }
  173.  
  174.   if(millis() > NAnoteTime +1000){
  175.     digitalWrite(ledR, 1);
  176.   }
  177.  
  178.  
  179.  
  180.  
  181.  
  182. }
  183.  
  184.  
  185. void ISR10k(){
  186.   TIMEmicros = micros();
  187.  
  188.   for(uint32_t i = 0; i < numberOfSols; i++){
  189.     if(sol[i].gate){
  190.       if(!sol[i].stayOnMode || !sol[i].forceStayOnMode){
  191.         if(TIMEmicros > sol[i].releaseTime){
  192.           //p("[");p(TIMEmicros);p("]");p("(");p(micros());pl(")");
  193.           gateSol(i,0);
  194.         }
  195.       }
  196.     }
  197.   }
  198.  
  199. }
  200.  
  201.  
  202. void ISRStepper(){
  203.   digitalWrite(2,1);
  204.   for(uint32_t i = 0; i < numberOfSteppers; i++){    
  205.       if(stepp[i].gate){
  206.         digitalWrite(stepp[i].enPin,0);
  207.         stepp[i].fCount++;
  208.           if(stepp[i].fCount > stepp[i].fFlip){
  209.           stepp[i].fCount = 0;
  210.           stepp[i].stepPinState = !stepp[i].stepPinState;
  211.           digitalWrite(stepp[i].stepPin,stepp[i].stepPinState);
  212.           digitalWrite(stepp[i].directionPin,stepp[i].dir);
  213.           stepp[i].stepCount++;
  214.           if(stepp[i].stepCount>=stepp[i].stepsBeforeReverse){
  215.             stepp[i].stepCount = 0;
  216.             stepp[i].dir = !stepp[i].dir;
  217.           }
  218.         }
  219.       }
  220.       else{
  221.         digitalWrite(stepp[i].enPin,1);
  222.       }
  223.   }
  224.  
  225. /*
  226.   TIMEmicros = micros();
  227.   if(TIMEmicros > lastTIMEmicros + 10){
  228.     lastTIMEmicros = TIMEmicros;
  229.     for(uint32_t i = 0; i < numberOfSols; i++){
  230.       if(sol[i].gate){
  231.         if(!sol[i].stayOnMode || !sol[i].forceStayOnMode){
  232.           if(TIMEmicros > sol[i].releaseTime){
  233.             //p("[");p(TIMEmicros);p("]");p("(");p(micros());pl(")");
  234.             gateSol(i,0);
  235.           }
  236.         }
  237.       }
  238.     }
  239. }*/
  240.  
  241.   digitalWrite(2,0);
  242.  
  243. }
  244.  
  245. void greenled(bool en){
  246.   if(en){
  247.     analogWrite(ledG,240);
  248.   }else{
  249.     analogWrite(ledG,256);
  250.     //digitalWrite(ledG,1);
  251.   }
  252.  
  253. }
  254. /*
  255. inline uint16_t indOffset(int32_t change,int32_t Size){
  256.  
  257.   int32_t temp = Cindex + change;
  258.   if(temp < 0){
  259.     return Size + temp;
  260.   }else{
  261.     return temp;
  262.   }
  263.  
  264. }*/
  265.  
  266.  
  267. //-------------------------------------------------------------------------------------------------------------------------
  268. // CONTROL
  269. //-------------------------------------------------------------------------------------------------------------------------
  270.  
  271. void setSolBaseOntimeFromMIDI(uint8_t ID, uint8_t midiVal){
  272.   if(ID < 0){return;}
  273.   if(ID >=numberOfSols){return;}
  274.  
  275.   if(midiVal == 0){
  276.     setSolBaseOntime(ID, 20000000); //20seconds
  277.     sol[ID].stayOnMode = 1;
  278.   }else{
  279.     setSolBaseOntime(ID, (uint32_t)( 300000 * pow( ((float)midiVal/127.0),4 ) ) );
  280.     sol[ID].stayOnMode = 0;
  281.   }
  282.   updateEEPROMflag = 1;
  283.   updateEEPROMflagTime = millis()+10000;
  284. }
  285.  
  286. void setSolBaseOntime(uint8_t ID, uint32_t microSeconds){
  287.   if(ID < 0){return;}
  288.   if(ID >=numberOfSols){return;}
  289.  
  290.   sol[ID].baseOnTime = microSeconds;
  291. }
  292.  
  293. void setStepperFequencyFromMIDI(uint8_t ID,uint8_t note){
  294.   float freq = 0;
  295.   if(note > 127){
  296.     gateStepp(ID,0);
  297.   }else{
  298.     freq = pow(2,((float)((note+(SteppOctaveShift*12)) - 57))/12) * masterTuning ;
  299.     //pl(freq);
  300.     setStepperFequency(ID,freq);
  301.     gateStepp(ID,1);
  302.   }
  303. }
  304.  
  305. //2^((149-49)/12) * 440 = 141917.50
  306. //2^((48 -49)/12) * 440 = 415.30469
  307. //1000000/7 = 142857.142
  308. //171.99(172) = 142857.142 / (415.30469 * 2)
  309. //415.282 = 142857.149 / (172 * 2)
  310. //415.282
  311.  
  312. void setStepperFequency(uint8_t ID,float freq){
  313.   if(freq < 0){return;}
  314.   //if(freq > 4200){freq = 4200;}
  315.  
  316.   stepp[ID].fCount = 0;
  317.   float fFlipFloat = (1000000.0 / (float)stepperPeriod) / (freq * 2.0);
  318.   stepp[ID].fFlip = (uint32_t)round(fFlipFloat);
  319.   stepp[ID].freqOut = freq;//(1000000.0 / (float)stepperPeriod) / (float)(stepp[ID].fFlip * 2);  
  320.   //p("stepper set: "); p(stepp[ID].freqOut); p("  ");p (fFlipFloat); p("  "); pl(stepp[ID].fFlip);
  321. }
  322.  
  323. void setSolVelocity(uint8_t ID,uint8_t velocity){
  324.   if(ID < 0){return;}
  325.   if(ID >=numberOfSols){return;}
  326.  
  327.   if(velocity > 110){
  328.     sol[ID].velocityMultiplyer = 2;
  329.     sol[ID].onTimeSet = (uint32_t)(sol[ID].baseOnTime * sol[ID].velocityMultiplyer);
  330.     sol[ID].forceStayOnMode = 0;
  331.   }else if(velocity == 0){   //not used....
  332.     sol[ID].velocityMultiplyer = 10000;
  333.     sol[ID].onTimeSet = 20000000;
  334.     sol[ID].forceStayOnMode = 1;
  335.   }else{
  336.     sol[ID].velocityMultiplyer = 1;
  337.     sol[ID].onTimeSet = (uint32_t)(sol[ID].baseOnTime);
  338.     sol[ID].forceStayOnMode = 0;
  339.   }
  340. }
  341.  
  342. void setServBasePositionFromMIDI(uint8_t ID, uint8_t Control, uint8_t val127){
  343.   if(!serv[ID].en){return;}
  344.  
  345.   if(Control == 1){
  346.     serv[ID].position1 = (uint8_t)((float)val127 * 1.4173);
  347.   }else if(Control == 2){
  348.     serv[ID].position2 = (uint8_t)((float)val127 * 1.4173);
  349.   }else{
  350.     return;
  351.   }
  352.  
  353.   if(serv[ID].gate){
  354.     setServo(ID, serv[ID].position2);
  355.   }else{
  356.     setServo(ID, serv[ID].position1);
  357.   }
  358.  
  359.   updateEEPROMflag = 1;
  360.   updateEEPROMflagTime = millis()+10000;
  361. }
  362.  
  363. void setServoFromMIDI(uint8_t ID, uint8_t val127){
  364.  setServo(ID, val127 * 1.4173);  
  365. }
  366.  
  367. void setServo(uint8_t ID, uint8_t angle){
  368.   if(!serv[ID].en){return;}
  369.   p("servo: ");p(ID);p(", angle: ");p(angle);
  370.  
  371.    switch(ID){
  372.     case 0: servo0.write(angle); break;
  373.     case 1: servo1.write(angle); break;
  374.     case 2: servo2.write(angle); break;
  375.     case 3: servo3.write(angle); break;
  376.     case 4: servo4.write(angle); break;
  377.     case 5: servo5.write(angle); break;
  378.     case 6: servo6.write(angle); break;
  379.    }
  380. }
  381.  
  382. inline void gateSol(uint8_t ID,bool state){
  383.   if(ID < 0){return;}
  384.   if(ID >= numberOfSols){return;}
  385.   if(!sol[ID].en){return;}
  386.  
  387.   if(state){
  388.     sol[ID].trigTime = micros();
  389.     sol[ID].releaseTime = sol[ID].trigTime + sol[ID].onTimeSet;
  390.     digitalWrite(sol[ID].pin, sol[ID].polarity);
  391.     //p("ID:"); p(ID); p("  pin:"); p(sol[ID].pin); p("  state:"); p(sol[ID].polarity);p("   trigtime:"); pl(sol[ID].trigTime);
  392.     sol[ID].gate = 1;
  393.   }else{
  394.     //offtime = micros();
  395.     digitalWrite(sol[ID].pin, !(sol[ID].polarity));//
  396.     //p("ID:"); p(ID); p("  pin:"); p(sol[ID].pin); p("  state:"); p(!sol[ID].polarity);p("   time:"); pl(offtime);
  397.     sol[ID].gate = 0;
  398.   }
  399. }
  400.  
  401. inline void gateStepp(uint8_t ID,bool state){
  402.   if(ID < 0){return;}
  403.   stepp[ID].gate = state;
  404. }
  405.  
  406. inline void gateServ(uint8_t ID,bool state){
  407.   if(ID < 0){return;}
  408.   if(ID >=numberOfServos){return;}
  409.   if(!serv[ID].en){return;}
  410.  
  411.   if(state){
  412.     setServo(ID,serv[ID].position2);
  413.     //p("ID:"); p(ID); p("  pin:"); p(sol[ID].pin); p("  state:"); p(sol[ID].polarity);p("   trigtime:"); pl(sol[ID].trigTime);
  414.     serv[ID].gate = 1;
  415.   }else{
  416.     setServo(ID,serv[ID].position1);
  417.     //p("ID:"); p(ID); p("  pin:"); p(sol[ID].pin); p("  state:"); p(!sol[ID].polarity);p("   time:"); pl(offtime);
  418.     serv[ID].gate = 0;
  419.   }
  420. }
  421.  
  422.  
  423. //-------------------------------------------------------------------------------------------------------------------------
  424. // DEVICES
  425. //-------------------------------------------------------------------------------------------------------------------------
  426.  
  427. void deviceSetup(){
  428. //configureSolenoid(uint8_t ID, uint8_t drivePin, uint8_t note, uint8_t midiCC, bool polarity, bool bidirectional);
  429. //configureStepper(uint8_t ID, uint8_t stepPinIn, uint8_t directionPinIn,uint8_t enablePin, uint32_t stepsBeforeReverse);
  430. //configureServo   (uint8_t ID, uint8_t pwmPin, uint8_t note, uint8_t midiCC1, uint8_t midiCC2);
  431.  
  432.     configureSolenoid(1,  4,   55, 20, 1, 0);
  433.     configureSolenoid(2,  5,   56, 21, 1, 0);
  434.     configureSolenoid(3,  6,   57, 22, 1, 0);
  435.     configureSolenoid(4,  7,   58, 23, 1, 0);
  436.     configureSolenoid(5,  8,   59, 24, 1, 0);
  437.     configureSolenoid(6,  9,   60, 25, 1, 0);
  438.     configureSolenoid(7,  10,  61, 26, 1, 0);
  439.     configureSolenoid(8,  11,  62, 27, 1, 0);
  440.     configureSolenoid(9,  14,  63, 28, 1, 0);
  441.     configureSolenoid(10, 15,  64, 29, 1, 0);
  442.     configureSolenoid(11, 16,  65, 30, 1, 0);
  443.     configureSolenoid(12, 17,  66, 46, 1, 0);
  444.     configureSolenoid(13, 18,  67, 47, 1, 0);
  445.     configureSolenoid(14, 19,  68, 48, 1, 0);
  446.     configureSolenoid(15, 20,  69, 49, 1, 0);
  447.     configureSolenoid(16, 21,  70, 50, 1, 0);
  448.     configureSolenoid(17, 22,  71, 51, 1, 0);
  449.     configureSolenoid(18, 23,  72, 52, 1, 0);
  450.     configureSolenoid(19, 12,  73, 53, 1, 0);
  451.     configureSolenoid(20, 40,  74, 54, 1, 0);
  452.     configureSolenoid(21, 41,  75, 55, 1, 0);
  453.     configureSolenoid(22, 42,  76, 56, 1, 0);
  454.     configureSolenoid(23, 51,  77, 57, 1, 0);
  455.     configureSolenoid(24, 52,  78, 58, 1, 0);
  456.     configureSolenoid(25, 53,  79, 59, 1, 0);
  457.  
  458.     configureServo(1,  29,   53, 102, 103);
  459.     configureServo(2,  30,   52, 104, 105);
  460.     configureServo(3,  35,   51, 106, 107);
  461.     configureServo(4,  36,   50, 108, 109);
  462.     configureServo(5,  37,   49, 110, 111);
  463.     configureServo(6,  38,   48, 112, 113);
  464.  
  465.     numVoices = 4;
  466.     StepperMIDICC = 114;
  467.     configureStepper(0,  24,   25, 54, 1000000);
  468.     configureStepper(1,  26,   27, 55, 1000000);
  469.     configureStepper(2,  31,   32, 56, 1000000);
  470.     configureStepper(3,  34,   33, 57, 1000000);
  471.  
  472.     //Floppy
  473.     configureStepper(4,  49,   50, 48, 80);
  474.  
  475. }
  476.  
  477. void configureSolenoid(uint8_t ID, uint8_t drivePin, uint8_t note, uint8_t midiCC, bool polarity,bool bidirectional){
  478.   sol[ID].pin = drivePin;
  479.   sol[ID].polarity = polarity;
  480.   pinMode(sol[ID].pin, OUTPUT);
  481.   digitalWrite(sol[ID].pin, !(sol[ID].polarity));
  482.   sol[ID].midiNote = note;
  483.   sol[ID].midiCC = midiCC;
  484.   sol[ID].bidirectional = bidirectional;
  485.   sol[ID].en = 1;
  486. }
  487.  
  488. void configureStepper(uint8_t ID, uint8_t stepPinIn, uint8_t directionPinIn,uint8_t enablePin, uint32_t stepsBeforeReverse){
  489.   stepp[ID].stepPin = stepPinIn;
  490.   stepp[ID].directionPin = directionPinIn;
  491.   stepp[ID].enPin = enablePin;
  492.   pinMode(stepp[ID].stepPin, OUTPUT);
  493.   digitalWrite(stepp[ID].stepPin, 0);
  494.   pinMode(stepp[ID].directionPin, OUTPUT);
  495.   digitalWrite(stepp[ID].directionPin, 0);
  496.   pinMode(stepp[ID].enPin, OUTPUT);
  497.   digitalWrite(stepp[ID].enPin, 0);
  498.   stepp[ID].stepsBeforeReverse = stepsBeforeReverse;
  499.   stepp[ID].en = 1;
  500. }
  501.  
  502. void configureServo(uint8_t ID, uint8_t pwmPin, uint8_t note, uint8_t midiCC1, uint8_t midiCC2){
  503.   serv[ID].pwmPin = pwmPin;
  504.   serv[ID].midiNote = note;
  505.   serv[ID].midiCC1 = midiCC1;
  506.   serv[ID].midiCC2 = midiCC2;
  507.   serv[ID].en = 1;
  508.  
  509.   switch(ID){
  510.     case 0: servo0.attach(pwmPin); break;
  511.     case 1: servo1.attach(pwmPin); break;
  512.     case 2: servo2.attach(pwmPin); break;
  513.     case 3: servo3.attach(pwmPin); break;
  514.     case 4: servo4.attach(pwmPin); break;
  515.     case 5: servo5.attach(pwmPin); break;
  516.     case 6: servo6.attach(pwmPin); break;
  517.   }
  518. }
  519.  
  520. //-------------------------------------------------------------------------------------------------------------------------
  521. // EEPROM
  522. //-------------------------------------------------------------------------------------------------------------------------
  523.  
  524. void writeEEPROM(){
  525.   uint16_t Offset = 0;
  526.   uint32_t temp1 = 0;
  527.  
  528.   Offset = 0;
  529.   for(uint32_t i = 0; i < numberOfSols; i++){
  530.     if(sol[i].en){
  531.       EEPROM.get((Offset+(4*i)),temp1);
  532.       if(sol[i].baseOnTime != temp1){
  533.         EEPROM.put((Offset+(4*i)),(uint32_t)sol[i].baseOnTime);
  534.       }
  535.     }
  536.   }
  537.  
  538.   uint8_t temp2 = 0;
  539.   Offset = 200;
  540.   for(uint32_t i = 0; i < numberOfServos; i++){
  541.      if(serv[i].en){
  542.       EEPROM.get((Offset+(2*i)),temp2);
  543.       if(serv[i].position1 != temp2){
  544.         EEPROM.put((Offset+(2*i)),(uint8_t)serv[i].position1);
  545.       }
  546.       EEPROM.get((1+Offset+(2*i)),temp2);
  547.       if(serv[i].position2 != temp2){
  548.         EEPROM.put((1+Offset+(2*i)),(uint8_t)serv[i].position2);
  549.       }
  550.     }
  551.   }
  552.   pl("WRITING EEPROM");
  553. }
  554.  
  555. void readEEPROM(){
  556.   uint16_t Offset = 0;
  557.   uint32_t temp1 = 0;
  558.   Offset = 0;
  559.   for(uint32_t i = 0; i < numberOfSols; i++){
  560.     if(sol[i].en){
  561.       EEPROM.get((Offset+(4*i)),temp1);
  562.       //pl(temp1);
  563.       if(temp1!=0xFFFFFFFF){
  564.         sol[i].baseOnTime = temp1;
  565.       }
  566.     }
  567.   }
  568.  
  569.   uint8_t temp2 = 0;
  570.   Offset = 200;
  571.   for(uint32_t i = 0; i < numberOfServos; i++){
  572.      if(serv[i].en){
  573.       EEPROM.get((Offset+(2*i)),temp2);
  574.       //pl(temp2);
  575.       if(temp2!=0xFF){
  576.         serv[i].position1 = temp2;
  577.       }
  578.       EEPROM.get((1+Offset+(2*i)),temp2);
  579.       //pl(temp2);
  580.       if(temp2!=0xFF){
  581.         serv[i].position2 = temp2;
  582.       }
  583.     }
  584.    
  585.   }
  586.  
  587. }
  588.  
  589. //-------------------------------------------------------------------------------------------------------------------------
  590. // MIDI
  591. //-------------------------------------------------------------------------------------------------------------------------
  592.  
  593. void midiSetup(){
  594.   midiReset();
  595.   usbMIDI.setHandleNoteOn(midiNoteOn);
  596.   usbMIDI.setHandleNoteOff(midiNoteOff);
  597.   //usbMIDI.setHandlePitchChange(midiPitchChange);
  598.   usbMIDI.setHandleControlChange(midiControlChange);
  599.  
  600.   MIDI.setHandleNoteOn(midiNoteOn);
  601.   MIDI.setHandleNoteOff(midiNoteOff);
  602.   //MIDI.setHandlePitchBend(midiPitchChange);
  603.   MIDI.setHandleControlChange(midiControlChange);
  604.   MIDI.begin(0);
  605.   midiReset();
  606. }
  607.  
  608. //-----------------------------------------------------------------------------------------------------------------------------
  609.  
  610. void midiNoteOn(byte channel, byte note, byte velocity){//60 == 0 == 33.3333
  611. p("note on:  "); p(channel);p("  ");p(note);p("  ");p(velocity);pl( );
  612.  
  613.   noteIndicator[note] = 1;
  614.   greenled(1);//on
  615.   bool NAnote = 1;
  616.  
  617.   switch(channel){
  618.    case 10:
  619.       for(uint32_t ID=0;ID<numberOfSols;ID++){
  620.         if(sol[ID].midiNote == note){
  621.           NAnote = 0;
  622.           setSolVelocity(ID,velocity);
  623.           gateSol(ID,1);
  624.           p("ID:"); p(ID); p("  base:"); p(sol[ID].baseOnTime); p("  mulit:"); p(sol[ID].velocityMultiplyer);p("   output:"); pl(sol[ID].onTimeSet);
  625.           break;
  626.         }
  627.       }
  628.       for(uint32_t ID=0;ID<numberOfServos;ID++){
  629.         if(serv[ID].midiNote == note){
  630.           NAnote = 0;
  631.           gateServ(ID,1);
  632.         }
  633.       }
  634.       if(NAnote){digitalWrite(ledR, 0); NAnoteTime = millis();}
  635.       break;
  636.    case 1:
  637.       addNote(0,note);
  638.       distrubuteNotesToVoices(notes[0], voices, numVoices);
  639.       for(uint32_t i = 0; i< numVoices; i++){
  640.         setStepperFequencyFromMIDI(i,voices[i]);
  641.       }
  642.       break;
  643.    case 2:
  644.       addNote(1,note);
  645.       distrubuteNotesToVoices(notes[1], floppyVoice, 1);
  646.       setStepperFequencyFromMIDI(4,floppyVoice[0]);
  647.       break;
  648.    default:
  649.      digitalWrite(ledR, 0);
  650.      NAnoteTime = millis();
  651.      break;
  652.   }
  653.  
  654.  
  655. }
  656.  
  657. //-----------------------------------------------------------------------------------------------------------------------------
  658. void midiNoteOff(byte channel, byte note, byte velocity){
  659.   p("note off:  "); p(channel);p("  ");p(note);p("  ");p(velocity);pl( );
  660.  
  661.    switch(channel){
  662.    case 10:
  663.     //if(velocity == 0){ //fix for note-Off-0-velocity being actually note-on.... Dosent work, cannot distiguish between Real and Fake note-Off-0-velocity
  664.     //  midiNoteOn(channel,note,velocity);
  665.     //}else{
  666.         for(uint32_t ID=0;ID<numberOfSols;ID++){
  667.           if(sol[ID].midiNote == note){
  668.             if(sol[ID].stayOnMode || sol[ID].forceStayOnMode){
  669.               gateSol(ID,0);
  670.               break;
  671.             }
  672.           }
  673.         }
  674.         for(uint32_t ID=0;ID<numberOfServos;ID++){
  675.           if(serv[ID].midiNote == note){
  676.             gateServ(ID,0);
  677.           }
  678.         }
  679.     //}
  680.     break;
  681.    case 1:
  682.     remNote(0,note);
  683.     distrubuteNotesToVoices(notes[0], voices, numVoices);
  684.     for(uint32_t i = 0; i< numVoices; i++){
  685.       setStepperFequencyFromMIDI(i,voices[i]);
  686.     }
  687.     break;
  688.    case 2:
  689.     remNote(1,note);
  690.     distrubuteNotesToVoices(notes[1], floppyVoice, 1);
  691.     setStepperFequencyFromMIDI(4,floppyVoice[0]);
  692.     break;
  693.    default:
  694.     break;
  695.   }
  696.  
  697.   noteIndicator[note] = 0;
  698.   bool res = 0;
  699.   for(uint32_t note = 0; note < 128; note++){
  700.     if(noteIndicator[note]){res = 1;}
  701.   }
  702.   greenled(res);
  703. }
  704. //-----------------------------------------------------------------------------------------------------------------------------
  705. void midiControlChange(byte channel, byte control, byte value){
  706.   p("control:  "); p(channel);p("  ");p(control);p("  ");p(value);pl( );
  707.  
  708.  switch(channel){
  709.    case 10:
  710.  
  711.     for(uint32_t ID=0;ID<numberOfSols;ID++){
  712.       if(sol[ID].midiCC == control){
  713.         setSolBaseOntimeFromMIDI(ID, value);
  714.         p("ID:"); p(ID); p("  base:"); p(sol[ID].baseOnTime); p("  mulit:"); p(sol[ID].velocityMultiplyer);p("   output:"); pl(sol[ID].onTimeSet);
  715.       }
  716.     }
  717.     for(uint32_t ID=0;ID<numberOfServos;ID++){
  718.       if(serv[ID].midiCC1 == control){
  719.         setServBasePositionFromMIDI(ID, 1, value);
  720.       }
  721.       if(serv[ID].midiCC2 == control){
  722.         setServBasePositionFromMIDI(ID, 2, value);
  723.       }
  724.     }    
  725.    
  726.     break;
  727.    case 1:
  728.     if(control == StepperMIDICC){
  729.       SteppOctaveShift = ((round((float)value / 12.7)) - 5);
  730.     }
  731.     break;
  732.    case 2:
  733.     if(control == StepperMIDICC){
  734.       SteppOctaveShift = ((round((float)value / 12.7)) - 5);
  735.     }
  736.     break;
  737.  
  738.    default:
  739.      digitalWrite(ledR, 0);
  740.      NAnoteTime = millis();
  741.     break;
  742.   }
  743.  
  744. }
  745. //-----------------------------------------------------------------------------------------------------------------------------
  746. void midiReset(){
  747.    // notesOn = 0;
  748.     //memset(noteBuffer,0,sizeof(noteBuffer));
  749. }
  750. //-----------------------------------------------------------------------------------------------------------------------------
  751. void setupNotes(){
  752.   memset(voices,255,sizeof(voices));
  753.   memset(notes,255,sizeof(notes));
  754.   numNotes[0] = 0;
  755.   numNotes[1] = 0;
  756. }
  757.  
  758. uint8_t addNote(uint8_t chan, uint8_t note){
  759.   p("Add:"); pl(note);
  760.   if(chan > 4){return 254;}
  761.   if(note > 127){return 254;}
  762.  
  763.   for(uint32_t i = 0; i < 128; i++){
  764.     if(notes[chan][i] == note){
  765.       return 254;//do nothing error
  766.     }
  767.     if(notes[chan][i] == 255){
  768.       break;
  769.     }
  770.   }
  771.   notes[chan][numNotes[chan]] = note;
  772.   numNotes[chan]++;
  773.   return note;
  774. }
  775. //{15,74,56,33, 255,255,255,255}
  776. //{15,74,33,33,255,255,255,255}
  777. //{15,74,33,255,255,255,255,255}
  778.  
  779. //{15,66,255,255,255,255,255,255}
  780. //{66,66,255,255,255,255,255,255}
  781. //{66,255,255,255,255,255,255,255}
  782. uint8_t remNote(uint8_t chan, uint8_t note){
  783.   p("Rem:"); pl(note);
  784.   if(chan > 4){return 254;}
  785.   if(note > 127){return 254;}
  786.  
  787.   uint8_t newNote = 253;
  788.  
  789.   for(uint32_t i = 0; i < 128; i++){
  790.     if(notes[chan][i] == note){
  791.       for(uint32_t k = i; k < 128; k++){
  792.         notes[chan][k] = notes[chan][k+1];
  793.         if(notes[chan][k] == 255){
  794.           if(k==0){
  795.             newNote = 255; //gate off
  796.           }else{
  797.             newNote = notes[chan][k-1];        
  798.           }
  799.           goto SUCSESS;
  800.         }
  801.       }
  802.     }
  803.     if(notes[chan][i] == 255){
  804.       return 254;//do nothing error
  805.     }
  806.   }
  807.  
  808.   SUCSESS:
  809.   numNotes[chan]--;
  810.   return newNote; //if newNote is 255, gate off
  811. }
  812.  
  813. void distrubuteNotesToVoices(uint8_t *note, uint8_t *voice, uint8_t numberOfVoices){
  814.   //[255][255][255]
  815.   //{8,255,255,255,255,255,255,255}
  816.   uint8_t ignoreV[numberOfVoices];
  817.   uint8_t ignoreN[numberOfVoices];
  818.  
  819.   memset(ignoreV,0,sizeof(ignoreV));
  820.   memset(ignoreN,0,sizeof(ignoreN));
  821.  
  822.   uint8_t s = 0;
  823.   for(uint8_t n = 0; n<128; n++){
  824.     if((n >= numberOfVoices)&&(note[n] == 255)){
  825.       s = n - numberOfVoices;
  826.       break;
  827.     }
  828.   }
  829.   //p("shift:"); pl(s);
  830.  
  831.   //find allready-allocated note-voice combos, and mark them to be skipped
  832.   for(uint8_t v = 0; v<numberOfVoices; v++){
  833.     if(voice[v] != 255){
  834.       for(uint8_t n = 0; n<numberOfVoices; n++){
  835.         if(note[n+s] != 255){
  836.           if(voice[v] == note[n+s]){
  837.             ignoreV[v] = 1;
  838.             ignoreN[n] = 1;
  839.             break;
  840.           }
  841.         }
  842.       }
  843.     }
  844.   }
  845.  
  846.   //p("V[");p(ignoreV[0]);p("][");p(ignoreV[1]);p("][");p(ignoreV[2]);pl("]");
  847.   //p("N[");p(ignoreN[0]);p("][");p(ignoreN[1]);p("][");p(ignoreN[2]);pl("]");
  848.  
  849.   //allocate notes to voices unless that are marked to be ignored
  850.   for(uint8_t v = 0; v<numberOfVoices; v++){
  851.     if(!ignoreV[v]){
  852.       for(uint8_t n = 0; n<numberOfVoices; n++){
  853.         if(!ignoreN[n]){
  854.           voice[v] = note[n+s];
  855.           ignoreV[v] = 1;
  856.           ignoreN[n] = 1;
  857.           break;
  858.         }
  859.       }
  860.     }
  861.   }
  862.  
  863.   //find where oldest note is in voices
  864.   //
  865.  
  866.   return;
  867. }
  868.  
  869. void printNotes(uint8_t chan){
  870.   p("chan");
  871.   p(chan);
  872.   p(" notes:");
  873.   p(numNotes[chan]);
  874.   p(" {");
  875.   for(uint32_t i = 0; i < 10; i++){
  876.    p(notes[chan][i]);
  877.    p(",");
  878.   }
  879.   pl("}");
  880.   p("[");p(voices[0]);p("][");p(voices[1]);p("][");p(voices[2]);p("][");p(voices[3]);p("]");
  881.   pl();
  882.   p("[");p(stepp[0].freqOut);p("][");p(stepp[1].freqOut);p("][");p(stepp[2].freqOut);p("][");p(stepp[3].freqOut);p("]");
  883.   pl();
  884.   p("[");p(stepp[0].gate);p("][");p(stepp[1].gate);p("][");p(stepp[2].gate);p("][");p(stepp[3].gate);p("]");
  885.   pl();
  886. }
Add Comment
Please, Sign In to add comment