Countdown for HB and CQ. Escape key stops CQ and resets HB timer
This commit is contained in:
parent
55f04d3cd7
commit
3d3be02830
134
mainwindow.cpp
134
mainwindow.cpp
@ -875,14 +875,9 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
|||||||
TxAgainTimer.setSingleShot(true);
|
TxAgainTimer.setSingleShot(true);
|
||||||
connect(&TxAgainTimer, SIGNAL(timeout()), this, SLOT(TxAgain()));
|
connect(&TxAgainTimer, SIGNAL(timeout()), this, SLOT(TxAgain()));
|
||||||
|
|
||||||
heartbeatTimer.setSingleShot(false);
|
repeatTimer.setSingleShot(false);
|
||||||
connect(&heartbeatTimer, &QTimer::timeout, this, &MainWindow::checkHeartbeat);
|
repeatTimer.setInterval(1000);
|
||||||
|
connect(&repeatTimer, &QTimer::timeout, this, &MainWindow::checkRepeat);
|
||||||
m_heartbeat.setSingleShot(false);
|
|
||||||
connect(&m_heartbeat, &QTimer::timeout, this, &MainWindow::sendHeartbeat);
|
|
||||||
|
|
||||||
m_cq.setSingleShot(false);
|
|
||||||
connect(&m_cq, &QTimer::timeout, this, &MainWindow::sendCQ);
|
|
||||||
|
|
||||||
connect(m_wideGraph.data (), SIGNAL(setFreq3(int,int)),this,
|
connect(m_wideGraph.data (), SIGNAL(setFreq3(int,int)),this,
|
||||||
SLOT(setFreq4(int,int)));
|
SLOT(setFreq4(int,int)));
|
||||||
@ -3729,6 +3724,46 @@ void MainWindow::writeAllTxt(QString message, int bits)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QDateTime MainWindow::nextTransmitCycle(){
|
||||||
|
auto timestamp = DriftingDateTime::currentDateTimeUtc();
|
||||||
|
|
||||||
|
// remove milliseconds
|
||||||
|
auto t = timestamp.time();
|
||||||
|
t.setHMS(t.hour(), t.minute(), t.second());
|
||||||
|
timestamp.setTime(t);
|
||||||
|
|
||||||
|
// round to 15 second increment
|
||||||
|
int secondsSinceEpoch = (timestamp.toMSecsSinceEpoch()/1000);
|
||||||
|
int delta = roundUp(secondsSinceEpoch, 15) + 1 - secondsSinceEpoch;
|
||||||
|
timestamp = timestamp.addSecs(delta);
|
||||||
|
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::resetAutomaticIntervalTransmissions(bool stopCQ, bool stopHB){
|
||||||
|
resetCQTimer(stopCQ);
|
||||||
|
resetHeartbeatTimer(stopHB);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::resetCQTimer(bool stop){
|
||||||
|
if(ui->cqMacroButton->isChecked() && m_cqInterval > 0){
|
||||||
|
ui->cqMacroButton->setChecked(false);
|
||||||
|
if(!stop){
|
||||||
|
ui->cqMacroButton->setChecked(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::resetHeartbeatTimer(bool stop){
|
||||||
|
// toggle the heartbeat timer if we have a repeating heartbeat
|
||||||
|
if(ui->hbMacroButton->isChecked() && m_hbInterval > 0){
|
||||||
|
ui->hbMacroButton->setChecked(false);
|
||||||
|
if(!stop){
|
||||||
|
ui->hbMacroButton->setChecked(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::decodeDone ()
|
void MainWindow::decodeDone ()
|
||||||
{
|
{
|
||||||
dec_data.params.nagain=0;
|
dec_data.params.nagain=0;
|
||||||
@ -4681,6 +4716,9 @@ void MainWindow::guiUpdate()
|
|||||||
// update the dial frequency once per second..
|
// update the dial frequency once per second..
|
||||||
displayDialFrequency();
|
displayDialFrequency();
|
||||||
|
|
||||||
|
// update repeat button text once per second..
|
||||||
|
updateRepeatButtonDisplay();
|
||||||
|
|
||||||
// once per second...but not when we're transmitting
|
// once per second...but not when we're transmitting
|
||||||
if(!m_transmitting){
|
if(!m_transmitting){
|
||||||
// process all received activity...
|
// process all received activity...
|
||||||
@ -5587,6 +5625,9 @@ void MainWindow::createMessageTransmitQueue(QString const& text){
|
|||||||
|
|
||||||
displayTextForFreq(lines.join("") + " \u2301 ", freq, DriftingDateTime::currentDateTimeUtc(), true, true, true);
|
displayTextForFreq(lines.join("") + " \u2301 ", freq, DriftingDateTime::currentDateTimeUtc(), true, true, true);
|
||||||
|
|
||||||
|
// if we're transmitting a message to be displayed, we should bump the repeat buttons...
|
||||||
|
resetAutomaticIntervalTransmissions(false, false);
|
||||||
|
|
||||||
// keep track of the last message text sent
|
// keep track of the last message text sent
|
||||||
m_lastTxMessage = text;
|
m_lastTxMessage = text;
|
||||||
}
|
}
|
||||||
@ -5870,8 +5911,18 @@ void MainWindow::prepareHeartbeat(){
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void MainWindow::checkHeartbeat(){
|
void MainWindow::checkRepeat(){
|
||||||
|
if(ui->hbMacroButton->isChecked() && m_hbInterval > 0 && m_nextHeartbeat.isValid()){
|
||||||
|
if(DriftingDateTime::currentDateTimeUtc().secsTo(m_nextHeartbeat) <= 0){
|
||||||
|
sendHeartbeat();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ui->cqMacroButton->isChecked() && m_cqInterval > 0 && m_nextCQ.isValid()){
|
||||||
|
if(DriftingDateTime::currentDateTimeUtc().secsTo(m_nextCQ) <= 0){
|
||||||
|
sendCQ();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString MainWindow::calculateDistance(QString const& value, int *pDistance, int *pAzimuth)
|
QString MainWindow::calculateDistance(QString const& value, int *pDistance, int *pAzimuth)
|
||||||
@ -6556,6 +6607,10 @@ void MainWindow::buildRepeatMenu(QMenu *menu, QPushButton * button, int * interv
|
|||||||
connect(action, &QAction::toggled, this, [this, minutes, interval, button](bool checked){
|
connect(action, &QAction::toggled, this, [this, minutes, interval, button](bool checked){
|
||||||
if(checked){
|
if(checked){
|
||||||
*interval = minutes;
|
*interval = minutes;
|
||||||
|
if(minutes > 0){
|
||||||
|
// force a re-toggle
|
||||||
|
button->setChecked(false);
|
||||||
|
}
|
||||||
button->setChecked(minutes > 0);
|
button->setChecked(minutes > 0);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -6576,9 +6631,11 @@ void MainWindow::sendHeartbeat(){
|
|||||||
void MainWindow::on_hbMacroButton_toggled(bool checked){
|
void MainWindow::on_hbMacroButton_toggled(bool checked){
|
||||||
if(checked){
|
if(checked){
|
||||||
if(m_hbInterval){
|
if(m_hbInterval){
|
||||||
|
m_nextHeartbeat = nextTransmitCycle().addSecs(m_hbInterval * 60);
|
||||||
|
|
||||||
m_heartbeat.setInterval((m_hbInterval * 60) * 1000);
|
if(!repeatTimer.isActive()){
|
||||||
m_heartbeat.start();
|
repeatTimer.start();
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
sendHeartbeat();
|
sendHeartbeat();
|
||||||
@ -6587,8 +6644,10 @@ void MainWindow::on_hbMacroButton_toggled(bool checked){
|
|||||||
ui->hbMacroButton->setChecked(false);
|
ui->hbMacroButton->setChecked(false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_heartbeat.stop();
|
m_nextHeartbeat = QDateTime{};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateRepeatButtonDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_hbMacroButton_clicked(){
|
void MainWindow::on_hbMacroButton_clicked(){
|
||||||
@ -6610,18 +6669,24 @@ void MainWindow::sendCQ(){
|
|||||||
|
|
||||||
void MainWindow::on_cqMacroButton_toggled(bool checked){
|
void MainWindow::on_cqMacroButton_toggled(bool checked){
|
||||||
if(checked){
|
if(checked){
|
||||||
|
if(m_cqInterval){
|
||||||
|
m_nextCQ = nextTransmitCycle().addSecs(m_cqInterval * 60);
|
||||||
|
|
||||||
|
if(!repeatTimer.isActive()){
|
||||||
|
repeatTimer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
sendCQ();
|
sendCQ();
|
||||||
|
|
||||||
if(m_cqInterval){
|
|
||||||
m_cq.setInterval((m_cqInterval * 60) * 1000);
|
|
||||||
m_cq.start();
|
|
||||||
} else {
|
|
||||||
// make this button emulate a single press button
|
// make this button emulate a single press button
|
||||||
ui->cqMacroButton->setChecked(false);
|
ui->cqMacroButton->setChecked(false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_cq.stop();
|
m_nextCQ= QDateTime{};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateRepeatButtonDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_cqMacroButton_clicked(){
|
void MainWindow::on_cqMacroButton_clicked(){
|
||||||
@ -7613,6 +7678,7 @@ void MainWindow::on_stopTxButton_clicked() //Stop Tx
|
|||||||
ui->cbFirst->setStyleSheet ("");
|
ui->cbFirst->setStyleSheet ("");
|
||||||
|
|
||||||
resetMessage();
|
resetMessage();
|
||||||
|
resetAutomaticIntervalTransmissions(true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::rigOpen ()
|
void MainWindow::rigOpen ()
|
||||||
@ -8389,6 +8455,33 @@ void MainWindow::updateButtonDisplay(){
|
|||||||
ui->queryButton->setDisabled(isTransmitting || emptyCallsign);
|
ui->queryButton->setDisabled(isTransmitting || emptyCallsign);
|
||||||
ui->deselectButton->setDisabled(isTransmitting || emptyCallsign);
|
ui->deselectButton->setDisabled(isTransmitting || emptyCallsign);
|
||||||
ui->queryButton->setText(emptyCallsign ? "Directed" : QString("Directed to %1").arg(selectedCallsign));
|
ui->queryButton->setText(emptyCallsign ? "Directed" : QString("Directed to %1").arg(selectedCallsign));
|
||||||
|
|
||||||
|
// refresh repeat button text too
|
||||||
|
updateRepeatButtonDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::updateRepeatButtonDisplay(){
|
||||||
|
if(ui->hbMacroButton->isChecked() && m_hbInterval > 0 && m_nextHeartbeat.isValid()){
|
||||||
|
auto secs = DriftingDateTime::currentDateTimeUtc().secsTo(m_nextHeartbeat);
|
||||||
|
if(secs > 0){
|
||||||
|
ui->hbMacroButton->setText(QString("HB (%1)").arg(secs));
|
||||||
|
} else {
|
||||||
|
ui->hbMacroButton->setText(QString("HB (now)"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ui->hbMacroButton->setText("HB");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ui->cqMacroButton->isChecked() && m_cqInterval > 0 && m_nextCQ.isValid()){
|
||||||
|
auto secs = DriftingDateTime::currentDateTimeUtc().secsTo(m_nextCQ);
|
||||||
|
if(secs > 0){
|
||||||
|
ui->cqMacroButton->setText(QString("CQ (%1)").arg(secs));
|
||||||
|
} else {
|
||||||
|
ui->cqMacroButton->setText(QString("CQ (now)"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ui->cqMacroButton->setText("CQ");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::updateTextDisplay(){
|
void MainWindow::updateTextDisplay(){
|
||||||
@ -8775,6 +8868,9 @@ void MainWindow::processRxActivity() {
|
|||||||
// log it to the display!
|
// log it to the display!
|
||||||
displayTextForFreq(d.text, d.freq, d.utcTimestamp, false, isFirst, isLast);
|
displayTextForFreq(d.text, d.freq, d.utcTimestamp, false, isFirst, isLast);
|
||||||
|
|
||||||
|
// if we've received a message to be displayed, we should bump the repeat buttons...
|
||||||
|
resetAutomaticIntervalTransmissions(true, false);
|
||||||
|
|
||||||
if(isLast){
|
if(isLast){
|
||||||
clearOffsetDirected(d.freq);
|
clearOffsetDirected(d.freq);
|
||||||
}
|
}
|
||||||
@ -9088,6 +9184,10 @@ void MainWindow::processCommandActivity() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if(!isAllCall){
|
if(!isAllCall){
|
||||||
|
// if we've received a message to be displayed, we should bump the repeat buttons...
|
||||||
|
resetAutomaticIntervalTransmissions(true, false);
|
||||||
|
|
||||||
|
// and we should play the sound notification if there is one...
|
||||||
playSoundNotification(m_config.sound_dm_path());
|
playSoundNotification(m_config.sound_dm_path());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
18
mainwindow.h
18
mainwindow.h
@ -317,7 +317,7 @@ private slots:
|
|||||||
bool prepareNextMessageFrame();
|
bool prepareNextMessageFrame();
|
||||||
bool isFreqOffsetFree(int f, int bw);
|
bool isFreqOffsetFree(int f, int bw);
|
||||||
int findFreeFreqOffset(int fmin, int fmax, int bw);
|
int findFreeFreqOffset(int fmin, int fmax, int bw);
|
||||||
void checkHeartbeat();
|
void checkRepeat();
|
||||||
QString calculateDistance(QString const& grid, int *pDistance=nullptr, int *pAzimuth=nullptr);
|
QString calculateDistance(QString const& grid, int *pDistance=nullptr, int *pAzimuth=nullptr);
|
||||||
void on_driftSpinBox_valueChanged(int n);
|
void on_driftSpinBox_valueChanged(int n);
|
||||||
void on_driftSyncButton_clicked();
|
void on_driftSyncButton_clicked();
|
||||||
@ -665,7 +665,7 @@ private:
|
|||||||
QTimer minuteTimer;
|
QTimer minuteTimer;
|
||||||
QTimer splashTimer;
|
QTimer splashTimer;
|
||||||
QTimer p1Timer;
|
QTimer p1Timer;
|
||||||
QTimer heartbeatTimer;
|
QTimer repeatTimer;
|
||||||
|
|
||||||
QString m_path;
|
QString m_path;
|
||||||
QString m_baseCall;
|
QString m_baseCall;
|
||||||
@ -835,9 +835,10 @@ private:
|
|||||||
QQueue<QString> m_foxQSOinProgress; //QSOs in progress: Fox has sent a report
|
QQueue<QString> m_foxQSOinProgress; //QSOs in progress: Fox has sent a report
|
||||||
QQueue<qint64> m_foxRateQueue;
|
QQueue<qint64> m_foxRateQueue;
|
||||||
|
|
||||||
bool m_nextHeartbeatQueued = false;
|
int m_hbInterval;
|
||||||
bool m_nextHeartPaused = false;
|
int m_cqInterval;
|
||||||
QDateTime m_nextHeartbeat;
|
QDateTime m_nextHeartbeat;
|
||||||
|
QDateTime m_nextCQ;
|
||||||
QDateTime m_dateTimeQSOOn;
|
QDateTime m_dateTimeQSOOn;
|
||||||
QDateTime m_dateTimeLastTX;
|
QDateTime m_dateTimeLastTX;
|
||||||
|
|
||||||
@ -864,10 +865,6 @@ private:
|
|||||||
double m_toneSpacing;
|
double m_toneSpacing;
|
||||||
int m_firstDecode;
|
int m_firstDecode;
|
||||||
QProgressDialog m_optimizingProgress;
|
QProgressDialog m_optimizingProgress;
|
||||||
int m_hbInterval;
|
|
||||||
QTimer m_heartbeat;
|
|
||||||
int m_cqInterval;
|
|
||||||
QTimer m_cq;
|
|
||||||
MessageClient * m_messageClient;
|
MessageClient * m_messageClient;
|
||||||
PSK_Reporter *psk_Reporter;
|
PSK_Reporter *psk_Reporter;
|
||||||
APRSISClient * m_aprsClient;
|
APRSISClient * m_aprsClient;
|
||||||
@ -906,6 +903,7 @@ private:
|
|||||||
void postDecode (bool is_new, QString const& message);
|
void postDecode (bool is_new, QString const& message);
|
||||||
void displayTransmit();
|
void displayTransmit();
|
||||||
void updateButtonDisplay();
|
void updateButtonDisplay();
|
||||||
|
void updateRepeatButtonDisplay();
|
||||||
void updateTextDisplay();
|
void updateTextDisplay();
|
||||||
void updateFrameCountEstimate(int count);
|
void updateFrameCountEstimate(int count);
|
||||||
void updateTextStatsDisplay(QString text, int count);
|
void updateTextStatsDisplay(QString text, int count);
|
||||||
@ -954,6 +952,10 @@ private:
|
|||||||
, QString const& his_call
|
, QString const& his_call
|
||||||
, QString const& his_grid) const;
|
, QString const& his_grid) const;
|
||||||
void read_wav_file (QString const& fname);
|
void read_wav_file (QString const& fname);
|
||||||
|
QDateTime nextTransmitCycle();
|
||||||
|
void resetAutomaticIntervalTransmissions(bool stopCQ, bool stopHB);
|
||||||
|
void resetCQTimer(bool stop);
|
||||||
|
void resetHeartbeatTimer(bool stop);
|
||||||
void decodeDone ();
|
void decodeDone ();
|
||||||
void subProcessFailed (QProcess *, int exit_code, QProcess::ExitStatus);
|
void subProcessFailed (QProcess *, int exit_code, QProcess::ExitStatus);
|
||||||
void subProcessError (QProcess *, QProcess::ProcessError);
|
void subProcessError (QProcess *, QProcess::ProcessError);
|
||||||
|
Loading…
Reference in New Issue
Block a user