JS8Call-Improved master
Loading...
Searching...
No Matches
Transceiver.h
1#ifndef TRANSCEIVER_HPP__
2#define TRANSCEIVER_HPP__
3
4#include "JS8_Main/Radio.h"
5#include "JS8_Main/qt_helpers.h"
6
7#include <QObject>
8
9class QString;
10
11//
12// Abstract Transceiver Interface
13//
14// This is the minimal generic interface to a rig.
15//
16// Responsibilities
17//
18// Provides a Qt slot to set the frequency, mode and PTT of some
19// transceiver. This is a Qt slot so that it may be invoked across a
20// thread boundary.
21//
22// Provides a synchronisation Qt slot which should be implemented in
23// sub-classes in such a way that normal operation of the rig is not
24// disturbed. This is intended to be use to poll rig state
25// periodically and changing VFO to read the other VFO frequency or
26// mode for example should not be done since the operator may be
27// tuning the VFO at the time and would be surprised by an unprompted
28// VFO change.
29//
30// Provides a control interface using Qt slots to start and stop the
31// rig control and PTT connections.
32//
33// These are Qt slots rather than the constructor and destructor
34// because it is expected that the concrete Transceiver
35// implementations will run in a separate thread from where they are
36// constructed.
37//
38// Qt signals are defined to notify clients of asynchronous rig state
39// changes and failures. These can and are expected to cross thread
40// boundaries.
41//
42// A signal finished() is defined that concrete Transceiver
43// implementations must emit when they are ripe for destruction. This
44// is intended to be used by clients that move the Transceiver
45// instance to a thread and need to use QObject::deleteLater() to
46// safely dispose of the Transceiver instance. Implementations should
47// expect Qt slot calls after emitting finished, it is up to the
48// implementation whether these slot invocations are ignored.
49//
50class Transceiver : public QObject {
51 Q_OBJECT
52 Q_ENUMS(MODE)
53
54 public:
55 using Frequency = Radio::Frequency;
56
57 protected:
58 Transceiver(QObject *parent) : QObject{parent} {}
59
60 public:
61 virtual ~Transceiver() {}
62
63 enum MODE {
64 UNK,
65 CW,
66 CW_R,
67 USB,
68 LSB,
69 FSK,
70 FSK_R,
71 DIG_U,
72 DIG_L,
73 AM,
74 FM,
75 DIG_FM
76 };
77 Q_ENUM(MODE)
78
79 //
80 // Aggregation of all of the rig and PTT state accessible via this
81 // interface.
82 //
83 class TransceiverState {
84 public:
85 TransceiverState()
86 : online_{false}, rx_frequency_{0}, tx_frequency_{0}, mode_{UNK},
87 split_{Split::unknown}, ptt_{false} {}
88
89 bool online() const { return online_; }
90 Frequency frequency() const { return rx_frequency_; }
91 Frequency tx_frequency() const { return tx_frequency_; }
92 bool split() const { return Split::on == split_; }
93 MODE mode() const { return mode_; }
94 bool ptt() const { return ptt_; }
95
96 void online(bool state) { online_ = state; }
97 void frequency(Frequency f) { rx_frequency_ = f; }
98 void tx_frequency(Frequency f) { tx_frequency_ = f; }
99 void split(bool state) { split_ = state ? Split::on : Split::off; }
100 void mode(MODE m) { mode_ = m; }
101 void ptt(bool state) { ptt_ = state; }
102
103 private:
104 bool online_;
105 Frequency rx_frequency_;
106 Frequency tx_frequency_; // 0 means use Rx
107 MODE mode_;
108 enum class Split { unknown, off, on } split_;
109 bool ptt_;
110 // Don't forget to update the debug print and != operator if you
111 // add more members here
112
113 friend QDebug operator<<(QDebug, TransceiverState const &);
114 friend bool operator!=(TransceiverState const &,
115 TransceiverState const &);
116 };
117
118 //
119 // The following slots and signals are expected to all run in the
120 // same thread which is not necessarily the main GUI thread. It is
121 // up to the client of the Transceiver class to organise the
122 // allocation to a thread and the lifetime of the object instances.
123 //
124
125 // Apply state changes to the rig. The sequence_number parameter
126 // will be included in any status updates generated after this
127 // transaction is processed. The sequence number may be used to
128 // ignore any status updates until the results of this transaction
129 // have been processed thus avoiding any unwanted "ping-pong" due to
130 // signals crossing in transit.
131 Q_SLOT virtual void set(Transceiver::TransceiverState const &,
132 unsigned sequence_number) noexcept = 0;
133
134 // Connect and disconnect.
135 Q_SLOT virtual void start(unsigned sequence_number) noexcept = 0;
136 Q_SLOT virtual void stop() noexcept = 0;
137
138 //
139 // asynchronous status updates
140 //
141
142 // 0 - 1Hz
143 // 1 - 10Hz rounded
144 // -1 - 10Hz truncated
145 // 2 - 100Hz rounded
146 // -2 - 100Hz truncated
147 Q_SIGNAL void resolution(int);
148
149 // rig state changed
150 Q_SIGNAL void update(Transceiver::TransceiverState const &,
151 unsigned sequence_number) const;
152
153 // something went wrong - not recoverable, start new instance
154 Q_SIGNAL void failure(QString const &reason) const;
155
156 // Ready to be destroyed.
157 Q_SIGNAL void finished() const;
158};
159
160Q_DECLARE_METATYPE(Transceiver::TransceiverState);
161#if QT_VERSION < 0x050500
162Q_DECLARE_METATYPE(Transceiver::MODE);
163#endif
164
165#if !defined(QT_NO_DEBUG_STREAM)
166ENUM_QDEBUG_OPS_DECL(Transceiver, MODE);
167
168QDebug operator<<(QDebug, Transceiver::TransceiverState const &);
169#endif
170
171ENUM_QDATASTREAM_OPS_DECL(Transceiver, MODE);
172ENUM_CONVERSION_OPS_DECL(Transceiver, MODE);
173
174bool operator!=(Transceiver::TransceiverState const &,
176bool operator==(Transceiver::TransceiverState const &,
178
179#endif
Definition Transceiver.h:83