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.
Diff: main.cpp
- Revision:
- 0:c12e968e5b60
- Child:
- 1:a4ce08417c60
diff -r 000000000000 -r c12e968e5b60 main.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp Tue Jun 23 06:22:47 2015 +0000
@@ -0,0 +1,153 @@
+//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){}
+}
\ No newline at end of file