Pages: [1]   Go Down
Author Topic: MIDI controller- how to un multiplex?  (Read 923 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey, the MIDI controller sketch below was written (by a long lost associate) to run on a diecimila, with 5 rotary encoders & 16 switches connected via an LS138 multiplexer (grouped as 'puff switches', 'knife switches', 'momentary click switches' & 'pir switch'), with piezo drumpads & 'lovehandles' skin resistance meter voltage going into analog ins.

I want to adapt it to run on a mega, plugging the switches etc straight into digital inputs on the arduino, dispensing with the multiplexer. I guess I need to remove the bank code & assign the inputs to digital ins? Also the multiplexer board was doing the de-bouncing. Any tips for a noob on how to do this would be much appreciated, many thanks, raymondo




int A = LOW;int B = LOW;int enclaststate[6]={LOW,LOW,LOW,LOW,LOW,LOW};int encoderflag[6]={LOW,LOW,LOW,LOW,LOW,LOW};
int cccurrentvalue[6]={0,0,0,0,0,0};int banknum;int encodercount[6]={0,0,0,0,0,0};int lovecheck = 0;
int switches[] = {LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW};
int lovehandles;int lovehandlesflag = LOW;int inputnum;int input;int piezopin;int drumvelocity;
int drumpad[5] = {53,54,55,56,57};int decay[5] = {0,0,0,0,0};int handlescount = 0;
void setup(){
  Serial.begin(31250);DDRB = B00000000;PORTB = B00000000;DDRD = B00000000;PORTD = B00000001;}
  // Port D - 0 is Rx, 1 is Tx, 7 4 & 2 are mux outs to ls138, Port B is 8 bank inputs / outputs
void loop(){//do our piezo drums , wired to the analog ins
  for (piezopin=0;piezopin<=4;piezopin++){// setup the count to read the 5 drumpads
    drumvelocity=analogRead(piezopin);if (drumvelocity/2>=25){
    if(drumvelocity>=decay[piezopin]){midiCC(0x90,drumpad[piezopin],drumvelocity/2);delay(10);}decay[piezopin]=drumvelocity;delay(1);}}
  lovehandles=analogRead(5);if (lovehandles>35){if (lovehandlesflag==LOW){midiCC(0x90,88,127);delay(1);midiCC(0x80,88,127);lovehandlesflag = HIGH;}
if((lovehandles/2)!=lovecheck){midiCC(0xB0,25,lovehandles/2);lovecheck=lovehandles/2;}}else{lovehandlesflag=LOW;}//read the lovehandles send controller and note on/off
 // do our 8 banks multiplexed to the digital ins
  for (banknum=7; banknum>=0; banknum--){ // set a loop of 8, 1 slot per bank
  if (banknum==0){PORTD = B00000001;} // set the bank address, binary 000 outs
  else if (banknum==1){PORTD = B00000101;}// set the bank address, binary 001 outs
  else if (banknum==2){PORTD = B00010001;// set the bank address, binary 010  ins unused so far
   //for(inputnum=8; inputnum<=13; inputnum++){swhandler(inputnum+12,inputnum-8);}
 }
  else if (banknum==3){PORTD = B00010101;// set the bank address, binary 011  puff switches and pir
    for(inputnum=8; inputnum<=13; inputnum++){if(digitalRead(inputnum)==HIGH){midiCC(0x90,inputnum+20,127);delay(10);}}//!!!!!!!!!!put the delay in here
  inputnum=6;input=(digitalRead(inputnum));// deal with pir switch, it's normally high going low
       if((input==HIGH)&&(switches[6]==LOW)){midiCC(0x80,35,127);switches[6]=HIGH;}
      // if a switch is pressed ON send a midi off, set the check value to ON
       if((switches[6]==HIGH) && (input==LOW)) {midiCC(0x90,35,127);switches[6]=LOW;}}
  else if (banknum==4){PORTD = B10000001;// set the bank address, binary 100 knife switches
    for(inputnum=8; inputnum<=13; inputnum++){swhandler(inputnum+28,inputnum+8);}}
  else if (banknum==5){PORTD = B10000101;// set the bank address, binary 101  momentary led click-switches
    for(inputnum=8; inputnum<=13; inputnum++){swhandler(inputnum+36,inputnum+16);}}     
  else if (banknum==6){PORTD = B10010001;enchandler(13,4);enchandler(11,5);enchandler(9,75);}//encoders
  else{PORTD = B10010101;enchandler(13,1);enchandler(11,2);enchandler(9,3);}}}//encoders
//delay(50); // stall to see the leds
/* function send a Midi message.use 'midiCC(command byte, data, data)' 0xB0 = controller, 0x80 = note on,
0x90 = note off data bytes 0-127 0x00-0x7f eg 0x80 0x34 0x0F note on, note 34, velocity 127*/
void midiCC(char CC_data, char c_num, char c_val){
Serial.print(CC_data, BYTE);Serial.print(c_num, BYTE);Serial.print(c_val, BYTE);}
// function to handle encoders / amend midi controllers
void enchandler(int y,int x){A=digitalRead(y);B=digitalRead(y-1);// fetch encoder states y is pin, x is array member / controller number
    // check for movement, direction and midi controller range
    if ((A==HIGH) && (enclaststate
  • ==LOW)){encodercount
  • =0;if (encoderflag
  • ==LOW){midiCC(0x90,x+12,127);delay(1);midiCC(0x80,x+12,127);encoderflag
  • =HIGH;}
      //reset stationary count, deal with the start midi note and set flag   
    if(B == HIGH){if(cccurrentvalue
  • != 127){cccurrentvalue
  • ++;}}//positive move or negative move
    else{if(cccurrentvalue
  • != 0){cccurrentvalue
  • --;}}midiCC(0xB0,x,cccurrentvalue
  • );}//send the controller data
    else{encodercount
  • ++;if ((encodercount
  • ==1000)&&(encoderflag
  • ==HIGH)){midiCC(0x90,x+18,127);delay(1);midiCC(0x80,x+18,127);
  encoderflag
  • =LOW;}}
    enclaststate
  • = A;}// save the state for comparison n1ext time round
//function to read a switch and send a midi note on / off message
void swhandler(int note, int arraymember){input=(digitalRead(inputnum));// read the input pin
if((input==HIGH)&&(switches[arraymember]==LOW)){midiCC(0x90,note,127);delay(1);midiCC(0x80,note,127);switches[arraymember]=HIGH;}
// if a switch is pressed ON send a midi ON / off, set the check value to ON
if((switches[arraymember]==HIGH) && (input==LOW)) {midiCC(0x90,note+36,127);delay(1);midiCC(0x80,note+36,127);switches[arraymember]=LOW;}}
// if a switch is released send an on / OFF + 36, set the check value to OFF

Logged

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 208
Posts: 8842
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

One problem is that the author used Direct Port Access to set multiple output bits and the mapping between ports and pins is different on the Mega.

This spreadsheet shows the mappings between ports and pins:

https://spreadsheets.google.com/spreadsheet/pub?key=0AtfNMvfWhA_ccnRId19SNmVWTDE0MEtTOV9HOEdQa0E&gid=0

Re-formatting makes the code easier to read:
Code:
int A = LOW;
int B = LOW;
int enclaststate[6]={LOW,LOW,LOW,LOW,LOW,LOW};
int encoderflag[6]={LOW,LOW,LOW,LOW,LOW,LOW};
int cccurrentvalue[6]={0,0,0,0,0,0};
int banknum;
int encodercount[6]={0,0,0,0,0,0};
int lovecheck = 0;
int switches[] = {LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW};
int lovehandles;
int lovehandlesflag = LOW;
int inputnum;
int input;
int piezopin;
int drumvelocity;
int drumpad[5] = {53,54,55,56,57};
int decay[5] = {0,0,0,0,0};
int handlescount = 0;

void setup(){
  Serial.begin(31250);
  DDRB = B00000000;
  PORTB = B00000000;
  DDRD = B00000000;
  PORTD = B00000001;
}

// Port D - 0 is Rx, 1 is Tx, 7 4 & 2 are mux outs to ls138, Port B is 8 bank inputs / outputs
void loop(){//do our piezo drums , wired to the analog ins
  for (piezopin=0;piezopin<=4;piezopin++){// setup the count to read the 5 drumpads
    drumvelocity=analogRead(piezopin);
    if (drumvelocity/2>=25){
      if(drumvelocity>=decay[piezopin]){
        midiCC(0x90,drumpad[piezopin],drumvelocity/2);
        delay(10);
      }
      decay[piezopin]=drumvelocity;
      delay(1);
    }
  }
  lovehandles=analogRead(5);
  if (lovehandles>35){
    if (lovehandlesflag==LOW){
      midiCC(0x90,88,127);
      delay(1);
      midiCC(0x80,88,127);
      lovehandlesflag = HIGH;
    }
    if((lovehandles/2)!=lovecheck){
      midiCC(0xB0,25,lovehandles/2);
      lovecheck=lovehandles/2;
    }
  }
  else{
    lovehandlesflag=LOW;
  }//read the lovehandles send controller and note on/off
 
  // do our 8 banks multiplexed to the digital ins
  for (banknum=7; banknum>=0; banknum--){ // set a loop of 8, 1 slot per bank
    if (banknum==0){
      PORTD = B00000001;
    } // set the bank address, binary 000 outs
    else if (banknum==1){
      PORTD = B00000101;
    }// set the bank address, binary 001 outs
    else if (banknum==2){
      PORTD = B00010001;// set the bank address, binary 010  ins unused so far
      //for(inputnum=8; inputnum<=13; inputnum++){swhandler(inputnum+12,inputnum-8);}
    }
    else if (banknum==3){
      PORTD = B00010101;// set the bank address, binary 011  puff switches and pir
      for(inputnum=8; inputnum<=13; inputnum++){
        if(digitalRead(inputnum)==HIGH){
          midiCC(0x90,inputnum+20,127);
          delay(10);
        }
      }//!!!!!!!!!!put the delay in here
      inputnum=6;
      input=(digitalRead(inputnum));// deal with pir switch, it's normally high going low
      if((input==HIGH)&&(switches[6]==LOW)){
        midiCC(0x80,35,127);
        switches[6]=HIGH;
      }
      // if a switch is pressed ON send a midi off, set the check value to ON
      if((switches[6]==HIGH) && (input==LOW)) {
        midiCC(0x90,35,127);
        switches[6]=LOW;
      }
    }
    else if (banknum==4){
      PORTD = B10000001;// set the bank address, binary 100 knife switches
      for(inputnum=8; inputnum<=13; inputnum++){
        swhandler(inputnum+28,inputnum+8);
      }
    }
    else if (banknum==5){
      PORTD = B10000101;// set the bank address, binary 101  momentary led click-switches
      for(inputnum=8; inputnum<=13; inputnum++){
        swhandler(inputnum+36,inputnum+16);
      }
    }     
    else if (banknum==6){
      PORTD = B10010001;
      enchandler(13,4);
      enchandler(11,5);
      enchandler(9,75);
    }//encoders
    else{
      PORTD = B10010101;
      enchandler(13,1);
      enchandler(11,2);
      enchandler(9,3);
    }
  }
}//encoders
//delay(50); // stall to see the leds
/* function send a Midi message.use 'midiCC(command byte, data, data)' 0xB0 = controller, 0x80 = note on,
 0x90 = note off data bytes 0-127 0x00-0x7f eg 0x80 0x34 0x0F note on, note 34, velocity 127*/
void midiCC(char CC_data, char c_num, char c_val){
  Serial.print(CC_data, BYTE);
  Serial.print(c_num, BYTE);
  Serial.print(c_val, BYTE);
}
// function to handle encoders / amend midi controllers
void enchandler(int y,int x){
  A=digitalRead(y);
  B=digitalRead(y-1);// fetch encoder states y is pin, x is array member / controller number
  // check for movement, direction and midi controller range
  if ((A==HIGH) && (enclaststate[x]==LOW)){
    encodercount[x]=0;
    if (encoderflag[x]==LOW){
      midiCC(0x90,x+12,127);
      delay(1);
      midiCC(0x80,x+12,127);
      encoderflag[x]=HIGH;
    }
    //reset stationary count, deal with the start midi note and set flag   
    if(B == HIGH){
      if(cccurrentvalue[x]!= 127){
        cccurrentvalue[x]++;
      }
    }//positive move or negative move
    else{
      if(cccurrentvalue[x]!= 0){
        cccurrentvalue[x]--;
      }
    }
    midiCC(0xB0,x,cccurrentvalue[x]);
  }//send the controller data
  else{
    encodercount[x]++;
    if ((encodercount[x]==1000)&&(encoderflag[x]==HIGH)){
      midiCC(0x90,x+18,127);
      delay(1);
      midiCC(0x80,x+18,127);
      encoderflag[x]=LOW;
    }
  }
  enclaststate[x] = A;
}// save the state for comparison n1ext time round

//function to read a switch and send a midi note on / off message
void swhandler(int note, int arraymember){
  input=(digitalRead(inputnum));// read the input pin
  if((input==HIGH)&&(switches[arraymember]==LOW)){
    midiCC(0x90,note,127);
    delay(1);
    midiCC(0x80,note,127);
    switches[arraymember]=HIGH;
  }
  // if a switch is pressed ON send a midi ON / off, set the check value to ON
  if((switches[arraymember]==HIGH) && (input==LOW)) {
    midiCC(0x90,note+36,127);
    delay(1);
    midiCC(0x80,note+36,127);
    switches[arraymember]=LOW;
  }
}
// if a switch is released send an on / OFF + 36, set the check value to OFF
Logged

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for that John, it looks better thinner & taller! & a useful link, Ray
Logged

Pages: [1]   Go Up
Jump to: