Real-time spectrum analyzer for ST Nucleo F401RE using Seeed Studio 2.8'' TFT Touch Shield V2.0.
Dependencies: SeeedStudioTFTv2 UITDSP_ADDA UIT_FFT_Real mbed
main.cpp@0:c5b026c2d07e, 2015-07-26 (annotated)
- Committer:
- MikamiUitOpen
- Date:
- Sun Jul 26 02:48:23 2015 +0000
- Revision:
- 0:c5b026c2d07e
1
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
MikamiUitOpen | 0:c5b026c2d07e | 1 | //-------------------------------------------------------------- |
MikamiUitOpen | 0:c5b026c2d07e | 2 | // Spectrum analyzer |
MikamiUitOpen | 0:c5b026c2d07e | 3 | // input PC_3 |
MikamiUitOpen | 0:c5b026c2d07e | 4 | // sampling frquency 10 kHz |
MikamiUitOpen | 0:c5b026c2d07e | 5 | // window Hamming window |
MikamiUitOpen | 0:c5b026c2d07e | 6 | // number of data 240 points |
MikamiUitOpen | 0:c5b026c2d07e | 7 | // number of FFT 512 points |
MikamiUitOpen | 0:c5b026c2d07e | 8 | // preemphasis 1st-order difference |
MikamiUitOpen | 0:c5b026c2d07e | 9 | // |
MikamiUitOpen | 0:c5b026c2d07e | 10 | // Touch pannel |
MikamiUitOpen | 0:c5b026c2d07e | 11 | // upper ---- left: update display |
MikamiUitOpen | 0:c5b026c2d07e | 12 | // right: freeze display |
MikamiUitOpen | 0:c5b026c2d07e | 13 | // lower ---- left: bar chart of FFT |
MikamiUitOpen | 0:c5b026c2d07e | 14 | // center: line chart of FFT |
MikamiUitOpen | 0:c5b026c2d07e | 15 | // right: line chart of linear prediction |
MikamiUitOpen | 0:c5b026c2d07e | 16 | // When you touch the touch pannel, PZT speaker connected PB_1 |
MikamiUitOpen | 0:c5b026c2d07e | 17 | // sounds "pi" generated using PWM object. |
MikamiUitOpen | 0:c5b026c2d07e | 18 | // |
MikamiUitOpen | 0:c5b026c2d07e | 19 | // 2015/07/25, Copyright (c) 2015 MIKAMI, Naoki |
MikamiUitOpen | 0:c5b026c2d07e | 20 | //-------------------------------------------------------------- |
MikamiUitOpen | 0:c5b026c2d07e | 21 | |
MikamiUitOpen | 0:c5b026c2d07e | 22 | #include "ADC_Interrupt.hpp" // for ADC using interrupt |
MikamiUitOpen | 0:c5b026c2d07e | 23 | #include "FFT_Analysis.hpp" |
MikamiUitOpen | 0:c5b026c2d07e | 24 | #include "SpectrumDisplay.hpp" |
MikamiUitOpen | 0:c5b026c2d07e | 25 | #include "LPC_Analysis.hpp" |
MikamiUitOpen | 0:c5b026c2d07e | 26 | |
MikamiUitOpen | 0:c5b026c2d07e | 27 | using namespace Mikami; |
MikamiUitOpen | 0:c5b026c2d07e | 28 | |
MikamiUitOpen | 0:c5b026c2d07e | 29 | const int N_FFT_ = 512; // number of date for FFT |
MikamiUitOpen | 0:c5b026c2d07e | 30 | const int N_DATA_ = 240; // number of data to be analyzed |
MikamiUitOpen | 0:c5b026c2d07e | 31 | |
MikamiUitOpen | 0:c5b026c2d07e | 32 | const int X0_ = 36; // Origin for x axis |
MikamiUitOpen | 0:c5b026c2d07e | 33 | const int Y0_ = 200; // Origin for y axis |
MikamiUitOpen | 0:c5b026c2d07e | 34 | const float DB1_ = 2.8f; // Pixels for 1 dB |
MikamiUitOpen | 0:c5b026c2d07e | 35 | const int BIN_ = 1; // Pixels per bin |
MikamiUitOpen | 0:c5b026c2d07e | 36 | const int MAX_DB_ = 60; // Maximum dB |
MikamiUitOpen | 0:c5b026c2d07e | 37 | |
MikamiUitOpen | 0:c5b026c2d07e | 38 | const int FS_ = 10000; // Sampling frequency: 10 kHz |
MikamiUitOpen | 0:c5b026c2d07e | 39 | |
MikamiUitOpen | 0:c5b026c2d07e | 40 | // Pointer of object for using Seeed Studio 2.8" TFT Touch Shield V2.0 |
MikamiUitOpen | 0:c5b026c2d07e | 41 | SeeedStudioTFTv2* lcd_; |
MikamiUitOpen | 0:c5b026c2d07e | 42 | |
MikamiUitOpen | 0:c5b026c2d07e | 43 | ADC_Intr adc_(PC_3, FS_); // for external mic connected with PC3 |
MikamiUitOpen | 0:c5b026c2d07e | 44 | PeakHolder mag_(0.9998f); // for input volume |
MikamiUitOpen | 0:c5b026c2d07e | 45 | FftAnalyzer fft_(N_DATA_, N_FFT_); |
MikamiUitOpen | 0:c5b026c2d07e | 46 | LpcAnalyzer lpc_(N_DATA_, 16, N_FFT_); |
MikamiUitOpen | 0:c5b026c2d07e | 47 | |
MikamiUitOpen | 0:c5b026c2d07e | 48 | float volume_ = 0; |
MikamiUitOpen | 0:c5b026c2d07e | 49 | float bufIn_[N_DATA_]; // Buffer for input signal |
MikamiUitOpen | 0:c5b026c2d07e | 50 | volatile bool analysisOk_; |
MikamiUitOpen | 0:c5b026c2d07e | 51 | |
MikamiUitOpen | 0:c5b026c2d07e | 52 | PwmOut sound_(PB_1); |
MikamiUitOpen | 0:c5b026c2d07e | 53 | Timeout off_; |
MikamiUitOpen | 0:c5b026c2d07e | 54 | |
MikamiUitOpen | 0:c5b026c2d07e | 55 | void IsrTimeout() { sound_.write(0); } |
MikamiUitOpen | 0:c5b026c2d07e | 56 | |
MikamiUitOpen | 0:c5b026c2d07e | 57 | // Interrupt service routine for ADC |
MikamiUitOpen | 0:c5b026c2d07e | 58 | void AdcIsr() |
MikamiUitOpen | 0:c5b026c2d07e | 59 | { |
MikamiUitOpen | 0:c5b026c2d07e | 60 | static int count = 0; // counter of input buffer |
MikamiUitOpen | 0:c5b026c2d07e | 61 | |
MikamiUitOpen | 0:c5b026c2d07e | 62 | bufIn_[count] = adc_.Read(); // Read from PC_3 |
MikamiUitOpen | 0:c5b026c2d07e | 63 | volume_ = mag_.Execute(fabs(bufIn_[count])); |
MikamiUitOpen | 0:c5b026c2d07e | 64 | |
MikamiUitOpen | 0:c5b026c2d07e | 65 | if (++count >= N_DATA_) |
MikamiUitOpen | 0:c5b026c2d07e | 66 | { |
MikamiUitOpen | 0:c5b026c2d07e | 67 | count = 0; |
MikamiUitOpen | 0:c5b026c2d07e | 68 | analysisOk_ = true; // This permits to FFT analysis |
MikamiUitOpen | 0:c5b026c2d07e | 69 | } |
MikamiUitOpen | 0:c5b026c2d07e | 70 | } |
MikamiUitOpen | 0:c5b026c2d07e | 71 | |
MikamiUitOpen | 0:c5b026c2d07e | 72 | int main() |
MikamiUitOpen | 0:c5b026c2d07e | 73 | { |
MikamiUitOpen | 0:c5b026c2d07e | 74 | lcd_ = new SeeedStudioTFTv2 (A3, A1, A2, A0, // X+, X-, Y+, Y- |
MikamiUitOpen | 0:c5b026c2d07e | 75 | D11, D12, D13, // MOSI, MISO, SCLK |
MikamiUitOpen | 0:c5b026c2d07e | 76 | D5, D6, D7, D4); // CS_TFT, DC_TFT, BL_TFT, CS_SD |
MikamiUitOpen | 0:c5b026c2d07e | 77 | |
MikamiUitOpen | 0:c5b026c2d07e | 78 | SpectrumDisplay disp(lcd_, N_FFT_, X0_, Y0_, |
MikamiUitOpen | 0:c5b026c2d07e | 79 | DB1_, BIN_, MAX_DB_, FS_); |
MikamiUitOpen | 0:c5b026c2d07e | 80 | |
MikamiUitOpen | 0:c5b026c2d07e | 81 | analysisOk_ = false; |
MikamiUitOpen | 0:c5b026c2d07e | 82 | adc_.SetIntrVec(AdcIsr); // Assign ISR for ADC interrupt |
MikamiUitOpen | 0:c5b026c2d07e | 83 | sound_.period_us((int)(1.0e6f/4000.0f)); |
MikamiUitOpen | 0:c5b026c2d07e | 84 | |
MikamiUitOpen | 0:c5b026c2d07e | 85 | |
MikamiUitOpen | 0:c5b026c2d07e | 86 | int touchBefore = 0; |
MikamiUitOpen | 0:c5b026c2d07e | 87 | int touchNow = 0; |
MikamiUitOpen | 0:c5b026c2d07e | 88 | // bool runBefore = true; |
MikamiUitOpen | 0:c5b026c2d07e | 89 | bool update = true; |
MikamiUitOpen | 0:c5b026c2d07e | 90 | float xn[N_DATA_]; // data to be analyzed |
MikamiUitOpen | 0:c5b026c2d07e | 91 | float db[N_FFT_/2+1]; // Log powerspectrum |
MikamiUitOpen | 0:c5b026c2d07e | 92 | |
MikamiUitOpen | 0:c5b026c2d07e | 93 | // Timer tim; |
MikamiUitOpen | 0:c5b026c2d07e | 94 | while (true) |
MikamiUitOpen | 0:c5b026c2d07e | 95 | if (analysisOk_) |
MikamiUitOpen | 0:c5b026c2d07e | 96 | { |
MikamiUitOpen | 0:c5b026c2d07e | 97 | // Sampled signals to working area |
MikamiUitOpen | 0:c5b026c2d07e | 98 | for (int n=0; n<N_DATA_; n++) |
MikamiUitOpen | 0:c5b026c2d07e | 99 | xn[n] = bufIn_[n]; |
MikamiUitOpen | 0:c5b026c2d07e | 100 | |
MikamiUitOpen | 0:c5b026c2d07e | 101 | // tim.reset(); |
MikamiUitOpen | 0:c5b026c2d07e | 102 | // Read touched Position |
MikamiUitOpen | 0:c5b026c2d07e | 103 | NVIC_DisableIRQ(ADC_IRQn); |
MikamiUitOpen | 0:c5b026c2d07e | 104 | point pos; // Touched position |
MikamiUitOpen | 0:c5b026c2d07e | 105 | |
MikamiUitOpen | 0:c5b026c2d07e | 106 | // tim.start(); |
MikamiUitOpen | 0:c5b026c2d07e | 107 | lcd_->getPixel(pos); |
MikamiUitOpen | 0:c5b026c2d07e | 108 | // tim.stop(); |
MikamiUitOpen | 0:c5b026c2d07e | 109 | |
MikamiUitOpen | 0:c5b026c2d07e | 110 | adc_.Select1stChannel(); |
MikamiUitOpen | 0:c5b026c2d07e | 111 | NVIC_ClearPendingIRQ(ADC_IRQn); |
MikamiUitOpen | 0:c5b026c2d07e | 112 | NVIC_EnableIRQ(ADC_IRQn); |
MikamiUitOpen | 0:c5b026c2d07e | 113 | // printf("Execution time: %d micro seconds\r\n", tim.read_us()); |
MikamiUitOpen | 0:c5b026c2d07e | 114 | |
MikamiUitOpen | 0:c5b026c2d07e | 115 | // Display log spectrum |
MikamiUitOpen | 0:c5b026c2d07e | 116 | float offset = 30; |
MikamiUitOpen | 0:c5b026c2d07e | 117 | |
MikamiUitOpen | 0:c5b026c2d07e | 118 | // Sound "pi" 0.1 seconds |
MikamiUitOpen | 0:c5b026c2d07e | 119 | if ( (pos.x != 320) && (pos.y !=0) ) |
MikamiUitOpen | 0:c5b026c2d07e | 120 | { |
MikamiUitOpen | 0:c5b026c2d07e | 121 | sound_.write(0.5f); |
MikamiUitOpen | 0:c5b026c2d07e | 122 | off_.attach(&IsrTimeout, 0.1f); |
MikamiUitOpen | 0:c5b026c2d07e | 123 | } |
MikamiUitOpen | 0:c5b026c2d07e | 124 | |
MikamiUitOpen | 0:c5b026c2d07e | 125 | // If touched upper, update: left, freeze: right |
MikamiUitOpen | 0:c5b026c2d07e | 126 | if (pos.y > 120) |
MikamiUitOpen | 0:c5b026c2d07e | 127 | { |
MikamiUitOpen | 0:c5b026c2d07e | 128 | if (pos.x <160) update = false; |
MikamiUitOpen | 0:c5b026c2d07e | 129 | else update = true; |
MikamiUitOpen | 0:c5b026c2d07e | 130 | } |
MikamiUitOpen | 0:c5b026c2d07e | 131 | |
MikamiUitOpen | 0:c5b026c2d07e | 132 | if (update) |
MikamiUitOpen | 0:c5b026c2d07e | 133 | { |
MikamiUitOpen | 0:c5b026c2d07e | 134 | printf("\r\n%d, %d", pos.x, pos.y); |
MikamiUitOpen | 0:c5b026c2d07e | 135 | if ( (pos.x != 320) && (pos.y != 0) |
MikamiUitOpen | 0:c5b026c2d07e | 136 | && (pos.y < 120) ) // Touched lower? |
MikamiUitOpen | 0:c5b026c2d07e | 137 | { |
MikamiUitOpen | 0:c5b026c2d07e | 138 | if (pos.x < 107) touchNow = 2; |
MikamiUitOpen | 0:c5b026c2d07e | 139 | else if (pos.x < 213) touchNow = 1; |
MikamiUitOpen | 0:c5b026c2d07e | 140 | else touchNow = 0; |
MikamiUitOpen | 0:c5b026c2d07e | 141 | |
MikamiUitOpen | 0:c5b026c2d07e | 142 | if (touchNow != touchBefore) touchBefore = touchNow; |
MikamiUitOpen | 0:c5b026c2d07e | 143 | } |
MikamiUitOpen | 0:c5b026c2d07e | 144 | |
MikamiUitOpen | 0:c5b026c2d07e | 145 | // Spectrum analysis |
MikamiUitOpen | 0:c5b026c2d07e | 146 | if (touchNow < 2) fft_.Execute(xn, db); |
MikamiUitOpen | 0:c5b026c2d07e | 147 | else lpc_.Execute(xn, db); |
MikamiUitOpen | 0:c5b026c2d07e | 148 | |
MikamiUitOpen | 0:c5b026c2d07e | 149 | if (touchNow == 0) disp.BarChart(db, offset); |
MikamiUitOpen | 0:c5b026c2d07e | 150 | else disp.LineChart(db, offset); |
MikamiUitOpen | 0:c5b026c2d07e | 151 | |
MikamiUitOpen | 0:c5b026c2d07e | 152 | disp.DisplayVolume(volume_); // Display volume of input |
MikamiUitOpen | 0:c5b026c2d07e | 153 | } |
MikamiUitOpen | 0:c5b026c2d07e | 154 | |
MikamiUitOpen | 0:c5b026c2d07e | 155 | wait(0.1f); |
MikamiUitOpen | 0:c5b026c2d07e | 156 | analysisOk_ = false; |
MikamiUitOpen | 0:c5b026c2d07e | 157 | } |
MikamiUitOpen | 0:c5b026c2d07e | 158 | } |
MikamiUitOpen | 0:c5b026c2d07e | 159 | |
MikamiUitOpen | 0:c5b026c2d07e | 160 |