'jdl+cdk 12.07.05: mutliplexed play+menu for 18F252
'************************************************************************
'Setup
'************************************************************************
DEFINE OSC 20
' Define ADCIN parameters
DEFINE ADC_BITS 10 ' Set number of bits in result
DEFINE ADC_CLOCK 3 ' Set clock source (3=rc)
DEFINE ADC_SAMPLEUS 15 ' Set sampling time in uS
'Enable communication out to MIDI
DEFINE HSER_RCSTA 90h ' enable the receive register
DEFINE HSER_TXSTA 20h ' enable the transmit register
DEFINE HSER_BAUD 31250 ' set the baud rate
TRISA = %00000001 ' Set PORTA.0 to input
ADCON1 = %10000010 ' Set PORTA analog and right justify result
TRISC = %10110000 'Set RC0-RC3 and RC6 to output
inhibitPin VAR PORTA.1
inputPin CON 0
GREENLEDpin VAR PORTB.6
REDLEDpin VAR PORTB.7
PLAYMENUpin VAR PORTB.5
'************************************************************************
'END Setup
'************************************************************************
'************************************************************************
'Declare Variables
'************************************************************************
'Declare Size of Array CONSTANTS
numinput CON 16
numlibrary CON 35
'Declare CONSTANTS AND COUNTER VARIABLEs
locktime CON 300
menuth CON 300
threshold CON 125
resetthreshold CON threshold*3/4
volumemin CON 25
i VAR BYTE
timecount VAR WORD
'Declare ADC VARIABLES
ADCVar VAR WORD
volume VAR BYTE
'Declare ARRAYS
hold VAR WORD[numinput]
impulsetoggle VAR BYTE[numinput]
sounds VAR BYTE[numinput]
finger VAR BYTE[numinput]
mutetoggle VAR BYTE[numinput]
soundlib VAR BYTE[numlibrary]
lock VAR BIT[numinput] '1 is open to change, 0 is locked
'initialize volume and toggle ARRAYS:
volume=50 'mid volume
FOR i=0 TO numinput
impulsetoggle[i] = 0 'means okay to go
mutetoggle[i]=0 'means don't sound off
NEXT
'initialize soundlib ARRAY
soundlib[0]=25 '!!real kick
soundlib[1]=27 '!side kick
soundlib[2]=31 '!!hard snare
soundlib[3]=32 '!drum sticks together
soundlib[4]=33 '!kick drum
soundlib[5]=34 '!!hard sharp drum
soundlib[6]=35 '!!Kick drum
soundlib[7]=36 '!duller kick drum
soundlib[8]=37 '!two sticks snare
soundlib[9]=38 '!hard snare
soundlib[10]=40 '!!nice snare
soundlib[11]=41 '!!hollowish boong drum
soundlib[12]=42 '!!tssst high hat
soundlib[13]=43 '!kick drum
soundlib[14]=44 '!tsst high hat
soundlib[15]=45 '!hollowish bong drum
soundlib[16]=46 '!!lounder cymbal
soundlib[17]=47 '!hollowish bong drum
soundlib[18]=48 '!higher hollowish bong drum
soundlib[19]=49 '!!loud cymbal
soundlib[20]=50 '!hollow shalllow boong
soundlib[21]=51 '!!cymbal tap
soundlib[22]=53 '!traingle like tap
soundlib[23]=54 '!tamborunie shake
soundlib[24]=55 '!lower tambourine shake
soundlib[25]=56 '!tin can smack
soundlib[26]=57 '!!louder cmybal crash
soundlib[27]=59 '!soft cymbal hit
soundlib[28]=60 '!hollow bongo
soundlib[29]=61 '!lower hollow bongo
soundlib[30]=62 '!muted bongo
soundlib[31]=63 '!!nice bongo
soundlib[32]=64 '!!nice2 bongo
soundlib[33]=65 '!!steel drum
soundlib[34]=66 '!!steel drum2
'initialize the finger[] sound locator
finger[0] = 10
finger[1] = 12
finger[2] = 16
finger[3] = 19
finger[4] = 0
finger[8] = 10
finger[9] = 12
finger[10] = 16
finger[11] = 19
finger[12] = 0
'Load sounds[] using finger[] as reference to soundlib[]
FOR i=0 TO (numinput-1)
sounds[i] = soundlib[finger[i]]
NEXT
'intialize all elements of lock[] as locked
FOR i=0 TO (numinput-1)
lock[i]=0
NEXT
'*************************
'Declare Play/Menu toggle variable
playmenu VAR BIT ' 0 play, 1 menu
lastplaymenu VAR BIT
' initialize playmenu
playmenu=0
'************************************************************************
'END Declare Variables
'************************************************************************
'************************************************************************
'MAIN
'************************************************************************
MAIN:
playmenu = PLAYMENUpin
'Look for change to PLAY
IF lastplaymenu ==1 AND playmenu ==0 THEN
'set all lock[] to locked
FOR i=0 TO (numinput-1)
lock[i]=0
NEXT
SEROUT2 PORTA.2, 16468, [200,220,0,0]
ENDIF
'Look fro change to MENU
IF lastplaymenu ==0 AND playmenu ==1 THEN
SEROUT2 PORTA.2, 16468, [200,221,0,0]
ENDIF
lastplaymenu=playmenu
IF playmenu == 0 THEN
GOTO PLAY
ELSE
GOTO MENU
ENDIF
GOTO MAIN
'************************************************************************
'END MAIN
'************************************************************************
'************************************************************************
'PLAY
'************************************************************************
PLAY:
'SET STATUS LEDS
HIGH GREENLEDpin 'Turn on green LED indicate play mode on
LOW REDLEDpin 'Turn off red LED
'code:
FOR i=0 TO (numinput-1)
'Turn off inputs:
HIGH inhibitPin
'Set the address you want to read
PORTC = i 'channelVar
'Turn on inputs
LOW inhibitPin
'Get reading from FSR (assume 0-1000):
ADCIN inputPin, ADCVar
hold[i]=ADCVar'This is an extra step
' SEROUT2 PORTA.2, 16468, ["finger ",DEC i, "reading ", DEC ADCVar,10,13]
IF hold[i] > threshold AND impulsetoggle[i]=0 THEN
'Here we look 6 more times to find peak
FOR timecount=0 TO 6
ADCIN inputPin, ADCVar
IF ADCVar > hold[i] THEN
hold[i]=ADCVar
ENDIF
NEXT
'Convert hold to volume
volume=hold[i]/8
volume=volume+volumemin
IF volume>125 THEN
volume=125
ENDIF
'noteon channel 1
HSEROUT [$90, sounds[i] ,volume]
SEROUT2 PORTA.2, 16468, [200,i,sounds[i],volume]
'reset impulsetoggle
impulsetoggle[i]=1
'set mutetoggle to trigger
mutetoggle[i]=1
ENDIF
NEXT
'Reset Toggles and Noteoff Loop
'NO NEED TO MULTIPLEX
FOR i=0 TO (numinput-1)
'Send Noteoff signal and reset mutetoggle
IF hold[i]<threshold AND mutetoggle[i]==1 THEN
HSEROUT [$80, sounds[i], $00]
mutetoggle[i]=0
ENDIF
'RESET impulsetoggle
IF hold[i]<resetthreshold THEN
impulsetoggle[i]=0
ENDIF
NEXT
GOTO MAIN
'************************************************************************
'END PLAY
'************************************************************************
'************************************************************************
'MENU
'************************************************************************
MENU:
'SET STATUS LEDS
LOW GREENLEDpin 'Turn off green LED
HIGH REDLEDpin 'Turn on red LED indicate menu mode on
'code:
FOR i = 0 TO (numinput-1)
'Turn off inputs:
HIGH inhibitPin
'Set the address you want to read
PORTC = i 'channelVar
'Turn on inputs
LOW inhibitPin
timecount=0
'read input
ADCIN inputPin, ADCVar
IF ADCVar > menuth THEN
WHILE ADCVar > menuth
timecount=timecount+1
'pause
PAUSE 2
ADCIN inputPin, ADCVar
WEND
IF timecount > locktime THEN
lock[i]=lock[i] +1 'lock is a bit so this flips it
SEROUT2 PORTA.2, 16468, [200,i,210,0]
ELSE
IF lock[i]==1 THEN 'system open: change note
finger[i]=(finger[i]+1)//numlibrary
sounds[i]=soundlib[finger[i]]
ENDIF
HSEROUT [$80, sounds[i-1] ,00] 'use constant volume
HSEROUT [$90, sounds[i] ,90] 'use constant volume
SEROUT2 PORTA.2, 16468, [200,i,sounds[i],0]
ENDIF
ENDIF
NEXT
PAUSE 100 'Helps get rid of noise
GOTO MAIN
'************************************************************************
'END MENU
'************************************************************************
'/*
' Serial Codes:
' Inside Play Mode: [startbit, finger, sound, velocity]
' Inside Menu Mode: [startbit, finger, sound, 0]
' UNLOCK: [startbit, finger, UNLOCK, 0]
' LOCK: [startbit, finger, LOCK, 0]
' Transfer Play Mode: [startbit, PLAY, 0, 0]
' Transfer Menu Mode: [startbit, MENU, 0, 0]
' Serial Codes:
' Inside Play Mode: [555, 0-9, 0-50, 0-127]
' Inside Menu Mode: [555, 0-9, 0-50, 0 ]
' UNLOCK: [555, 0-9, 210, 0]
' LOCK: [555, 0-9, 211, 0]
' Transfer Play Mode: [555, 220, 0, 0]
' Transfer Menu Mode: [555, 221, 0, 0]
'*/
'import processing.serial.*;
'Serial myPort; // The serial port
'Finger[] f= new Finger[10];
'PFont font;
'Smsg serialmsg;
'int initial=-1;
'boolean waiting;
'int count=0;
'//Global Variables
' boolean Play; //true if in Play mode false if in Menu mode
' int startbit=200;
' int playmsg=220;
' int menumsg=221;
'void setup()
'{
' size(500,500);
' background(0);
' smooth();
' //LOAD font
' font = loadFont("ArialMT-48.vlw");
' textFont(font, 12);
' //INITIALIZE Fingers
' initializeF();
' //INITIALIZE Variables
' serialmsg= new Smsg(0,0,0);
' Play=true;
' //DEAL with serial
' println(Serial.list());
' myPort = new Serial(this, Serial.list()[0], 9600);
' //initialize getting to punctuation bit
' while(initial != startbit)
' {
' if (myPort.available() > 0)
' {
' initial = myPort.read();
' println(initial);
' }
' }
' waiting = false;
' count=0;
'}
'void draw()
'{
' background(0);
' readPORT();
' renderF();
' //render mode
' if(Play)
' {
' text("PLAY",20,20);
' }
' else
' {
' text("MENU",20,20);
' }
' resetFvel();
'}
'/////////////////////////////////////////PAGE2
' void readPORT()
' {
' int code;
' if (myPort.available() > 0)
' {
' code = myPort.read();
' if(code == startbit)
' { count=0;}
' else if(count==0)
' { serialmsg.setMSG(0,code);
' count=1;}
' else if(count==1)
' { serialmsg.setMSG(1,code);
' count=2;}
' else if(count==2)
' { serialmsg.setMSG(2,code);
' evalmsg(serialmsg);}
' }
' }
'///////////////////////////////////////////PAGE 3
' void evalmsg(Smsg SEmsg)
' {
' int[] msg= new int[3];
' //parse message apart here, assume its a array
' msg[0]=SEmsg.getMSG(0);
' msg[1]=SEmsg.getMSG(1);
' msg[2]=SEmsg.getMSG(2);
' //EVALUATE HIT CODES
' if(msg[0] >-1 && msg[0] <13)
' {
' if(msg[0]>=5)//Corrects for the fact one hand is 8-12
' {
' msg[0]=msg[0]-3;
' }
' if(Play)
' {
' f[msg[0]].setVELOCITY(2*msg[2]);
' }
' else if(Play==false && (msg[1]==210 || msg[1]==211) )//Unlock
' {
' f[msg[0]].setLOCKED(!f[msg[0]].getLOCKED());
' }
' else //MENU MODE
' {
' if(f[msg[0]].getLOCKED()==false)
' {
' f[msg[0]].setSOUND((f[msg[0]].getSOUND()+1)%15);
' }
' else
' {
' f[msg[0]].setVELOCITY(100);
' }
' }
' }
' //SWITCH TO PLAY
' if(msg[0] == playmsg)
' {
' Play=true;
' lockF();
' }
' //SWITCH TO MENU
' if(msg[0] == menumsg)
' {
' Play=false;
' }
' }
' /////////////////////////////////////
' void resetFvel()
' {
' for(int i=0; i < f.length; i++)
' {
' if(f[i].getVELOCITY() > 0)
' {
' f[i].setVELOCITY(f[i].getVELOCITY()-1);
' }
' }
' }
' void lockF()
' {
' for(int i=0; i < f.length; i++)
' {
' f[i].setLOCKED(true);
' }
' }
' void renderF()
' {
' for(int i=0; i < f.length; i++)
' {
' f[i].render();
' }
' }
' void initializeF()
' {
' for(int i=0; i < f.length; i++)
' {
' f[i]= new Finger(100 + i*20, 100, i, 0, true);
' }
' }
'///////////////////////////////////////////////////PAGE 4
'class Finger
'{
' float x, y;
' int sound;
' float velocity;
' boolean locked;
' String[] sounds= new String[15];
' Finger(float x_, float y_, int sound_, float velocity_, boolean locked_)
' {
' x=x_;
' y=y_;
' sound=sound_;
' velocity=velocity_;
' locked=locked_;
' sounds[0]="a";
' sounds[1]="b";
' sounds[2]="c";
' sounds[3]="d";
' sounds[4]="e";
' sounds[5]="f";
' sounds[6]="g";
' sounds[7]="h";
' sounds[8]="i";
' sounds[9]="j";
' sounds[10]="k";
' sounds[11]="l";
' sounds[12]="m";
' sounds[13]="n";
' sounds[14]="o";
' }//END Finger
' int getSOUND() {return sound;}
' void setSOUND(int sound_) {sound = sound_;}
' float getVELOCITY() {return velocity;}
' void setVELOCITY(float v_) {velocity=v_;}
' boolean getLOCKED() {return locked;}
' void setLOCKED(boolean l_) {locked=l_;}
' void render()
' {
' noStroke();
' fill(255-velocity);
' ellipse(x,y,10+velocity/10,10+velocity/10);
' text(sounds[sound], x, y-20);
' if(locked==false)
' {
' for(int i=0; i<sounds.length; i++)
' {
' if(i==sound)
' {fill(255,0,0);}
' else
' {fill(255);}
' text(sounds[i],x,y+i*15+20);
' }
' }
' }//END render
'}//END Finger
'/////////////////////////////////////////////////////PAGE 5
'class Smsg
'{
' int[] b= new int[3];
' Smsg(int b0, int b1, int b2)
' {
' b[0]=b0;
' b[1]=b1;
' b[2]=b2;
' }
' int getMSG(int i) {return b[i];}
' void setMSG(int i, int bin) {b[i] = bin;}
'}