Changeset - 34ecc16e1717
[Not reviewed]
default
0 1 0
Hasan Yavuz Ă–ZDERYA - 10 years ago 2015-07-27 16:01:41
hy@ozderya.net
better error reporting in case of ASCII parsing error
1 file changed with 20 insertions and 4 deletions:
0 comments (0 inline, 0 general)
mainwindow.cpp
Show inline comments
 
@@ -118,395 +118,411 @@ MainWindow::MainWindow(QWidget *parent) 
 
    numberFormatButtons.addButton(ui->rbFloat,  NumberFormat_float);
 
    numberFormatButtons.addButton(ui->rbASCII,  NumberFormat_ASCII);
 

	
 
    QObject::connect(&numberFormatButtons, SIGNAL(buttonToggled(int, bool)),
 
                     this, SLOT(onNumberFormatButtonToggled(int, bool)));
 

	
 
    // init port signals
 
    QObject::connect(&(this->serialPort), SIGNAL(error(QSerialPort::SerialPortError)),
 
                     this, SLOT(onPortError(QSerialPort::SerialPortError)));
 

	
 
    // set limits for axis limit boxes
 
    ui->spYmin->setRange((-1) * std::numeric_limits<double>::max(),
 
                         std::numeric_limits<double>::max());
 

	
 
    ui->spYmax->setRange((-1) * std::numeric_limits<double>::max(),
 
                         std::numeric_limits<double>::max());
 

	
 
    // init data arrays and plot
 

	
 
    numOfSamples = ui->spNumOfSamples->value();
 
    numOfChannels = 1;
 

	
 
    dataX.resize(numOfSamples);
 
    for (int i = 0; i < dataX.size(); i++)
 
    {
 
        dataX[i] = i;
 
    }
 

	
 
    // init channel data and curve list
 
    for (unsigned int i = 0; i < numOfChannels; i++)
 
    {
 
        channelsData.append(DataArray(numOfSamples, 0.0));
 
        curves.append(new QwtPlotCurve());
 
        curves[i]->setSamples(dataX, channelsData[i]);
 
        curves[i]->setPen(makeColor(i));
 
        curves[i]->attach(ui->plot);
 
    }
 

	
 
    // init auto scale
 
    ui->plot->setAxis(ui->cbAutoScale->isChecked(),
 
                      ui->spYmin->value(), ui->spYmax->value());
 

	
 
    // init grid
 
    ui->plot->showGrid(ui->actionGrid->isChecked());
 
    ui->plot->showMinorGrid(ui->actionMinorGrid->isChecked());
 

	
 
    // init number format
 
    if (numberFormatButtons.checkedId() >= 0)
 
    {
 
        selectNumberFormat((NumberFormat) numberFormatButtons.checkedId());
 
    }
 
    else
 
    {
 
        selectNumberFormat(NumberFormat_uint8);
 
    }
 

	
 
    // Init sps (sample per second) counter
 
    sampleCount = 0;
 
    spsLabel.setText("0sps");
 
    spsLabel.setToolTip("samples per second (total of all channels)");
 
    ui->statusBar->addPermanentWidget(&spsLabel);
 
    spsTimer.start(SPS_UPDATE_TIMEOUT * 1000);
 
    QObject::connect(&spsTimer, &QTimer::timeout,
 
                     this, &MainWindow::spsTimerTimeout);
 

	
 
    // Init demo mode
 
    demoCount = 0;
 
    demoTimer.setInterval(100);
 
    QObject::connect(&demoTimer, &QTimer::timeout,
 
                     this, &MainWindow::demoTimerTimeout);
 
    QObject::connect(ui->actionDemoMode, &QAction::toggled,
 
                     this, &MainWindow::enableDemo);
 

	
 
    {   // init demo indicator
 
        QwtText demoText(" DEMO RUNNING ");  // looks better with spaces
 
        demoText.setColor(QColor("white"));
 
        demoText.setBackgroundBrush(Qt::darkRed);
 
        demoText.setBorderRadius(4);
 
        demoText.setRenderFlags(Qt::AlignLeft | Qt::AlignTop);
 
        demoIndicator.setText(demoText);
 
        demoIndicator.hide();
 
        demoIndicator.attach(ui->plot);
 
    }
 

	
 
}
 

	
 
MainWindow::~MainWindow()
 
{
 
    for (auto curve : curves)
 
    {
 
        delete curve;
 
    }
 

	
 
    if (serialPort.isOpen())
 
    {
 
        serialPort.close();
 
    }
 
    delete ui;
 
    ui = NULL; // we check if ui is deleted in messageHandler
 
}
 

	
 
void MainWindow::setupAboutDialog()
 
{
 
    Ui_AboutDialog uiAboutDialog;
 
    uiAboutDialog.setupUi(&aboutDialog);
 

	
 
    QObject::connect(uiAboutDialog.pbAboutQt, &QPushButton::clicked,
 
                     [](){ QApplication::aboutQt();});
 

	
 
    QString aboutText = uiAboutDialog.lbAbout->text();
 
    aboutText.replace("$VERSION_STRING$", VERSION_STRING);
 
    aboutText.replace("$VERSION_REVISION$", VERSION_REVISION);
 
    uiAboutDialog.lbAbout->setText(aboutText);
 
}
 

	
 
void MainWindow::onPortToggled(bool open)
 
{
 
    // make sure demo mode is disabled
 
    if (open && isDemoRunning()) enableDemo(false);
 
    ui->actionDemoMode->setEnabled(!open);
 
}
 

	
 
void MainWindow::onDataReady()
 
{
 
    if (!ui->actionPause->isChecked())
 
    {
 
        // a package is a set of channel data like {CHAN0_SAMPLE, CHAN1_SAMPLE...}
 
        int packageSize = sampleSize * numOfChannels;
 
        int bytesAvailable = serialPort.bytesAvailable();
 

	
 
        if (bytesAvailable > 0 && skipByteRequested)
 
        {
 
            serialPort.read(1);
 
            skipByteRequested = false;
 
            bytesAvailable--;
 
        }
 

	
 
        if (bytesAvailable < packageSize)
 
        {
 
            return;
 
        }
 
        else
 
        {
 
            int numOfPackagesToRead =
 
                (bytesAvailable - (bytesAvailable % packageSize)) / packageSize;
 
            QVector<DataArray> channelSamples(numOfChannels);
 
            for (unsigned int ci = 0; ci < numOfChannels; ci++)
 
            {
 
                channelSamples[ci].resize(numOfPackagesToRead);
 
            }
 

	
 
            int i = 0;
 
            while(i < numOfPackagesToRead)
 
            {
 
                for (unsigned int ci = 0; ci < numOfChannels; ci++)
 
                {
 
                    channelSamples[ci].replace(i, (this->*readSample)());
 
                }
 
                i++;
 
            }
 

	
 
            for (unsigned int ci = 0; ci < numOfChannels; ci++)
 
            {
 
                addChannelData(ci, channelSamples[ci]);
 
            }
 
        }
 
    }
 
    else
 
    {
 
        serialPort.clear(QSerialPort::Input);
 
    }
 
}
 

	
 
void MainWindow::onDataReadyASCII()
 
{
 
    while(serialPort.canReadLine())
 
    {
 
        QByteArray line = serialPort.readLine();
 

	
 
        // discard data if paused
 
        if (ui->actionPause->isChecked())
 
        {
 
            return;
 
        }
 

	
 
        line = line.trimmed();
 
        auto separatedValues = line.split(',');
 

	
 
        if (separatedValues.length() >= int(numOfChannels))
 
        {
 
            for (unsigned int ci = 0; ci < numOfChannels; ci++)
 
            {
 
                double channelSample = separatedValues[ci].toDouble();
 
                addChannelData(ci, DataArray({channelSample}));
 
                bool ok;
 
                double channelSample = separatedValues[ci].toDouble(&ok);
 
                if (ok)
 
                {
 
                    addChannelData(ci, DataArray({channelSample}));
 
                }
 
                else
 
                {
 
                    qWarning() << "Data parsing error for channel: " << ci;
 
                }
 
            }
 
        }
 
        else // there is missing channel data
 
        {
 
            qWarning() << "Incoming data is missing data for some channels!";
 
            for (int ci = 0; ci < separatedValues.length(); ci++)
 
            {
 
                double channelSample = separatedValues[ci].toDouble();
 
                addChannelData(ci, DataArray({channelSample}));
 
                bool ok;
 
                double channelSample = separatedValues[ci].toDouble(&ok);
 
                if (ok)
 
                {
 
                    addChannelData(ci, DataArray({channelSample}));
 
                }
 
                else
 
                {
 
                    qWarning() << "Data parsing error for channel: " << ci;
 
                }
 
            }
 
        }
 
    }
 
}
 

	
 
void MainWindow::onPortError(QSerialPort::SerialPortError error)
 
{
 
    switch(error)
 
    {
 
        case QSerialPort::NoError :
 
            break;
 
        case QSerialPort::ResourceError :
 
            qWarning() << "Port error: resource unavaliable; most likely device removed.";
 
            if (serialPort.isOpen())
 
            {
 
                qWarning() << "Closing port on resource error: " << serialPort.portName();
 
                portControl.togglePort();
 
            }
 
            portControl.loadPortList();
 
            break;
 
        case QSerialPort::DeviceNotFoundError:
 
            qCritical() << "Device doesn't exists: " << serialPort.portName();
 
            break;
 
        case QSerialPort::PermissionError:
 
            qCritical() << "Permission denied. Either you don't have \
 
required privileges or device is already opened by another process.";
 
            break;
 
        case QSerialPort::OpenError:
 
            qWarning() << "Device is already opened!";
 
            break;
 
        case QSerialPort::NotOpenError:
 
            qCritical() << "Device is not open!";
 
            break;
 
        case QSerialPort::ParityError:
 
            qCritical() << "Parity error detected.";
 
            break;
 
        case QSerialPort::FramingError:
 
            qCritical() << "Framing error detected.";
 
            break;
 
        case QSerialPort::BreakConditionError:
 
            qCritical() << "Break condition is detected.";
 
            break;
 
        case QSerialPort::WriteError:
 
            qCritical() << "An error occurred while writing data.";
 
            break;
 
        case QSerialPort::ReadError:
 
            qCritical() << "An error occurred while reading data.";
 
            break;
 
        case QSerialPort::UnsupportedOperationError:
 
            qCritical() << "Operation is not supported.";
 
            break;
 
        case QSerialPort::TimeoutError:
 
            qCritical() << "A timeout error occurred.";
 
            break;
 
        case QSerialPort::UnknownError:
 
            qCritical() << "Unknown error!";
 
            break;
 
        default:
 
            qCritical() << "Unhandled port error: " << error;
 
            break;
 
    }
 
}
 

	
 
void MainWindow::skipByte()
 
{
 
    skipByteRequested = true;
 
}
 

	
 
void MainWindow::addChannelData(unsigned int channel, DataArray data)
 
{
 
    DataArray* channelDataArray = &(channelsData[channel]);
 
    int offset = numOfSamples - data.size();
 

	
 
    if (offset < 0)
 
    {
 
        for (unsigned int i = 0; i < numOfSamples; i++)
 
        {
 
            (*channelDataArray)[i] = data[i - offset];
 
        }
 
    }
 
    else if (offset == 0)
 
    {
 
        (*channelDataArray) = data;
 
    }
 
    else
 
    {
 
        // shift old samples
 
        int shift = data.size();
 
        for (int i = 0; i < offset; i++)
 
        {
 
            (*channelDataArray)[i] = (*channelDataArray)[i + shift];
 
        }
 
        // place new samples
 
        for (int i = 0; i < data.size(); i++)
 
        {
 
            (*channelDataArray)[offset + i] = data[i];
 
        }
 
    }
 

	
 
    // update plot
 
    curves[channel]->setSamples(dataX, (*channelDataArray));
 
    ui->plot->replot(); // TODO: replot after all channel data updated
 

	
 
    sampleCount += data.size();
 
}
 

	
 
void MainWindow::clearPlot()
 
{
 
    for (unsigned int ci = 0; ci < numOfChannels; ci++)
 
    {
 
        channelsData[ci].fill(0.0);
 
        curves[ci]->setSamples(dataX, channelsData[ci]);
 
    }
 

	
 
    // update plot
 
    ui->plot->replot();
 
}
 

	
 
void MainWindow::onNumOfSamplesChanged(int value)
 
{
 
    unsigned int oldNum = this->numOfSamples;
 
    numOfSamples = value;
 

	
 
    // resize data arrays
 
    if (numOfSamples < oldNum)
 
    {
 
        dataX.resize(numOfSamples);
 
        for (unsigned int ci = 0; ci < numOfChannels; ci++)
 
        {
 
            channelsData[ci].remove(0, oldNum - numOfSamples);
 
        }
 
    }
 
    else if(numOfSamples > oldNum)
 
    {
 
        dataX.resize(numOfSamples);
 
        for (unsigned int i = oldNum; i < numOfSamples; i++)
 
        {
 
            dataX[i] = i;
 
            for (unsigned int ci = 0; ci < numOfChannels; ci++)
 
            {
 
                channelsData[ci].prepend(0);
 
            }
 
        }
 
    }
 
}
 

	
 
void MainWindow::onNumOfChannelsChanged(int value)
 
{
 
    unsigned int oldNum = this->numOfChannels;
 
    this->numOfChannels = value;
 

	
 
    if (numOfChannels > oldNum)
 
    {
 
        // add new channels
 
        for (unsigned int i = 0; i < numOfChannels - oldNum; i++)
 
        {
 
            channelsData.append(DataArray(numOfSamples, 0.0));
 
            curves.append(new QwtPlotCurve());
 
            curves.last()->setSamples(dataX, channelsData.last());
 
            curves.last()->setPen(makeColor(curves.length()-1));
 
            curves.last()->attach(ui->plot);
 
        }
 
    }
 
    else if(numOfChannels < oldNum)
 
    {
 
        // remove channels
 
        for (unsigned int i = 0; i < oldNum - numOfChannels; i++)
 
        {
 
            channelsData.removeLast();
 
            auto curve = curves.takeLast();
 
            curve->detach();
 
            delete curve;
 
        }
 
    }
 
}
 

	
 
void MainWindow::onAutoScaleChecked(bool checked)
 
{
 
    if (checked)
 
    {
 
        ui->plot->setAxis(true);
 
        ui->lYmin->setEnabled(false);
 
        ui->lYmax->setEnabled(false);
 
        ui->spYmin->setEnabled(false);
 
        ui->spYmax->setEnabled(false);
 
    }
 
    else
 
    {
 
        ui->lYmin->setEnabled(true);
 
        ui->lYmax->setEnabled(true);
 
        ui->spYmin->setEnabled(true);
 
        ui->spYmax->setEnabled(true);
0 comments (0 inline, 0 general)