js8call/JS8_Transceiver/TransceiverBase.cpp

202 lines
6 KiB
C++
Raw Permalink Normal View History

2026-01-18 12:53:55 -06:00
/**
* @file TransceiverBase.cpp
* @brief Implementation of the TransceiverBase class
* Implements the Transceiver abstract interface as template methods and
* provides a new abstract interface with similar functionality
*/
2026-01-18 12:53:55 -06:00
#include "TransceiverBase.h"
#include <QDebug>
#include <QString>
#include <QThread>
#include <QTimer>
2026-01-18 12:53:55 -06:00
#include <exception>
#include "moc_TransceiverBase.cpp"
namespace {
auto const unexpected = TransceiverBase::tr("Unexpected rig error");
}
void TransceiverBase::start(unsigned sequence_number) noexcept {
QString message;
try {
may_update u{this, true};
shutdown();
startup();
last_sequence_number_ = sequence_number;
} catch (std::exception const &e) {
message = e.what();
} catch (...) {
message = unexpected;
}
if (!message.isEmpty()) {
offline(message);
}
}
void TransceiverBase::set(TransceiverState const &s,
unsigned sequence_number) noexcept {
TRACE_CAT("TransceiverBase", "#:" << sequence_number << s);
QString message;
try {
may_update u{this, true};
bool was_online{requested_.online()};
if (!s.online() && was_online) {
shutdown();
} else if (s.online() && !was_online) {
shutdown();
startup();
}
if (requested_.online()) {
bool ptt_on{false};
bool ptt_off{false};
if (s.ptt() != requested_.ptt()) {
ptt_on = s.ptt();
ptt_off = !s.ptt();
}
if (ptt_off) {
do_ptt(false);
do_post_ptt(false);
QThread::msleep(100); // some rigs cannot process CAT
// commands while switching from
// Tx to Rx
}
if (s.frequency() // ignore bogus zero frequencies
&& ((s.frequency() != requested_.frequency() // and QSY
|| (s.mode() != UNK &&
s.mode() != requested_.mode())) // or mode change
|| ptt_off)) // or just returned to rx
{
do_frequency(s.frequency(), s.mode(), ptt_off);
do_post_frequency(s.frequency(), s.mode());
// record what actually changed
requested_.frequency(actual_.frequency());
requested_.mode(actual_.mode());
}
if (!s.tx_frequency() ||
(s.tx_frequency() > 10000 // ignore bogus startup values
&& s.tx_frequency() <
std::numeric_limits<Frequency>::max() - 10000)) {
if ((s.tx_frequency() != requested_.tx_frequency() // and QSY
|| (s.mode() != UNK &&
s.mode() != requested_.mode())) // or mode change
// || s.split () != requested_.split ())) // or split change
|| (s.tx_frequency() && ptt_on)) // or about to tx split
{
hamlib_bug_bandaid(s);
do_tx_frequency(s.tx_frequency(), s.mode(), ptt_on);
do_post_tx_frequency(s.tx_frequency(), s.mode());
// record what actually changed
requested_.tx_frequency(actual_.tx_frequency());
requested_.split(actual_.split());
}
}
if (ptt_on) {
do_ptt(true);
do_post_ptt(true);
QThread::msleep(100); // some rigs cannot process CAT
// commands while switching from
// Rx to Tx
}
// record what actually changed
requested_.ptt(actual_.ptt());
}
last_sequence_number_ = sequence_number;
} catch (std::exception const &e) {
message = e.what();
} catch (...) {
message = unexpected;
}
if (!message.isEmpty()) {
offline(message);
}
}
void TransceiverBase::startup() {
Q_EMIT resolution(do_start());
do_post_start();
actual_.online(true);
requested_.online(true);
}
void TransceiverBase::shutdown() {
may_update u{this};
if (requested_.online()) {
try {
// try and ensure PTT isn't left set
do_ptt(false);
do_post_ptt(false);
if (requested_.split()) {
// try and reset split mode
do_tx_frequency(0, UNK, true);
do_post_tx_frequency(0, UNK);
}
} catch (...) {
// don't care about exceptions
}
}
do_stop();
do_post_stop();
actual_.online(false);
requested_.online(false);
}
void TransceiverBase::stop() noexcept {
QString message;
try {
shutdown();
} catch (std::exception const &e) {
message = e.what();
} catch (...) {
message = unexpected;
}
if (!message.isEmpty()) {
offline(message);
} else {
Q_EMIT finished();
}
}
void TransceiverBase::update_rx_frequency(Frequency rx) {
actual_.frequency(rx);
requested_.frequency(rx); // track rig changes
}
void TransceiverBase::update_other_frequency(Frequency tx) {
actual_.tx_frequency(tx);
}
void TransceiverBase::update_split(bool state) { actual_.split(state); }
void TransceiverBase::update_mode(MODE m) {
actual_.mode(m);
requested_.mode(m); // track rig changes
}
void TransceiverBase::update_PTT(bool state) { actual_.ptt(state); }
void TransceiverBase::update_complete(bool force_signal) {
if ((do_pre_update() && actual_ != last_) || force_signal) {
Q_EMIT update(actual_, last_sequence_number_);
last_ = actual_;
}
}
void TransceiverBase::offline(QString const &reason) {
Q_EMIT failure(reason);
try {
shutdown();
} catch (...) {
// don't care
}
}
Q_LOGGING_CATEGORY(transceiverbase_js8, "transceiverbase.js8", QtWarningMsg)