mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-11-03 13:30:52 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			165 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			165 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#ifndef TRANSCEIVER_BASE_HPP__
 | 
						|
#define TRANSCEIVER_BASE_HPP__
 | 
						|
 | 
						|
#include <stdexcept>
 | 
						|
 | 
						|
#include <QString>
 | 
						|
 | 
						|
#include "Logger.hpp"
 | 
						|
#include "Transceiver.hpp"
 | 
						|
 | 
						|
//
 | 
						|
// Base Transceiver Implementation
 | 
						|
//
 | 
						|
//  Behaviour common to all Transceiver implementations.
 | 
						|
//
 | 
						|
// Collaborations
 | 
						|
//
 | 
						|
//  Implements the Transceiver abstract  interface as template methods
 | 
						|
//  and provides  a new abstract interface  with similar functionality
 | 
						|
//  (do_XXXXX operations). Provides and  calls abstract interface that
 | 
						|
//  gets  called post  the above  operations (do_post_XXXXX)  to allow
 | 
						|
//  caching implementation etc.
 | 
						|
//
 | 
						|
//  A  key factor  is  to  catch all  exceptions  thrown by  sub-class
 | 
						|
//  implementations where  the template method  is a Qt slot  which is
 | 
						|
//  therefore  likely  to  be  called   by  Qt  which  doesn't  handle
 | 
						|
//  exceptions. Any exceptions are converted to Transceiver::failure()
 | 
						|
//  signals.
 | 
						|
//
 | 
						|
//  Sub-classes update the stored state via a protected interface.
 | 
						|
//
 | 
						|
// Responsibilities:
 | 
						|
//
 | 
						|
//  Wrap incoming  Transceiver messages catching all  exceptions in Qt
 | 
						|
//  slot driven  messages and converting  them to Qt signals.  This is
 | 
						|
//  done because exceptions  make concrete Transceiver implementations
 | 
						|
//  simpler  to   write,  but  exceptions  cannot   cross  signal/slot
 | 
						|
//  boundaries  (especially across  threads).  This  also removes  any
 | 
						|
//  requirement for the client code to handle exceptions.
 | 
						|
//
 | 
						|
//  Maintain the  state of the  concrete Transceiver instance  that is
 | 
						|
//  passed back via  the Transceiver::update(TransceiverState) signal,
 | 
						|
//  it   is  still   the   responsibility   of  concrete   Transceiver
 | 
						|
//  implementations to emit  the state_change signal when  they have a
 | 
						|
//  status update.
 | 
						|
//
 | 
						|
//  Maintain    a   go/no-go    status   for    concrete   Transceiver
 | 
						|
//  implementations  ensuring only  a valid  sequence of  messages are
 | 
						|
//  passed. A concrete Transceiver instance  must be started before it
 | 
						|
//  can receive  messages, any exception thrown  takes the Transceiver
 | 
						|
//  offline.
 | 
						|
//
 | 
						|
//  Implements methods  that concrete Transceiver  implementations use
 | 
						|
//  to update the Transceiver state.  These do not signal state change
 | 
						|
//  to  clients  as  this  is   the  responsibility  of  the  concrete
 | 
						|
//  Transceiver implementation, thus allowing multiple state component
 | 
						|
//  updates to be signalled together if required.
 | 
						|
//
 | 
						|
class TransceiverBase
 | 
						|
  : public Transceiver
 | 
						|
{
 | 
						|
  Q_OBJECT;
 | 
						|
 | 
						|
protected:
 | 
						|
  TransceiverBase (logger_type * logger, QObject * parent)
 | 
						|
    : Transceiver {logger, parent}
 | 
						|
    , last_sequence_number_ {0}
 | 
						|
  {}
 | 
						|
 | 
						|
public:
 | 
						|
  //
 | 
						|
  // Implement the Transceiver abstract interface.
 | 
						|
  //
 | 
						|
  void start (unsigned sequence_number) noexcept override final;
 | 
						|
  void set (TransceiverState const&,
 | 
						|
            unsigned sequence_number) noexcept override final;
 | 
						|
  void stop () noexcept override final;
 | 
						|
 | 
						|
  //
 | 
						|
  // Query operations
 | 
						|
  //
 | 
						|
  TransceiverState const& state () const {return actual_;}
 | 
						|
 | 
						|
protected:
 | 
						|
  //
 | 
						|
  // Error exception which is thrown to signal unexpected errors.
 | 
						|
  //
 | 
						|
  struct error
 | 
						|
    : public std::runtime_error
 | 
						|
  {
 | 
						|
    explicit error (char const * const msg) : std::runtime_error (msg) {}
 | 
						|
    explicit error (QString const& msg) : std::runtime_error (msg.toStdString ()) {}
 | 
						|
  };
 | 
						|
 | 
						|
  // Template methods that sub classes implement to do what they need to do.
 | 
						|
  //
 | 
						|
  // These methods may throw exceptions to signal errors.
 | 
						|
  virtual int do_start () = 0;  // returns resolution, See Transceiver::resolution
 | 
						|
  virtual void do_post_start () {}
 | 
						|
 | 
						|
  virtual void do_stop () = 0;
 | 
						|
  virtual void do_post_stop () {}
 | 
						|
 | 
						|
  virtual void do_frequency (Frequency, MODE, bool no_ignore) = 0;
 | 
						|
  virtual void do_post_frequency (Frequency, MODE) {}
 | 
						|
 | 
						|
  virtual void do_tx_frequency (Frequency, MODE, bool no_ignore) = 0;
 | 
						|
  virtual void do_post_tx_frequency (Frequency, MODE) {}
 | 
						|
 | 
						|
  virtual void do_mode (MODE) = 0;
 | 
						|
  virtual void do_post_mode (MODE) {}
 | 
						|
 | 
						|
  virtual void do_ptt (bool = true) = 0;
 | 
						|
  virtual void do_post_ptt (bool = true) {}
 | 
						|
 | 
						|
  virtual bool do_pre_update () {return true;}
 | 
						|
 | 
						|
  // sub classes report rig state changes with these methods
 | 
						|
  void update_rx_frequency (Frequency);
 | 
						|
  void update_other_frequency (Frequency = 0);
 | 
						|
  void update_split (bool);
 | 
						|
  void update_mode (MODE);
 | 
						|
  void update_PTT (bool = true);
 | 
						|
 | 
						|
  // Calling this eventually triggers the Transceiver::update(State) signal.
 | 
						|
  void update_complete (bool force_signal = false);
 | 
						|
 | 
						|
  // sub class may asynchronously take the rig offline by calling this
 | 
						|
  void offline (QString const& reason);
 | 
						|
 | 
						|
private:
 | 
						|
  void startup ();
 | 
						|
  void shutdown ();
 | 
						|
  bool maybe_low_resolution (Frequency low_res, Frequency high_res);
 | 
						|
 | 
						|
  // use this convenience class to notify in update methods
 | 
						|
  class may_update
 | 
						|
  {
 | 
						|
  public:
 | 
						|
    explicit may_update (TransceiverBase * self, bool force_signal = false)
 | 
						|
      : self_ {self}
 | 
						|
      , force_signal_ {force_signal}
 | 
						|
    {}
 | 
						|
    ~may_update () {self_->update_complete (force_signal_);}
 | 
						|
  private:
 | 
						|
    TransceiverBase * self_;
 | 
						|
    bool force_signal_;
 | 
						|
  };
 | 
						|
 | 
						|
  TransceiverState requested_;
 | 
						|
  TransceiverState actual_;
 | 
						|
  TransceiverState last_;
 | 
						|
  unsigned last_sequence_number_;    // from set state operation
 | 
						|
};
 | 
						|
 | 
						|
// some loggimg macros
 | 
						|
#define CAT_TRACE(MSG) LOG_LOG_LOCATION (logger (), trace, MSG)
 | 
						|
#define CAT_DEBUG(MSG) LOG_LOG_LOCATION (logger (), debug, MSG)
 | 
						|
#define CAT_INFO(MSG) LOG_LOG_LOCATION (logger (), info, MSG)
 | 
						|
#define CAT_WARNING(MSG) LOG_LOG_LOCATION (logger (), warning, MSG)
 | 
						|
#define CAT_ERROR(MSG) LOG_LOG_LOCATION (logger (), error, MSG)
 | 
						|
#define CAT_FATAL(MSG) LOG_LOG_LOCATION (logger (), fatal, MSG)
 | 
						|
 | 
						|
#endif
 |