Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
main.cpp
- Committer:
- dallegre
- Date:
- 2015-06-23
- Revision:
- 0:c12e968e5b60
- Child:
- 1:a4ce08417c60
File content as of revision 0:c12e968e5b60:
//delay dsp for stm32f401re nucleo board with openmusiclabs audio codec shield. Need to jumpter the i2c pins from the
//top right arduino headers on the nucleo board to the bottom left 2 pins on the codec shield. Bottom left i2c pins are
//not mbed enabled on the nucleo boards.
//Also need to install a 11.2896MHz crystal on nucleo board and connect the appropriate jumpers as explained in the nucleo
//user manual. Two 20pf capacitors are used with the crystal. The series resistors going from the crystal to the stm32 chip
//are just shorts.
//Preceed audio path with a 1/47 voltage divider and follow with a 47X inverting op amp to bring up to eurorack levels. Use DC
//blocking cap after the op amp.
//Note that this is setup for the left input only and drives both outputs. It is easy to modify the code for stereo effects
//and both inputs.
//June 2015..
//Added interpolation so it acts more like a bbd or tape delay. It is easy to switch between cosine and linear interpolation.
//Cubic interpolation might be a possibility if I can figure out how it works.
//Added a nice lowpass filter class. Might want to put the delay in a class like this for reverb work. Need to make an oscillator next.
#define DELAYLEN 11500 //24,000 is about as far as you can go in the ram.
#define SAMPLINGFREQ 22 //roughly the smapling frequency in KHz. options are 22,29,44,88 for 22khz,29khz,etc..
#include "mbed.h"
#include "dsp.h"
#include "codec.h"
SPI spi(SPI_MOSI,SPI_MISO,SPI_SCK);
Ticker timer;
Ticker timer2;
AnalogIn analog_value(A1); //delay time pot
AnalogIn analog_value2(A0); //feedback amount pot
DigitalOut cs(D10);
int left_out = 0, right_out = 0, left_out_u = 0, right_out_u = 0, left_in = 0, right_in = 0,
index1 = 0, index2 = (DELAYLEN*0.99), index3 = (DELAYLEN*0.99);
uint16_t left_in_u = 0, meas = 0, measprev = 0;
float left_in_f = 0, feedback = 0, feedback2 = 0, feedback3 = 0, offset = 10.0,
meas2f = 0.5, measf = 0, measf2 = 0, measf3 = 0, left_out_f = 0, right_out_f = 0;
float audioFeedbackRight,audioFeedbackLeft;
float LPdampingFreq = 11000, HPdampingFreq = 100; //some parameters you might want to adjust.
int LPdampingPoles = 2, HPdampingPoles = 0; //I don't think the highpass is quite working.
OnePoleLp audioFilter; //might use this as a mor thorough DC offset removal tool. Not yet implemented.
OnePoleHp audioFilterHP;
OnePoleLp feedbackFilter;
OnePoleLp lengthFilter;
Delay delayLeft;
Delay delayRight;
void I2S_send(void){
cs.write(0); //0 for left output
left_in = spi.write(left_out);
cs.write(1); //1 for right output
right_in = spi.write(right_out);
left_in_f = intToFloat(left_in);
/////////////////////////////////////////dsp part//////////////////////////////////////////////////////////////////////
//process control signals
feedback2 = feedbackFilter.process(feedback);
feedback3 = feedbackFilter.process(feedback2);
//update delay times with every audio sample if you're going to filter them.
measf2 = lengthFilter.process(measf);
measf3 = lengthFilter.process(measf2);
measf3 *= (DELAYLEN); //convert to delay index normalization
//process audio
///*
//*/
left_out_f = delayLeft.process(left_in_f,audioFeedbackRight*feedback3,measf3);
right_out_f = delayRight.process(left_in_f,audioFeedbackLeft*feedback3,measf3+offset); //add an offset in just for shits.
left_out_u = satAdd(left_in_f,left_out_f);
right_out_u = satAdd(left_in_f,right_out_f);
//a little damping of the feedback
audioFeedbackRight = audioFilter.process(right_out_f);
for(int i = 0; i < LPdampingPoles - 1; i++){
audioFeedbackRight = audioFilter.process(audioFeedbackRight);
}
for(int i = 0; i < HPdampingPoles; i++){
audioFeedbackRight = audioFilterHP.process(audioFeedbackRight);
}
audioFeedbackLeft = audioFilter.process(left_out_f);
for(int i = 0; i < LPdampingPoles - 1; i++){
audioFeedbackLeft = audioFilter.process(audioFeedbackLeft);
}
for(int i = 0; i < HPdampingPoles; i++){
audioFeedbackLeft = audioFilterHP.process(audioFeedbackLeft);
}
/////////////////////////////////////////end of dsp part/////////////////////////////////////////////////////////////////
left_out = unsignedToSigned(left_out_u);
right_out = unsignedToSigned(right_out_u);
}
void analog_read(void){
//this is the stuff for the feedback amount pot
meas2f = analog_value2.read_u16(); //converts unint16 value to float
feedback = meas2f/4100; //now you have a value between 0 and 1 that will control the feedback amount.
//this is the stuff for the delay time pot
meas = 4096 - analog_value.read_u16(); //values go from 1 to 4095
//if(abs(meas - measprev) > 5){
measprev = meas;
measf = meas;
measf /= 4200; //this number took some tweaking.
measf *= measf;
//}
}
int main(){
//set up baud rate for 11.2MHz crystal
pc.baud(.7*9600*2);
wait(.1);
//do I2C transfter to initialize codec
codecInit();
//initialize fixed filters
double feedbackCutoff = 10.0/(SAMPLINGFREQ*1000); //adjust these cutoffs according to taste.
feedbackFilter.setFc(feedbackCutoff);
double lengthCutoff = 3.0/(SAMPLINGFREQ*1000);
lengthFilter.setFc(lengthCutoff);
//initialize audio filter
double audioCutoff = LPdampingFreq/(SAMPLINGFREQ*1000); //adjust these cutoffs according to taste.
audioFilter.setFc(audioCutoff);
audioCutoff = HPdampingFreq/(SAMPLINGFREQ*1000); //adjust these cutoffs according to taste.
audioFilterHP.setFc(audioCutoff);
//set up I2S
spi.frequency(8e6*2); //8MHz spi. This is fast enough for 88KHz 16 bit sampling.
spi.format(16,0); //16 bit. clock polarity 0, phase 0.
wait(.1);
//audio rate timers. 29 and 44 are not very good. Might want to use an external clock for the Nucleo.
if(SAMPLINGFREQ == 22)
timer.attach(&I2S_send,32e-6); //22KHz sampling. 12.2008MHz/512 = 21.876KHz. 1/(21.876KHz(8/11.2008)) = 64e-6 Sec and / by 2 because the codec divides by to before sending the osc out.
if(SAMPLINGFREQ == 29)
timer.attach(&I2S_send,24e-6); //29.168KHz sampling. 11.2008MHz/384 = 19.168KHz. 1/(29.168KHz(8/11.2008)) = 48.0012e-6 Sec and / by 2 because the codec divides by to before sending the osc out.
if(SAMPLINGFREQ == 44)
timer.attach(&I2S_send,16.0e-6); //44.1KHz sampling. almost exactly 32e-6 and then divide by 2. Doesn't sound right yet.
if(SAMPLINGFREQ == 88)
timer.attach(&I2S_send,8e-6); //88KHz sampling. Need to calculate.
//control signal timer
timer2.attach(&analog_read,25e-3);
//go!
while(1){}
}