#include "TCITransceiver.hpp" #include #include #include #include #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) #include #endif #include "commons.h" #include "NetworkServerLookup.hpp" #include "moc_TCITransceiver.cpp" namespace { char const * const TCI_transceiver_1_name {"TCI Client RX1"}; char const * const TCI_transceiver_2_name {"TCI Client RX2"}; QString map_mode (Transceiver::MODE mode) { switch (mode) { case Transceiver::AM: return "am"; case Transceiver::CW: return "cw"; // case Transceiver::CW_R: return "CW-R"; case Transceiver::USB: return "usb"; case Transceiver::LSB: return "lsb"; // case Transceiver::FSK: return "RTTY"; // case Transceiver::FSK_R: return "RTTY-R"; case Transceiver::DIG_L: return "digl"; case Transceiver::DIG_U: return "digu"; case Transceiver::FM: return "wfm"; case Transceiver::DIG_FM: return "nfm"; default: break; } return ""; } static const QString SmTZ(";"); static const QString SmDP(":"); static const QString SmCM(","); static const QString SmTrue("true"); static const QString SmFalse("false"); // Command maps static const QString CmdDevice("device"); static const QString CmdReceiveOnly("receive_only"); static const QString CmdTrxCount("trx_count"); static const QString CmdChannelCount("channels_count"); static const QString CmdVfoLimits("vfo_limits"); static const QString CmdIfLimits("if_limits"); static const QString CmdModeList("modulations_list"); static const QString CmdMode("modulation"); static const QString CmdReady("ready"); static const QString CmdStop("stop"); static const QString CmdStart("start"); static const QString CmdPreamp("preamp"); static const QString CmdDds("dds"); static const QString CmdIf("if"); static const QString CmdTrx("trx"); static const QString CmdRxEnable("rx_enable"); static const QString CmdTxEnable("tx_enable"); static const QString CmdRxChannelEnable("rx_channel_enable"); static const QString CmdRitEnable("rit_enable"); static const QString CmdRitOffset("rit_offset"); static const QString CmdXitEnable("xit_enable"); static const QString CmdXitOffset("xit_offset"); static const QString CmdSplitEnable("split_enable"); static const QString CmdIqSR("iq_samplerate"); static const QString CmdIqStart("iq_start"); static const QString CmdIqStop("iq_stop"); static const QString CmdCWSpeed("cw_macros_speed"); static const QString CmdCWDelay("cw_macros_delay"); static const QString CmdSpot("spot"); static const QString CmdSpotDelete("spot_delete"); static const QString CmdFilterBand("rx_filter_band"); static const QString CmdVFO("vfo"); static const QString CmdVersion("protocol"); //protocol:esdr,1.2; static const QString CmdTune("tune"); static const QString CmdRxMute("rx_mute"); static const QString CmdSmeter("rx_smeter"); static const QString CmdPower("tx_power"); static const QString CmdSWR("tx_swr"); static const QString CmdECoderRX("ecoder_switch_rx"); static const QString CmdECoderVFO("ecoder_switch_channel"); static const QString CmdAudioSR("audio_samplerate"); static const QString CmdAudioStart("audio_start"); static const QString CmdAudioStop("audio_stop"); static const QString CmdAppFocus("app_focus"); static const QString CmdVolume("volume"); static const QString CmdSqlEnable("sql_enable"); static const QString CmdSqlLevel("sql_level"); static const QString CmdDrive("drive"); static const QString CmdTuneDrive("tune_drive"); static const QString CmdMute("mute"); static const QString CmdRxSensorsEnable("rx_sensors_enable"); static const QString CmdTxSensorsEnable("tx_sensors_enable"); static const QString CmdRxSensors("rx_sensors"); static const QString CmdTxSensors("tx_sensors"); static const QString CmdAgcMode("agc_mode"); static const QString CmdAgcGain("agc_gain"); static const QString CmdLock("lock"); } extern "C" { void fil4_(qint16*, qint32*, qint16*, qint32*, float*); } extern dec_data dec_data; extern float gran(); // Noise generator (for tests only) #define RAMP_INCREMENT 64 // MUST be an integral factor of 2^16 #if defined (WSJT_SOFT_KEYING) # define SOFT_KEYING WSJT_SOFT_KEYING #else # define SOFT_KEYING 1 #endif double constexpr TCITransceiver::m_twoPi; void TCITransceiver::register_transceivers (TransceiverFactory::Transceivers * registry, unsigned id1, unsigned id2) { (*registry)[TCI_transceiver_1_name] = TransceiverFactory::Capabilities {id1, TransceiverFactory::Capabilities::tci, true}; (*registry)[TCI_transceiver_2_name] = TransceiverFactory::Capabilities {id2, TransceiverFactory::Capabilities::tci, true}; } static constexpr quint32 AudioHeaderSize = 16u*sizeof(quint32); TCITransceiver::TCITransceiver (std::unique_ptr wrapped,QString const& rignr, QString const& address, bool use_for_ptt, int poll_interval, QObject * parent) : PollingTransceiver {poll_interval, parent} , wrapped_ {std::move (wrapped)} , rx_ {rignr} , server_ {address} , use_for_ptt_ {use_for_ptt} , errortable {tr("ConnectionRefused"), tr("RemoteHostClosed"), tr("HostNotFound"), tr("SocketAccess"), tr("SocketResource"), tr("SocketTimeout"), tr("DatagramTooLarge"), tr("Network"), tr("AddressInUse"), tr("SocketAddressNotAvailable"), tr("UnsupportedSocketOperation"), tr("UnfinishedSocketOperation"), tr("ProxyAuthenticationRequired"), tr("SslHandshakeFailed"), tr("ProxyConnectionRefused"), tr("ProxyConnectionClosed"), tr("ProxyConnectionTimeout"), tr("ProxyNotFound"), tr("ProxyProtocol"), tr("Operation"), tr("SslInternal"), tr("SslInvalidUserData"), tr("Temporary"), tr("UnknownSocket") } , error_ {""} , do_snr_ {(poll_interval & do__snr) == do__snr} , do_pwr_ {(poll_interval & do__pwr) == do__pwr} , rig_power_ {(poll_interval & rig__power) == rig__power} , rig_power_off_ {(poll_interval & rig__power_off) == rig__power_off} , tci_audio_ {(poll_interval & tci__audio) == tci__audio} , commander_ {nullptr} , tci_timer1_ {nullptr} , tci_loop1_ {nullptr} , tci_timer2_ {nullptr} , tci_loop2_ {nullptr} , tci_timer3_ {nullptr} , tci_loop3_ {nullptr} , wavptr_ {nullptr} , m_jtdxtime {nullptr} , m_downSampleFactor {4} , m_buffer ((m_downSampleFactor > 1) ? new short [max_buffer_size * m_downSampleFactor] : nullptr) , m_quickClose {false} , m_phi {0.0} , m_toneSpacing {0.0} , m_fSpread {0.0} , m_state {Idle} , m_tuning {false} , m_cwLevel {false} , m_j0 {-1} , m_toneFrequency0 {1500.0} , debug_file_ {QDir(QStandardPaths::writableLocation (QStandardPaths::DataLocation)).absoluteFilePath ("jtdx_debug.txt").toStdString()} , wav_file_ {QDir(QStandardPaths::writableLocation (QStandardPaths::DataLocation)).absoluteFilePath ("tx.wav").toStdString()} { m_samplesPerFFT = 6912 / 2; tci_Ready = false; trxA = 0; trxB = 0; cntIQ = 0; bIQ = false; inConnected = false; audioSampleRate = 48000u; mapCmd_[CmdDevice] = Cmd_Device; mapCmd_[CmdReceiveOnly] = Cmd_ReceiveOnly; mapCmd_[CmdTrxCount] = Cmd_TrxCount; mapCmd_[CmdChannelCount] = Cmd_ChannelCount; mapCmd_[CmdVfoLimits] = Cmd_VfoLimits; mapCmd_[CmdIfLimits] = Cmd_IfLimits; mapCmd_[CmdModeList] = Cmd_ModeList; mapCmd_[CmdMode] = Cmd_Mode; mapCmd_[CmdReady] = Cmd_Ready; mapCmd_[CmdStop] = Cmd_Stop; mapCmd_[CmdStart] = Cmd_Start; mapCmd_[CmdPreamp] = Cmd_Preamp; mapCmd_[CmdDds] = Cmd_Dds; mapCmd_[CmdIf] = Cmd_If; mapCmd_[CmdTrx] = Cmd_Trx; mapCmd_[CmdRxEnable] = Cmd_RxEnable; mapCmd_[CmdTxEnable] = Cmd_TxEnable; mapCmd_[CmdRxChannelEnable] = Cmd_RxChannelEnable; mapCmd_[CmdRitEnable] = Cmd_RitEnable; mapCmd_[CmdRitOffset] = Cmd_RitOffset; mapCmd_[CmdXitEnable] = Cmd_XitEnable; mapCmd_[CmdXitOffset] = Cmd_XitOffset; mapCmd_[CmdSplitEnable] = Cmd_SplitEnable; mapCmd_[CmdIqSR] = Cmd_IqSR; mapCmd_[CmdIqStart] = Cmd_IqStart; mapCmd_[CmdIqStop] = Cmd_IqStop; mapCmd_[CmdCWSpeed] = Cmd_CWSpeed; mapCmd_[CmdCWDelay] = Cmd_CWDelay; mapCmd_[CmdFilterBand] = Cmd_FilterBand; mapCmd_[CmdVFO] = Cmd_VFO; mapCmd_[CmdVersion] = Cmd_Version; mapCmd_[CmdTune] = Cmd_Tune; mapCmd_[CmdRxMute] = Cmd_RxMute; mapCmd_[CmdSmeter] = Cmd_Smeter; mapCmd_[CmdPower] = Cmd_Power; mapCmd_[CmdSWR] = Cmd_SWR; mapCmd_[CmdECoderRX] = Cmd_ECoderRX; mapCmd_[CmdECoderVFO] = Cmd_ECoderVFO; mapCmd_[CmdAudioSR] = Cmd_AudioSR; mapCmd_[CmdAudioStart] = Cmd_AudioStart; mapCmd_[CmdAudioStop] = Cmd_AudioStop; mapCmd_[CmdAppFocus] = Cmd_AppFocus; mapCmd_[CmdVolume] = Cmd_Volume; mapCmd_[CmdSqlEnable] = Cmd_SqlEnable; mapCmd_[CmdSqlLevel] = Cmd_SqlLevel; mapCmd_[CmdDrive] = Cmd_Drive; mapCmd_[CmdTuneDrive] = Cmd_TuneDrive; mapCmd_[CmdMute] = Cmd_Mute; mapCmd_[CmdRxSensorsEnable] = Cmd_RxSensorsEnable; mapCmd_[CmdTxSensorsEnable] = Cmd_TxSensorsEnable; mapCmd_[CmdRxSensors] = Cmd_RxSensors; mapCmd_[CmdTxSensors] = Cmd_TxSensors; mapCmd_[CmdAgcMode] = Cmd_AgcMode; mapCmd_[CmdAgcGain] = Cmd_AgcGain; mapCmd_[CmdLock] = Cmd_Lock; } void TCITransceiver::onConnected() { inConnected = true; // printf("%s(%0.1f) TCI connected\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset()); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI connected\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset()); fclose (pFile); #endif } void TCITransceiver::onDisconnected() { inConnected = false; // printf("%s(%0.1f) TCI disconnected\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset()); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI disconnected\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset()); fclose (pFile); #endif } void TCITransceiver::onError(QAbstractSocket::SocketError err) { //qDebug() << "WebInThread::onError"; // printf("%s(%0.1f) TCI error:%d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),err); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI error:%d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),err); fclose (pFile); #endif error_ = tr ("TCI websocket error: %1").arg (errortable.at (err)); } int TCITransceiver::do_start (JTDXDateTime * jtdxtime) { if (tci_audio_) QThread::currentThread()->setPriority(QThread::HighPriority); // printf("do_start tci_Ready:%d\n",tci_Ready); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"do_start tci_Ready:%d\n",tci_Ready); fclose (pFile); #endif TRACE_CAT ("TCITransceiver", "starting"); m_jtdxtime = jtdxtime; if (wrapped_) wrapped_->start (0,m_jtdxtime); url_.setUrl("ws://" + server_); //server_ if (url_.host() == "") url_.setHost("localhost"); if (url_.port() == -1) url_.setPort(40001); if (!commander_) { commander_ = new QWebSocket {}; // QObject takes ownership // printf ("commander created"); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"commander created"); fclose (pFile); #endif connect(commander_,SIGNAL(connected()),this,SLOT(onConnected())); connect(commander_,SIGNAL(disconnected()),this,SLOT(onDisconnected())); connect(commander_,SIGNAL(binaryMessageReceived(QByteArray)),this,SLOT(onBinaryReceived(QByteArray))); connect(commander_,SIGNAL(textMessageReceived(QString)),this,SLOT(onMessageReceived(QString))); connect(commander_,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(onError(QAbstractSocket::SocketError))); } if (!tci_loop1_) { tci_loop1_ = new QEventLoop {this}; } if (!tci_timer1_) { tci_timer1_ = new QTimer {this}; tci_timer1_ -> setSingleShot(true); connect( tci_timer1_, &QTimer::timeout, tci_loop1_, &QEventLoop::quit); connect( this, &TCITransceiver::tci_done1, tci_loop1_, &QEventLoop::quit); } if (!tci_loop2_) { tci_loop2_ = new QEventLoop {this}; } if (!tci_timer2_) { tci_timer2_ = new QTimer {this}; tci_timer2_ -> setSingleShot(true); connect( tci_timer2_, &QTimer::timeout, tci_loop2_, &QEventLoop::quit); connect( this, &TCITransceiver::tci_done2, tci_loop2_, &QEventLoop::quit); } if (!tci_loop3_) { tci_loop3_ = new QEventLoop {this}; } if (!tci_timer3_) { tci_timer3_ = new QTimer {this}; tci_timer3_ -> setSingleShot(true); connect( tci_timer3_, &QTimer::timeout, tci_loop3_, &QEventLoop::quit); connect( this, &TCITransceiver::tci_done3, tci_loop3_, &QEventLoop::quit); } tx_fifo = 0; tx_top_ = true; tci_Ready = false; ESDR3 = false; HPSDR = false; band_change = false; trxA = 0; trxB = 0; busy_rx_frequency_ = false; busy_mode_ = false; busy_other_frequency_ = false; busy_split_ = false; busy_drive_ = false; busy_PTT_ = false; busy_rx2_ = false; rx2_ = false; requested_rx2_ = false; started_rx2_ = false; split_ = false; requested_split_ = false; started_split_ = false; PTT_ = false; requested_PTT_ = false; mode_ = ""; requested_mode_ = ""; started_mode_ = ""; requested_rx_frequency_ = ""; rx_frequency_ = ""; requested_other_frequency_ = ""; other_frequency_ = ""; requested_drive_ = ""; drive_ = ""; level_ = -54; power_ = 0; swr_ = 0; m_bufferPos = 0; m_downSampleFactor =4; m_ns = 999; audio_ = false; requested_stream_audio_ = false; stream_audio_ = false; _power_ = false; // printf ("%s(%0.1f) TCI open %s rig_power:%d rig_power_off:%d tci_audio:%d do_snr:%d do_pwr:%d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),url_.toString().toStdString().c_str(),rig_power_,rig_power_off_,tci_audio_,do_snr_,do_pwr_); #if JTDX_DEBUG_TO_FILE pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI open %s rig_power:%d rig_power_off:%d tci_audio:%d do_snr:%d do_pwr:%d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),url_.toString().toStdString().c_str(),rig_power_,rig_power_off_,tci_audio_,do_snr_,do_pwr_); fclose (pFile); #endif commander_->open (url_); mysleep1 (1500); // if (ESDR3) mysleep1 (500); else mysleep1 (100); mysleep1 (210); if (HPSDR) { busy_split_ = true; const QString cmd = CmdSplitEnable + SmDP + rx_ + SmTZ; sendTextMessage(cmd); mysleep2(500); busy_split_ = false; } if (error_.isEmpty()) { tci_Ready = true; if (!_power_) { if (rig_power_) { rig_power(true); mysleep1(1000); if(!_power_) throw error {tr ("TCI SDR could not be switched on")}; } else { tci_Ready = false; throw error {tr ("TCI SDR is not switched on")}; } } if (rx_ == "1" && !rx2_) { rx2_enable (true); if (!rx2_) { tci_Ready = false; throw error {tr ("TCI RX2 could not be enabled")}; } } if (tci_audio_) { stream_audio (true); mysleep1(500); if (!stream_audio_) { tci_Ready = false; throw error {tr ("TCI Audio could not be switched on")}; } } if (ESDR3) { const QString cmd = CmdRxSensorsEnable + SmDP + (do_snr_ ? "true" : "false") + SmCM + "500" + SmTZ; sendTextMessage(cmd); } else if (do_snr_) { const QString cmd = CmdSmeter + SmDP + rx_ + SmCM + "0" + SmTZ; sendTextMessage(cmd); } if (!requested_rx_frequency_.isEmpty()) do_frequency(string_to_frequency (requested_rx_frequency_),get_mode(true),false); if (!requested_other_frequency_.isEmpty()) do_tx_frequency(string_to_frequency (requested_other_frequency_),get_mode(true),false); else if (requested_split_ != split_) {/*printf("splt from start %d\n",requested_split_);*/ rig_split();} // split_ = requested_split_; mysleep2(100);} if (!requested_drive_.isEmpty() && requested_drive_ != drive_) { busy_drive_ = true; if (ESDR3) { const QString cmd = CmdDrive + SmDP + rx_ + SmCM + requested_drive_ + SmTZ; sendTextMessage(cmd); } else { const QString cmd = CmdDrive + SmDP + requested_drive_ + SmTZ; sendTextMessage(cmd); } } do_poll (); if (ESDR3) { const QString cmd = CmdTxSensorsEnable + SmDP + (do_pwr_ ? "true" : "false") + SmCM + "500" + SmTZ; sendTextMessage(cmd); } if (stream_audio_) do_audio(true); TRACE_CAT ("TCITransceiver", "started"); // printf("%s(%0.1f) TCI Transceiver started\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset()); #if JTDX_DEBUG_TO_FILE pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI Transceiver started\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset()); fclose (pFile); #endif return 0; } else { // printf("%s(%0.1f) TCI Transceiver not started %s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),error_.toStdString().c_str()); #if JTDX_DEBUG_TO_FILE pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI Transceiver not started %s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),error_.toStdString().c_str()); fclose (pFile); #endif if (error_.isEmpty()) throw error {tr ("TCI could not be opened")}; else throw error {error_}; } } void TCITransceiver::do_stop () { // printf ("TCI close\n"); if (!commander_) return; #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"TCI close\n"); #endif if (stream_audio_ && tci_Ready && inConnected && _power_) { stream_audio (false); mysleep1(500); // printf ("TCI audio closed\n"); #if JTDX_DEBUG_TO_FILE fprintf (pFile,"TCI audio closed\n"); #endif } if (tci_Ready && inConnected && _power_) { requested_other_frequency_ = ""; if (started_split_ != split_) {requested_split_ = started_split_; rig_split();} if (started_mode_ != mode_) sendTextMessage(mode_to_command(started_mode_)); if (!started_rx2_ && rx2_) { rx2_enable (false); } } if (_power_ && rig_power_off_ && tci_Ready && inConnected && _power_) { rig_power(false); mysleep1(500); // printf ("TCI power down\n"); #if JTDX_DEBUG_TO_FILE fprintf (pFile,"TCI power down\n"); #endif } tci_Ready = false; if (commander_) { if (inConnected) commander_->close(QWebSocketProtocol::CloseCodeNormal,"end"); delete commander_, commander_ = nullptr; // printf ("commander "); #if JTDX_DEBUG_TO_FILE fprintf (pFile,"commander "); #endif } if (tci_timer1_) { if (tci_timer1_->isActive()) tci_timer1_->stop(); delete tci_timer1_, tci_timer1_ = nullptr; // printf ("timer1 "); #if JTDX_DEBUG_TO_FILE fprintf (pFile,"timer1 "); #endif } if (tci_loop1_) { tci_loop1_->quit(); delete tci_loop1_, tci_loop1_ = nullptr; // printf ("loop1 "); #if JTDX_DEBUG_TO_FILE fprintf (pFile,"loop1 "); #endif } if (tci_timer2_) { if (tci_timer2_->isActive()) tci_timer2_->stop(); delete tci_timer2_, tci_timer2_ = nullptr; // printf ("timer2 "); #if JTDX_DEBUG_TO_FILE fprintf (pFile,"timer2 "); #endif } if (tci_loop2_) { tci_loop2_->quit(); delete tci_loop2_, tci_loop2_ = nullptr; // printf ("loop2 "); #if JTDX_DEBUG_TO_FILE fprintf (pFile,"loop2 "); #endif } if (tci_timer3_) { if (tci_timer3_->isActive()) tci_timer3_->stop(); delete tci_timer3_, tci_timer3_ = nullptr; // printf ("timer3 "); #if JTDX_DEBUG_TO_FILE fprintf (pFile,"timer3 "); #endif } if (tci_loop3_) { tci_loop3_->quit(); delete tci_loop3_, tci_loop3_ = nullptr; // printf ("loop3 "); #if JTDX_DEBUG_TO_FILE fprintf (pFile,"loop3 "); #endif } if (wrapped_) wrapped_->stop (); TRACE_CAT ("TCITransceiver", "stopped"); // printf ("deleted\nTCI closed\n"); #if JTDX_DEBUG_TO_FILE fprintf (pFile,"deleted\nTCI closed\n"); fclose (pFile); #endif } void TCITransceiver::onMessageReceived(const QString &str) { //qDebug() << "From WEB" << str; QStringList cmd_list = str.split(";", SkipEmptyParts); #if JTDX_DEBUG_TO_FILE FILE * pFile; #endif for (QString cmds : cmd_list){ QStringList cmd = cmds.split(":", SkipEmptyParts); QStringList args = cmd.last().split(",", SkipEmptyParts); Tci_Cmd idCmd = mapCmd_[cmd.first()]; // if (idCmd != Cmd_Power && idCmd != Cmd_SWR && idCmd != Cmd_Smeter && idCmd != Cmd_AppFocus && idCmd != Cmd_RxSensors && idCmd != Cmd_TxSensors) { printf ("%s(%0.1f) TCI message received:|%s| ",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),str.toStdString().c_str()); printf("idCmd : %d args : %s\n",idCmd,args.join("|").toStdString().c_str());} #if JTDX_DEBUG_TO_FILE if (idCmd != Cmd_Power && idCmd != Cmd_SWR && idCmd != Cmd_Smeter && idCmd != Cmd_AppFocus && idCmd != Cmd_RxSensors && idCmd != Cmd_TxSensors) { pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI message received:|%s| ",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),str.toStdString().c_str()); fprintf (pFile,"idCmd : %d args : %s\n",idCmd,args.join("|").toStdString().c_str()); fclose (pFile); } #endif //qDebug() << cmds << idCmd; if (idCmd <=0) continue; switch (idCmd) { case Cmd_Smeter: if(args.at(0)==rx_ && args.at(1) == "0") level_ = args.at(2).toInt() + 73; break; case Cmd_RxSensors: if(args.at(0)==rx_) level_ = args.at(1).split(".")[0].toInt() + 73; // printf("Smeter=%d\n",level_); break; case Cmd_TxSensors: if(args.at(0)==rx_) { power_ = 10 * args.at(3).split(".")[0].toInt() + args.at(3).split(".")[1].toInt(); swr_ = 10 * args.at(4).split(".")[0].toInt() + args.at(4).split(".")[1].toInt(); // printf("Power=%d SWR=%d\n",power_,swr_); } break; case Cmd_SWR: // printf("%s(%0.1f) Cmd_SWR : %s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),args.join("|").toStdString().c_str()); swr_ = 10 * args.at(0).split(".")[0].toInt() + args.at(0).split(".")[1].toInt(); break; case Cmd_Power: power_ = 10 * args.at(0).split(".")[0].toInt() + args.at(0).split(".")[1].toInt(); // printf("%s(%0.1f) Cmd_Power : %s %d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),args.join("|").toStdString().c_str(),power_); break; case Cmd_VFO: // printf("%s(%0.1f) Cmd_VFO : %s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),args.join("|").toStdString().c_str()); // printf("band_change:%d busy_other_frequency_:%d timer1_remaining:%d timer2_remaining:%d",band_change,busy_other_frequency_,tci_timer1_->remainingTime(),tci_timer2_->remainingTime()); #if JTDX_DEBUG_TO_FILE pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) Cmd_VFO : %s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),args.join("|").toStdString().c_str()); fprintf (pFile,"band_change:%d busy_other_frequency_:%d timer1_remaining:%d timer2_remaining:%d",band_change,busy_other_frequency_,tci_timer1_->remainingTime(),tci_timer2_->remainingTime()); #endif if(args.at(0)==rx_ && args.at(1) == "0") { if (args.at(2).left(1) != "-") rx_frequency_ = args.at(2); if (!tci_Ready && requested_rx_frequency_.isEmpty()) {requested_rx_frequency_ = rx_frequency_; } if (busy_rx_frequency_ && !band_change) { // printf (" cmdvfo0 done1"); #if JTDX_DEBUG_TO_FILE fprintf (pFile," cmdvfo0 done1"); #endif tci_done1(); } else if (!tci_timer2_->isActive() && split_) { // printf (" cmdvfo0 timer2 start 210"); #if JTDX_DEBUG_TO_FILE fprintf (pFile," cmdvfo0 timer2 start 210"); #endif tci_timer2_->start(210); } } else if (args.at(0)==rx_ && args.at(1) == "1") { if (args.at(2).left(1) != "-") other_frequency_ = args.at(2); // if (!tci_Ready && requested_other_frequency_.isEmpty()) requested_other_frequency_ = other_frequency_; if (band_change && tci_timer1_->isActive()) { // printf (" cmdvfo1 done1"); #if JTDX_DEBUG_TO_FILE fprintf (pFile," cmdvfo1 done1"); #endif band_change = false; tci_timer2_->start(210); tci_done1(); } else if (busy_other_frequency_) { // printf (" cmdvfo1 done2"); #if JTDX_DEBUG_TO_FILE fprintf (pFile," cmdvfo1 done2"); #endif tci_done2(); } else if (tci_timer2_->isActive()) { // printf (" cmdvfo1 timer2 reset 210"); #if JTDX_DEBUG_TO_FILE fprintf (pFile," cmdvfo1 timer2 reset 210"); #endif tci_timer2_->start(210); } else if (other_frequency_ != requested_other_frequency_ && tci_Ready && split_ && !tci_timer2_->isActive()) { // printf (" cmdvfo1 timer2 start 210"); #if JTDX_DEBUG_TO_FILE fprintf (pFile," cmdvfo1 timer2 start 210"); #endif tci_timer2_->start(210); } } // printf("->%d\n",tci_timer2_->remainingTime()); #if JTDX_DEBUG_TO_FILE fprintf(pFile,"->%d\n",tci_timer2_->remainingTime()); fclose (pFile); #endif break; case Cmd_Mode: // printf("%s(%0.1f) Cmd_Mode : %s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),args.join("|").toStdString().c_str()); #if JTDX_DEBUG_TO_FILE pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) Cmd_Mode : %s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),args.join("|").toStdString().c_str()); fclose (pFile); #endif if(args.at(0)==rx_) { if (ESDR3 || HPSDR) { if (args.at(1) == "0" ) mode_ = args.at(2).toLower(); else mode_ = args.at(1).toLower(); } else mode_ = args.at(1); if (started_mode_.isEmpty()) started_mode_ = mode_; if (busy_mode_) tci_done1(); else if (!requested_mode_.isEmpty() && requested_mode_ != mode_ && !band_change) { sendTextMessage(mode_to_command(requested_mode_)); } } break; case Cmd_SplitEnable: // printf("%s(%0.1f) Cmd_SplitEnable : %s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),args.join("|").toStdString().c_str()); #if JTDX_DEBUG_TO_FILE pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) Cmd_SplitEnable : %s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),args.join("|").toStdString().c_str()); fclose (pFile); #endif if(args.at(0)==rx_) { if (args.at(1) == "false") split_ = false; else if (args.at(1) == "true") split_ = true; if (!tci_Ready) {started_split_ = split_;} else if (busy_split_) tci_done2(); else if (requested_split_ != split_ && !tci_timer2_->isActive()) { tci_timer2_->start(210); rig_split(); } } break; case Cmd_Drive: // printf("%s(%0.1f) Cmd_Drive : %s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),args.join("|").toStdString().c_str()); #if JTDX_DEBUG_TO_FILE pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) Cmd_Drive : %s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),args.join("|").toStdString().c_str()); fclose (pFile); #endif if((!ESDR3 && !HPSDR) || args.at(0)==rx_) { if (ESDR3 || HPSDR) drive_ = args.at(1); else drive_ = args.at(0); if (requested_drive_.isEmpty()) requested_drive_ = drive_; busy_drive_ = false; } break; case Cmd_Trx: // printf("%s(%0.1f) Cmd_Trx : %s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),args.join("|").toStdString().c_str()); #if JTDX_DEBUG_TO_FILE pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) Cmd_Trx : %s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),args.join("|").toStdString().c_str()); fclose (pFile); #endif if(args.at(0)==rx_) { if (args.at(1) == "false") PTT_ = false; else if (args.at(1) == "true") PTT_ = true; if (tci_Ready && requested_PTT_ == PTT_) tci_done3(); else if (tci_Ready && !PTT_) { requested_PTT_ = PTT_; update_PTT(PTT_); power_ = 0; if (do_pwr_) update_power (0); swr_ = 0; if (do_pwr_) update_swr (0); } } break; case Cmd_AudioStart: // printf("%s(%0.1f) Cmd_AudioStart : %s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),args.join("|").toStdString().c_str()); #if JTDX_DEBUG_TO_FILE pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) Cmd_AudioStart : %s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),args.join("|").toStdString().c_str()); fclose (pFile); #endif if(args.at(0)==rx_) { stream_audio_ = true; if (tci_Ready) { //printf ("cmdaudiostart done1\n"); tci_done1();} } break; case Cmd_RxEnable: // printf("%s(%0.1f) Cmd_RxEnable : %s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),args.join("|").toStdString().c_str()); #if JTDX_DEBUG_TO_FILE pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) Cmd_RxEnable : %s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),args.join("|").toStdString().c_str()); fclose (pFile); #endif if(args.at(0)=="1") { if (args.at(1) == "false") rx2_ = false; else if (args.at(1) == "true") rx2_ = true; if(!tci_Ready) {requested_rx2_ = rx2_; started_rx2_ = rx2_;} else if (tci_Ready && busy_rx2_ && requested_rx2_ == rx2_) tci_done1(); } break; case Cmd_AudioStop: // printf("%s(%0.1f) CmdAudioStop : %s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),args.join("|").toStdString().c_str()); #if JTDX_DEBUG_TO_FILE pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) CmdAudioStop : %s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),args.join("|").toStdString().c_str()); fclose (pFile); #endif if(args.at(0)==rx_) { stream_audio_ = false; if (tci_Ready) { //printf ("cmdaudiostop done1\n"); tci_done1();} } break; case Cmd_Start: // printf("%s(%0.1f) CmdStart : %s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),args.join("|").toStdString().c_str()); #if JTDX_DEBUG_TO_FILE pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) CmdStart : %s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),args.join("|").toStdString().c_str()); fclose (pFile); #endif _power_ = true; // printf ("cmdstart done1\n"); if (tci_Ready) tci_done1(); break; case Cmd_Stop: // printf("%s(%0.1f) CmdStop : %s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),args.join("|").toStdString().c_str()); #if JTDX_DEBUG_TO_FILE pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) CmdStop : %s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),args.join("|").toStdString().c_str()); fclose (pFile); #endif if (tci_Ready && PTT_) { PTT_ = false; requested_PTT_ = PTT_; update_PTT(PTT_); power_ = 0; if (do_pwr_) update_power (0); swr_ = 0; if (do_pwr_) update_swr (0); m_state = Idle; Q_EMIT tci_mod_active(m_state != Idle); } _power_ = false; if (tci_timer1_->isActive()) { /*printf ("cmdstop done1\n");*/ tci_done1();} else { tci_Ready = false; } break; case Cmd_Version: // printf("%s(%0.1f) CmdVersion : %s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),args.join("|").toStdString().c_str()); #if JTDX_DEBUG_TO_FILE pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) CmdVersion : %s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),args.join("|").toStdString().c_str()); fclose (pFile); #endif if(args.at(0)=="ExpertSDR3") ESDR3 = true; else if (args.at(0)=="Thetis") HPSDR = true; break; case Cmd_Device: // printf("%s(%0.1f) CmdDevice : %s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),args.join("|").toStdString().c_str()); #if JTDX_DEBUG_TO_FILE pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) CmdDevice : %s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),args.join("|").toStdString().c_str()); fclose (pFile); #endif if((args.at(0)=="SunSDR2DX" || args.at(0)=="SunSDR2PRO") && !ESDR3) tx_top_ = false; // printf ("tx_top_:%d\n",tx_top_); break; case Cmd_Ready: // printf("%s(%0.1f) CmdReady : %s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),args.join("|").toStdString().c_str()); #if JTDX_DEBUG_TO_FILE pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) CmdReady : %s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),args.join("|").toStdString().c_str()); fclose (pFile); #endif tci_done1(); break; default: break; } } } void TCITransceiver::sendTextMessage(const QString &message) { if (inConnected) commander_->sendTextMessage(message); } void TCITransceiver::onBinaryReceived(const QByteArray &data) { /* if (++cntIQ % 50 == 0){ bIQ = !bIQ; nIqBytes+=data.size(); printf("receiveIQ\n"); emit receiveIQ(bIQ,nIqBytes); nIqBytes = 0; } else { nIqBytes+=data.size(); } */ Data_Stream *pStream = (Data_Stream*)(data.data()); if (pStream->type != last_type) { // printf ("%s(%0.1f) binary received type=%d last_type=%d %d samplerate %d stream_size %d frame_size %d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),pStream->type,last_type,data.size(),pStream->sampleRate,pStream->length,data.size()); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) binary received type=%d last_type=%d %d samplerate %d stream_size %d frame_size %d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),pStream->type,last_type,data.size(),pStream->sampleRate,pStream->length,data.size()); fclose (pFile); #endif last_type = pStream->type; #if JTDX_DEBUG_TO_FILE if (last_type == TxChrono) { // audio transmit starts struct { char ariff[4]; //ChunkID: "RIFF" int nchunk; //ChunkSize: 36+SubChunk2Size char awave[4]; //Format: "WAVE" char afmt[4]; //Subchunk1ID: "fmt " int lenfmt; //Subchunk1Size: 16 short int nfmt2; //AudioFormat: 1 short int nchan2; //NumChannels: 1 int nsamrate; //SampleRate: 12000 int nbytesec; //ByteRate: SampleRate*NumChannels*BitsPerSample/8 short int nbytesam2; //BlockAlign: NumChannels*BitsPerSample/8 short int nbitsam2; //BitsPerSample: 16 char adata[4]; //Subchunk2ID: "data" int ndata; //Subchunk2Size: numSamples*NumChannels*BitsPerSample/8 } hdr; int npts=static_cast(m_period) * 48000; wavptr_ = fopen(wav_file_.c_str(),"wb"); if (wavptr_ != NULL) { // Write a WAV header hdr.ariff[0]='R'; hdr.ariff[1]='I'; hdr.ariff[2]='F'; hdr.ariff[3]='F'; hdr.nchunk=36 + 2*npts; hdr.awave[0]='W'; hdr.awave[1]='A'; hdr.awave[2]='V'; hdr.awave[3]='E'; hdr.afmt[0]='f'; hdr.afmt[1]='m'; hdr.afmt[2]='t'; hdr.afmt[3]=' '; hdr.lenfmt=16; hdr.nfmt2=1; hdr.nchan2=1; hdr.nsamrate=48000; hdr.nbytesec=2*48000; hdr.nbytesam2=2; hdr.nbitsam2=16; hdr.adata[0]='d'; hdr.adata[1]='a'; hdr.adata[2]='t'; hdr.adata[3]='a'; hdr.ndata=2*npts; fwrite(&hdr,sizeof(hdr),1,wavptr_); } } else if (last_type == RxAudioStream) { // audio switched back to resceive if (wavptr_ != NULL) { fclose(wavptr_); wavptr_ = nullptr; } } #endif } if (pStream->type == Iq_Stream){ bool tx = false; if (pStream->receiver == 0){ tx = trxA == 0; trxA = 1; } if (pStream->receiver == 1) { tx = trxB == 0; trxB = 1; } // printf("sendIqData\n"); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"sendIqData\n"); fclose (pFile); #endif emit sendIqData(pStream->receiver,pStream->length,pStream->data,tx); qDebug() << "IQ" << data.size() << pStream->length; } else if (pStream->type == RxAudioStream && audio_ && pStream->receiver == rx_.toUInt()){ // printf("%s(%0.1f) writeAudioData\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset()); writeAudioData(pStream->data,pStream->length); qDebug() << "Audio" << data.size() << pStream->length; } else if (pStream->type == TxChrono && pStream->receiver == rx_.toUInt()){ mtx_.lock(); tx_fifo += 1; tx_fifo &= 7; int ssize = AudioHeaderSize+pStream->length*sizeof(float)*2; // printf("%s(%0.1f) TxChrono ",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset()); quint16 tehtud; if (m_tx1[tx_fifo].size() != ssize) {m_tx1[tx_fifo].resize(ssize);/* m_tx1[tx_fifo].fill('\0x00');*/} Data_Stream * pOStream1 = (Data_Stream*)(m_tx1[tx_fifo].data()); pOStream1->receiver = pStream->receiver; pOStream1->sampleRate = pStream->sampleRate; pOStream1->format = pStream->format; pOStream1->codec = 0; pOStream1->crc = 0; pOStream1->length = pStream->length; pOStream1->type = TxAudioStream; // for (size_t i = 0; i < pStream->length; i++) pOStream1->data[i] = 0; // printf("%s(%0.1f) txAudioChrono %d %d %d",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),ssize,pStream->length,pStream->sampleRate); tehtud = readAudioData(pOStream1->data,pOStream1->length); // printf(" %s(%0.1f) tehtud%d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),tehtud); if (tehtud && tehtud != pOStream1->length) { quint16 valmis = tehtud; // printf("%s(%0.1f) Audio build 1 mismatch requested %d done %d",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),pOStream1->length,tehtud); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) Audio build 1 mismatch requested %d done %d",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),pOStream1->length,tehtud); #endif tehtud = readAudioData(pOStream1->data + valmis,pOStream1->length - valmis); // printf("got %d\n",tehtud); #if JTDX_DEBUG_TO_FILE fprintf (pFile,"got %d\n",tehtud); fclose (pFile); #endif // if (tehtud && tehtud != pOStream1->length - valmis) { // valmis += tehtud; // for (size_t i = 0; i < pOStream1->length - valmis; i++) pOStream1->data[i+valmis] = 0; // } // else if (tehtud == 0) for (size_t i = 0; i < pOStream1->length - valmis; i++) pOStream1->data[i+valmis] = 0; // } // else if (tehtud == 0) { // for (size_t i = 0; i < pStream->length; i++) pOStream1->data[i] = 0; } #if JTDX_DEBUG_TO_FILE if (wavptr_ != NULL) { static constexpr float K = 0x7FFF; for (size_t i = 0; i < pOStream1->length; i+=2) { qint16 value = static_cast(K*pOStream1->data[i]); fwrite(&value,2,1,wavptr_); } } #endif tx_fifo2 = tx_fifo; mtx_.unlock(); if (!inConnected || commander_->sendBinaryMessage(m_tx1[tx_fifo2]) != m_tx1[tx_fifo2].size()) { // printf("%s(%0.1f) Sent 1 loaded failed\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset()); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) Sent 1 loaded failed\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset()); fclose (pFile); #endif } }// else printf ("Unused binary message received type=%d receiver=%d\n",pStream->type,pStream->receiver); } void TCITransceiver::txAudioData(quint32 len, float * data) { QByteArray tx; // printf("%s(%0.1f) txAudioData %d %ld\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),len,(AudioHeaderSize+len*sizeof(float)*2)); tx.resize(AudioHeaderSize+len*sizeof(float)*2); // printf("%s(%0.1f) txAudioData %d %d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),len,tx.size()); // Data_Stream * pStream = reinterpret_cast(tx.data()); Data_Stream * pStream = (Data_Stream*)(tx.data()); pStream->receiver = 0; pStream->sampleRate = audioSampleRate; pStream->format = 3; pStream->codec = 0; pStream->crc = 0; pStream->length = len; pStream->type = TxAudioStream; memcpy(pStream->data,data,len*sizeof(float)*2); commander_->sendBinaryMessage(tx); } quint32 TCITransceiver::writeAudioData (float * data, qint32 maxSize) { static unsigned mstr0=999999; qint64 ms0 = m_jtdxtime->currentMSecsSinceEpoch2() % 86400000; //m_jtdxtime -> currentMSecsSinceEpoch2() % 86400000; unsigned mstr = ms0 % int(1000.0*m_period); // ms into the nominal Tx start time if(mstr < mstr0/2) { //When mstr has wrapped around to 0, restart the buffer dec_data.params.kin = 0; m_bufferPos = 0; // printf("%s(%0.1f) reset buffer mstr:%d mstr0:%d maxSize:%d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),mstr,mstr0,maxSize); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) reset buffer mstr:%d mstr0:%d maxSize:%d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),mstr,mstr0,maxSize); fclose (pFile); #endif } mstr0=mstr; // no torn frames Q_ASSERT (!(maxSize % static_cast (bytesPerFrame))); // these are in terms of input frames (not down sampled) size_t framesAcceptable ((sizeof (dec_data.d2) / sizeof (dec_data.d2[0]) - dec_data.params.kin) * m_downSampleFactor); size_t framesAccepted (qMin (static_cast (maxSize / bytesPerFrame), framesAcceptable)); if (framesAccepted < static_cast (maxSize / bytesPerFrame)) { qDebug () << "dropped " << maxSize / bytesPerFrame - framesAccepted << " frames of data on the floor!" << dec_data.params.kin << mstr; // printf("%s(%0.1f) dropped %ld frames of data %d %d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),maxSize / bytesPerFrame - framesAccepted,dec_data.params.kin,mstr); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) dropped %ld frames of data %d %d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),maxSize / bytesPerFrame - framesAccepted,dec_data.params.kin,mstr); fclose (pFile); #endif } for (unsigned remaining = framesAccepted; remaining; ) { size_t numFramesProcessed (qMin (m_samplesPerFFT * m_downSampleFactor - m_bufferPos, remaining)); if(m_downSampleFactor > 1) { // printf ("%s(%0.1f) writeAudioData maxs %d bytesPerFrame %ld Accepted %ld remaining %d Processed %ld Bufferpos %d kin %d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(), // m_jtdxtime->GetOffset(),maxSize,bytesPerFrame,framesAccepted,remaining,numFramesProcessed,m_bufferPos,dec_data.params.kin); store (&data[(framesAccepted - remaining) * bytesPerFrame], numFramesProcessed, &m_buffer[m_bufferPos]); m_bufferPos += numFramesProcessed; if(m_bufferPos==m_samplesPerFFT*m_downSampleFactor) { qint32 framesToProcess (m_samplesPerFFT * m_downSampleFactor); qint32 framesAfterDownSample (m_samplesPerFFT); if(m_downSampleFactor > 1 && dec_data.params.kin>=0 && dec_data.params.kin < (NTMAX*12000 - framesAfterDownSample)) { fil4_(&m_buffer[0], &framesToProcess, &dec_data.d2[dec_data.params.kin], &framesAfterDownSample, &dec_data.dd2[dec_data.params.kin]); dec_data.params.kin += framesAfterDownSample; } else { // qDebug() << "framesToProcess = " << framesToProcess; // qDebug() << "dec_data.params.kin = " << dec_data.params.kin; // qDebug() << "secondInPeriod = " << secondInPeriod(); // qDebug() << "framesAfterDownSample" << framesAfterDownSample; } // printf("%s(%0.1f) frameswritten %d downSampleFactor %d samplesPerFFT %d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),dec_data.params.kin,m_downSampleFactor,m_samplesPerFFT); Q_EMIT tciframeswritten (dec_data.params.kin); // printf("%s(%0.1f) frameswritten done\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset()); m_bufferPos = 0; } } else { // printf ("%s(%0.1f) writeAudioData2 maxs %d bytesPerFrame %ld Accepted %ld remaining %d Processed %ld Bufferpos %d kin %d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),maxSize,bytesPerFrame,framesAccepted,remaining,numFramesProcessed,m_bufferPos,dec_data.params.kin); store (&data[(framesAccepted - remaining) * bytesPerFrame], numFramesProcessed, &dec_data.d2[dec_data.params.kin]); m_bufferPos += numFramesProcessed; dec_data.params.kin += numFramesProcessed; if (m_bufferPos == static_cast (m_samplesPerFFT)) { // printf("%s(%0.1f) frameswritten2 %d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),dec_data.params.kin); Q_EMIT tciframeswritten (dec_data.params.kin); // printf("%s(%0.1f) frameswritten2 done\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset()); m_bufferPos = 0; } } remaining -= numFramesProcessed; } return maxSize; // we drop any data past the end of the buffer on // the floor until the next period starts } void TCITransceiver::rx2_enable (bool on) { // printf ("%s(%0.1f) TCI rx2_enable:%d->%d busy:%d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),rx2_,on,busy_rx2_); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI rx2_enable:%d->%d busy:%d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),rx2_,on,busy_rx2_); fclose (pFile); #endif if (busy_rx2_) return; requested_rx2_ = on; busy_rx2_ = true; const QString cmd = CmdRxEnable + SmDP + "1" + SmCM + (requested_rx2_ ? "true" : "false") + SmTZ; sendTextMessage(cmd); mysleep1(1000); busy_rx2_ = false; } void TCITransceiver::rig_split () { // printf ("%s(%0.1f) TCI rig_split:%d->%d busy:%d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),split_,requested_split_,busy_split_); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI rig_split:%d->%d busy:%d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),split_,requested_split_,busy_split_); fclose (pFile); #endif if (busy_split_) return; if (tci_timer2_->isActive()) mysleep2(0); busy_split_ = true; const QString cmd = CmdSplitEnable + SmDP + rx_ + SmCM + (requested_split_ ? "true" : "false") + SmTZ; sendTextMessage(cmd); mysleep2(500); busy_split_ = false; if (requested_split_ == split_) update_split (split_); else { // printf ("%s(%0.1f) TCI failed set split:%d->%d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),split_,requested_split_); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI failed set split:%d->%d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),split_,requested_split_); fclose (pFile); #endif error_ = tr ("TCI failed set split"); } } void TCITransceiver::rig_power (bool on) { TRACE_CAT ("TCITransceiver", on << state ()); // printf ("%s(%0.1f) TCI rig_power:%d _power_:%d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),on,_power_); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI rig_power:%d _power_:%d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),on,_power_); fclose (pFile); #endif if (on != _power_) { if (on) { const QString cmd = CmdStart + SmTZ; sendTextMessage(cmd); } else { const QString cmd = CmdStop + SmTZ; sendTextMessage(cmd); } } } void TCITransceiver::stream_audio (bool on) { TRACE_CAT ("TCITransceiver", on << state ()); // printf ("%s(%0.1f) TCI stream_audio:%d stream_audio_:%d requested_stream_audio_:%d rx_=%s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),on,stream_audio_,requested_stream_audio_,rx_.toStdString().c_str()); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI stream_audio:%d stream_audio_:%d requested_stream_audio_:%d rx_=%s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),on,stream_audio_,requested_stream_audio_,rx_.toStdString().c_str()); fclose (pFile); #endif if (on != stream_audio_ && tci_Ready) { requested_stream_audio_ = on; if (on) { const QString cmd = CmdAudioStart + SmDP + rx_ + SmTZ; sendTextMessage(cmd); } else { const QString cmd = CmdAudioStop + SmDP + rx_ + SmTZ; sendTextMessage(cmd); } } } void TCITransceiver::do_audio (bool on) { TRACE_CAT ("TCITransceiver", on << state ()); // printf ("%s(%0.1f) TCI do_audio:%d audio_:%d state:%d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),on,audio_,state().audio()); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI do_audio:%d audio_:%d state:%d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),on,audio_,state().audio()); fclose (pFile); #endif if (on) { dec_data.params.kin = 0; m_bufferPos = 0; } audio_ = on; } void TCITransceiver::do_period (double period) { TRACE_CAT ("TCITransceiver", period << state ()); // printf ("%s(%0.1f) TCI do_period:%0.1f m_period_:%0.1f state:%0.1f\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),period,m_period,state().period()); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI do_period:%0.1f m_period_:%0.1f state:%0.1f\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),period,m_period,state().period()); fclose (pFile); #endif m_period = period; } void TCITransceiver::do_txvolume (qreal volume) { TRACE_CAT ("TCITransceiver", volume << state ()); QString drive = QString::number(round(100 - volume * 2.2222222)); // printf ("%s(%0.1f) TCI tci_Ready:%d do_txvolume:%0.1f state:%0.1f drive:%s drive_:%s drive_busy:%d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),tci_Ready,volume,state().volume(),drive.toStdString().c_str(),drive_.toStdString().c_str(),busy_drive_); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI tci_Ready:%d do_txvolume:%0.1f state:%0.1f drive:%s drive_:%s drive_busy:%d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),tci_Ready,volume,state().volume(),drive.toStdString().c_str(),drive_.toStdString().c_str(),busy_drive_); fclose (pFile); #endif requested_drive_ = drive; if (busy_drive_ || !tci_Ready || drive_ == drive) { if (busy_drive_) busy_drive_ = false; } else { busy_drive_ = true; if (ESDR3) { const QString cmd = CmdDrive + SmDP + rx_ + SmCM + drive + SmTZ; sendTextMessage(cmd); } else { const QString cmd = CmdDrive + SmDP + drive + SmTZ; sendTextMessage(cmd); } } } void TCITransceiver::do_blocksize (qint32 blocksize) { TRACE_CAT ("TCITransceiver", blocksize << state ()); // printf ("%s(%0.1f) TCI do_blocksize:%d m_samplesPerFFT:%d state:%d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),blocksize,m_samplesPerFFT,state().blocksize()); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI do_blocksize:%d m_samplesPerFFT:%d state:%d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),blocksize,m_samplesPerFFT,state().blocksize()); fclose (pFile); #endif m_samplesPerFFT = blocksize; } void TCITransceiver::do_ptt (bool on) { TRACE_CAT ("TCITransceiver", on << state ()); // printf ("%s(%0.1f) TCI do_ptt:%d PTT_:%d requested_PTT_:%d busy_PTT_:%d state:%d use_for_ptt:%d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),on,PTT_,requested_PTT_,busy_PTT_,state().ptt(),use_for_ptt_); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI do_ptt:%d PTT_:%d requested_PTT_:%d busy_PTT_:%d state:%d use_for_ptt:%d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),on,PTT_,requested_PTT_,busy_PTT_,state().ptt(),use_for_ptt_); fclose (pFile); #endif if (use_for_ptt_) { if (on != PTT_) { if (!inConnected && !error_.isEmpty()) throw error {error_}; // if (!inConnected){ PTT_ = on; update_PTT(on); return; } else if (busy_PTT_ || !tci_Ready || !_power_) return; else busy_PTT_ = true; requested_PTT_ = on; if (ESDR3) { const QString cmd = CmdTrx + SmDP + rx_ + SmCM + (on ? "true" : "false") + SmCM + "tci"+ SmTZ; sendTextMessage(cmd); } else { const QString cmd = CmdTrx + SmDP + rx_ + SmCM + (on ? "true" : "false") + SmTZ; sendTextMessage(cmd); } mysleep3(1000); busy_PTT_ = false; if (requested_PTT_ == PTT_) { update_PTT(PTT_); if (PTT_ && do_snr_) update_level (-54); else { power_ = 0; if (do_pwr_) update_power (0); swr_ = 0; if (do_pwr_) update_swr (0); } } else { // printf ("%s(%0.1f) TCI failed set ptt %d->%d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),PTT_,requested_PTT_); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI failed set ptt %d->%d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),PTT_,requested_PTT_); fclose (pFile); #endif error_ = tr ("TCI failed to set ptt"); // tci_Ready = false; // throw error {tr ("TCI failed to set ptt")}; } } else update_PTT(on); } else { TRACE_CAT ("TCITransceiver", "TCI should use PTT via CAT"); throw error {tr ("TCI should use PTT via CAT")}; } } void TCITransceiver::do_frequency (Frequency f, MODE m, bool no_ignore) { TRACE_CAT ("TCITransceiver", f << state ()); auto f_string = frequency_to_string (f); // printf ("%s(%0.1f) TCI do_frequency:%s current_frequency:%s mode:%s current_mode:%s no_ignore:%d busy:%d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),f_string.toStdString().c_str(),rx_frequency_.toStdString().c_str(),map_mode(m).toStdString().c_str(),requested_mode_.toStdString().c_str(),no_ignore,busy_rx_frequency_); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI do_frequency:%s current_frequency:%s mode:%s current_mode:%s no_ignore:%d busy:%d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),f_string.toStdString().c_str(),rx_frequency_.toStdString().c_str(),map_mode(m).toStdString().c_str(),requested_mode_.toStdString().c_str(),no_ignore,busy_rx_frequency_); fclose (pFile); #endif if (tci_Ready && busy_rx_frequency_ && no_ignore) { // printf ("%s(%0.1f) TCI do_frequency critical no_ignore set vfo will be missed\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset()); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI do_frequency critical no_ignore set vfo will be missed\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset()); fclose (pFile); #endif } if (busy_rx_frequency_) return; else { requested_rx_frequency_ = f_string; requested_mode_ = map_mode (m); } if (tci_Ready && _power_) { if (rx_frequency_ != requested_rx_frequency_) { busy_rx_frequency_ = true; band_change = abs(rx_frequency_.toInt()-requested_rx_frequency_.toInt()) > 1000000; const QString cmd = CmdVFO + SmDP + rx_ + SmCM + "0" + SmCM + requested_rx_frequency_ + SmTZ; sendTextMessage(cmd); mysleep1(2000); // if (band_change) mysleep1(500); if (requested_rx_frequency_ == rx_frequency_) update_rx_frequency (f); else { // printf ("%s(%0.1f) TCI failed set rxfreq:%s->%s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),rx_frequency_.toStdString().c_str(),requested_rx_frequency_.toStdString().c_str()); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI failed set rxfreq:%s->%s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),rx_frequency_.toStdString().c_str(),requested_rx_frequency_.toStdString().c_str()); fclose (pFile); #endif error_ = tr ("TCI failed set rxfreq"); // tci_Ready = false; // throw error {tr ("TCI failed set rxfreq")}; } busy_rx_frequency_ = false; } else update_rx_frequency (string_to_frequency (rx_frequency_)); if (!requested_mode_.isEmpty() && requested_mode_ != mode_ && !busy_mode_) { busy_mode_ = true; sendTextMessage(mode_to_command(requested_mode_)); mysleep1(1000); if (requested_mode_.isEmpty() || requested_mode_ == mode_) update_mode (m); else { // printf ("%s(%0.1f) TCI failed set mode %s->%s",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),mode_.toStdString().c_str(),requested_mode_.toStdString().c_str()); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI failed set mode %s->%s",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),mode_.toStdString().c_str(),requested_mode_.toStdString().c_str()); fclose (pFile); #endif error_ = tr ("TCI failed set mode"); // tci_Ready = false; // throw error {tr ("TCI failed set mode")}; } busy_mode_ = false; } // if (band_change) { // tci_timer2_->start(210); // band_change = false; // } } else { update_rx_frequency (f); update_mode (m); } } void TCITransceiver::do_tx_frequency (Frequency tx, MODE mode, bool no_ignore) { TRACE_CAT ("TCITransceiver", tx << state ()); auto f_string = frequency_to_string (tx); // printf ("%s(%0.1f) TCI do_tx_frequency:%s current_frequency:%s mode:%s no_ignore:%d busy:%d timer:%d remaining:%d band_change:%d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),f_string.toStdString().c_str(),other_frequency_.toStdString().c_str(),map_mode(mode).toStdString().c_str(),no_ignore,busy_other_frequency_,tci_timer2_->isActive(),tci_timer2_->remainingTime(),band_change); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI do_tx_frequency:%s current_frequency:%s mode:%s no_ignore:%d busy:%d timer:%d remaining:%d band_change:%d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),f_string.toStdString().c_str(),other_frequency_.toStdString().c_str(),map_mode(mode).toStdString().c_str(),no_ignore,busy_other_frequency_,tci_timer2_->isActive(),tci_timer2_->remainingTime(),band_change); fclose (pFile); #endif if (tci_Ready && busy_other_frequency_ && no_ignore) { // printf ("%s(%0.1f) TCI do_txfrequency critical no_ignore set tx vfo will be missed\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset()); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI do_txfrequency critical no_ignore set tx vfo will be missed\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset()); fclose (pFile); #endif } if (busy_other_frequency_) return; requested_other_frequency_ = f_string; requested_mode_ = map_mode (mode); if (tx) { requested_split_ = true; if (tci_Ready && _power_) { if (band_change && !tci_timer2_->isActive()) {if (!HPSDR) mysleep2(210); else mysleep2(2000);} else if (tci_timer2_->isActive()) mysleep2(0); if (requested_split_ != split_) rig_split(); else update_split (split_); if (other_frequency_ != requested_other_frequency_) { busy_other_frequency_ = true; // printf ("%s(%0.1f) TCI VFO1 command sent\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset()); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI VFO1 command sent\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset()); fclose (pFile); #endif const QString cmd = CmdVFO + SmDP + rx_ + SmCM + "1" + SmCM + requested_other_frequency_ + SmTZ; sendTextMessage(cmd); mysleep2(1000); if (requested_other_frequency_ == other_frequency_) update_other_frequency (tx); else { // printf ("%s(%0.1f) TCI failed set txfreq:%s->%s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),other_frequency_.toStdString().c_str(),requested_other_frequency_.toStdString().c_str()); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI failed set txfreq:%s->%s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),other_frequency_.toStdString().c_str(),requested_other_frequency_.toStdString().c_str()); fclose (pFile); #endif error_ = tr ("TCI failed set txfreq"); // tci_Ready = false; // throw error {tr ("TCI failed set txfreq")}; } busy_other_frequency_ = false; } else update_other_frequency (string_to_frequency (other_frequency_)); } else { update_split (requested_split_); update_other_frequency (tx); } } else { requested_split_ = false; requested_other_frequency_ = ""; if (tci_Ready && _power_) { if (band_change) {mysleep2(2000); if (!HPSDR) mysleep2(200);} if (tci_timer2_->isActive()) mysleep2(0); if (requested_split_ != split_) rig_split(); else update_split (split_); update_other_frequency (tx); } else { update_split (requested_split_); update_other_frequency (tx); } } } void TCITransceiver::do_mode (MODE m) { TRACE_CAT ("TCITransceiver", m << state ()); auto m_string = map_mode (m); // printf ("%s(%0.1f) TCI do_mode:%s->%s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),mode_.toStdString().c_str(),m_string.toStdString().c_str()); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI do_mode:%s->%s\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),mode_.toStdString().c_str(),m_string.toStdString().c_str()); fclose (pFile); #endif if (requested_mode_ != m_string) requested_mode_ = m_string; if (!requested_mode_.isEmpty() && mode_ != requested_mode_ && !busy_mode_) { busy_mode_ = true; sendTextMessage(mode_to_command(requested_mode_)); mysleep1(1000); if (requested_mode_ == mode_) update_mode (m); else { // printf ("%s(%0.1f) TCI failed set mode %s->%s",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),mode_.toStdString().c_str(),requested_mode_.toStdString().c_str()); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI failed set mode %s->%s",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),mode_.toStdString().c_str(),requested_mode_.toStdString().c_str()); fclose (pFile); #endif error_ = tr ("TCI failed set mode"); // tci_Ready = false; // throw error {tr ("TCI failed set mode")}; } busy_mode_ = false; } } void TCITransceiver::do_poll () { if (!inConnected) { // printf("%s(%0.1f) TCI do_poll |%s| split:%d ptt:%d rx_busy:%d tx_busy:%d level:%d power:%d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),error_.toStdString().c_str(),state ().split (),state (). ptt (),busy_rx_frequency_,busy_other_frequency_,level_,power_); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI do_poll |%s| split:%d ptt:%d rx_busy:%d tx_busy:%d level:%d power:%d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),error_.toStdString().c_str(),state ().split (),state (). ptt (),busy_rx_frequency_,busy_other_frequency_,level_,power_); fclose (pFile); #endif } if (/*!inConnected && */!error_.isEmpty()) {tci_Ready = false; throw error {error_};} else if (!tci_Ready) throw error {tr ("TCI could not be opened")}; update_rx_frequency (string_to_frequency (rx_frequency_)); update_split(split_); if (state ().split ()) { if (other_frequency_ == requested_other_frequency_) update_other_frequency (string_to_frequency (other_frequency_)); else if (!busy_rx_frequency_) do_tx_frequency(string_to_frequency (requested_other_frequency_),get_mode(true),false); } update_mode (get_mode()); if (do_pwr_ && PTT_) {update_power (power_ * 100); update_swr (swr_*10);} if (do_snr_ && !PTT_) { update_level (level_); if(!ESDR3) { const QString cmd = CmdSmeter + SmDP + rx_ + SmCM + "0" + SmTZ; sendTextMessage(cmd); } } } auto TCITransceiver::get_mode (bool requested) -> MODE { MODE m {UNK}; if (requested) { if ("am" == requested_mode_) { m = AM; } else if ("cw" == requested_mode_) { m = CW; } else if ("wfm" == requested_mode_) { m = FM; } else if ("nfm" == requested_mode_) { m = DIG_FM; } else if ("lsb" == requested_mode_) { m = LSB; } else if ("usb" == requested_mode_) { m = USB; } else if ("digl" == requested_mode_) { m = DIG_L; } else if ("digu" == requested_mode_) { m = DIG_U; } } else { if ("am" == mode_) { m = AM; } else if ("cw" == mode_) { m = CW; } else if ("wfm" == mode_) { m = FM; } else if ("nfm" == mode_) { m = DIG_FM; } else if ("lsb" == mode_) { m = LSB; } else if ("usb" == mode_) { m = USB; } else if ("digl" == mode_) { m = DIG_L; } else if ("digu" == mode_) { m = DIG_U; } } return m; } QString TCITransceiver::mode_to_command (QString m_string) const { // if (ESDR3) { // const QString cmd = CmdMode + SmDP + rx_ + SmCM + m_string.toUpper() + SmTZ; // return cmd; // } else { const QString cmd = CmdMode + SmDP + rx_ + SmCM + m_string + SmTZ; return cmd; // } } QString TCITransceiver::frequency_to_string (Frequency f) const { // number is localized and in kHz, avoid floating point translation // errors by adding a small number (0.1Hz) // auto f_string = QString {"%L2"}.arg (f); auto f_string = QString {}.setNum(f); // f_string = f_string.simplified().remove(' '); // f_string = f_string.replace(",",""); // f_string = f_string.replace(".",""); // f_string = f_string.replace("'",""); // f_string = f_string.replace("’",""); // printf ("frequency_to_string3 |%s|\n",f_string.toStdString().c_str()); return f_string; } auto TCITransceiver::string_to_frequency (QString s) const -> Frequency { // temporary hack because Commander is returning invalid UTF-8 bytes s.replace (QChar {QChar::ReplacementCharacter}, locale_.groupSeparator ()); bool ok; auto f = QLocale::c ().toDouble (s, &ok); // temporary fix if (!ok) { throw error {tr ("TCI sent an unrecognized frequency") + " |" + s + "|"}; } return f; } void TCITransceiver::mysleep1 (int ms) { // tci_timer1->setSingleShot(true); // printf("%s(%0.1f) TCI sleep1 start %d %d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),ms,tci_timer1_->isActive()); if (ms) tci_timer1_->start(ms); tci_loop1_->exec(); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI sleep1 %d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),tci_timer1_->isActive()); fclose (pFile); #endif // printf("%s(%0.1f) TCI sleep1 end %d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),tci_timer1_->isActive()); if (tci_timer1_->isActive() && tci_Ready) tci_timer1_->stop(); } void TCITransceiver::mysleep2 (int ms) { // tci_timer2->setSingleShot(true); // printf("%s(%0.1f) TCI sleep2 start %d %d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),ms,tci_timer2_->isActive()); if (ms) tci_timer2_->start(ms); tci_loop2_->exec(); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI sleep2 %d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),tci_timer2_->isActive()); fclose (pFile); #endif // printf("%s(%0.1f) TCI sleep2 end %d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),tci_timer2_->isActive()); if (tci_timer2_->isActive()) tci_timer2_->stop(); } void TCITransceiver::mysleep3 (int ms) { // tci_timer3->setSingleShot(true); // printf("%s(%0.1f) TCI sleep3 start %d %d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),ms,tci_timer3_->isActive()); if (ms) tci_timer3_->start(ms); tci_loop3_->exec(); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI sleep3 %d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),tci_timer3_->isActive()); fclose (pFile); #endif // printf("%s(%0.1f) TCI sleep3 end %d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),tci_timer3_->isActive()); if (tci_timer3_->isActive()) tci_timer3_->stop(); } // Modulator part void TCITransceiver::do_modulator_start (unsigned symbolsLength, double framesPerSymbol, double frequency, double toneSpacing, bool synchronize, double dBSNR, double TRperiod) { // QThread::currentThread()->setPriority(QThread::HighPriority); // Q_ASSERT (stream); // Time according to this computer which becomes our base time qint64 ms0 = m_jtdxtime->currentMSecsSinceEpoch2() % 86400000; // qDebug() << "ModStart" << QDateTime::currentDateTimeUtc().toString("hh:mm:ss.sss"); unsigned mstr = ms0 % int(1000.0*m_period); // ms into the nominal Tx start time if (m_state != Idle) { // stop (); throw error {tr ("TCI modulator not Idle")}; } m_quickClose = false; m_symbolsLength = symbolsLength; m_isym0 = std::numeric_limits::max (); // big number m_frequency0 = 0.; m_phi = 0.; m_addNoise = dBSNR < 0.; m_nsps = framesPerSymbol; m_trfrequency = frequency; m_amp = std::numeric_limits::max (); m_toneSpacing = toneSpacing; m_TRperiod=TRperiod; unsigned delay_ms=1000; if(m_nsps==1920) delay_ms=500; //FT8 else if(m_nsps==576) { delay_ms=500; //FT4 } // noise generator parameters if (m_addNoise) { m_snr = qPow (10.0, 0.05 * (dBSNR - 6.0)); m_fac = 3000.0; if (m_snr > 1.0) m_fac = 3000.0 / m_snr; } // round up to an exact portion of a second that allows for startup delays //m_ic = (mstr / delay_ms) * audioSampleRate * delay_ms / 1000; auto mstr2 = mstr - delay_ms; if (mstr <= delay_ms) { m_ic = 0; } else { m_ic = mstr2 * (audioSampleRate / 1000); } m_silentFrames = 0; // calculate number of silent frames to send if (m_ic == 0 && synchronize && !m_tuning) { m_silentFrames = audioSampleRate / (1000 / delay_ms) - (mstr * (audioSampleRate / 1000)); } m_state = (synchronize && m_silentFrames) ? Synchronizing : Active; // printf ("%s(%0.1f) TCI modulator startdelay_ms=%d ASR=%d mstr=%d mstr2=%d m_ic=%d s_Frames=%lld synchronize=%d m_tuning=%d State=%d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),delay_ms,audioSampleRate,mstr,mstr2,m_ic,m_silentFrames,synchronize,m_tuning,m_state); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI modulator startdelay_ms=%d ASR=%d mstr=%d mstr2=%d m_ic=%d s_Frames=%lld synchronize=%d m_tuning=%d State=%d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),delay_ms,audioSampleRate,mstr,mstr2,m_ic,m_silentFrames,synchronize,m_tuning,m_state); fclose (pFile); #endif Q_EMIT tci_mod_active(m_state != Idle); } void TCITransceiver::do_tune (bool newState) { // printf("%s(%0.1f) TCI modulator tune %d ->%d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),m_tuning,newState); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI modulator tune %d ->%d\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),m_tuning,newState); fclose (pFile); #endif m_tuning = newState; if (!m_tuning) do_modulator_stop (true); } void TCITransceiver::do_modulator_stop (bool quick) { m_quickClose = quick; if(m_state != Idle) { m_state = Idle; Q_EMIT tci_mod_active(m_state != Idle); } tx_audio_ = false; } quint16 TCITransceiver::readAudioData (float * data, qint32 maxSize) { double toneFrequency=1500.0; if(m_nsps==6) { toneFrequency=1000.0; m_trfrequency=1000.0; m_frequency0=1000.0; } if(maxSize==0) return 0; qint64 numFrames (maxSize/bytesPerFrame); float * samples (reinterpret_cast (data)); float * end (samples + numFrames * bytesPerFrame); // printf("%s(%0.1f) readAudioData %f %f %lld %lld %d %p %p\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),m_nsps,m_TRperiod,numFrames,m_silentFrames,maxSize,samples,end); qint64 framesGenerated (0); switch (m_state) { case Synchronizing: { if (m_silentFrames) { // send silence up to first second framesGenerated = qMin (m_silentFrames, numFrames); for ( ; samples != end; samples = load (0, samples)) { // silence } m_silentFrames -= framesGenerated; return framesGenerated * bytesPerFrame; } m_state = Active; Q_EMIT tci_mod_active(m_state != Idle); m_cwLevel = false; m_ramp = 0; // prepare for CW wave shaping } // fall through case Active: { unsigned int isym=0; qint16 sample=0; if(!m_tuning) isym=m_ic/(4.0*m_nsps); // Actual fsample=48000 bool slowCwId=((isym >= m_symbolsLength) && (icw[0] > 0)); m_nspd=2560; // 22.5 WPM if(m_TRperiod > 16.0 && slowCwId) { // Transmit CW ID? m_dphi = m_twoPi*m_trfrequency/audioSampleRate; unsigned ic0 = m_symbolsLength * 4 * m_nsps; unsigned j(0); while (samples != end) { j = (m_ic - ic0)/m_nspd + 1; // symbol of this sample bool level {bool (icw[j])}; m_phi += m_dphi; if (m_phi > m_twoPi) m_phi -= m_twoPi; sample=0; float amp=32767.0; float x=0.0; if(m_ramp!=0) { x=qSin(float(m_phi)); if(SOFT_KEYING) { amp=qAbs(qint32(m_ramp)); if(amp>32767.0) amp=32767.0; } sample=round(amp*x); } if (int (j) <= icw[0] && j < NUM_CW_SYMBOLS) { // stopu condition samples = load (postProcessSample (sample), samples); ++framesGenerated; ++m_ic; } else { m_state = Idle; // printf("%s(%0.1f) TCI modulator Idle1 %lld frames generated\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),framesGenerated); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI modulator Idle1 %lld frames generated\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),framesGenerated); fclose (pFile); #endif Q_EMIT tci_mod_active(m_state != Idle); return framesGenerated * bytesPerFrame; } // adjust ramp if ((m_ramp != 0 && m_ramp != std::numeric_limits::min ()) || level != m_cwLevel) { // either ramp has terminated at max/min or direction has changed m_ramp += RAMP_INCREMENT; // ramp } m_cwLevel = level; } return framesGenerated * bytesPerFrame; } //End of code for CW ID double const baud (12000.0 / m_nsps); // fade out parameters (no fade out for tuning) unsigned int i0,i1; if(m_tuning) { i1 = i0 = 9999 * m_nsps; } else { i0=(m_symbolsLength - 0.017) * 4.0 * m_nsps; i1= m_symbolsLength * 4.0 * m_nsps; } sample=0; for (unsigned i = 0; i < numFrames && m_ic <= i1; ++i) { // printf("algus %d %lld %d %d",i,numFrames,m_ic,i1); if(m_TRperiod > 16.0 || m_tuning) { isym=0; if(!m_tuning) isym=m_ic / (4.0 * m_nsps); //Actual fsample=48000 if (isym != m_isym0 || m_trfrequency != m_frequency0) { if(itone[0]>=100) { m_toneFrequency0=itone[0]; } else { if(m_toneSpacing==0.0) { m_toneFrequency0=m_trfrequency + itone[isym]*baud; } else { m_toneFrequency0=m_trfrequency + itone[isym]*m_toneSpacing; } } // qDebug() << "B" << m_ic << numFrames << isym << itone[isym] << toneFrequency0 << m_nsps; m_dphi = m_twoPi * m_toneFrequency0 / audioSampleRate; m_isym0 = isym; m_frequency0 = m_trfrequency; //??? } int j=m_ic/480; if(m_fSpread>0.0 and j!=m_j0) { #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) float x1=QRandomGenerator::global ()->generateDouble (); float x2=QRandomGenerator::global ()->generateDouble (); #else float x1=(float)qrand()/RAND_MAX; float x2=(float)qrand()/RAND_MAX; #endif toneFrequency = m_toneFrequency0 + 0.5*m_fSpread*(x1+x2-1.0); m_dphi = m_twoPi * toneFrequency / audioSampleRate; m_j0=j; } m_phi += m_dphi; if (m_phi > m_twoPi) m_phi -= m_twoPi; //ramp for first tone if (m_ic==0) m_amp = m_amp * 0.008144735; if (m_ic > 0 and m_ic < 191) m_amp = m_amp / 0.975; //ramp for last tone if (m_ic > i0) m_amp = 0.99 * m_amp; if (m_ic > i1) m_amp = 0.0; sample=qRound(m_amp*qSin(m_phi)); } //transmit from a precomputed FT8 wave[] array: if(!m_tuning and (m_toneSpacing < 0.0)) { m_amp=32767.0; sample=qRound(m_amp*foxcom_.wave[m_ic]); } samples = load (postProcessSample (sample), samples); ++framesGenerated; ++m_ic; } // printf("sample saved %lld %d\n",framesGenerated,m_ic); if (m_amp == 0.0) { // TODO G4WJS: compare double with zero might not be wise if (icw[0] == 0) { // no CW ID to send m_state = Idle; // printf("%s(%0.1f) TCI modulator Idle2 %lld frames generated\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),framesGenerated); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI modulator Idle2 %lld frames generated\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),framesGenerated); fclose (pFile); #endif Q_EMIT tci_mod_active(m_state != Idle); return framesGenerated * bytesPerFrame; } m_phi = 0.0; } m_frequency0 = m_trfrequency; // done for this chunk - continue on next call if (samples != end && framesGenerated) { // printf("%s(%0.1f) TCI modulator Idle3 %lld frames generated\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),framesGenerated); #if JTDX_DEBUG_TO_FILE FILE * pFile = fopen (debug_file_.c_str(),"a"); fprintf (pFile,"%s(%0.1f) TCI modulator Idle3 %lld frames generated\n",m_jtdxtime->currentDateTimeUtc2().toString("hh:mm:ss.zzz").toStdString().c_str(),m_jtdxtime->GetOffset(),framesGenerated); fclose (pFile); #endif } while (samples != end) { // pad block with silence samples = load (0, samples); ++framesGenerated; } return framesGenerated * bytesPerFrame; } // fall through case Idle: while (samples != end) samples = load (0, samples); } Q_ASSERT (Idle == m_state); return 0; } qint16 TCITransceiver::postProcessSample (qint16 sample) const { if (m_addNoise) { // Test frame, we'll add noise qint32 s = m_fac * (gran () + sample * m_snr / 32768.0); if (s > std::numeric_limits::max ()) { s = std::numeric_limits::max (); } if (s < std::numeric_limits::min ()) { s = std::numeric_limits::min (); } sample = s; } return sample; }