243 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			243 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
|   | #include "TransceiverBase.hpp"
 | ||
|  | 
 | ||
|  | #include <exception>
 | ||
|  | 
 | ||
|  | #include <QString>
 | ||
|  | #include <QTimer>
 | ||
|  | #include <QThread>
 | ||
|  | #include <QDebug>
 | ||
|  | 
 | ||
|  | #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
 | ||
|  |                 { | ||
|  |                   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
 | ||
|  |     } | ||
|  | } |