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

Committer:
MikamiUitOpen
Date:
2015-07-26
Revision:
0:c5b026c2d07e

File content as of revision 0:c5b026c2d07e:

//--------------------------------------------------------------
// Spectrum analyzer
//      input               PC_3
//      sampling frquency   10 kHz
//      window              Hamming window
//      number of data      240 points
//      number of FFT       512 points
//      preemphasis         1st-order difference
//
// Touch pannel
//      upper ---- left:   update display
//                 right:  freeze display
//      lower ---- left:   bar chart of FFT
//                 center: line chart of FFT
//                 right:  line chart of linear prediction
// When you touch the touch pannel, PZT speaker connected PB_1
// sounds "pi" generated using PWM object.
//
// 2015/07/25, Copyright (c) 2015 MIKAMI, Naoki
//--------------------------------------------------------------

#include "ADC_Interrupt.hpp"    // for ADC using interrupt
#include "FFT_Analysis.hpp"
#include "SpectrumDisplay.hpp"
#include "LPC_Analysis.hpp"

using namespace Mikami;

const int N_FFT_ = 512;     // number of date for FFT
const int N_DATA_ = 240;    // number of data to be analyzed 

const int X0_ = 36;         // Origin for x axis
const int Y0_ = 200;        // Origin for y axis
const float DB1_ = 2.8f;    // Pixels for 1 dB
const int BIN_ = 1;         // Pixels per bin
const int MAX_DB_ = 60;     // Maximum dB

const int FS_ = 10000;      // Sampling frequency: 10 kHz

// Pointer of object for using Seeed Studio 2.8" TFT Touch Shield V2.0
SeeedStudioTFTv2* lcd_;

ADC_Intr adc_(PC_3, FS_);   // for external mic connected with PC3
PeakHolder mag_(0.9998f);   // for input volume
FftAnalyzer fft_(N_DATA_, N_FFT_);
LpcAnalyzer lpc_(N_DATA_, 16, N_FFT_);

float volume_ = 0;
float bufIn_[N_DATA_];      // Buffer for input signal
volatile bool analysisOk_;

PwmOut sound_(PB_1);
Timeout off_;

void IsrTimeout() { sound_.write(0); }

// Interrupt service routine for ADC
void AdcIsr()
{
    static int count = 0;   // counter of input buffer

    bufIn_[count] = adc_.Read(); // Read from PC_3
    volume_ = mag_.Execute(fabs(bufIn_[count]));

    if (++count >= N_DATA_)
    {
        count = 0;
        analysisOk_ = true;      // This permits to FFT analysis
    }
}

int main()
{
    lcd_ = new SeeedStudioTFTv2 (A3, A1, A2, A0,   // X+, X-, Y+, Y-
                                 D11, D12, D13,    // MOSI, MISO, SCLK
                                 D5, D6, D7, D4);  // CS_TFT, DC_TFT, BL_TFT, CS_SD

    SpectrumDisplay disp(lcd_, N_FFT_, X0_, Y0_,
                         DB1_, BIN_, MAX_DB_, FS_);

    analysisOk_ = false;
    adc_.SetIntrVec(AdcIsr);    // Assign ISR for ADC interrupt
    sound_.period_us((int)(1.0e6f/4000.0f));


    int touchBefore = 0;
    int touchNow = 0;
//    bool runBefore = true;
    bool update = true;
    float xn[N_DATA_];      // data to be analyzed
    float db[N_FFT_/2+1];   // Log powerspectrum

//    Timer tim;
    while (true)
        if (analysisOk_)
        {
            // Sampled signals to working area
            for (int n=0; n<N_DATA_; n++)
                xn[n] = bufIn_[n];

//            tim.reset();
            // Read touched Position
            NVIC_DisableIRQ(ADC_IRQn);
            point pos;      // Touched position

//            tim.start();
            lcd_->getPixel(pos);
//            tim.stop();

            adc_.Select1stChannel();
            NVIC_ClearPendingIRQ(ADC_IRQn);
            NVIC_EnableIRQ(ADC_IRQn);
//            printf("Execution time: %d micro seconds\r\n", tim.read_us());

            // Display log spectrum
            float offset = 30;
            
            // Sound "pi" 0.1 seconds
            if ( (pos.x != 320) && (pos.y !=0) )
            {
                sound_.write(0.5f);
                off_.attach(&IsrTimeout, 0.1f);
            }
            
            // If touched upper, update: left, freeze: right
            if (pos.y > 120)
            {
                if (pos.x <160) update = false;
                else            update = true;
            }
            
            if (update)
            {
                printf("\r\n%d, %d", pos.x, pos.y);
                if ( (pos.x != 320) && (pos.y != 0)
                                    && (pos.y < 120) )    // Touched lower?
                {
                    if (pos.x < 107) touchNow = 2;
                    else if (pos.x < 213) touchNow = 1;
                        else              touchNow = 0;

                    if (touchNow != touchBefore) touchBefore = touchNow;
                }

                // Spectrum analysis
                if (touchNow < 2) fft_.Execute(xn, db);
                else              lpc_.Execute(xn, db);

                if (touchNow == 0) disp.BarChart(db, offset);
                else               disp.LineChart(db, offset);

                disp.DisplayVolume(volume_);    // Display volume of input
            }

            wait(0.1f);
            analysisOk_ = false;
        }
}