Arduino UNO Guitar Pedal V 0.5

#include <SPI.h> #include <TimerOne.h> #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) volatile unsigned int input; //Analog input volatile unsigned int pot1; //stored value of the Left Potentiometer volatile unsigned int pot2; //stored value of the Right Potentiometer volatile boolean newSample=false; // new sample check volatile byte ibb; //used to force a slight delay on the ADAC conversions. volatile byte LSW; //store the value of the left momentary switch volatile byte RSW; //store the value of the right momentary switch int LED = 2; // Led to indicate if the effect is on or off int LeftSW=4; //left momentary foot switch input int RightSW=3; //right momentary foot switch input boolean RightDown=false; boolean LeftFown=false; boolean RightToggle = false; boolean LeftToggle = false; ///+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ void setup() { Serial.begin(115200); pinMode(10, OUTPUT); pinMode(8,OUTPUT); pinMode(LED,OUTPUT); pinMode(RightSW, INPUT); pinMode(LeftSW, INPUT); digitalWrite(8, LOW); // set adc prescaler to 64 for 19kHz sampling frequency cbi(ADCSRA, ADPS2); sbi(ADCSRA, ADPS1); sbi(ADCSRA, ADPS0); cbi(ADMUX,ADLAR); // 8-Bit ADC in ADCH Register cbi(ADMUX,REFS0); // VCC Reference sbi(ADMUX,REFS1); cbi(ADMUX,MUX0); // Set Input Multiplexer to Channel 0 cbi(ADMUX,MUX1); cbi(ADMUX,MUX2); cbi(ADMUX,MUX3); // Timer2 PWM Mode set to fast PWM cbi (TCCR2A, COM2A0); sbi (TCCR2A, COM2A1); sbi (TCCR2A, WGM20); sbi (TCCR2A, WGM21); cbi (TCCR2B, WGM22); // Timer2 Clock Prescaler to : 1 sbi (TCCR2B, CS20); cbi (TCCR2B, CS21); cbi (TCCR2B, CS22); Timer1.initialize(33); // ~= 15k*2 Hz Timer1.attachInterrupt( Sample ); SPI.begin(); SPI.setBitOrder(MSBFIRST); SPI.setDataMode(SPI_MODE0); } ///+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ///The Sample Interupt Function /// THis function does all the sampling. /// I have Two knobs on this effect pedal that can control /// different paramters. All together i'm using Three analog /// inputs. THis code is a little hacked but i'll describe what /// I'm doing here: /// 1) I read the audio input every other time the sample is triggered /// 2) I read the knob input every time the sample is not being read. /// The knobes are alternated as well when it comes to reading. /// Example Sequence: /// intercept1 : Audio input is read /// intercept2 : Knob 1 is read /// intercept3 : Audio input is read /// intercept4 : Knob 2 in read. /// .... /// /// volatile boolean samplesw = true; volatile boolean potsw=false; boolean isFirst=true; void Sample(){ if(samplesw){ samplesw=false; input = ADCL; input = input | (ADCH << 8); if(potsw) sbi(ADMUX,MUX0); // read Pot1; B000 B001 else sbi(ADMUX,MUX1); newSample=true; }else { samplesw=true; if (potsw){ potsw=false; pot2 = ADCL; pot2 = pot2 | (ADCH <<8); //pot1 = (pot1 * 50)/1023; cbi(ADMUX,MUX0); //B001 B000 }else { potsw=true; //sbi(ADMUX,MUX1); pot1 = ADCL; pot1 = pot1 | (ADCH <<8); cbi(ADMUX,MUX1); /// set back to read analog 0 B010 B000 // read digital inputs RSW = (PIND & (1 << RightSW)); LSW = (PIND & (1 << LeftSW)); //gain = 1.5 * ((float)pot1/1023.0); //iteration = -1; } } ibb++; // short delay before start conversion ibb--; ibb++; ibb--; sbi(ADCSRA,ADSC); // start next conversion } ///+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ///Write to DAC /// i use an external DAC and use the SPI inout to write to it. /// The chip i use is the MPC4911 void writecmd(unsigned int value){ //digitalWrite(10,LOW); // 76543210 PORTB = PORTB & !(B00000100); // set low int data = (value) << 2; // The 4911 has certain bits that need to be set at the most significant bits. These are: // 0|1 write vs ignore // 0|1 unbuffered vs buffered // 0|1 2X gain vs no gain // 0|1 shutdown vs active mode // 0x7000 will give me write + buffered + 2x gain + active mode data = 0x7000 | data; //Serial.println(data, BIN); SPI.transfer(data>>8); SPI.transfer(data); //digitalWrite(10,HIGH); PORTB = PORTB | (B00000100); // set High } ///+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ///Effect Switch Check /// Checks the button to see if the effect has been turned on. /// There is some delay times added here with the 'now' and 'rwait' variables. /// This to prevent the arduino from reading multiple presses while the switch /// is initially being pressed. When you first press the switch it can connect /// and disconnect multitple times right as the internal coneections are being /// made. This will cause the pedal to be unpredicatable at selecting the next /// effect. /// Parameters: /// * now - The current time in milliseconds. This is to ensure delay to prevent bounce. int last=0; int rwait=0; boolean rdown=0; void effectOn(int now){ last = now; if(RSW == LOW && (now - rwait) > 15000){ //Serial.println("Down"); rwait = now; if(!rdown){ //Serial.println("Toggle"); RightToggle=!RightToggle; rdown=true; } }else if(RSW > 0 && (now - rwait) > 15000 && rdown){ //Serial.println("UP"); rdown=false; } if(RightToggle)// 76543210 PORTD = PORTD | B00100100; else PORTD = PORTD & !(B00100100); } ///+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //Effect Select... iterate though effects. /// There is some delay times added here with the 'now' and 'lwait' variables. /// This to prevent the arduino from reading multiple presses while the switch /// is initially being pressed. When you first press the switch it can connect /// and disconnect multitple times right as the internal coneections are being /// made. This will cause the pedal to be unpredicatable at selecting the next /// effect. /// * NumEfct - The number of effects that are programmed minus 1. If you have 3 effects then this number should be 2. /// * now - This is the current time in milliseconds. This is to ensure delay to prevent bounce. int selected=0; int llast; int lwait; int ldown; int effectSelect(int NumEfct, int now){ llast = now; if(LSW == LOW && (now - lwait) > 15000){ //Serial.println("Down"); lwait = now; if(!ldown){ //Serial.println("Toggle"); LeftToggle=!LeftToggle; ldown=true; selected++; } }else if(LSW > 0 && (now - lwait) > 15000 && ldown){ //Serial.println("UP"); ldown=false; } if(selected > NumEfct) selected =0; return selected; } ///+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //Main Loop void loop() { while(!newSample); // wait for a new sample int now = micros(); unsigned long output = 0; //input=input*20*pot1/1023; //gain //Serial.println((20*pot2)/1023); newSample=false; //Serial.println(input); //check switches // input = input * 2 * pot1 / 50; effectOn(now); int sw = effectSelect(2, now); if(sw==0){ output = sampleAndHold(input, pot1); //output=input; } else if(sw == 1){ output=andDistortion(input, pot1); }else if(sw == 2){ output=sampleAndHold(input, LFO(pot1)); } writecmd( (output * 11 * pot2) /1023); // add gain... This one goes to 11! } ///+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ///Effects //// Effect 0: Sample and Hold /// Used to lower the sampling rate int sah_i=0; int sah_hold; int sampleAndHold(int input, int holdTime){ int ht = holdTime/10; if(sah_i==0){ sah_hold=input; sah_i++; }else if(sah_i < ht){ sah_i++; }else if(sah_i >= ht){ sah_i=0; } return sah_hold; } //Effect 1: Logic Function distortion // This just does a logical AND with the Hex value in the array /// Use once of the knobes to change the value that will be anded /// the input. int crush[] = {0x3FF, //0 0x0EE,//1 0x0DD,//2 0x0BB,//3 0x077,//4 0x0CC,//5 0x099,//6 0x033,//7 0x066,//8 0x088,//9 0x011,//10 0x022,//11 0x044};//12 int andDistortion(int input, int selector){ int c = selector*20/1023; //Serial.println(c); return input&crush[c]; } ///Effect 2: Sample and Hold with LFO /// Used to change the sample rate at the rate of the LFO /// Nothing new to add here since we are using effect0 plus some supporting functions //+++++++++++++++++++++++++++++++++++++++++++++++ //supporting functions //triangle LFO int samp=0; int sr=15000; int lfo_skip=0; int lfo_hold=0; int LFO(int _skip){ if(lfo_skip == 0){ lfo_hold++; lfo_skip++; if(lfo_hold >= 100){ lfo_hold=0; } }else{ lfo_skip+=_skip+1; if(lfo_skip >= 1000){ lfo_skip=0; } } //Serial.println(lfo_skip); return lfo_hold; }

No comments:

Post a Comment