Skip to content

Commit

Permalink
Fixed management of serial interface parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
SergejBre committed May 17, 2021
1 parent 4dc3462 commit da856cb
Show file tree
Hide file tree
Showing 6 changed files with 216 additions and 159 deletions.
102 changes: 59 additions & 43 deletions SynchroTimeApp/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ MainWindow::MainWindow( QWidget *parent ) :
QMainWindow( parent ),
ui( new Ui::MainWindow ),
m_pConsole( nullptr ),
m_pSettings( nullptr ),
m_pSettingsDialog( nullptr ),
m_pThread( nullptr ),
m_pRTC( nullptr )
Expand All @@ -70,10 +71,10 @@ MainWindow::MainWindow( QWidget *parent ) :
m_pConsole = new Console;
m_pConsole->setEnabled( false );
setCentralWidget( m_pConsole );
m_pSettingsDialog = new SettingsDialog( this );
m_pSettings = new Settings();
this->readSettings();
// Here, the settings of the serial interface is retrieved from the configuration file.
m_pSettingsDialog->fillSettingsUi();
m_pSettingsDialog = new SettingsDialog( m_pSettings, this );
QObject::connect( m_pSettingsDialog, &SettingsDialog::settingsError, this, &MainWindow::handleSettingsError );

rate = new QLabel;
ui->statusBar->addPermanentWidget( rate, 0 );
Expand Down Expand Up @@ -116,6 +117,9 @@ MainWindow::~MainWindow()
m_pThread->quit();
m_pThread->wait( WAIT_FOR_STREAM );
}
if ( m_pSettings != nullptr ) {
delete m_pSettings;
}

delete ui;
}
Expand Down Expand Up @@ -151,23 +155,26 @@ void MainWindow::readSettings()
settings.beginGroup( QStringLiteral( "ULayout" ));
settings.endGroup();

Q_ASSERT( m_pSettingsDialog != nullptr );
Settings_t *const p = m_pSettingsDialog->serialPortSettings();
Q_ASSERT( m_pSettings != nullptr );
settings.beginGroup( QStringLiteral( "SerialPort" ));
p->name = settings.value( QStringLiteral( "portName" ), QStringLiteral( "ttyUSB0" )).toString();
p->baudRate = settings.value( QStringLiteral( "baudRate" ), 115200 ).toUInt();
p->stringBaudRate = settings.value( QStringLiteral( "baudRate" ), 115200 ).toString();
p->stringDataBits = settings.value( QStringLiteral( "dataBits" ), 8 ).toString();
p->stringParity = settings.value( QStringLiteral( "parity" ), QStringLiteral( "NoParity" )).toString();
p->stringStopBits = settings.value( QStringLiteral( "stopBits" ), 1 ).toString();
p->stringFlowControl = settings.value( QStringLiteral( "flowControl" ), QStringLiteral( "None" )).toString();
#ifdef Q_OS_WIN
m_pSettings->name = settings.value( QStringLiteral( "portName" ), QStringLiteral( "COM5" )).toString();
#else
m_pSettings->name = settings.value( QStringLiteral( "portName" ), QStringLiteral( "ttyUSB0" )).toString();
#endif
m_pSettings->baudRate = settings.value( QStringLiteral( "baudRate" ), 115200 ).toUInt();
m_pSettings->stringBaudRate = settings.value( QStringLiteral( "baudRate" ), 115200 ).toString();
m_pSettings->stringDataBits = settings.value( QStringLiteral( "dataBits" ), 8 ).toString();
m_pSettings->stringParity = settings.value( QStringLiteral( "parity" ), QStringLiteral( "NoParity" )).toString();
m_pSettings->stringStopBits = settings.value( QStringLiteral( "stopBits" ), 1 ).toString();
m_pSettings->stringFlowControl = settings.value( QStringLiteral( "flowControl" ), QStringLiteral( "None" )).toString();
settings.endGroup();

settings.beginGroup( QStringLiteral( "AdditionalOptions" ));
p->correctionFactor = settings.value( QStringLiteral( "correctionFactor" ), -12.8 ).toFloat();
p->accessRateEnabled = settings.value( QStringLiteral( "accessRateEnabled" ), true ).toBool();
p->statusControlEnabled = settings.value( QStringLiteral( "statusControlEnabled" ), true ).toBool();
p->requestRate = settings.value( QStringLiteral( "requestRate" ), 500 ).toInt();
m_pSettings->correctionFactor = settings.value( QStringLiteral( "correctionFactor" ), -12.8 ).toFloat();
m_pSettings->accessRateEnabled = settings.value( QStringLiteral( "accessRateEnabled" ), true ).toBool();
m_pSettings->statusControlEnabled = settings.value( QStringLiteral( "statusControlEnabled" ), true ).toBool();
m_pSettings->requestRate = settings.value( QStringLiteral( "requestRate" ), 500 ).toInt();
settings.endGroup();
}

Expand Down Expand Up @@ -198,25 +205,24 @@ void MainWindow::writeSettings() const
settings.beginGroup( QStringLiteral( "ULayot" ));
settings.endGroup();

Q_ASSERT( m_pSettingsDialog != nullptr );
const Settings p = m_pSettingsDialog->settings();
Q_ASSERT( m_pSettings != nullptr );
settings.beginGroup( QStringLiteral( "SerialPort" ));
if ( p.isChanged ) {
settings.setValue( QStringLiteral( "PortName" ), p.name );
settings.setValue( QStringLiteral( "baudRate" ), p.baudRate );
settings.setValue( QStringLiteral( "dataBits" ), p.stringDataBits );
settings.setValue( QStringLiteral( "parity" ), p.stringParity );
settings.setValue( QStringLiteral( "stopBits" ), p.stringStopBits );
settings.setValue( QStringLiteral( "flowControl" ), p.stringFlowControl );
if ( m_pSettings->isChanged ) {
settings.setValue( QStringLiteral( "PortName" ), m_pSettings->name );
settings.setValue( QStringLiteral( "baudRate" ), m_pSettings->baudRate );
settings.setValue( QStringLiteral( "dataBits" ), m_pSettings->stringDataBits );
settings.setValue( QStringLiteral( "parity" ), m_pSettings->stringParity );
settings.setValue( QStringLiteral( "stopBits" ), m_pSettings->stringStopBits );
settings.setValue( QStringLiteral( "flowControl" ), m_pSettings->stringFlowControl );
}
settings.endGroup();

settings.beginGroup( QStringLiteral( "AdditionalOptions" ));
if ( p.isChanged ) {
settings.setValue( QStringLiteral( "correctionFactor" ), QString::number( p.correctionFactor ) );
settings.setValue( QStringLiteral( "accessRateEnabled" ), QString::number( p.accessRateEnabled ) );
settings.setValue( QStringLiteral( "statusControlEnabled" ), QString::number( p.statusControlEnabled ) );
settings.setValue( QStringLiteral( "requestRate" ), QString::number( p.requestRate ) );
if ( m_pSettings->isChanged ) {
settings.setValue( QStringLiteral( "correctionFactor" ), QString::number( m_pSettings->correctionFactor ) );
settings.setValue( QStringLiteral( "accessRateEnabled" ), QString::number( m_pSettings->accessRateEnabled ) );
settings.setValue( QStringLiteral( "statusControlEnabled" ), QString::number( m_pSettings->statusControlEnabled ) );
settings.setValue( QStringLiteral( "requestRate" ), QString::number( m_pSettings->requestRate ) );
}
settings.endGroup();
}
Expand All @@ -228,8 +234,8 @@ void MainWindow::writeSettings() const
void MainWindow::about()
{
QMessageBox::about(this, QObject::tr("About SynchroTime App"),
QObject::tr("The <b>SynchroTime</b> application is used for fine tuning "
"and calibration of the <b>RTC DS3231</b> module."
QObject::tr("The <b>SynchroTime</b> application is used to adjust "
"and calibration the <b>RTC DS3231</b> module."
"<br /><b>Version</b> %1"
"<br /><b>Copyright</b> © 2021 sergej1@email.ua"
"<br /><br />For more information follow the link to the "
Expand All @@ -243,9 +249,9 @@ void MainWindow::about()
//!
void MainWindow::putRate( const float rate )
{
Q_ASSERT( this->m_pSettingsDialog != nullptr );
Q_ASSERT( this->m_pSettings != nullptr );
Q_ASSERT( this->rate != nullptr );
if ( this->m_pSettingsDialog->settings().accessRateEnabled )
if ( this->m_pSettings->accessRateEnabled )
this->rate->setText( QString::number( rate, 'f', 3 ).prepend( QStringLiteral("Access rate, ms ")) );
}

Expand All @@ -261,16 +267,26 @@ void MainWindow::handleError( const QString &error )
QMessageBox::critical( this, QObject::tr( "Serial Port Error" ), error, QMessageBox::Ok );
}

//! \brief MainWindow::handleSettingsError
//!
//! Slot for handling errors that occurred when changing the settings of the serial port interface.
//!
//! \param error of the type QString&
void MainWindow::handleSettingsError( const QString &error )
{
showStatusMessage( error );
}

//!
//! \brief MainWindow::connectRTC
//! Procedure for creating a separate thread for communication with a device.
//!
void MainWindow::connectRTC()
{
m_pThread = ::new( std::nothrow ) QThread( this );
auto p = m_pSettingsDialog->settings();
// There is no need to specify the parent. The parent will be a thread when we move our RTC object into it.
m_pRTC = ::new( std::nothrow ) RTC( p );
Q_ASSERT( m_pSettings != nullptr );
m_pRTC = ::new( std::nothrow ) RTC( m_pSettings );
if ( m_pThread != nullptr && m_pRTC != nullptr ) {
// We move the RTC object to a separate thread so that synchronous pending operations do not block the main GUI thread.
// Create a connection: Delete the RTC object when the stream ends. start the thread.
Expand All @@ -295,11 +311,11 @@ void MainWindow::connectRTC()
QObject::connect(m_pRTC, &RTC::portError, this, &MainWindow::handleError);

showStatusMessage( QObject::tr( "Connected to %1 port, baud rate %2 / %3–%4–%5" )
.arg(p.name)
.arg(p.stringBaudRate)
.arg(p.dataBits)
.arg(p.parity == QSerialPort::NoParity ? 'N' : p.parity == QSerialPort::EvenParity ? 'E' : p.parity == QSerialPort::OddParity ? 'O' : p.parity == QSerialPort::SpaceParity ? 'S' : 'M')
.arg(p.stopBits) );
.arg(m_pSettings->name)
.arg(m_pSettings->stringBaudRate)
.arg(m_pSettings->dataBits)
.arg(m_pSettings->parity == QSerialPort::NoParity ? 'N' : m_pSettings->parity == QSerialPort::EvenParity ? 'E' : m_pSettings->parity == QSerialPort::OddParity ? 'O' : m_pSettings->parity == QSerialPort::SpaceParity ? 'S' : 'M')
.arg(m_pSettings->stopBits) );
}
else {
m_pThread->quit();
Expand Down Expand Up @@ -385,8 +401,8 @@ void MainWindow::tickClock()
void MainWindow::help()
{
QMessageBox::information( this, QObject::tr( "Help" ),
QObject::tr("<h4>The Application is used for fine tuning "
"and calibration of the RTC DS3231 module</h4>"
QObject::tr("<h4>The Application is used to adjust "
"and calibration the RTC DS3231 module</h4>"
"<ol><li>To select the correct <b>serial port</b>, "
"you need to go to the Port Settings and select its name and parameters.</li>"
"<li>Use the <b>information request</b> to get the information from DS3231 module. "
Expand Down
3 changes: 3 additions & 0 deletions SynchroTimeApp/mainwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class QLabel;
class QThread;
class QTimer;
class RTC;
struct Settings;

namespace Ui {
class MainWindow;
Expand Down Expand Up @@ -70,6 +71,7 @@ private slots:

void putRate( const float rate );
void handleError( const QString &error );
void handleSettingsError( const QString &error );

private:
Ui::MainWindow *ui;
Expand All @@ -78,6 +80,7 @@ private slots:
QLCDNumber *clock;
QTimer *m_pTimer;
Console *m_pConsole;
Settings *m_pSettings;
SettingsDialog *m_pSettingsDialog;
// RTC and a separate thread in which it will work.
QThread *m_pThread;
Expand Down
39 changes: 22 additions & 17 deletions SynchroTimeApp/rtc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@
// Includes
//------------------------------------------------------------------------------
#include "rtc.h"
#include "serialportsettings.h"
#include <QDebug>
#include <QThread>
#include <QDateTime>
#include <QElapsedTimer>
#include <QTimer>
#include <QSerialPort>
#include <QtEndian>
#include <cmath>

Expand All @@ -40,7 +40,7 @@
#define STARTBYTE 0x40 //!< The starting byte of the data set from the communication protocol.
#define DEVICE_ID 0x00 //!< ID of the RTC device.
#define WAIT_REBOOT 2500 //!< Interval for a time-out in milliseconds
#define WAIT_TIME 50 //!< The waiting time for the reading or written in milliseconds
#define WAIT_TIME 100 //!< The waiting time for the reading or written in milliseconds
#define ESC_RED QStringLiteral("\x1b[31m") //!< ESCAPE sequence for red.
#define ESC_YELLOW QStringLiteral("\x1b[33m") //!< ESCAPE sequence for yellow.
#define ESC_BLUE QStringLiteral("\x1b[36m") //!< ESCAPE sequence for blue.
Expand Down Expand Up @@ -96,26 +96,26 @@ RTC::RTC( const QString &portName, QObject *parent )

//! \brief RTC::RTC
//! Default Constructor.
//! \param portSettings of the type const Settings_t&. Reference to an parameters of the serial port.
//! \param parent of the type *QObject - pThread.
//! \param portSettings of the type const Settings *const. Reference to an parameters of the serial port.
//! \param parent of the type QObject* - pThread.
//! \note There is no need to specify the parent.
//! The parent will be a thread when we move our RTC object into it.
RTC::RTC( const Settings_t &portSettings, QObject *parent )
RTC::RTC( const Settings *const portSettings, QObject *parent )
: QObject( parent ),
m_pSerialPort( nullptr ),
m_isBusy( false ),
m_pTimerCheckConnection( nullptr ),
m_correctionFactor( portSettings.correctionFactor )
m_correctionFactor( portSettings->correctionFactor )
{
// Initialization of the serial interface.
m_pSerialPort = ::new( std::nothrow ) QSerialPort( this );
if ( m_pSerialPort != nullptr ) {
m_pSerialPort->setPortName( portSettings.name );
m_pSerialPort->setBaudRate( portSettings.baudRate );
m_pSerialPort->setDataBits( portSettings.dataBits );
m_pSerialPort->setParity( portSettings.parity );
m_pSerialPort->setStopBits( portSettings.stopBits );
m_pSerialPort->setFlowControl( portSettings.flowControl );
m_pSerialPort->setPortName( portSettings->name );
m_pSerialPort->setBaudRate( portSettings->baudRate );
m_pSerialPort->setDataBits( portSettings->dataBits );
m_pSerialPort->setParity( portSettings->parity );
m_pSerialPort->setStopBits( portSettings->stopBits );
m_pSerialPort->setFlowControl( portSettings->flowControl );

QObject::connect( m_pSerialPort, static_cast<void (QSerialPort::*)(QSerialPort::SerialPortError)>(&QSerialPort::error),
this, &RTC::handleError );
Expand All @@ -124,8 +124,8 @@ RTC::RTC( const Settings_t &portSettings, QObject *parent )

// Create a timer with 1 second intervals.
m_pTimerCheckConnection = ::new( std::nothrow ) QTimer( this );
if ( m_pTimerCheckConnection != nullptr && portSettings.statusControlEnabled ) {
m_pTimerCheckConnection->setInterval( portSettings.requestRate );
if ( m_pTimerCheckConnection != nullptr && portSettings->statusControlEnabled ) {
m_pTimerCheckConnection->setInterval( portSettings->requestRate );

// After a time of 1 s, the statusRequest() command is called.
// This is where the lambda function is used to avoid creating a slot.
Expand Down Expand Up @@ -392,11 +392,16 @@ const QByteArray RTC::sendRequest( Request request, quint8 size, const quint8 *c
// Sleep 50 ms, waiting for the microcontroller to process the data and respond
// thread()->msleep( WAIT_TIME );
// Reading data from RTC.
if ( ready && m_pSerialPort->waitForReadyRead( WAIT_TIME ) ) {
m_isBusy = false;
if ( ready ) {
if ( m_pSerialPort->waitForReadyRead( WAIT_TIME ) ) {
m_isBusy = false;
}
else {
emit portError( QStringLiteral( "No response received from the device: " ) + m_pSerialPort->errorString() );
}
}
else {
emit portError( QStringLiteral( "No response received from the device: " ) + m_pSerialPort->errorString() );
emit portError( QStringLiteral( "Failed to send data to device: " ) + m_pSerialPort->errorString() );
}
return m_pSerialPort->readAll();
}
Expand Down
6 changes: 3 additions & 3 deletions SynchroTimeApp/rtc.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
// Includes
//------------------------------------------------------------------------------
#include <QObject>
#include "serialportsettings.h"
#include <QtSerialPort/QSerialPort>

//------------------------------------------------------------------------------
// Preprocessor
Expand Down Expand Up @@ -59,8 +59,8 @@ enum class StatusMessages : quint8
//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------
class QSerialPort;
class QTimer;
struct Settings;

//! \class RTC
//!
Expand All @@ -73,7 +73,7 @@ class RTC : public QObject

public:
explicit RTC( const QString &portName, QObject *parent = 0 );
explicit RTC( const Settings_t &portSettings, QObject *parent = 0 );
explicit RTC( const Settings *const portSettings, QObject *parent = 0 );
~RTC();

// Connection check function.
Expand Down
Loading

0 comments on commit da856cb

Please sign in to comment.