Qt/real time App for ESP32 CODE

CODE documentation

(Header only files )
headers

mainwindow.h

            #ifndef MAINWINDOW_H
            #define MAINWINDOW_H

            #include < QDial >
            #include < QSerialPort >
            #include < QSerialPortInfo >
            #include < QMainWindow >

            #include "filterlpf.h"
            #include "stat_proc.h"
            #include "frequency_dom.h"


            QT_BEGIN_NAMESPACE
            namespace Ui { class MainWindow; }
            QT_END_NAMESPACE

            class MainWindow : public QMainWindow
            {
                Q_OBJECT

            public:
                MainWindow(QWidget *parent = nullptr);
                ~MainWindow();

            private:
                Ui::MainWindow *ui;


                // Port opening global. vars ..
                QSerialPort *esp32;
                filterLPF* LPF;
                stat_proc* HIST;
                stat_proc* HIST2;

                frequency_dom* FFT;


                QByteArray serialData;
                QString serialBuffer;


                QVector ti,s;            // time, signal
                QVector x_vec,y_vec;     // processed time signal ...

                QVector y_hist;          // probability vector

                QVector xf, yf;          //
                QVector x_b, y_b, t_b;    // buffered measurement

                // ESP32 specific IDENTIFICATION
                static const int ESP32_VENDOR = 4292;
                static const int ESP32_PID    = 60000;



            private slots:

                int  on_sliderMoved();
                void on_submitPresets();

              // serial related::
                void scan_ports();
                void read_serial_data();
                void stop_serial_connection();


              // plotting related::
                void plot_rt_input(QVector, QVector);
                void plot_rt_input_processed(QVector, QVector);
                void plot_rt_hist(QVector,QVector);
                void plot_rt_hist_2(QVector,QVector);

              // action control
              void interrupter();


              // label setter
              void set_hist_labels(double, double, double);

                void on_pushButton_released();
            };
            #endif // MAINWINDOW_H


            

mainwindow.cpp

    MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);


    ui->hSliderBaud->setMinimum(1);
    ui->hSliderBaud->setMaximum(8);
    ui->hSliderBaud->setValue(8);



    //|||||||| Set Default Baud Rate to 115200

    ui->lblBitRate->setText(QString("%1").arg(115200));
    ui->edtBufferSize->setText("1800");
    ui->edtVectorSize->setText("250");
    ui->listWidget->addItem("Application ready... ");


     // set dB slider

     ui->dialSGain->setMinimum(-30);
     ui->dialSGain->setMaximum(30);
     ui->dialSGain->setValue(0);


     //||| Initialize serial port...


     //||| PLOT SETUPS
     // setup the plot_1
     ui->plot_1->addGraph(0);
     ui->plot_1->graph(0)->setPen(QPen(Qt::darkBlue, 0.8));

     ui->plot_2->addGraph(0);
     ui->plot_2->graph(0)->setPen(QPen(Qt::darkRed, 0.7));



     // MEASUREMENT SECTION
     //BUFFERING
     int BSize = ui->edtBufferSize->text().toInt();  // take the value from edit window

     ui->pBarBuffering->setMinimum(0);
     ui->pBarBuffering->setMaximum(BSize);

     ui->radLPF->setAutoExclusive(false);
     ui->radPP->setAutoExclusive(false);
     ui->radHist->setAutoExclusive(false);


    //|||||CONNECTIONS
    connect(ui->hSliderBaud, SIGNAL(valueChanged(int)), SLOT(on_sliderMoved()));
    connect(ui->cmdSubmit, SIGNAL(clicked()), SLOT(on_submitPresets()));
    connect(ui->cmdStopSerial, SIGNAL(clicked()), SLOT(stop_serial_connection()));


}// end of constructor


MainWindow::~MainWindow()
{
    delete ui;
    delete esp32;
    delete LPF;
    delete FFT;
}
  

    //[1] baud rate ..
    int MainWindow::on_sliderMoved()
    {    
       ui->listWidget->takeItem(ui->listWidget->currentRow());
    // baud rate presets:    
    
       // {9600, 14400, 19200, 38400, 57600, 115200};
        /*
        QSerialPort::Baud1200	1200	1200 baud.
        QSerialPort::Baud2400	2400	2400 baud.
        QSerialPort::Baud4800	4800	4800 baud.
        QSerialPort::Baud9600	9600	9600 baud.
        QSerialPort::Baud19200	19200	19200 baud.
        QSerialPort::Baud38400	38400	38400 baud.
        QSerialPort::Baud57600	57600	57600 baud.
        QSerialPort::Baud115200	115200	115200 baud.
        */
       int baud[] = {1200, 2400, 4800, 9600, 19200, 38400, 57600,115200};
    
        // reading baud rate from slider ..
        int w = ui->hSliderBaud->value();
        ui->lblBitRate->setText(QString("%1").arg(baud[w-1]));
        int baudRate = baud[w-1];
      
        // output to application window ...
        QString output = "Baud rate has been set to: " + QString::number(baudRate) + " bits/s";
        ui->listWidget->addItem(output);
      
        return baud[w-1];
          
        }
        
        //[2] ... when serial setup is pressed ..
        
        void MainWindow::on_submitPresets()
        {
        
            QString bufferSize = ui->edtBufferSize->text();
            QString VectorSize = ui->edtVectorSize->text();
        
            ui->listWidget->takeItem(ui->listWidget->currentRow());
            QString output = "Number of symbols in a buffer: " + bufferSize+ " (signs)\n";
                    output +="Size of vector: " + VectorSize;
        
            ui->listWidget->clear();
            ui->listWidget->addItem(output);
            on_sliderMoved();
            scan_ports();
        
        }
        
        //[3] ... san the ports
        
  
        void MainWindow::scan_ports()
        {
          qInfo()<<"ports scanning.. ";
          /*
            *  TESTING CODE FOR OPEN PORTS
          */
        
        
            qDebug() << "Descirption available ports:"  << QSerialPortInfo::availablePorts().length() <<"\n";
        
              foreach(const QSerialPortInfo& serialPortInfo, QSerialPortInfo::availablePorts() )
              {
                      qDebug() << "||||||||||||||||||||||||||||||||||||||||Serial ports information: \n";
                      qDebug() << "No.of available ports:"  << QSerialPortInfo::availablePorts().length();
                      qDebug() << "Has vendor ID        :"  << serialPortInfo.hasVendorIdentifier();
                      qDebug() << "Vendor ID            :"  << serialPortInfo.vendorIdentifier();
                      qDebug() << "Has Product ID       :"  << serialPortInfo.hasProductIdentifier();
                      qDebug() << "Product ID           :"  << serialPortInfo.productIdentifier();
        
              }
        
        
            QString port_info = "No. Available ports: " +QString::number( QSerialPortInfo::availablePorts().length());
        
            foreach(const QSerialPortInfo& serialPortInfo, QSerialPortInfo::availablePorts() )
            {
        
                port_info += "\nHas vendor ID \t: "  + QString::number( serialPortInfo.hasVendorIdentifier()) ;
                port_info += "\nVendor \t: "  + QString::number( serialPortInfo.vendorIdentifier());
                port_info += "\nHas Product ID\t: "  + QString::number( serialPortInfo.hasProductIdentifier());
                port_info += "\nProduct ID\t: "  + QString::number( serialPortInfo.productIdentifier());
            }
 
        
            ui->listWidget->addItem(port_info);
        
            //|||| DETECT THE ESP32 MODEL
            bool esp32_available =false;
            QString espPortName;
        
                // for each available of serial ports
                foreach(const QSerialPortInfo& serialPortInfo, QSerialPortInfo::availablePorts())
                {
                    if(serialPortInfo.hasProductIdentifier() && serialPortInfo.hasVendorIdentifier())
                    { // if hardvare has vendor and product id
        
                        if(serialPortInfo.productIdentifier() == ESP32_PID && serialPortInfo.vendorIdentifier() == ESP32_VENDOR)
                        { // confirm there is ESP 32 at the port
                            esp32_available = true;
                            qDebug() << "\t\t ESP 32 ... microcontroller found";
                            espPortName = serialPortInfo.portName();
                            qDebug() << "\t\t At the active port:" << espPortName;
                            ui->listWidget->addItem("ESP32 Found at port: " + espPortName);
                        }
                    }
                }
        
        
          //||| IF ESP32 HAS BEEN DETECTED
            if(esp32_available)
            {
                // now open and configure ESP32 port ...
                qDebug()<< "Found ESP port .. \n ";
        
                int BRATE = on_sliderMoved();
                qInfo()<<"Baud Rate : " << BRATE;
        
                esp32 =  new QSerialPort();
                esp32->setPortName(espPortName);
                esp32->open(QSerialPort::ReadOnly);
        
                switch (BRATE)
                {
        
                case 1200: esp32->setBaudRate(QSerialPort::Baud1200);
                    break;
                case 2400: esp32->setBaudRate(QSerialPort::Baud2400);
                    break;
                case 4800: esp32->setBaudRate(QSerialPort::Baud4800);
                    break;
                case 9600: esp32->setBaudRate(QSerialPort::Baud9600);
                    break;
                case 19200: esp32->setBaudRate(QSerialPort::Baud19200);
                    break;
                case 38400: esp32->setBaudRate(QSerialPort::Baud38400);
                    break;
                case 57600: esp32->setBaudRate(QSerialPort::Baud57600);
                    break;
                case 115200: esp32->setBaudRate(QSerialPort::Baud115200);
                    break;
                default:
                    esp32->setBaudRate(QSerialPort::Baud115200);
                    break;
                }
        
                esp32->setDataBits(QSerialPort::Data8);
                esp32->setFlowControl(QSerialPort::NoFlowControl);
                esp32->setParity(QSerialPort::NoParity);
                esp32->setStopBits(QSerialPort::OneStop);
        
                //|||NOW START READING DATA
                QObject::connect(esp32, SIGNAL(readyRead()), this, SLOT(read_serial_data()));   //| this is where you call readSerial()
                LPF = new filterLPF();
                //LPF->pingMe();
        
                // histogram processing
        
                HIST = new stat_proc();
                HIST2 = new stat_proc();
                ui->plot_3->addGraph();
                  ui->plot_3->addGraph();
                ui->plot_4->addGraph();

                  // this par was never utilized ... 
                FFT = new frequency_dom();
        
            }
            else
            {
                qDebug() << "Could not find the correct port for esp \n ";
                QMessageBox::information(this, "Serial Port Error", "Couldn't open seral port of a device ...   ");
        
            }
    
          } //:: end of fn
       
        
buffering process buffering process fifo principle
    
//[4] Real- time processing
//|||||||||||||
//|||||||||||||
//|||||||||||||
//|||||||||||||
//|||||||||||||

void MainWindow::read_serial_data()
{


    // PRESETS
    //|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
    // SET LABEL TO Input processing plot
    if(ui->radPP->isChecked()){ ui->lblInputProc->setText("ON");}
    else if( !ui->radLPF->isChecked()){ui->lblInputProc->setText("OFF");}



    // RED THE GAIN
    //|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
    double gain = ui->dialSGain->value();           //| gain in dB
    ui->lblGain->setText(QString::number(gain));    //| set the user input to the screen



    clock_t c1, c2; // start the clock
    //|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
    //|||| Buffer size is set in UI and here is to be read again ...
        QString b_size = ui->edtBufferSize->text();
        int BUFFER_SIZE = b_size.toDouble();

    //||| int CLR_L= ui->lblValuesBuffer->text().toInt(); // when to pop front the value from the vectro
        QString clr_l = ui->edtVectorSize->text();
        int clear_size = clr_l.toInt();

          serialData = esp32->readAll();
          serialBuffer += QString::fromStdString(serialData.toStdString());   //| accumulating to buffer

            static int i  = 0;   //| static counter of buffers
            static int j  = 0;   //| static counter of index values in a buffer


    c1 = clock(); // sart clock


   //|||| BUFFERING TO BUFFER SIZE
    if(serialBuffer.size()>BUFFER_SIZE)
    {    i++; // count the buffers in total
         QStringList li = serialBuffer.split("*");  // splitting sign

         // read how many symbols are in the buffer and plot to UI
             ui->lblBuffer->setText(QString::number(serialBuffer.length()));
             ui->lblValuesBuffer->setText(QString::number(li.length()));
             ui->lblCountBuffers->setText(QString::number(i));

         // Push the values from the list to vectors
         for(int k = 0; k < li.length(); k++)
         {
             double value = li[k].toDouble();

                 //=========================================================================================
                 //| POST PROCESSING CHAIN
                 //|........................................................................................
                 //|
                 //|           o----->| GAIN | o----> | Sampling FREQ| o----> | LPF | o---> | STAT |
                 //|
                 //=========================================================================================
                 if(ui->radPP->isChecked())
                 {

                     //||  "X -Axis"
                     //||  IF TIME DOMAIN ON/OFF ...

                         if(ui->radTimSignal->isChecked())
                         {
                             ui->lblDom->setText("time");
                             double dt = 1/ ui->edtFS->text().toDouble();
                             x_vec.push_back((double)j*dt);

                         }else if(ui->radTimSignal->isCheckable())
                         {
                             ui->lblDom->setText("samples");
                                x_vec.push_back((double)j);
                         }

                     //|| "Y - Axis"
                     //|| FOR SIGNAL Filtering ...
                     //|| checek weather checke: if filter is on ... and if cutoff frequency is provided
                         double gain_db = ui->dialSGain->value();
                         ui->lcdRead->display(QString::number(gain_db));
                         double GAIN = pow(10,gain_db/10.0);

                         // FILTER LPF
                         if(ui->radLPF->isChecked() &&
                                 ui->edtFC->text().isEmpty() == false &&
                                 ui->edtFS->text().isEmpty()==false)
                         {
                             double fc, fs, f_value;

                                 // pick up the value from the UI
                                  fc = ui->edtFC->text().toDouble();

                                  // entered by the user ...
                                  fs = ui->edtFS->text().toDouble();

                                 // filtering of a signal
                                 LPF->setCoeffs(fc, fs);
                                 f_value = LPF->filter(value, fc, fs);
                                 y_vec.push_back( LPF->gain(f_value,GAIN));


                        //|| - STATISTICAL MEASUREMENT PROCESSING ...
                        //||
                        //|| FOR STAT PROCESSING:: UI - Inputs taken
                        //||
                        //||=========================================================================================

                                 double min, max, N;

                                // show the inputs ..........................................
                                 N = ui->edtStatN->text().toDouble();

                                 min = ui->edtStatMIN->text().toDouble();
                                 max = ui->edtStatMAX->text().toDouble();

                                // show the inputs to parameter labels
                                  ui->lbl_stat_classes->setText(QString::number(N));
                                  ui->lbl_stat_min->setText(QString::number(min));
                                  ui->lbl_stat_max->setText(QString::number(max));

                                // calculate class and step 'd'
                                  double span = max - min;
                                  double d    = span/N;

                                // show class and step to parameter labels
                                  ui->lblHSpan ->setText(QString::number(span));
                                  ui->lblCWidth->setText(QString::number(d));


                            //||=========================================================================================
                            //|| do statistics on filtered values ...

                                  double val = LPF->gain(f_value,GAIN);
                                  ui->lblBuffFull->setText(QString::number(HIST->x.size()));

                                  if(ui->radHist->isChecked())
                                  {

                                       set_hist_labels(N, min, max);
                                       double buff_max = ui->edtSamples->text().toDouble(); // buffer maximum
                                       ui->pBarBuffering->setMaximum(buff_max);

                                       //HIST->hist(val, ui->edtStatN->text().toDouble(), min, max);
                                       HIST2->hist(val, ui->edtStatN->text().toDouble(), min, max);
                                       ui->pBarBuffering->setValue(HIST2->x.size());

                                            if(buff_max == HIST2->x.length())
                                            {
                                                interrupter();
                                            }
                                            else if(HIST2->x.length() > buff_max)    // if number exceeds the given size .. clean hist vector "NAsty error !"
                                            {
                                                HIST2->x.clear();
                                                HIST2->h.clear();
                                            }


                                      }else if(ui->radHist->isCheckable())               // when measurement turned off , clean histogram vectors
                                      {
                                          HIST2->x.clear();
                                          HIST2->h.clear();
                                      }

                          }
                         else
                         {
                             //|| Only processing is on ...ie. GAIN/ NO FILTERING
                             //||
                             //||=========================================================================================

                                y_vec.push_back( value*GAIN);


                             //|| take the user values from UI
                                double N   = ui->edtStatN->text().toDouble();        // take number of bins
                                double min = ui->edtStatMIN->text().toDouble();      // take minimum
                                double max = ui->edtStatMAX->text().toDouble();      // take maximum
                                double buff_max = ui->edtSamples->text().toDouble(); // buffer maximum
                                set_hist_labels(N, min, max);                        // set them around the plot_3


                             if(ui->radHist->isChecked())
                             {

                                HIST->hist(value*GAIN, N, min, max);


                                ui->lblBuffFull->setText(QString::number(HIST->x.size()));
                                ui->pBarBuffering->setMaximum(buff_max);
                                ui->pBarBuffering->setValue(HIST->x.size());

                                // when buffer is filled

                                    if(buff_max == HIST->x.length())
                                    {
                                        // interrupt all, to plot and clear vectors
                                        // reconnect.. then proceed

                                        interrupter();

                                    }
                                    else if(HIST->x.length() > buff_max)
                                    {
                                        HIST->x.clear();
                                        HIST->h.clear();
                                    }
                             }
                             else if(ui->radHist->isCheckable())
                             {
                                 HIST->x.clear();
                                 HIST->h.clear();

                             }
                         }


                         // CLEAN VECTORS WHEN FULL
                         if(x_vec.length()>clear_size && y_vec.length()>clear_size)
                            {
                                 x_vec.pop_front();
                                 y_vec.pop_front();
                             }


                 }
                 else if(ui->radPP->isCheckable())
                 {
                     // if pre-processing has been turned off ...
                     ui->lblDom->setText("samples");
                 }


             //=========================================================================================
             // NON PROCESSED VALUES
             //=========================================================================================

                     s.push_back(value);
                         j++;                                // push the signal value to the vector 's'
                         ti.push_back((double)j);            // write an index to the time vector


                     if(s.length()>clear_size && ti.length()>clear_size)
                     {
                         s.pop_front();
                         ti.pop_front();
                     }

          }// end of vector manipulations ...


         //|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
         //||| BUFFER CLEANING
         serialBuffer.clear();
         li.clear();


         //||| CLOCK measurment end/  time for a buffer ...
         c2 = clock();
         double t_buffer = (double)(c2-c1)/CLOCKS_PER_SEC;
         ui->lblBtime->setText(QString::number(t_buffer));


         //||| Plotting the results to plot_1
         plot_rt_input(ti, s);


         // if radio button is checked .. plot either same inputs
         // either processed rt inputs ...

             if( ui->radPP->isChecked()){


                 plot_rt_input_processed(x_vec,y_vec);


             }else if(!ui->radPP->isChecked())
             {
                 plot_rt_input_processed(ti,s);

             }
      }

  }
  
    
//||| CLOSE SERIAL CONNECTION
void MainWindow::stop_serial_connection()
{


    esp32->close();                            // close the port
    if(HIST != nullptr)
    {

        delete HIST;
        qInfo()<< "Histogram deleted...";
    }


    if(HIST2 != nullptr)
    {

        delete HIST2;
        qInfo()<< "Histogram 2 deleted...";
    }

    if(LPF!= nullptr)
    {
        qInfo()<< "LPF deleted";
        delete LPF;
    }

    if(esp32 != nullptr)
    {
        qInfo()<< "port deleted";
        delete esp32;
    }



    if(FFT != nullptr)
    {
        qInfo()<<"frequency domain object deleted ... ";
        delete FFT;
    }


    ti.clear();
    s.clear();

    ui->listWidget->clear();
    ui->listWidget->addItem("Serial connection stopped... ");

}

  
    
// INTERRUPTER OF MEASUREMENT ...
void MainWindow::interrupter()
{

    esp32->close();

    if(!HIST->x.isEmpty()) // ako je histogram 1 pun, isplotaj, pobrisi ga
     {

        //qInfo()<<"Highest histogram value is befor plotting :" << HIST->histMaxVal();
        plot_rt_hist(HIST->x, HIST->h);

        HIST->x.clear();
        HIST->h.clear();
    }


    if(! HIST2->x.isEmpty())
    { // HIST 2 has been used

            //plot_rt_hist_2(HIST->x, HIST->h);
            plot_rt_hist_2(HIST2->x, HIST2->h);

            HIST->x.clear();
            HIST->h.clear();

    }


    scan_ports();
}


  
// PLOTTING FUNCTIONS
void MainWindow::plot_rt_input(QVector ti, QVector s)
{
    ui->plot_1->graph(0)->setData(ti, s);

        ui->plot_1->xAxis2->setVisible(true);
        ui->plot_1->xAxis2->setTickLabels(false);
        ui->plot_1->yAxis2->setVisible(true);
        ui->plot_1->yAxis2->setTickLabels(false);


        ui->plot_1->yAxis->setLabel("Input: x");
        ui->plot_1->xAxis->setLabel("[sample] ");


    ui->plot_1->rescaleAxes();

     double max_val = *std::max_element(s.constBegin(), s.constEnd());
     ui->plot_1->yAxis->setRange(-3*max_val, 3*max_val);


    ui->plot_1->replot();
    ui->plot_1->update();

}



void MainWindow::plot_rt_hist(QVector x, QVector h )
{

    ui->plot_3->graph(0)->setData(x, h);
    ui->plot_3->graph(0)->setLineStyle((QCPGraph::LineStyle)2);

        ui->plot_3->xAxis2->setVisible(true);
        ui->plot_3->xAxis2->setTickLabels(false);
        ui->plot_3->yAxis2->setVisible(true);
        ui->plot_3->yAxis2->setTickLabels(false);


        ui->plot_3->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
        ui->plot_3->legend->setVisible(false);
        ui->plot_3->yAxis->setLabel("Histogram");
        ui->plot_3->xAxis->setLabel("  ");

        ui->plot_3->rescaleAxes();
        ui->plot_3->yAxis->setRange(-0.1*HIST->histMaxVal(), HIST->histMaxVal()*1.2);


    ui->plot_3->replot();
    ui->plot_3->update();
}

void MainWindow:: plot_rt_hist_2(QVector x,QVector h)
{


    ui->plot_4->graph(0)->setPen(QPen(Qt::red));
    ui->plot_4->graph(0)->setData(x, h);
    ui->plot_4->graph(0)->setLineStyle((QCPGraph::LineStyle)2);

        ui->plot_4->xAxis2->setVisible(true);
        ui->plot_4->xAxis2->setTickLabels(false);
        ui->plot_4->yAxis2->setVisible(true);
        ui->plot_4->yAxis2->setTickLabels(false);


          ui->plot_4->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
          ui->plot_4->legend->setVisible(false);
          ui->plot_4->yAxis->setLabel("Histogram");
          ui->plot_4->xAxis->setLabel(" ");

    ui->plot_4->rescaleAxes();    
    ui->plot_4->yAxis->setRange(-0.1*HIST2->histMaxVal(), HIST2->histMaxVal()*1.2);
    ui->plot_4->replot();
    ui->plot_4->update();
}

void MainWindow::plot_rt_input_processed(QVector x, QVector y)
{
    ui->plot_2->graph(0)->setData(x, y);

      ui->plot_2->xAxis2->setVisible(true);
      ui->plot_2->xAxis2->setTickLabels(false);
      ui->plot_2->yAxis2->setVisible(true);
      ui->plot_2->yAxis2->setTickLabels(false);

      ui->plot_2->yAxis->setLabel("Output: y");
      ui->plot_2->xAxis->setLabel(ui->lblDom->text()+"[s]");


      double max_val = *std::max_element(s.constBegin(), s.constEnd());

      ui->plot_2->rescaleAxes();
      ui->plot_2->yAxis->setRange(-3*max_val, 3*max_val);


    ui->plot_2->replot();
    ui->plot_2->update();
}

void MainWindow::set_hist_labels(double N, double min, double max)
{
    double span = max - min;
    ui->lblHSpan->setText(QString::number(span));
    ui->lbl_stat_classes->setText(QString::number(N));
    ui->lbl_stat_min->setText(QString::number(min));
    ui->lbl_stat_max->setText(QString::number(max));
    ui->lblCWidth->setText(QString::number(span/N));
}



void MainWindow::on_pushButton_released()
{
    MainWindow::close();
}

User interface elements

UI elements

filterlpf.h

#ifndef FILTERLPF_H
#define FILTERLPF_H

#include < Object >
#include < QDebug >

// filter coefficients for BIQUAD type
struct Coeff
{
        double a1,a2;
        double b0,b1,b2;

};

// difference equation of a filter ...
struct DEQ
{
    //set up the coefficients

    double b0,b1,b2;
    double a1,a2;

    // set up the x[n-1], x[n-2] ...
    double x1,x2;
    double y0,y1,y2;

    double process(const Coeff& fltCoeff, double x0)
    {

     // read in the coefficients
       b0 = fltCoeff.b0;
       b1 = fltCoeff.b1;
       b2 = fltCoeff.b2;

       a1 = fltCoeff.a1;
       a2 = fltCoeff.a2;

       y0 = b0*x0 + b1*x1 + b2*x2 - a1*y1 -a2*y2;

       x2 = x1;
       x1 = x0;
       y2 = y1;
       y1 = y0;
       return y0;
    }
};


// filterLPF called from the heap ...
class filterLPF : public QObject
{
    Q_OBJECT

private:
    #define PI 3.14159265358979323846;
    double a1,a2;
    double b0,b1,b2;


public:

    explicit filterLPF(QObject *parent = nullptr); // constructor

    Coeff coeff;                                   // has one structure of coefficients
    DEQ   diffEq;                                  // has one difference equation biquad system


    Coeff LPF_butter(double, double);              // returns full filter structure
    void setCoeffs(double, double);                // sets coefficients
    void getCoeffs();                              // types the coefficients to console

    // run the difference equation
    double gain(double x0, double gain);           // gain the signal after filtering
    double filter(double x0, double, double);      // utilize the whole filter


};

/* inside of MAIN thread ... use this as follows
 * Application note...
 *
 * #include "filterlpf.h"
 *
 *
 * // create somwhere ...
  filterLPF* LPF = new FilteLPF();

  LPF->setCoeffs(10, 1e3);
  LPF->getCoeffs();             // if to be noticed

  some loop ...should take place for utilizing difference equation ...

   while()
   {
       double x = sin(12*PI*f*dt);

       double y1 = LPF-> filter(x, 10, 1e3); fitler the signal
       double y2 = LPF->gain(f_value,GAIN);  amplify the stuff ..

            }

            delete LPF;

*/





#endif // FILTERLPF_H





  

filter.cpp

  #include "filterLPF.h"
#include < cmath >

filterLPF::filterLPF(QObject *parent) : QObject(parent)
{
 qInfo()<< "Filter Object has been created";

}


//||||| Calculate coefficients for the butterworth filter
Coeff filterLPF::LPF_butter(double fc, double fs)
{
    Coeff LPF;
    const double ita =1.0/ tan(M_PI*fc/fs);
    const double q=sqrt(2.0);
    LPF.b0 =  1.0 / (1.0 + q*ita + ita*ita);
    LPF.b1 =  2*LPF.b0;
    LPF.b2 =  LPF.b0;
    LPF.a1 = -2.0 * (ita*ita - 1.0) * LPF.b0;
    LPF.a2 = (1.0 - q*ita + ita*ita) * LPF.b0;
    return LPF;
}


//||||| Set cofficients
void filterLPF::setCoeffs(double fc, double fs)
{
    Coeff K = LPF_butter( fc, fs);
    a1 = K.a1;
    a2 = K.a2;
    b0 = K.b0;
    b1 = K.b1;
    b2 = K.b2;
}



// GET Coefficients
void filterLPF::getCoeffs()
{
    qInfo()<< "a1" << this->a1;
    qInfo()<< "a2" << this->a2;
    qInfo()<< "b0" << this->b1;
    qInfo()<< "b1" << this->b1;
    qInfo()<< "b2" << this->b2;


}

// LPF utilization
double filterLPF::filter(double x0, double fc, double fs)
{
    return diffEq.process(LPF_butter(fc,fs), x0);
}

// GAINs the signal ...
double filterLPF::gain(double x0, double factor)
{
    double y0 = x0*factor;
    return y0;
}

stat_proc.h

#ifndef STAT_PROC_H
#define STAT_PROC_H

#include < QObject >



// now push the value throught the whole class ...
// and count the correspondent number within each
/*
 * histogram builder .. .
          i=0,  0-1 : *        | bin_l = 0 | bin_h = 1 | d = 1 |
                1-2 : ****     | bin_l = 1 | bin_h = 2 | d = 1 |
                2-3 : *********
                3-4 : ***************
                4-5 : ******************
          i*d,  5-6 : *******************
                6-7 : ***************
                7-8 : ********
                8-9 : ****
          i=N,  9-10: *
 *
 */


class stat_proc : public QObject
{
    Q_OBJECT


public:

    QVector<double >              // histogram values ...
    QVector<double > x;              // bin centers ..
    double min, max, d, N;
    explicit stat_proc(QObject *parent = nullptr);

    void sayHello();                // ping and prove class exists ..
    void hist(double,
              int,
              double,
              double);                      // return histogram values to the

    double histMaxVal();                    // return maximum value of histogram
    void typeHist();                        // put the results into console...

};

#endif // STAT_PROC_H

  

stat_proc.cpp

    #include "stat_proc.h"
    #include < QDebug >
    #include < iostream >
    
    
    stat_proc::stat_proc(QObject *parent) : QObject(parent)
    {
        x.clear();
        h.clear();
    }
    
    void stat_proc::sayHello()
    {
          qInfo() << "Stat processor has been initialized.... ";
    }
    
    
    
    // histogram of values given to the ...
    void stat_proc::hist(double val, int N, double min, double max)
    {
        double span = max - min;
        double d   = span/N;
        this->min = min;
        this->max = max;
        this->d   = d;
        this->N   = N;
    
        // fill the global vector h with zeros ..
        for(int i = 0; i < N; i++)
        {
                h.push_back(0.00);
        }
            double bin_l, bin_h, cbin;
            for(int i = 0; i < N; i++)
                {
                    bin_l = min + i*d;              // bin lower edge
                    bin_h = bin_l +d;               // bin higher edge
                    cbin  = (bin_h +bin_l) /2.0;    // cbin .. center of bins ...
    
                    x.push_back(cbin);
                    if(val >= bin_l && val< bin_h)
                    {
                        h[i] += 1;
                    }
                }
    }

    // type histogram from ...
    void stat_proc::typeHist()
    {
    
        double bin_h,bin_l, cbin;
        static int q = 0;
        q++;
    
        if(q==1)
        {
            qInfo() << "-------------------------------------------------";
            qInfo() << "N   :" << this->N ;
            qInfo() << "min :" << this->min;
            qInfo() << "max :" << this->max;
            qInfo() << "step:" << this->d;
            qInfo() << "-------------------------------------------------";
        }
    
        for(int i = 0; isayHello();
             HIST->hist(2.8, 20, -5, 5);
             HIST->hist(2.6, 20, -5, 5);
             HIST->hist(2.67, 20, -5, 5);
             HIST->hist(4.77, 20, -5, 5);
             HIST->typeHist();
     *
     *
     *
    Stat processor has been initialized....
    After streaming ::
    
    -------------------------------------------------
    N   : 20
    min : -5
    max : 5
    step: 0.5
    -------------------------------------------------
    -------------------------------------------------
    1  | -5 : -4.5 	 ||  -4.75 	  3 ||
    2  | -4.5 : -4 	 ||  -4.25 	  3 ||
    3  | -4 : -3.5 	 ||  -3.75 	  3 ||
    4  | -3.5 : -3 	 ||  -3.25 	  2 ||
    5  | -3 : -2.5 	 ||  -2.75 	  3 ||
    6  | -2.5 : -2 	 ||  -2.25 	  4 ||
    7  | -2 : -1.5 	 ||  -1.75 	  18 ||
    8  | -1.5 : -1 	 ||  -1.25 	  202 ||
    9  | -1 : -0.5 	 ||  -0.75 	  711 ||
    10 | -0.5 : 0 	 ||  -0.25 	  1552 ||
    11 | 0 : 0.5 	 ||  0.25 	  1880 ||
    12 | 0.5 : 1 	 ||  0.75 	  1333 ||
    13 | 1 : 1.5 	 ||  1.25 	  417 ||
    14 | 1.5 : 2 	 ||  1.75 	  74 ||
    15 | 2 : 2.5 	 ||  2.25 	  10 ||
    16 | 2.5 : 3 	 ||  2.75 	  7 ||
    17 | 3 : 3.5 	 ||  3.25 	  8 ||
    18 | 3.5 : 4 	 ||  3.75 	  3 ||
    19 | 4 : 4.5 	 ||  4.25 	  9 ||
    20 | 4.5 : 5 	 ||  4.75 	  5 ||
    
    */
  

frequency_dom.h has not been utilizet within this code thoug, still here for the sake of documentation

(Reason: single thread cannot handle it anymore, it chockes the process .. )

      #ifndef FREQUENCY_DOM_H
      #define FREQUENCY_DOM_H

      #include < QObject >
      #include < complex >
      #include < iostream >
      #include < valarray >
      #include < vector >
      #include < cmath >

      using namespace std;


      class frequency_dom : public QObject
      {
          Q_OBJECT
      public:
          explicit frequency_dom(QObject *parent = nullptr);


          const double PI_ = 3.141592653589793238460;

          QVector < double > f;
          QVector < double > y;
          void dft();
      };


     #endif // FREQUENCY_DOM_H


    
      #include "frequency_dom.h"
      #include < QDebug >

      frequency_dom::frequency_dom(QObject *parent) : QObject(parent)
      {
        

      }

      void frequency_dom::dft()
      {
        // defintely need FFT here ... something fast 
        // non of three procedure here has been working fast enough .. what to do ... threads ?

        // see here: FFT Candidates
        // ( that did not pass the test ... and I did not use timers ! :< )

      }