/* Based on the flanger from openmusiclabs.com this program does a flanger effect, and interpolates between samples for a smoother sound output. a rampwave is used to set the variable delay. the min and max delay times it swing between is set by MIN and MAX. these are in samples, divide by 31.25ksps to get ms delay times. the push buttons determines how much the ramp increments by each time. this sets the frequency of the delay sweep, which is min/maxed by B_MIN/B_MAX. */ #include "mult16x8.h" //defining harware resources. #define LED 13 #define FOOTSWITCH 12 #define TOGGLE 2 #define PUSHBUTTON_1 A5 #define PUSHBUTTON_2 A4 //defining the output PWM parameters #define PWM_FREQ 0x00FF // pwm frequency - 31.3KHz #define PWM_MODE 0 // Fast (1) or Phase Correct (0) #define PWM_QTY 2 // 2 PWMs in parallel //defining FX parameters #define MIN 2 // min delay of ~60us #define MAX 200 // max delay of ~6ms #define SIZE MAX+10 // data buffer size - must be more than MAX int buffer[SIZE]; // create a data buffer byte dir = 1; // keeps track of up/down counting unsigned int location = 0; // incoming data buffer pointer byte button; // button checking timer byte counter = 4; // button counter (and start value) unsigned int fractional = 0x00; // fractional sample position int data_buffer; // temporary data storage to give a 1 sample buffer int toggle_position=0; int counter2=0; //buttons timer counter void setup() { //setup IO pinMode(FOOTSWITCH, INPUT_PULLUP); pinMode(TOGGLE, INPUT_PULLUP); pinMode(PUSHBUTTON_1, INPUT_PULLUP); pinMode(PUSHBUTTON_2, INPUT_PULLUP); pinMode(LED, OUTPUT); // setup ADC ADMUX = 0x60; // left adjust, adc0, internal vcc ADCSRA = 0xe5; // turn on adc, ck/32, auto trigger ADCSRB = 0x07; // t1 capture for trigger DIDR0 = 0x01; // turn off digital inputs for adc0 // setup PWM TCCR1A = (((PWM_QTY - 1) << 5) | 0x80 | (PWM_MODE << 1)); // TCCR1B = ((PWM_MODE << 3) | 0x11); // ck/1 TIMSK1 = 0x20; // interrupt on capture interrupt ICR1H = (PWM_FREQ >> 8); ICR1L = (PWM_FREQ & 0xff); DDRB |= ((PWM_QTY << 1) | 0x02); // turn on outputs sei(); // turn on interrupts - not really necessary with arduino } void loop() { if (digitalRead(FOOTSWITCH)) digitalWrite(LED, HIGH); else digitalWrite(LED, LOW);} ISR(TIMER1_CAPT_vect) { // all processing happens here // output the last value calculated OCR1AL = ((data_buffer + 0x8000) >> 8); // convert to unsigned, send out high byte OCR1BL = data_buffer; // send out low byte // get ADC data byte temp1 = ADCL; // you need to fetch the low byte first byte temp2 = ADCH; // yes it needs to be done this way int input = ((temp2 << 8) | temp1) + 0x8000; // make a signed 16b value //BUTTONS counter2++; //to save resources, the pushbuttons are checked every 2000 times. if(counter2==2000) { counter2=0; if (!digitalRead(PUSHBUTTON_1)) { if (counter > MIN) counter-=1; // if not at min, decrement } if (!digitalRead(PUSHBUTTON_2)) { if (counter < MAX) counter+=1; // if not at max, increment } //toggle switch { toggle_position = digitalRead(TOGGLE); } } // fetch/store data buffer[location] = input; // store current sample location++; // go to next sample position if (location >= SIZE) location = 0; // deal with buffer wrap int temp = location - (fractional >> 8); // find delayed sample if (temp < 0) temp += SIZE; // deal with buffer wrap int output = buffer[temp]; // fetch delayed sample if (toggle_position=1) output = buffer[temp]+input; if (toggle_position=0) output = buffer[temp]; temp -= 1; // find adjacent sample if (temp < 0) temp += SIZE; // deal with buffer wrap int output2 = buffer[temp]; // get adjacent sample if (toggle_position=1) output2 = buffer[temp]+input; if (toggle_position=0) output2 = buffer[temp]; // interpolate between adjacent samples int temp4; // create some temp variables int temp5; // multiply by distance to fractional position MultiSU16X8toH16(temp4, output, (0xff - (fractional & 0x00ff))); MultiSU16X8toH16(temp5, output2, (fractional & 0x00ff)); output = temp4 + temp5; // sum weighted samples // save value for playback next interrupt data_buffer = output; // up or down count as necessary till MIN/MAX is reached if (dir) { if ((fractional >> 8) >= MAX) dir = 0; fractional += counter; } else { if ((fractional >> 8) <= MIN) dir = 1; fractional -= counter;; } }