Change the Ledstrip with Different input signal frequency
Dependencies: PololuLedStrip mbed
main.cpp@0:dc6175686e56, 2014-07-28 (annotated)
- Committer:
- KongXiangyue
- Date:
- Mon Jul 28 13:48:16 2014 +0000
- Revision:
- 0:dc6175686e56
FFT input analogue and drive the PololuLed strip
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
KongXiangyue | 0:dc6175686e56 | 1 | #define SAMPLE_RATE 48000 |
KongXiangyue | 0:dc6175686e56 | 2 | |
KongXiangyue | 0:dc6175686e56 | 3 | |
KongXiangyue | 0:dc6175686e56 | 4 | #include "mbed.h" |
KongXiangyue | 0:dc6175686e56 | 5 | #include "adc.h" |
KongXiangyue | 0:dc6175686e56 | 6 | #include "PololuLedStrip.h" |
KongXiangyue | 0:dc6175686e56 | 7 | |
KongXiangyue | 0:dc6175686e56 | 8 | PololuLedStrip ledStrip(p8); |
KongXiangyue | 0:dc6175686e56 | 9 | |
KongXiangyue | 0:dc6175686e56 | 10 | #define LED_COUNT 60 |
KongXiangyue | 0:dc6175686e56 | 11 | rgb_color colors[LED_COUNT]; |
KongXiangyue | 0:dc6175686e56 | 12 | |
KongXiangyue | 0:dc6175686e56 | 13 | Serial pc(USBTX,USBRX); |
KongXiangyue | 0:dc6175686e56 | 14 | |
KongXiangyue | 0:dc6175686e56 | 15 | //extern "C" void cr4_fft_256_stm32(void *pssOUT, void *pssIN, uint16_t Nbin); |
KongXiangyue | 0:dc6175686e56 | 16 | extern "C" void fftR4(short *y, short *x, int N); |
KongXiangyue | 0:dc6175686e56 | 17 | |
KongXiangyue | 0:dc6175686e56 | 18 | //use the LED as a bargraph |
KongXiangyue | 0:dc6175686e56 | 19 | DigitalOut l1(LED1); |
KongXiangyue | 0:dc6175686e56 | 20 | DigitalOut l2(LED2); |
KongXiangyue | 0:dc6175686e56 | 21 | DigitalOut l3(LED3); |
KongXiangyue | 0:dc6175686e56 | 22 | DigitalOut l4(LED4); |
KongXiangyue | 0:dc6175686e56 | 23 | |
KongXiangyue | 0:dc6175686e56 | 24 | //set up a timer for timing FFT's |
KongXiangyue | 0:dc6175686e56 | 25 | Timer timer; |
KongXiangyue | 0:dc6175686e56 | 26 | |
KongXiangyue | 0:dc6175686e56 | 27 | //Used to change colour of LED strips |
KongXiangyue | 0:dc6175686e56 | 28 | //int testX = 0; |
KongXiangyue | 0:dc6175686e56 | 29 | |
KongXiangyue | 0:dc6175686e56 | 30 | //Set up filesystem so we can write some useful files |
KongXiangyue | 0:dc6175686e56 | 31 | |
KongXiangyue | 0:dc6175686e56 | 32 | LocalFileSystem local("local"); |
KongXiangyue | 0:dc6175686e56 | 33 | FILE *fp; |
KongXiangyue | 0:dc6175686e56 | 34 | |
KongXiangyue | 0:dc6175686e56 | 35 | //Set up a global buffer for audio data so interrupt can access it |
KongXiangyue | 0:dc6175686e56 | 36 | int Counter = 0; |
KongXiangyue | 0:dc6175686e56 | 37 | int16_t Buffer[5000]; |
KongXiangyue | 0:dc6175686e56 | 38 | int16_t VoltageBuffer[5000]; |
KongXiangyue | 0:dc6175686e56 | 39 | |
KongXiangyue | 0:dc6175686e56 | 40 | //Initialise ADC to maximum SAMPLE_RATE and cclk divide set to 1 |
KongXiangyue | 0:dc6175686e56 | 41 | ADC adc(SAMPLE_RATE, 1); |
KongXiangyue | 0:dc6175686e56 | 42 | |
KongXiangyue | 0:dc6175686e56 | 43 | int colourVoltage=0; |
KongXiangyue | 0:dc6175686e56 | 44 | |
KongXiangyue | 0:dc6175686e56 | 45 | |
KongXiangyue | 0:dc6175686e56 | 46 | |
KongXiangyue | 0:dc6175686e56 | 47 | //Our interrupt handler for audio sampling |
KongXiangyue | 0:dc6175686e56 | 48 | void sample_ADC(int chan, uint32_t value) { |
KongXiangyue | 0:dc6175686e56 | 49 | |
KongXiangyue | 0:dc6175686e56 | 50 | float s; |
KongXiangyue | 0:dc6175686e56 | 51 | s = adc.read(p20); |
KongXiangyue | 0:dc6175686e56 | 52 | int16_t b = (s -2048)*16; |
KongXiangyue | 0:dc6175686e56 | 53 | Buffer[Counter] = b; |
KongXiangyue | 0:dc6175686e56 | 54 | |
KongXiangyue | 0:dc6175686e56 | 55 | Counter += 1; |
KongXiangyue | 0:dc6175686e56 | 56 | /* bar graph */ |
KongXiangyue | 0:dc6175686e56 | 57 | |
KongXiangyue | 0:dc6175686e56 | 58 | int g = abs(s-2048); |
KongXiangyue | 0:dc6175686e56 | 59 | l1 = g > 0.1f*2048; |
KongXiangyue | 0:dc6175686e56 | 60 | l2 = g > 0.3f*2048; |
KongXiangyue | 0:dc6175686e56 | 61 | l3 = g > 0.6f*2048; |
KongXiangyue | 0:dc6175686e56 | 62 | l4 = g > 0.8f*2048; |
KongXiangyue | 0:dc6175686e56 | 63 | } |
KongXiangyue | 0:dc6175686e56 | 64 | |
KongXiangyue | 0:dc6175686e56 | 65 | |
KongXiangyue | 0:dc6175686e56 | 66 | |
KongXiangyue | 0:dc6175686e56 | 67 | |
KongXiangyue | 0:dc6175686e56 | 68 | |
KongXiangyue | 0:dc6175686e56 | 69 | |
KongXiangyue | 0:dc6175686e56 | 70 | int main() { |
KongXiangyue | 0:dc6175686e56 | 71 | |
KongXiangyue | 0:dc6175686e56 | 72 | while (1){ |
KongXiangyue | 0:dc6175686e56 | 73 | |
KongXiangyue | 0:dc6175686e56 | 74 | //Prepare for burst mode on all ADC pins and set up interrupt handler (using ADC library from Simon Blandford |
KongXiangyue | 0:dc6175686e56 | 75 | adc.append(sample_ADC); |
KongXiangyue | 0:dc6175686e56 | 76 | adc.startmode(0,0); |
KongXiangyue | 0:dc6175686e56 | 77 | adc.burst(1); |
KongXiangyue | 0:dc6175686e56 | 78 | adc.setup(p20,1); |
KongXiangyue | 0:dc6175686e56 | 79 | //introduce a delay as initial waveform has bias whilst decoupling cap charges |
KongXiangyue | 0:dc6175686e56 | 80 | wait(0.05); |
KongXiangyue | 0:dc6175686e56 | 81 | //start the interrupt and wait for about 4096 samples |
KongXiangyue | 0:dc6175686e56 | 82 | adc.interrupt_state(p20,1); |
KongXiangyue | 0:dc6175686e56 | 83 | wait(0.05); |
KongXiangyue | 0:dc6175686e56 | 84 | |
KongXiangyue | 0:dc6175686e56 | 85 | //Finsh up - Unset pin 20 |
KongXiangyue | 0:dc6175686e56 | 86 | adc.interrupt_state(p20,0); |
KongXiangyue | 0:dc6175686e56 | 87 | adc.setup(p20,0); |
KongXiangyue | 0:dc6175686e56 | 88 | int actual_rate = adc.actual_sample_rate(); |
KongXiangyue | 0:dc6175686e56 | 89 | //now lets try mellen fft------------------------- |
KongXiangyue | 0:dc6175686e56 | 90 | timer.reset(); |
KongXiangyue | 0:dc6175686e56 | 91 | timer.start(); |
KongXiangyue | 0:dc6175686e56 | 92 | #define MN 1024 /*Number of points*/ |
KongXiangyue | 0:dc6175686e56 | 93 | short mx[MN*2]; // input data 16 bit, 4 byte aligned x0r,x0i,x1r,x1i,.... |
KongXiangyue | 0:dc6175686e56 | 94 | short my[MN*2]; // output data 16 bit,4 byte aligned y0r,y0i,y1r,y1i,.... |
KongXiangyue | 0:dc6175686e56 | 95 | float mz[MN*2]; // to store the final result |
KongXiangyue | 0:dc6175686e56 | 96 | for (int i=0;i<MN*2;i++) mx[i]=0; |
KongXiangyue | 0:dc6175686e56 | 97 | for (int i=0;i<MN*2;i++) mz[i]=0; |
KongXiangyue | 0:dc6175686e56 | 98 | for (int i=0;i<MN;i=i+1) |
KongXiangyue | 0:dc6175686e56 | 99 | { mx[i*2]=Buffer[i];} |
KongXiangyue | 0:dc6175686e56 | 100 | //printf("Mellen set up took %i\n",timer.read_us()); |
KongXiangyue | 0:dc6175686e56 | 101 | //call functions |
KongXiangyue | 0:dc6175686e56 | 102 | timer.reset(); |
KongXiangyue | 0:dc6175686e56 | 103 | timer.start(); |
KongXiangyue | 0:dc6175686e56 | 104 | fftR4(my, mx, MN); |
KongXiangyue | 0:dc6175686e56 | 105 | //printf("Mellen fft took %i\n",timer.read_us()); |
KongXiangyue | 0:dc6175686e56 | 106 | //FILE* mlog = fopen("/local/mellen.csv","w"); |
KongXiangyue | 0:dc6175686e56 | 107 | |
KongXiangyue | 0:dc6175686e56 | 108 | //now write a CSV file to filesytem of frequency vs amplitude |
KongXiangyue | 0:dc6175686e56 | 109 | for (int i=0; i<MN; i=i+2) |
KongXiangyue | 0:dc6175686e56 | 110 | { |
KongXiangyue | 0:dc6175686e56 | 111 | // fprintf(mlog, "%d: %d -> %d\n", i, mx[i], my[i]); |
KongXiangyue | 0:dc6175686e56 | 112 | //fprintf(mlog, "%d,%f\n", int(actual_rate/MN/2*i),sqrt(float( (my[i]*my[i]) +(my[i+1]*my[i+1]) ) ) ); |
KongXiangyue | 0:dc6175686e56 | 113 | |
KongXiangyue | 0:dc6175686e56 | 114 | mz[i]=sqrt(float( (my[i]*my[i]) +(my[i+1]*my[i+1]) ) ) ; |
KongXiangyue | 0:dc6175686e56 | 115 | //fprintf(mlog, "%f\n", mz[i] ); |
KongXiangyue | 0:dc6175686e56 | 116 | } |
KongXiangyue | 0:dc6175686e56 | 117 | |
KongXiangyue | 0:dc6175686e56 | 118 | |
KongXiangyue | 0:dc6175686e56 | 119 | // detect the change of input frequency ****************************** |
KongXiangyue | 0:dc6175686e56 | 120 | float maxFreq=0; |
KongXiangyue | 0:dc6175686e56 | 121 | float max=0; |
KongXiangyue | 0:dc6175686e56 | 122 | for (int i=2;i<512;i=i+1){ |
KongXiangyue | 0:dc6175686e56 | 123 | |
KongXiangyue | 0:dc6175686e56 | 124 | if(mz[i]>max){ |
KongXiangyue | 0:dc6175686e56 | 125 | max = mz[i]; |
KongXiangyue | 0:dc6175686e56 | 126 | maxFreq=i; |
KongXiangyue | 0:dc6175686e56 | 127 | }//end if |
KongXiangyue | 0:dc6175686e56 | 128 | |
KongXiangyue | 0:dc6175686e56 | 129 | }//end for |
KongXiangyue | 0:dc6175686e56 | 130 | //fprintf(mlog, "%d\n",maxFreq ); |
KongXiangyue | 0:dc6175686e56 | 131 | |
KongXiangyue | 0:dc6175686e56 | 132 | int maxVoltage=0; |
KongXiangyue | 0:dc6175686e56 | 133 | for (int i=0;i<512;i=i+1){ |
KongXiangyue | 0:dc6175686e56 | 134 | |
KongXiangyue | 0:dc6175686e56 | 135 | if(mx[i]>maxVoltage){ |
KongXiangyue | 0:dc6175686e56 | 136 | maxVoltage = mx[i]; |
KongXiangyue | 0:dc6175686e56 | 137 | |
KongXiangyue | 0:dc6175686e56 | 138 | }//end if |
KongXiangyue | 0:dc6175686e56 | 139 | }//end for |
KongXiangyue | 0:dc6175686e56 | 140 | |
KongXiangyue | 0:dc6175686e56 | 141 | pc.printf(" the max = %f\n",max ); |
KongXiangyue | 0:dc6175686e56 | 142 | pc.printf(" the maxFreq = %f\n",maxFreq ); |
KongXiangyue | 0:dc6175686e56 | 143 | pc.printf(" the colourValtage = %d\n", maxVoltage ); |
KongXiangyue | 0:dc6175686e56 | 144 | |
KongXiangyue | 0:dc6175686e56 | 145 | |
KongXiangyue | 0:dc6175686e56 | 146 | /*for (int i = 0; i < LED_COUNT; i++){ |
KongXiangyue | 0:dc6175686e56 | 147 | colors[i] = (rgb_color){ 0, 0, 0 }; |
KongXiangyue | 0:dc6175686e56 | 148 | } |
KongXiangyue | 0:dc6175686e56 | 149 | |
KongXiangyue | 0:dc6175686e56 | 150 | if (maxFreq>60) maxFreq=60; // Limiting Length |
KongXiangyue | 0:dc6175686e56 | 151 | |
KongXiangyue | 0:dc6175686e56 | 152 | for (int i = 0; i < maxFreq; i++){ |
KongXiangyue | 0:dc6175686e56 | 153 | colors[i] = (rgb_color){ abs(maxVoltage/11),abs(255-(maxVoltage/11)) ,abs(255-(maxVoltage/11)+50) }; |
KongXiangyue | 0:dc6175686e56 | 154 | } |
KongXiangyue | 0:dc6175686e56 | 155 | ledStrip.write(colors, LED_COUNT);*/ |
KongXiangyue | 0:dc6175686e56 | 156 | int actualFreq= (actual_rate/MN/2*maxFreq); |
KongXiangyue | 0:dc6175686e56 | 157 | pc.printf(" actualFreq = %d\n", actualFreq ); |
KongXiangyue | 0:dc6175686e56 | 158 | |
KongXiangyue | 0:dc6175686e56 | 159 | |
KongXiangyue | 0:dc6175686e56 | 160 | //wait_ms(10); |
KongXiangyue | 0:dc6175686e56 | 161 | |
KongXiangyue | 0:dc6175686e56 | 162 | /*if (maxFreq>30){ |
KongXiangyue | 0:dc6175686e56 | 163 | //testX=200; |
KongXiangyue | 0:dc6175686e56 | 164 | for (int i = 0; i < LED_COUNT; i++){ |
KongXiangyue | 0:dc6175686e56 | 165 | colors[i] = (rgb_color){ 0, 20, 200 }; |
KongXiangyue | 0:dc6175686e56 | 166 | } |
KongXiangyue | 0:dc6175686e56 | 167 | } |
KongXiangyue | 0:dc6175686e56 | 168 | |
KongXiangyue | 0:dc6175686e56 | 169 | if ((maxFreq>22)&&(maxFreq<30)){// if frequency bigger than 966Hz |
KongXiangyue | 0:dc6175686e56 | 170 | //testX= 10; |
KongXiangyue | 0:dc6175686e56 | 171 | for (int i = 0; i < LED_COUNT; i++){ |
KongXiangyue | 0:dc6175686e56 | 172 | colors[i] = (rgb_color){ 250, 0, 0 }; |
KongXiangyue | 0:dc6175686e56 | 173 | |
KongXiangyue | 0:dc6175686e56 | 174 | } |
KongXiangyue | 0:dc6175686e56 | 175 | } |
KongXiangyue | 0:dc6175686e56 | 176 | if (maxFreq<22){ |
KongXiangyue | 0:dc6175686e56 | 177 | //testX=200; |
KongXiangyue | 0:dc6175686e56 | 178 | for (int i = 0; i < LED_COUNT; i++){ |
KongXiangyue | 0:dc6175686e56 | 179 | colors[i] = (rgb_color){ 0, 250, 0 }; |
KongXiangyue | 0:dc6175686e56 | 180 | } |
KongXiangyue | 0:dc6175686e56 | 181 | }*/ |
KongXiangyue | 0:dc6175686e56 | 182 | |
KongXiangyue | 0:dc6175686e56 | 183 | |
KongXiangyue | 0:dc6175686e56 | 184 | |
KongXiangyue | 0:dc6175686e56 | 185 | |
KongXiangyue | 0:dc6175686e56 | 186 | |
KongXiangyue | 0:dc6175686e56 | 187 | |
KongXiangyue | 0:dc6175686e56 | 188 | |
KongXiangyue | 0:dc6175686e56 | 189 | //----------- |
KongXiangyue | 0:dc6175686e56 | 190 | |
KongXiangyue | 0:dc6175686e56 | 191 | |
KongXiangyue | 0:dc6175686e56 | 192 | //fclose(mlog); |
KongXiangyue | 0:dc6175686e56 | 193 | Counter = 0; |
KongXiangyue | 0:dc6175686e56 | 194 | }// end while (1) |
KongXiangyue | 0:dc6175686e56 | 195 | |
KongXiangyue | 0:dc6175686e56 | 196 | |
KongXiangyue | 0:dc6175686e56 | 197 | } |