mirror of
https://github.com/JS8Call-improved/JS8Call-improved
synced 2026-08-13 17:47:36 -04:00
126 lines
4.2 KiB
C++
126 lines
4.2 KiB
C++
#ifndef TXLOOP_H
|
|
#define TXLOOP_H
|
|
|
|
#include "TwoPhaseSignal.h"
|
|
#include "Varicode.h"
|
|
|
|
#include <QDateTime>
|
|
#include <QTimer>
|
|
|
|
class TxLoop : public TwoPhaseSignal {
|
|
Q_OBJECT
|
|
|
|
private:
|
|
// Name, only used for logging:
|
|
const QString m_name;
|
|
// When do we need to start transmitting the next time?
|
|
QDateTime m_next_activity;
|
|
// How much tx_delay, in milliseconds, we need to be early.
|
|
qint64 m_tx_delay_ms;
|
|
// A timer that is supposed to wake us up when it is time.
|
|
// This will be m_tx_delay_ms earlier than m_next_activity.
|
|
QTimer m_next_activity_timer;
|
|
// The currently active JS8 m_submode.
|
|
Varicode::SubmodeType m_submode;
|
|
// Whether this loop is active (or else does nothing).
|
|
bool m_active;
|
|
// The loop's period: After how many milliseconds to repeat sending.
|
|
qint64 m_loop_period_ms;
|
|
|
|
public:
|
|
// Provide a "name" argument that can be used for logging.
|
|
TxLoop(const QString &name);
|
|
|
|
~TxLoop();
|
|
|
|
// The TX delay cannot be set to any value larger than this:
|
|
static constexpr qint64 MAX_TX_DELAY_MS = 1000;
|
|
|
|
inline bool isActive() const { return m_active; }
|
|
|
|
/**
|
|
* Return the timestamp when the payload signal is supposed to start.
|
|
* This timestamp will always point to a full second.
|
|
* The actual triggering happens tx_delay earlier.
|
|
*
|
|
* The value this returns is undetermined (arbitrary) when called while
|
|
* isActive() returns false.
|
|
*/
|
|
inline const QDateTime &nextActivity() const { return m_next_activity; }
|
|
|
|
/**
|
|
* Return the present period of the loop, in milliseconds, if isActive()
|
|
* returns true.
|
|
*
|
|
* Not sure this is useful, but: If isActive() returns false,
|
|
* this will hand out the previous period used, or,
|
|
* if this loop object has never been active, some reasonable initial value.
|
|
*/
|
|
inline qint64 period_ms() const { return m_loop_period_ms; }
|
|
|
|
signals:
|
|
/** Tells whoever wants to know that now is the time to push the PTT for TX
|
|
* delay: */
|
|
void triggerTxNow() const;
|
|
|
|
/**
|
|
* Tells whoever wants to know that our future plans have changed. Only an
|
|
* active loop will emit this.
|
|
*
|
|
* This signal is emitted in conjunction with triggerTxNow and also each
|
|
* time our onTxLoopPeriodChangeStart receives a signal.
|
|
*
|
|
* The QDateTime sent is the same that will be returned by nextActivity().
|
|
*
|
|
* In addition, it gets fired when some other incoming onXXX signal caused
|
|
* our next activity to change.
|
|
*/
|
|
void nextActivityChanged(const QDateTime &) const;
|
|
|
|
/** Tells whoever wants to know that we have become inactive. */
|
|
void canceled() const;
|
|
|
|
public slots:
|
|
/** Asks us to emit initial signals, either nextActivityChanged or, more
|
|
* likely, canceled. */
|
|
void onPlumbingCompleted() const;
|
|
/** Tells us that the DriftingDateTime has a new drift value. We'll adjust
|
|
* accordingly. Idempotent. */
|
|
void onDriftChange(qint64 new_drift);
|
|
/** Tells us that the next transmission organized by this loop will be in
|
|
* this new submode. Idempotent. */
|
|
void onModeChange(Varicode::SubmodeType new_submode);
|
|
/**
|
|
* Tells us that the desired TX delay
|
|
* (switch TX on a bit before the full second that starts the mode period)
|
|
* has changed. Idempotent.
|
|
*/
|
|
void onTxDelayChange(qint64 tx_delay_ms);
|
|
|
|
/**
|
|
* This starts or restarts the loop.
|
|
* You need to provide the desired period.
|
|
*
|
|
* After this signal has come in, isActive() will return true
|
|
* and triggerTxNow will fire every loop_period_ms milliseconds.
|
|
* This continues until the onLoopCancel signal is received.
|
|
*
|
|
* Calling this on a loop that is active will cause the schedule
|
|
* to be reset; i.e., this restarts the loop.
|
|
*/
|
|
void onTxLoopPeriodChangeStart(qint64 loop_period_ms);
|
|
|
|
/**
|
|
* Cancel the loop. After this signal has come in, isActive() will return
|
|
* false and triggerTxNow will not fire any longer. Loop activity will
|
|
* restart when a onTxLoopPeriodChangeStart signal is again received.
|
|
*
|
|
* This is idempotent, it does no harm to call this on an idle loop.
|
|
*/
|
|
void onLoopCancel();
|
|
|
|
private slots:
|
|
void onTimer();
|
|
};
|
|
|
|
#endif
|