Arduino UNO Guitar Pedal V 0.5
#include
#include
#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