Compare commits

..

14 Commits

Author SHA1 Message Date
Jordan Sherer 3b1519c603 Bump to v0.4.2 2018-08-12 10:38:59 -04:00
Jordan Sherer f30c2e3858 Fixed configuration of band hopping to reset cached band position after configuration save. Fixed issue with band hopping not working across a date transition 2018-08-12 10:35:19 -04:00
Jordan Sherer c60efba4ca Fixed display of messages that drift more than a few Hz during transmission 2018-08-12 10:03:14 -04:00
Jordan Sherer 5694b96f55 Fixed compound callsigns not displaying in the heard list 2018-08-12 09:23:05 -04:00
Jordan Sherer 52b6cea883 Bump to 0.4.1 2018-08-11 22:21:37 -04:00
Jordan Sherer fded3b5003 Allow changes to station message from external programs 2018-08-11 22:12:54 -04:00
Jordan Sherer de713e86fc Fixed printing of grid in compound call messages 2018-08-11 22:00:59 -04:00
Jordan Sherer ed9228d196 Fixed issues with double printing of messages and skipping printing some frames 2018-08-11 18:05:36 -04:00
Jordan Sherer 08357c4b11 Fixed issue with changing frequency in response to directed allcalls 2018-08-11 10:54:21 -04:00
Jordan Sherer 94d7b94f56 Fixed isFreqOffsetFree when responding to directed query 2018-08-11 10:45:39 -04:00
Jordan Sherer d3b593c953 Fixed alignment of red waterfall indicator 2018-08-11 10:38:38 -04:00
Jordan Sherer 8c8ddb533c Fixed issue with grid length. Fixed back-to-back CQs 2018-08-11 10:31:28 -04:00
Jordan Sherer c042a72d0d Fixed bug causing compound calls not to send when a grid locator larger than 4 characters was set in the configuration 2018-08-11 10:06:50 -04:00
Jordan Sherer a5b6984ede Fixed bug in configuring band hopping 2018-08-11 09:39:02 -04:00
13 changed files with 292 additions and 261 deletions
+27 -17
View File
@@ -298,8 +298,8 @@ public:
return { return {
band, band,
freq_.frequency(), freq_.frequency(),
qMin(a, b), a,
qMax(a, b), b,
description_.text ()}; description_.text ()};
} }
@@ -544,6 +544,7 @@ private:
bool frequency_calibration_disabled_; // not persistent bool frequency_calibration_disabled_; // not persistent
unsigned transceiver_command_number_; unsigned transceiver_command_number_;
QString dynamic_grid_; QString dynamic_grid_;
QString dynamic_qtc_;
// configuration fields that we publish // configuration fields that we publish
bool auto_switch_bands_; bool auto_switch_bands_;
@@ -597,7 +598,7 @@ private:
bool bHound_; bool bHound_;
bool x2ToneSpacing_; bool x2ToneSpacing_;
bool x4ToneSpacing_; bool x4ToneSpacing_;
bool use_dynamic_grid_; bool use_dynamic_info_;
QString opCall_; QString opCall_;
QString udp_server_name_; QString udp_server_name_;
port_type udp_server_port_; port_type udp_server_port_;
@@ -655,7 +656,7 @@ AudioDevice::Channel Configuration::audio_output_channel () const {return m_->au
bool Configuration::restart_audio_input () const {return m_->restart_sound_input_device_;} bool Configuration::restart_audio_input () const {return m_->restart_sound_input_device_;}
bool Configuration::restart_audio_output () const {return m_->restart_sound_output_device_;} bool Configuration::restart_audio_output () const {return m_->restart_sound_output_device_;}
auto Configuration::type_2_msg_gen () const -> Type2MsgGen {return m_->type_2_msg_gen_;} auto Configuration::type_2_msg_gen () const -> Type2MsgGen {return m_->type_2_msg_gen_;}
bool Configuration::use_dynamic_grid() const {return m_->use_dynamic_grid_; } bool Configuration::use_dynamic_grid() const {return m_->use_dynamic_info_; }
QString Configuration::my_callsign () const {return m_->my_callsign_;} QString Configuration::my_callsign () const {return m_->my_callsign_;}
QColor Configuration::color_CQ () const {return m_->color_CQ_;} QColor Configuration::color_CQ () const {return m_->color_CQ_;}
QColor Configuration::color_MyCall () const {return m_->color_MyCall_;} QColor Configuration::color_MyCall () const {return m_->color_MyCall_;}
@@ -839,16 +840,20 @@ bool Configuration::valid_n1mm_info () const
QString Configuration::my_grid() const QString Configuration::my_grid() const
{ {
auto the_grid = m_->my_grid_; auto grid = m_->my_grid_;
if (m_->use_dynamic_grid_ && m_->dynamic_grid_.size () >= 4) { if (m_->use_dynamic_info_ && m_->dynamic_grid_.size () >= 4) {
the_grid = m_->dynamic_grid_; grid = m_->dynamic_grid_;
} }
return the_grid; return grid;
} }
QString Configuration::my_station() const QString Configuration::my_station() const
{ {
return m_->my_station_; auto station = m_->my_station_;
if(m_->use_dynamic_info_ && !m_->dynamic_qtc_.isEmpty()){
station = m_->dynamic_qtc_;
}
return station;
} }
int Configuration::my_dBm() const { int Configuration::my_dBm() const {
@@ -870,13 +875,16 @@ int Configuration::activity_aging() const
return m_->activity_aging_; return m_->activity_aging_;
} }
void Configuration::set_location (QString const& grid_descriptor) void Configuration::set_dynamic_location (QString const& grid_descriptor)
{ {
// change the dynamic grid
qDebug () << "Configuration::set_location - location:" << grid_descriptor;
m_->dynamic_grid_ = grid_descriptor.trimmed (); m_->dynamic_grid_ = grid_descriptor.trimmed ();
} }
void Configuration::set_dynamic_station_message(QString const& qtc)
{
m_->dynamic_qtc_ = qtc.trimmed ();
}
namespace namespace
{ {
#if defined (Q_OS_MAC) #if defined (Q_OS_MAC)
@@ -1232,7 +1240,7 @@ void Configuration::impl::initialize_models ()
ui_->activity_aging_spin_box->setValue(activity_aging_); ui_->activity_aging_spin_box->setValue(activity_aging_);
ui_->station_message_line_edit->setText (my_station_.toUpper()); ui_->station_message_line_edit->setText (my_station_.toUpper());
ui_->qth_message_line_edit->setText (my_qth_.toUpper()); ui_->qth_message_line_edit->setText (my_qth_.toUpper());
ui_->use_dynamic_grid->setChecked(use_dynamic_grid_); ui_->use_dynamic_grid->setChecked(use_dynamic_info_);
ui_->labCQ->setStyleSheet(QString("background: %1").arg(color_CQ_.name())); ui_->labCQ->setStyleSheet(QString("background: %1").arg(color_CQ_.name()));
ui_->labMyCall->setStyleSheet(QString("background: %1").arg(color_MyCall_.name())); ui_->labMyCall->setStyleSheet(QString("background: %1").arg(color_MyCall_.name()));
ui_->labTx->setStyleSheet(QString("background: %1").arg(color_TxMsg_.name())); ui_->labTx->setStyleSheet(QString("background: %1").arg(color_TxMsg_.name()));
@@ -1458,7 +1466,7 @@ void Configuration::impl::read_settings ()
spot_to_psk_reporter_ = settings_->value ("PSKReporter", false).toBool (); spot_to_psk_reporter_ = settings_->value ("PSKReporter", false).toBool ();
id_after_73_ = settings_->value ("After73", false).toBool (); id_after_73_ = settings_->value ("After73", false).toBool ();
tx_QSY_allowed_ = settings_->value ("TxQSYAllowed", false).toBool (); tx_QSY_allowed_ = settings_->value ("TxQSYAllowed", false).toBool ();
use_dynamic_grid_ = settings_->value ("AutoGrid", false).toBool (); use_dynamic_info_ = settings_->value ("AutoGrid", false).toBool ();
auto loadedMacros = settings_->value ("Macros", QStringList {"TNX 73 GL"}).toStringList(); auto loadedMacros = settings_->value ("Macros", QStringList {"TNX 73 GL"}).toStringList();
@@ -1650,7 +1658,7 @@ void Configuration::impl::write_settings ()
settings_->setValue ("pwrBandTxMemory", pwrBandTxMemory_); settings_->setValue ("pwrBandTxMemory", pwrBandTxMemory_);
settings_->setValue ("pwrBandTuneMemory", pwrBandTuneMemory_); settings_->setValue ("pwrBandTuneMemory", pwrBandTuneMemory_);
settings_->setValue ("Region", QVariant::fromValue (region_)); settings_->setValue ("Region", QVariant::fromValue (region_));
settings_->setValue ("AutoGrid", use_dynamic_grid_); settings_->setValue ("AutoGrid", use_dynamic_info_);
} }
void Configuration::impl::set_rig_invariants () void Configuration::impl::set_rig_invariants ()
@@ -2093,14 +2101,16 @@ void Configuration::impl::accept ()
{ {
stations_.station_list(next_stations_.station_list ()); stations_.station_list(next_stations_.station_list ());
stations_.sort (StationList::switch_at_column); stations_.sort (StationList::switch_at_column);
Q_EMIT self_->band_schedule_changed(this->stations_);
} }
if (ui_->use_dynamic_grid->isChecked() && !use_dynamic_grid_ ) if (ui_->use_dynamic_grid->isChecked() && !use_dynamic_info_ )
{ {
// turning on so clear it so only the next location update gets used // turning on so clear it so only the next location update gets used
dynamic_grid_.clear (); dynamic_grid_.clear ();
} }
use_dynamic_grid_ = ui_->use_dynamic_grid->isChecked(); use_dynamic_info_ = ui_->use_dynamic_grid->isChecked();
write_settings (); // make visible to all write_settings (); // make visible to all
} }
+7 -1
View File
@@ -203,7 +203,11 @@ public:
void set_calibration (CalibrationParams); void set_calibration (CalibrationParams);
// Set the dynamic grid which is only used if configuration setting is enabled. // Set the dynamic grid which is only used if configuration setting is enabled.
void set_location (QString const&); void set_dynamic_location (QString const&);
// Set the dynamic statios message which is only used if configuration setting is enabled.
void set_dynamic_station_message(QString const& qtc);
// This method queries if a CAT and PTT connection is operational. // This method queries if a CAT and PTT connection is operational.
bool is_transceiver_online () const; bool is_transceiver_online () const;
@@ -270,6 +274,8 @@ public:
Q_SIGNAL void udp_server_changed (QString const& udp_server); Q_SIGNAL void udp_server_changed (QString const& udp_server);
Q_SIGNAL void udp_server_port_changed (port_type server_port); Q_SIGNAL void udp_server_port_changed (port_type server_port);
// This signal is emitted when the band schedule changes
Q_SIGNAL void band_schedule_changed (StationList &stations);
// //
// These signals are emitted and reflect transceiver state changes // These signals are emitted and reflect transceiver state changes
+21 -18
View File
@@ -77,21 +77,10 @@
<item row="0" column="1"> <item row="0" column="1">
<widget class="QLineEdit" name="grid_line_edit"> <widget class="QLineEdit" name="grid_line_edit">
<property name="toolTip"> <property name="toolTip">
<string>Maidenhead locator (only the first four characters are required).</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;4-digit Maidenhead Locator&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
</widget> <property name="maxLength">
</item> <number>4</number>
</layout>
</item>
<item>
<layout class="QFormLayout" name="formLayout_21">
<item row="0" column="0">
<widget class="QCheckBox" name="use_dynamic_grid">
<property name="toolTip">
<string>Check to allow grid changes from external programs</string>
</property>
<property name="text">
<string>AutoGrid</string>
</property> </property>
</widget> </widget>
</item> </item>
@@ -2091,6 +2080,20 @@ for assessing propagation and system performance.</string>
</property> </property>
</widget> </widget>
</item> </item>
<item>
<layout class="QFormLayout" name="formLayout_21">
<item row="0" column="0">
<widget class="QCheckBox" name="use_dynamic_grid">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Check to allow changes to grid, qtc, etc from external programs&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Accept Dynamic Station Information</string>
</property>
</widget>
</item>
</layout>
</item>
<item> <item>
<widget class="QCheckBox" name="udpWindowToFront"> <widget class="QCheckBox" name="udpWindowToFront">
<property name="visible"> <property name="visible">
@@ -3161,12 +3164,12 @@ soundcard changes</string>
</connection> </connection>
</connections> </connections>
<buttongroups> <buttongroups>
<buttongroup name="CAT_data_bits_button_group"/>
<buttongroup name="split_mode_button_group"/>
<buttongroup name="PTT_method_button_group"/>
<buttongroup name="TX_audio_source_button_group"/>
<buttongroup name="CAT_handshake_button_group"/> <buttongroup name="CAT_handshake_button_group"/>
<buttongroup name="CAT_stop_bits_button_group"/> <buttongroup name="CAT_stop_bits_button_group"/>
<buttongroup name="TX_mode_button_group"/> <buttongroup name="TX_mode_button_group"/>
<buttongroup name="CAT_data_bits_button_group"/>
<buttongroup name="split_mode_button_group"/>
<buttongroup name="TX_audio_source_button_group"/>
<buttongroup name="PTT_method_button_group"/>
</buttongroups> </buttongroups>
</ui> </ui>
+4 -6
View File
@@ -490,9 +490,8 @@ bool StationList::impl::setData (QModelIndex const& model_index, QVariant const&
auto t = QTime::fromString(s); auto t = QTime::fromString(s);
auto at = QDateTime(QDate(2000,1,1), t, Qt::UTC); auto at = QDateTime(QDate(2000,1,1), t, Qt::UTC);
auto until = stations_[row].switch_until_; auto until = stations_[row].switch_until_;
stations_[row].switch_at_ = at;
stations_[row].switch_at_ = qMin(at, until); stations_[row].switch_until_ = until;
stations_[row].switch_until_ = qMax(at, until);
Q_EMIT dataChanged (model_index, model_index, roles); Q_EMIT dataChanged (model_index, model_index, roles);
@@ -511,9 +510,8 @@ bool StationList::impl::setData (QModelIndex const& model_index, QVariant const&
auto t = QTime::fromString(s); auto t = QTime::fromString(s);
auto until = QDateTime(QDate(2000,1,1), t, Qt::UTC); auto until = QDateTime(QDate(2000,1,1), t, Qt::UTC);
auto at = stations_[row].switch_at_; auto at = stations_[row].switch_at_;
stations_[row].switch_at_ = at;
stations_[row].switch_at_ = qMin(at, until); stations_[row].switch_until_ = until;
stations_[row].switch_until_ = qMax(at, until);
Q_EMIT dataChanged (model_index, model_index, roles); Q_EMIT dataChanged (model_index, model_index, roles);
+1 -1
View File
@@ -1,6 +1,6 @@
# Version number components # Version number components
set (WSJTX_VERSION_MAJOR 0) set (WSJTX_VERSION_MAJOR 0)
set (WSJTX_VERSION_MINOR 4) set (WSJTX_VERSION_MINOR 4)
set (WSJTX_VERSION_PATCH 0) set (WSJTX_VERSION_PATCH 2)
set (WSJTX_RC 0) # release candidate number, comment out or zero for development versions set (WSJTX_RC 0) # release candidate number, comment out or zero for development versions
set (WSJTX_VERSION_IS_RELEASE 0) # set to 1 for final release build set (WSJTX_VERSION_IS_RELEASE 0) # set to 1 for final release build
+1 -1
View File
@@ -22,7 +22,7 @@ subroutine ft8apset(mycall12,mygrid6,hiscall12,hisgrid6,bcontest,apsym,iaptype)
! hisgrid=hisgrid6(1:4) ! hisgrid=hisgrid6(1:4)
!! if(len_trim(hisgrid).eq.0) hisgrid="EN50" !! if(len_trim(hisgrid).eq.0) hisgrid="EN50"
! if(index(hisgrid," ").eq.0) hisgrid="EN50" ! if(index(hisgrid," ").eq.0) hisgrid="EN50"
msg='tZQpZP-slh4+' msg='tZQpZP-slh4+' ! HELLO WORLD
i3bit=0 ! ### TEMPORARY ??? ### i3bit=0 ! ### TEMPORARY ??? ###
call genft8(msg,mygrid6,bcontest,i3bit,msgsent,msgbits,itone) call genft8(msg,mygrid6,bcontest,i3bit,msgsent,msgbits,itone)
apsym=2*msgbits-1 apsym=2*msgbits-1
+1 -42
View File
@@ -374,14 +374,11 @@ subroutine ft8b(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,lapon,lapcqonly, &
cycle cycle
endif endif
i3bit=4*decoded(73) + 2*decoded(74) + decoded(75) i3bit=4*decoded(73) + 2*decoded(74) + decoded(75)
iFreeText=decoded(57)
if(nbadcrc.eq.0) then if(nbadcrc.eq.0) then
decoded0=decoded decoded0=decoded
if(i3bit.eq.1) decoded(57:)=0
call extractmessage174(decoded,origmsg,ncrcflag) call extractmessage174(decoded,origmsg,ncrcflag)
decoded=decoded0 decoded=decoded0
! This needs fixing for messages with i3bit=1:
message(1:12)=origmsg(1:12) message(1:12)=origmsg(1:12)
call genft8(message,mygrid6,bcontest,i3bit,msgsent,msgbits,itone) call genft8(message,mygrid6,bcontest,i3bit,msgsent,msgbits,itone)
if(lsubtract) call subtractft8(dd0,itone,f1,xdt2) if(lsubtract) call subtractft8(dd0,itone,f1,xdt2)
@@ -398,48 +395,10 @@ subroutine ft8b(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,lapon,lapcqonly, &
xsnr2=db(xsig/xbase - 1.0) - 32.0 xsnr2=db(xsig/xbase - 1.0) - 32.0
if(.not.nagain) xsnr=xsnr2 if(.not.nagain) xsnr=xsnr2
if(xsnr .lt. -24.0) xsnr=-24.0 if(xsnr .lt. -24.0) xsnr=-24.0
! if(i3bit.eq.1) then
! do i=1,12
! i1hiscall(i)=ichar(hiscall12(i:i))
! enddo
! icrc10=crc10(c_loc(i1hiscall),12)
! write(cbits,1001) decoded
!1001 format(87i1)
! read(cbits,1002) ncrc10,nrpt
!1002 format(56x,b10,b6)
! irpt=nrpt-30
! i1=index(message,' ')
! i2=index(message(i1+1:),' ') + i1
! c1=message(1:i1)//' '
! c2=message(i1+1:i2)//' '
!
! if(ncrc10.eq.icrc10) msg37=c1//' RR73; '//c2//' <'// &
! trim(hiscall12)//'> '
! if(ncrc10.ne.icrc10) msg37=c1//' RR73; '//c2//' <...> '
!
!! msg37=c1//' RR73; '//c2//' <...> '
! write(msg37(35:37),1010) irpt
!1010 format(i3.2)
! if(msg37(35:35).ne.'-') msg37(35:35)='+'
!
! iz=len(trim(msg37))
! do iter=1,10 !Collapse multiple blanks
! ib2=index(msg37(1:iz),' ')
! if(ib2.lt.1) exit
! msg37=msg37(1:ib2)//msg37(ib2+2:)
! iz=iz-1
! enddo
! else
! msg37=message//' '
! endif
msg37=origmsg//' ' msg37=origmsg//' '
if(i3bit.gt.1) then msg37(22:22) = char(48 + i3bit)
msg37(22:22) = char(48 + i3bit)
endif
return return
endif endif
+18 -48
View File
@@ -62,21 +62,17 @@ program ft8code
msgchk=msg msgchk=msg
! Generate msgsent, msgbits, and itone ! Generate msgsent, msgbits, and itone
if(index(msg,';').le.0) then call packmsg(msg(1:22),dgen,itype,bcontest)
call packmsg(msg(1:22),dgen,itype,bcontest) msgtype=""
msgtype="" if(itype.eq.1) msgtype="Std Msg"
if(itype.eq.1) msgtype="Std Msg" if(itype.eq.2) msgtype="Type 1 pfx"
if(itype.eq.2) msgtype="Type 1 pfx" if(itype.eq.3) msgtype="Type 1 sfx"
if(itype.eq.3) msgtype="Type 1 sfx" if(itype.eq.4) msgtype="Type 2 pfx"
if(itype.eq.4) msgtype="Type 2 pfx" if(itype.eq.5) msgtype="Type 2 sfx"
if(itype.eq.5) msgtype="Type 2 sfx" if(itype.eq.6) msgtype="Free text"
if(itype.eq.6) msgtype="Free text" i3bit=0
i3bit=0 call genft8(msg(1:22),mygrid6,bcontest,i3bit,msgsent,msgbits,itone)
call genft8(msg(1:22),mygrid6,bcontest,i3bit,msgsent,msgbits,itone)
else
call foxgen_wrap(msg,msgbits,itone)
i3bit=1
endif
decoded=msgbits decoded=msgbits
i3bit=4*decoded(73) + 2*decoded(74) + decoded(75) i3bit=4*decoded(73) + 2*decoded(74) + decoded(75)
iFreeText=decoded(57) iFreeText=decoded(57)
@@ -85,40 +81,14 @@ program ft8code
call extractmessage174(decoded,message,ncrcflag) call extractmessage174(decoded,message,ncrcflag)
decoded=decoded0 decoded=decoded0
if(i3bit.eq.0) then if(bcontest) call fix_contest_msg(mygrid6,message)
if(bcontest) call fix_contest_msg(mygrid6,message) bad=" "
bad=" " comment=' '
comment=' ' if(itype.ne.6 .and. message.ne.msgchk) bad="*"
if(itype.ne.6 .and. message.ne.msgchk) bad="*" if(itype.eq.6 .and. message(1:13).ne.msgchk(1:13)) bad="*"
if(itype.eq.6 .and. message(1:13).ne.msgchk(1:13)) bad="*" if(itype.eq.6 .and. len(trim(msgchk)).gt.13) comment='truncated'
if(itype.eq.6 .and. len(trim(msgchk)).gt.13) comment='truncated' write(*,1020) imsg,msgchk,message,bad,i3bit,itype,msgtype,comment
write(*,1020) imsg,msgchk,message,bad,i3bit,itype,msgtype,comment
1020 format(i2,'.',1x,a22,1x,a22,1x,a1,2i2,1x,a10,1x,a9) 1020 format(i2,'.',1x,a22,1x,a22,1x,a1,2i2,1x,a10,1x,a9)
else
write(cbits,1001) decoded
1001 format(87i1)
read(cbits,1002) nrpt
1002 format(66x,b6)
irpt=nrpt-30
i1=index(message,' ')
i2=index(message(i1+1:),' ') + i1
c1=message(1:i1)//' '
c2=message(i1+1:i2)//' '
msg37=c1//' RR73; '//c2//' <...> '
write(msg37(35:37),1003) irpt
1003 format(i3.2)
if(msg37(35:35).ne.'-') msg37(35:35)='+'
iz=len(trim(msg37))
do iter=1,10 !Collapse multiple blanks into one
ib2=index(msg37(1:iz),' ')
if(ib2.lt.1) exit
msg37=msg37(1:ib2)//msg37(ib2+2:)
iz=iz-1
enddo
write(*,1021) imsg,msgchk,msg37
1021 format(i2,'.',1x,a40,1x,a37)
endif
enddo enddo
+197 -114
View File
@@ -695,6 +695,9 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
connect (&m_config, &Configuration::transceiver_failure, this, &MainWindow::handle_transceiver_failure); connect (&m_config, &Configuration::transceiver_failure, this, &MainWindow::handle_transceiver_failure);
connect (&m_config, &Configuration::udp_server_changed, m_messageClient, &MessageClient::set_server); connect (&m_config, &Configuration::udp_server_changed, m_messageClient, &MessageClient::set_server);
connect (&m_config, &Configuration::udp_server_port_changed, m_messageClient, &MessageClient::set_server_port); connect (&m_config, &Configuration::udp_server_port_changed, m_messageClient, &MessageClient::set_server_port);
connect (&m_config, &Configuration::band_schedule_changed, this, [this](){
this->m_bandHopped = true;
});
// set up configurations menu // set up configurations menu
connect (m_multi_settings, &MultiSettings::configurationNameChanged, [this] (QString const& name) { connect (m_multi_settings, &MultiSettings::configurationNameChanged, [this] (QString const& name) {
@@ -1333,16 +1336,33 @@ void MainWindow::tryBandHop(){
QDateTime d = QDateTime::currentDateTimeUtc(); QDateTime d = QDateTime::currentDateTimeUtc();
d.setDate(QDate(2000, 1, 1)); d.setDate(QDate(2000, 1, 1));
QDateTime startOfDay = QDateTime(QDate(2000, 1, 1), QTime(0, 0));
QDateTime endOfDay = QDateTime(QDate(2000, 1, 1), QTime(23, 59));
// see if we can find a needed band switch... // see if we can find a needed band switch...
foreach(auto station, stations){ foreach(auto station, stations){
// we can switch to this frequency if we're in the time range, inclusive of switch_at, exclusive of switch_until // we can switch to this frequency if we're in the time range, inclusive of switch_at, exclusive of switch_until
// and if we are switching to a different frequency than the last hop. this allows us to switch bands at that time, // and if we are switching to a different frequency than the last hop. this allows us to switch bands at that time,
// but then later we can later switch to a different band if needed without the automatic band switching to take over // but then later we can later switch to a different band if needed without the automatic band switching to take over
bool inTimeRange = (
(station.switch_at_ <= d && d <= station.switch_until_) || // <- normal range, 12-16 && 6-8, evalued as 12 <= d <= 16 || 6 <= d <= 8
(station.switch_until_ < station.switch_at_ && ( // <- say for a range of 12->2 & 2->12; 12->2,
(station.switch_at_ <= d && d <= endOfDay) || // should be evaluated as 12 <= d <= 23:59 || 00:00 <= d <= 2
(startOfDay <= d && d <= station.switch_until_)
))
);
bool noOverride = (
(m_bandHopped || (!m_bandHopped && station.frequency_ != m_bandHoppedFreq))
);
bool freqIsDifferent = (station.frequency_ != dialFreq);
bool canSwitch = ( bool canSwitch = (
station.switch_at_ <= d && inTimeRange &&
d <= station.switch_until_ && noOverride &&
(m_bandHopped || (!m_bandHopped && station.frequency_ != m_bandHoppedFreq)) && freqIsDifferent
station.frequency_ != dialFreq
); );
//qDebug() << "Can switch to" << station.band_name_ << "=" << canSwitch << station.switch_at_.time().toString("hh:mm") << "<=" << d.time().toString("hh:mm") << "<=" << station.switch_until_.time().toString("hh:mm") << m_bandHopped << m_bandHoppedFreq; //qDebug() << "Can switch to" << station.band_name_ << "=" << canSwitch << station.switch_at_.time().toString("hh:mm") << "<=" << d.time().toString("hh:mm") << "<=" << station.switch_until_.time().toString("hh:mm") << m_bandHopped << m_bandHoppedFreq;
@@ -3292,11 +3312,14 @@ void MainWindow::readFromStdout() //readFromStdout
} }
} }
// only display frames that are FT8Call frames (should decrease false decodes by at least 50%) // only display frames that are FT8Call frames (should decrease false decodes by at least 12%)
int bits = decodedtext.bits();
bool bValidFrame = ( bool bValidFrame = (
decodedtext.bits() == Varicode::FT8CallFirst || bits == Varicode::FT8Call ||
decodedtext.bits() == Varicode::FT8Call || ((bits & Varicode::FT8CallFirst) == Varicode::FT8CallFirst) ||
decodedtext.bits() == Varicode::FT8CallLast ((bits & Varicode::FT8CallLast) == Varicode::FT8CallLast) ||
((bits & Varicode::FT8CallReserved) == 0 /*Varicode::FT8CallReserved*/) // This is unused...so is invalid at this time...
); );
qDebug() << "valid" << bValidFrame << "decoded text" << decodedtext.message(); qDebug() << "valid" << bValidFrame << "decoded text" << decodedtext.message();
@@ -3335,7 +3358,7 @@ void MainWindow::readFromStdout() //readFromStdout
d.isBuffered = false; d.isBuffered = false;
// if we have any "first" frame, and a buffer is already established, clear it... // if we have any "first" frame, and a buffer is already established, clear it...
if(d.bits == Varicode::FT8CallFirst && m_messageBuffer.contains(d.freq/10*10)){ if(((d.bits & Varicode::FT8CallFirst) == Varicode::FT8CallFirst) && m_messageBuffer.contains(d.freq/10*10)){
qDebug() << "first message encountered, clearing existing buffer" << (d.freq/10*10); qDebug() << "first message encountered, clearing existing buffer" << (d.freq/10*10);
m_messageBuffer.remove(d.freq/10*10); m_messageBuffer.remove(d.freq/10*10);
} }
@@ -5632,29 +5655,35 @@ void MainWindow::clearActivity(){
update_dynamic_property(ui->extFreeTextMsgEdit, "transmitting", false); update_dynamic_property(ui->extFreeTextMsgEdit, "transmitting", false);
} }
void MainWindow::displayTextForFreq(QString text, int freq, QDateTime date, bool bold, bool newLine, bool clearLine){ void MainWindow::displayTextForFreq(QString text, int freq, QDateTime date, bool isTx, bool isNewLine, bool isLast){
int block = m_rxFrameBlockNumbers.contains(freq) ? m_rxFrameBlockNumbers[freq] : -1; int lowFreq = freq/10*10;
if(clearLine && block != -1){ int highFreq = lowFreq + 10;
auto c = ui->textEditRX->textCursor();
QTextBlock b = c.document()->findBlockByNumber(block); int block = -1;
c.setPosition(b.position()); if(m_rxFrameBlockNumbers.contains(freq)){
c.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); block =m_rxFrameBlockNumbers[freq];
c.deleteChar(); } else if(m_rxFrameBlockNumbers.contains(lowFreq)){
c.deleteChar(); block = m_rxFrameBlockNumbers[lowFreq];
block = -1; freq = lowFreq;
m_rxFrameBlockNumbers.remove(freq); } else if(m_rxFrameBlockNumbers.contains(highFreq)){
block = m_rxFrameBlockNumbers[highFreq];
freq = highFreq;
} }
if(newLine){ if(isNewLine){
m_rxFrameBlockNumbers.remove(freq); m_rxFrameBlockNumbers.remove(freq);
m_rxFrameBlockNumbers.remove(lowFreq);
m_rxFrameBlockNumbers.remove(highFreq);
block = -1; block = -1;
} }
block = writeMessageTextToUI(date, text, freq, bold, block); block = writeMessageTextToUI(date, text, freq, isTx, block);
// TODO: jsherer - might be better to see if the bits are "last" versus checking for the EOT // never cache tx or last lines
if(!text.contains("\u2301")){ if(!isTx && !isLast){
m_rxFrameBlockNumbers.insert(freq, block); m_rxFrameBlockNumbers.insert(freq, block);
m_rxFrameBlockNumbers.insert(lowFreq, block);
m_rxFrameBlockNumbers.insert(highFreq, block);
} }
} }
@@ -5765,8 +5794,7 @@ void MainWindow::createMessageTransmitQueue(QString const& text){
lines.append(dt.message()); lines.append(dt.message());
} }
//logMessageText(QDateTime::currentDateTimeUtc(), lines.join(""), freq, true); displayTextForFreq(lines.join(""), freq, QDateTime::currentDateTimeUtc(), true, true, true);
displayTextForFreq(lines.join(""), freq, QDateTime::currentDateTimeUtc(), true, true, false);
// keep track of the last message text sent // keep track of the last message text sent
m_lastTxMessage = text; m_lastTxMessage = text;
@@ -5840,7 +5868,7 @@ QStringList MainWindow::buildFT8MessageFrames(QString const& text){
// prepare compound // prepare compound
bool compound = Radio::is_compound_callsign(m_config.my_callsign()); bool compound = Radio::is_compound_callsign(m_config.my_callsign());
QString mygrid = m_config.my_grid(); QString mygrid = m_config.my_grid().left(4);
QString mycall = m_config.my_callsign(); QString mycall = m_config.my_callsign();
QString basecall = Radio::base_callsign(m_config.my_callsign()); QString basecall = Radio::base_callsign(m_config.my_callsign());
if(basecall != mycall){ if(basecall != mycall){
@@ -6009,8 +6037,7 @@ QStringList MainWindow::buildFT8MessageFrames(QString const& text){
line = lstrip(line); line = lstrip(line);
qDebug() << "before:" << line; qDebug() << "before:" << line;
bool shouldUseLargeChecksum = true; if(dirCmd == "#"){
if(shouldUseLargeChecksum && dirCmd == "#"){
line = line + " " + Varicode::checksum32(line); line = line + " " + Varicode::checksum32(line);
} else { } else {
line = line + " " + Varicode::checksum16(line); line = line + " " + Varicode::checksum16(line);
@@ -6093,9 +6120,10 @@ QString MainWindow::parseFT8Message(QString input, bool *isFree){
bool MainWindow::prepareNextMessageFrame() bool MainWindow::prepareNextMessageFrame()
{ {
m_i3bit = Varicode::FT8Call;
QString frame = popMessageFrame(); QString frame = popMessageFrame();
if(frame.isEmpty()){ if(frame.isEmpty()){
m_i3bit = Varicode::FT8;
ui->nextFreeTextMsg->clear(); ui->nextFreeTextMsg->clear();
return false; return false;
} else { } else {
@@ -6104,12 +6132,11 @@ bool MainWindow::prepareNextMessageFrame()
int count = m_txFrameCount; int count = m_txFrameCount;
int sent = count - m_txFrameQueue.count(); int sent = count - m_txFrameQueue.count();
m_i3bit = Varicode::FT8Call;
if(sent == 1){ if(sent == 1){
m_i3bit = Varicode::FT8CallFirst; m_i3bit |= Varicode::FT8CallFirst;
} }
if(count == sent){ if(count == sent){
m_i3bit = Varicode::FT8CallLast; m_i3bit |= Varicode::FT8CallLast;
} }
ui->startTxButton->setText(QString("Sending (%1/%2)").arg(sent).arg(count)); ui->startTxButton->setText(QString("Sending (%1/%2)").arg(sent).arg(count));
@@ -6129,6 +6156,11 @@ bool MainWindow::isFreqOffsetFree(int f, int bw){
return true; return true;
} }
// if this frequency is in our directed cache, it's always "free"
if(m_rxDirectedCache.contains(f/10*10)){
return true;
}
foreach(int offset, m_bandActivity.keys()){ foreach(int offset, m_bandActivity.keys()){
auto d = m_bandActivity[offset]; auto d = m_bandActivity[offset];
if(d.isEmpty()){ if(d.isEmpty()){
@@ -6232,15 +6264,15 @@ void MainWindow::checkBacon(){
void MainWindow::prepareBacon(){ void MainWindow::prepareBacon(){
QStringList lines; QStringList lines;
QString call = m_config.my_callsign(); QString mycall = m_config.my_callsign();
QString grid = m_config.my_grid().left(4); QString mygrid = m_config.my_grid().left(4);
// FT8Call Style // FT8Call Style
lines.append(QString("%1: BEACON %2").arg(call).arg(grid)); lines.append(QString("%1: BEACON %2").arg(mycall).arg(mygrid));
bool shouldTransmitTwoBeacons = false; bool shouldTransmitTwoBeacons = true;
if(shouldTransmitTwoBeacons){ if(shouldTransmitTwoBeacons){
lines.append(QString("%1: BEACON %2").arg(call).arg(grid)); lines.append(QString("%1: BEACON %2").arg(mycall).arg(mygrid));
} }
// Queue the beacon // Queue the beacon
@@ -6958,9 +6990,8 @@ void MainWindow::on_clearAction_triggered(QObject * sender){
} }
void MainWindow::on_cqMacroButton_clicked(){ void MainWindow::on_cqMacroButton_clicked(){
QString call = m_config.my_callsign(); QString mygrid = m_config.my_grid().left(4);
QString grid = m_config.my_grid().left(4); QString text = QString("CQCQCQ %1").arg(mygrid).trimmed();
QString text = QString("%1: CQCQCQ %2").arg(call).arg(grid).trimmed();
addMessageText(text); addMessageText(text);
} }
@@ -7293,6 +7324,7 @@ void MainWindow::on_tableWidgetRXAll_cellDoubleClicked(int row, int col){
QDateTime now = QDateTime::currentDateTimeUtc(); QDateTime now = QDateTime::currentDateTimeUtc();
QDateTime firstActivity = now; QDateTime firstActivity = now;
QString activityText; QString activityText;
bool isLast = false;
foreach(auto d, m_bandActivity[offset]){ foreach(auto d, m_bandActivity[offset]){
if(activityAging && d.utcTimestamp.secsTo(now)/60 >= activityAging){ if(activityAging && d.utcTimestamp.secsTo(now)/60 >= activityAging){
continue; continue;
@@ -7301,25 +7333,16 @@ void MainWindow::on_tableWidgetRXAll_cellDoubleClicked(int row, int col){
firstActivity = d.utcTimestamp; firstActivity = d.utcTimestamp;
} }
activityText.append(d.text); activityText.append(d.text);
}
if(!activityText.isEmpty()){
//int block = logMessageText(firstActivity, activityText, offset, false);
displayTextForFreq(activityText, offset, firstActivity, false, true, false); isLast = (d.bits & Varicode::FT8CallLast) == Varicode::FT8CallLast;
if(isLast){
// TODO: jsherer - evaluate recency cache... // can also use \u0004 \u2666 \u2404
// m_rxRecentCache.insert(offset/10*10, new QDateTime(QDateTime::currentDateTimeUtc()), 25); activityText.append(" \u2301 ");
}
#if 0
// drop the callsign (if one) in the edit window
foreach(auto d, m_callActivity.values()){
if(d.freq == offset){
addMessageText(d.call);
break;
} }
} }
#endif if(!activityText.isEmpty()){
displayTextForFreq(activityText, offset, firstActivity, false, true, isLast);
}
} }
void MainWindow::on_tableWidgetRXAll_selectionChanged(const QItemSelection &/*selected*/, const QItemSelection &/*deselected*/){ void MainWindow::on_tableWidgetRXAll_selectionChanged(const QItemSelection &/*selected*/, const QItemSelection &/*deselected*/){
@@ -8181,7 +8204,7 @@ void MainWindow::locationChange (QString const& location)
if (MaidenheadLocatorValidator::Acceptable == MaidenheadLocatorValidator ().validate (grid, len)) { if (MaidenheadLocatorValidator::Acceptable == MaidenheadLocatorValidator ().validate (grid, len)) {
qDebug() << "locationChange: Grid supplied is " << grid; qDebug() << "locationChange: Grid supplied is " << grid;
if (m_config.my_grid () != grid) { if (m_config.my_grid () != grid) {
m_config.set_location (grid); m_config.set_dynamic_location (grid);
genStdMsgs (m_rpt, false); genStdMsgs (m_rpt, false);
statusUpdate (); statusUpdate ();
} }
@@ -8299,12 +8322,20 @@ QString MainWindow::callsignSelected(){
} }
bool MainWindow::isRecentOffset(int offset){ bool MainWindow::isRecentOffset(int offset){
if(abs(offset - currentFreqOffset()) <= 10){
return true;
}
return ( return (
m_rxRecentCache.contains(offset/10*10) && m_rxRecentCache.contains(offset/10*10) &&
m_rxRecentCache[offset/10*10]->secsTo(QDateTime::currentDateTimeUtc()) < 120 m_rxRecentCache[offset/10*10]->secsTo(QDateTime::currentDateTimeUtc()) < 120
); );
} }
void MainWindow::markOffsetRecent(int offset){
m_rxRecentCache.insert(offset/10*10, new QDateTime(QDateTime::currentDateTimeUtc()), 10);
m_rxRecentCache.insert(offset/10*10+10, new QDateTime(QDateTime::currentDateTimeUtc()), 10);
}
bool MainWindow::isDirectedOffset(int offset){ bool MainWindow::isDirectedOffset(int offset){
return ( return (
m_rxDirectedCache.contains(offset/10*10) && m_rxDirectedCache.contains(offset/10*10) &&
@@ -8313,7 +8344,8 @@ bool MainWindow::isDirectedOffset(int offset){
} }
void MainWindow::markOffsetDirected(int offset){ void MainWindow::markOffsetDirected(int offset){
m_rxDirectedCache.insert(offset/10*10, new QDateTime(QDateTime::currentDateTimeUtc()), 25); m_rxDirectedCache.insert(offset/10*10, new QDateTime(QDateTime::currentDateTimeUtc()), 10);
m_rxDirectedCache.insert(offset/10*10+10, new QDateTime(QDateTime::currentDateTimeUtc()), 10);
} }
bool MainWindow::isMyCallIncluded(const QString &text){ bool MainWindow::isMyCallIncluded(const QString &text){
@@ -8363,18 +8395,31 @@ void MainWindow::processRxActivity() {
// if this is a compound message or it's a directed message needing a compound call, skip. // if this is a compound message or it's a directed message needing a compound call, skip.
// these messages will be displayed when the compound calls come through // these messages will be displayed when the compound calls come through
#if 0
if(d.isCompound || (d.isDirected && d.text.contains("<....>"))){ if(d.isCompound || (d.isDirected && d.text.contains("<....>"))){
#endif
// if this is a _partial_ directed message, skip until the complete call comes through.
if(d.isDirected && d.text.contains("<....>")){
continue; continue;
} }
int freq = d.freq / 10 * 10; // use the actual frequency and check its delta from our current frequency
// meaning, if our current offset is 1502 and the d.freq is 1492, the delta is <= 10;
bool shouldDisplay = abs(d.freq - currentFreqOffset()) <= 10;
bool shouldDisplay = abs(freq - currentFreqOffset()) <= 10; #if 0
// if this is a recent non-directed offset, bump the cache and display...
if(isRecentOffset(d.freq)){
markOffsetRecent(d.freq);
shouldDisplay = true;
}
#endif
// if this is a (recent) directed offset, bump the cache, and display... // if this is a (recent) directed offset, bump the cache, and display...
// this will allow a directed free text command followed by non-buffered data frames. // this will allow a directed free text command followed by non-buffered data frames.
if(isDirectedOffset(freq)){ if(isDirectedOffset(d.freq)){
markOffsetDirected(freq); markOffsetDirected(d.freq);
shouldDisplay = true; shouldDisplay = true;
} }
@@ -8391,33 +8436,29 @@ void MainWindow::processRxActivity() {
} }
#endif #endif
if(!shouldDisplay){ if(!shouldDisplay){
continue; continue;
} }
// ok, we're good to display...let's cache that fact and then display! // ok, we're good to display...let's cache that fact and then display!
bool isLast = d.bits == Varicode::FT8CallLast; markOffsetRecent(d.freq);
bool isFirst = (d.bits & Varicode::FT8CallFirst) == Varicode::FT8CallFirst;
bool isLast = (d.bits & Varicode::FT8CallLast) == Varicode::FT8CallLast;
// if we're the last message, let's display our EOT character
if (isLast) { if (isLast) {
// can also use \u0004 \u2666 \u2404 // can also use \u0004 \u2666 \u2404
d.text = QString("%1 \u2301 ").arg(d.text); d.text = QString("%1 \u2301 ").arg(d.text);
} }
// log it to the display! // log it to the display!
// int block = m_rxFrameBlockNumbers.contains(freq) ? m_rxFrameBlockNumbers[freq] : -1; displayTextForFreq(d.text, d.freq, d.utcTimestamp, false, isFirst, isLast);
// m_rxFrameBlockNumbers[freq] = logMessageText(d.utcTimestamp, d.text, d.freq, false, block);
// if (isLast) {
// m_rxFrameBlockNumbers.remove(freq);
// }
// m_rxRecentCache.insert(freq, new QDateTime(QDateTime::currentDateTimeUtc()), 25);
displayTextForFreq(d.text, d.freq, d.utcTimestamp, false, false, false);
if(isLast && !d.isBuffered){ if(isLast && !d.isBuffered){
// buffered commands need the rxFrameBlockNumbers cache so it can fixup its display // buffered commands need the rxFrameBlockNumbers cache so it can fixup its display
// all other "last" data frames can clear the rxFrameBlockNumbers cache so the next message will be on a new line. // all other "last" data frames can clear the rxFrameBlockNumbers cache so the next message will be on a new line.
m_rxFrameBlockNumbers.remove(freq); m_rxFrameBlockNumbers.remove(d.freq);
} }
} }
} }
@@ -8441,7 +8482,14 @@ void MainWindow::processCompoundActivity() {
} }
// if we don't have an initialized command, skip... // if we don't have an initialized command, skip...
if (buffer.cmd.bits != Varicode::FT8Call && buffer.cmd.bits != Varicode::FT8CallFirst && buffer.cmd.bits != Varicode::FT8CallLast) { int bits = buffer.cmd.bits;
bool validBits = (
bits == Varicode::FT8Call ||
((bits & Varicode::FT8CallFirst) == Varicode::FT8CallFirst) ||
((bits & Varicode::FT8CallLast) == Varicode::FT8CallLast) ||
((bits & Varicode::FT8CallReserved) == Varicode::FT8CallReserved)
);
if (!validBits) {
qDebug() << "-> buffer.cmd bits is invalid...skip"; qDebug() << "-> buffer.cmd bits is invalid...skip";
continue; continue;
} }
@@ -8464,7 +8512,7 @@ void MainWindow::processCompoundActivity() {
buffer.cmd.grid = d.grid; buffer.cmd.grid = d.grid;
buffer.cmd.isCompound = true; buffer.cmd.isCompound = true;
if (d.bits == Varicode::FT8CallLast) { if ((d.bits & Varicode::FT8CallLast) == Varicode::FT8CallLast) {
buffer.cmd.bits = d.bits; buffer.cmd.bits = d.bits;
} }
} }
@@ -8474,12 +8522,12 @@ void MainWindow::processCompoundActivity() {
buffer.cmd.to = d.call; buffer.cmd.to = d.call;
buffer.cmd.isCompound = true; buffer.cmd.isCompound = true;
if (d.bits == Varicode::FT8CallLast) { if ((d.bits & Varicode::FT8CallLast) == Varicode::FT8CallLast) {
buffer.cmd.bits = d.bits; buffer.cmd.bits = d.bits;
} }
} }
if (buffer.cmd.bits != Varicode::FT8CallLast) { if ((buffer.cmd.bits & Varicode::FT8CallLast) != Varicode::FT8CallLast) {
qDebug() << "-> still not last message...skip"; qDebug() << "-> still not last message...skip";
continue; continue;
} }
@@ -8503,7 +8551,7 @@ void MainWindow::processBufferedActivity() {
continue; continue;
} }
if (buffer.msgs.last().bits != Varicode::FT8CallLast) { if ((buffer.msgs.last().bits & Varicode::FT8CallLast) != Varicode::FT8CallLast) {
continue; continue;
} }
@@ -8517,19 +8565,23 @@ void MainWindow::processBufferedActivity() {
bool valid = false; bool valid = false;
bool shouldUseLargeChecksum = true; if(Varicode::isCommandBuffered(buffer.cmd.cmd)){
if(shouldUseLargeChecksum && buffer.cmd.cmd == "#"){ if(buffer.cmd.cmd == "#"){
checksum = message.right(6); checksum = message.right(6);
message = message.left(message.length() - 7); message = message.left(message.length() - 7);
valid = Varicode::checksum32Valid(checksum, message); valid = Varicode::checksum32Valid(checksum, message);
} else {
checksum = message.right(3);
message = message.left(message.length() - 4);
valid = Varicode::checksum16Valid(checksum, message);
}
} else { } else {
checksum = message.right(3); valid = true;
message = message.left(message.length() - 4);
valid = Varicode::checksum16Valid(checksum, message);
} }
if (valid) { if (valid) {
buffer.cmd.bits = Varicode::FT8CallLast; buffer.cmd.bits |= Varicode::FT8CallLast;
buffer.cmd.text = message; buffer.cmd.text = message;
buffer.cmd.isBuffered = true; buffer.cmd.isBuffered = true;
m_rxCommandQueue.append(buffer.cmd); m_rxCommandQueue.append(buffer.cmd);
@@ -8581,7 +8633,18 @@ void MainWindow::processCommandActivity() {
continue; continue;
} }
// we're only responding to allcall and our callsign at this point, but we'll log callsigns we've heard // log call activity...
CallDetail cd;
cd.call = d.from;
cd.grid = d.grid;
cd.snr = d.snr;
cd.freq = d.freq;
cd.bits = d.bits;
cd.utcTimestamp = d.utcTimestamp;
logCallActivity(cd, true);
// we're only responding to allcall and our callsign at this point, so we'll end after logging the callsigns we've heard
if (!isAllCall && d.to != m_config.my_callsign().trimmed() && d.to != Radio::base_callsign(m_config.my_callsign()).trimmed()) { if (!isAllCall && d.to != m_config.my_callsign().trimmed() && d.to != Radio::base_callsign(m_config.my_callsign()).trimmed()) {
continue; continue;
} }
@@ -8596,16 +8659,6 @@ void MainWindow::processCommandActivity() {
m_txAllcallCommandCache.insert(d.from, new QDateTime(QDateTime::currentDateTimeUtc()), 25); m_txAllcallCommandCache.insert(d.from, new QDateTime(QDateTime::currentDateTimeUtc()), 25);
} }
// log call activity...
CallDetail cd;
cd.call = d.from;
cd.grid = d.grid;
cd.snr = d.snr;
cd.freq = d.freq;
cd.bits = d.bits;
cd.utcTimestamp = d.utcTimestamp;
logCallActivity(cd, true);
// display the command activity // display the command activity
ActivityDetail ad; ActivityDetail ad;
ad.isLowConfidence = false; ad.isLowConfidence = false;
@@ -8615,24 +8668,36 @@ void MainWindow::processCommandActivity() {
ad.freq = d.freq; ad.freq = d.freq;
ad.snr = d.snr; ad.snr = d.snr;
ad.text = QString("%1: %2%3 ").arg(d.from).arg(d.to).arg(d.cmd); ad.text = QString("%1: %2%3 ").arg(d.from).arg(d.to).arg(d.cmd);
if(!d.grid.isEmpty()){
ad.text += d.grid;
}
if(!d.extra.isEmpty()){ if(!d.extra.isEmpty()){
ad.text += d.extra; ad.text += d.extra;
} }
if(!d.text.isEmpty()){ if(!d.text.isEmpty()){
ad.text += d.text; ad.text += d.text;
} }
bool isLast = ad.bits == Varicode::FT8CallLast; bool isLast = (ad.bits & Varicode::FT8CallLast) == Varicode::FT8CallLast;
if (isLast) { if (isLast) {
// can also use \u0004 \u2666 \u2404 // can also use \u0004 \u2666 \u2404
ad.text += QString(" \u2301 "); ad.text += QString(" \u2301 ");
} }
ad.utcTimestamp = d.utcTimestamp; ad.utcTimestamp = d.utcTimestamp;
// log it to the display!
displayTextForFreq(ad.text, ad.freq, ad.utcTimestamp, false, true, true); // we'd be double printing here if were on frequency, so let's be "smart" about this...
bool shouldDisplay = true;
if(shouldDisplay){
if(isRecentOffset(d.freq) && ui->textEditRX->find(QString("(%1)").arg(ad.freq), QTextDocument::FindBackward)){
// ... maybe we could delete the last line that had this message on this frequency...
auto c = ui->textEditRX->textCursor();
c.movePosition(QTextCursor::StartOfBlock);
c.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
qDebug() << "should display directed message, erasing last rx activity line..." << c.selectedText();
c.deleteChar();
c.deleteChar();
}
// log it to the display!
displayTextForFreq(ad.text, ad.freq, ad.utcTimestamp, false, true, false);
}
// and mark the offset as a directed offset so future free text is displayed // and mark the offset as a directed offset so future free text is displayed
markOffsetDirected(ad.freq); markOffsetDirected(ad.freq);
@@ -8739,8 +8804,11 @@ void MainWindow::processCommandActivity() {
continue; continue;
} }
// queue the reply here to be sent when a free interval is available // queue the reply here to be sent when a free interval is available on the frequency that was sent
enqueueMessage(PriorityNormal, reply, d.freq, nullptr); // unless, this is an allcall, to which we should be responding on a clear frequency offset
// we always want to make sure that the directed cache has been updated at this point so we have the
// most information available to make a frequency selection.
enqueueMessage(PriorityNormal, reply, isAllCall ? -1 : d.freq, nullptr);
} }
} }
@@ -8904,7 +8972,7 @@ void MainWindow::displayBandActivity() {
if (item.isLowConfidence) { if (item.isLowConfidence) {
item.text = QString("[%1]").arg(item.text); item.text = QString("[%1]").arg(item.text);
} }
if (item.bits == Varicode::FT8CallLast) { if ((item.bits & Varicode::FT8CallLast) == Varicode::FT8CallLast) {
// can also use \u0004 \u2666 \u2404 // can also use \u0004 \u2666 \u2404
item.text = QString("%1 \u2301 ").arg(item.text); item.text = QString("%1 \u2301 ").arg(item.text);
} }
@@ -9032,11 +9100,12 @@ void MainWindow::displayCallActivity() {
void MainWindow::postWSPRDecode (bool is_new, QStringList parts) void MainWindow::postWSPRDecode (bool is_new, QStringList parts)
{ {
if (parts.size () < 8) #if 0
if (parts.size () < 8)
{ {
parts.insert (6, ""); parts.insert (6, "");
} }
#if 0
m_messageClient->WSPR_decode (is_new, QTime::fromString (parts[0], "hhmm"), parts[1].toInt () m_messageClient->WSPR_decode (is_new, QTime::fromString (parts[0], "hhmm"), parts[1].toInt ()
, parts[2].toFloat (), Radio::frequency (parts[3].toFloat (), 6) , parts[2].toFloat (), Radio::frequency (parts[3].toFloat (), 6)
, parts[4].toInt (), parts[5], parts[6], parts[7].toInt () , parts[4].toInt (), parts[5], parts[6], parts[7].toInt ()
@@ -9094,6 +9163,8 @@ void MainWindow::networkMessage(Message const &message)
// STATION.GET_CALLSIGN - Get the current callsign // STATION.GET_CALLSIGN - Get the current callsign
// STATION.GET_GRID - Get the current grid locator // STATION.GET_GRID - Get the current grid locator
// STATION.SET_GRID - Set the current grid locator // STATION.SET_GRID - Set the current grid locator
// STATION.GET_QTC - Get the current station message
// STATION.SET_QTC - Set the current station message
if(type == "STATION.GET_CALLSIGN"){ if(type == "STATION.GET_CALLSIGN"){
sendNetworkMessage("STATION.CALLSIGN", m_config.my_callsign()); sendNetworkMessage("STATION.CALLSIGN", m_config.my_callsign());
return; return;
@@ -9105,11 +9176,22 @@ void MainWindow::networkMessage(Message const &message)
} }
if(type == "STATION.SET_GRID"){ if(type == "STATION.SET_GRID"){
m_config.set_location(message.value()); m_config.set_dynamic_location(message.value());
sendNetworkMessage("STATION.GRID", m_config.my_grid()); sendNetworkMessage("STATION.GRID", m_config.my_grid());
return; return;
} }
if(type == "STATION.GET_QTC"){
sendNetworkMessage("STATION.QTC", m_config.my_station());
return;
}
if(type == "STATION.SET_QTC"){
m_config.set_dynamic_station_message(message.value());
sendNetworkMessage("STATION.QTC", m_config.my_station());
return;
}
// RX.GET_CALL_ACTIVITY // RX.GET_CALL_ACTIVITY
// RX.GET_BAND_ACTIVITY // RX.GET_BAND_ACTIVITY
// RX.GET_TEXT // RX.GET_TEXT
@@ -9627,9 +9709,10 @@ void MainWindow::on_cbCQTx_toggled(bool b)
void MainWindow::statusUpdate () const void MainWindow::statusUpdate () const
{ {
#if 0
if (!ui) return; if (!ui) return;
auto submode = current_submode (); auto submode = current_submode ();
#if 0
m_messageClient->status_update (m_freqNominal, m_mode, m_hisCall, m_messageClient->status_update (m_freqNominal, m_mode, m_hisCall,
QString::number (ui->rptSpinBox->value ()), QString::number (ui->rptSpinBox->value ()),
m_modeTx, ui->autoButton->isChecked (), m_modeTx, ui->autoButton->isChecked (),
+2 -1
View File
@@ -133,7 +133,7 @@ public slots:
void logCallActivity(CallDetail d, bool spot=true); void logCallActivity(CallDetail d, bool spot=true);
QString lookupCallInCompoundCache(QString const &call); QString lookupCallInCompoundCache(QString const &call);
void clearActivity(); void clearActivity();
void displayTextForFreq(QString text, int freq, QDateTime date, bool bold, bool newLine, bool clearLine); void displayTextForFreq(QString text, int freq, QDateTime date, bool isTx, bool isNewLine, bool isLast);
int writeMessageTextToUI(QDateTime date, QString text, int freq, bool bold, int block=-1); int writeMessageTextToUI(QDateTime date, QString text, int freq, bool bold, int block=-1);
void addMessageText(QString text, bool clear=false); void addMessageText(QString text, bool clear=false);
void enqueueMessage(int priority, QString message, int freq, Callback c); void enqueueMessage(int priority, QString message, int freq, Callback c);
@@ -833,6 +833,7 @@ private:
bool isAllCallIncluded(QString const &text); bool isAllCallIncluded(QString const &text);
QString callsignSelected(); QString callsignSelected();
bool isRecentOffset(int offset); bool isRecentOffset(int offset);
void markOffsetRecent(int offset);
bool isDirectedOffset(int offset); bool isDirectedOffset(int offset);
void markOffsetDirected(int offset); void markOffsetDirected(int offset);
void processActivity(bool force=false); void processActivity(bool force=false);
+3 -2
View File
@@ -563,9 +563,10 @@ void CPlotter::DrawOverlay() //DrawOverlay()
overPainter.initFrom(this); overPainter.initFrom(this);
overPainter.setCompositionMode(QPainter::CompositionMode_Source); overPainter.setCompositionMode(QPainter::CompositionMode_Source);
overPainter.fillRect(0, 0, m_Size.width(), m_h, Qt::transparent); overPainter.fillRect(0, 0, m_Size.width(), m_h, Qt::transparent);
overPainter.setPen(Qt::red); QPen thinRed(Qt::red, 1);
overPainter.setPen(thinRed);
overPainter.drawLine(0, 30, 0, m_h); overPainter.drawLine(0, 30, 0, m_h);
overPainter.drawLine(fwidth, 30, fwidth, m_h); overPainter.drawLine(fwidth+1, 30, fwidth+1, m_h);
overPainter.setPen(penRed); overPainter.setPen(penRed);
overPainter.drawLine(0, 26, fwidth, 26); overPainter.drawLine(0, 26, fwidth, 26);
+6 -2
View File
@@ -75,6 +75,7 @@ QSet<int> buffered_cmds = {6, 7, 8};
QString callsign_pattern = QString("(?<callsign>[A-Z0-9/]+)"); QString callsign_pattern = QString("(?<callsign>[A-Z0-9/]+)");
QString optional_cmd_pattern = QString("(?<cmd>\\s?(?:AGN[?]|ACK|73|YES|NO|SNR|PWR|QSL[?]?|RR|HEARING|[?@&$%|!# ]))?"); QString optional_cmd_pattern = QString("(?<cmd>\\s?(?:AGN[?]|ACK|73|YES|NO|SNR|PWR|QSL[?]?|RR|HEARING|[?@&$%|!# ]))?");
QString optional_grid_pattern = QString("(?<grid>\\s?[A-R]{2}[0-9]{2})?"); QString optional_grid_pattern = QString("(?<grid>\\s?[A-R]{2}[0-9]{2})?");
QString optional_extended_grid_pattern = QString("^(?<grid>\\s?(?:[A-R]{2}[0-9]{2}(?:[A-X]{2}(?:[0-9]{2})?)*))?");
QString optional_pwr_pattern = QString("(?<pwr>(?<=PWR)\\s?\\d+\\s?[KM]?W)?"); QString optional_pwr_pattern = QString("(?<pwr>(?<=PWR)\\s?\\d+\\s?[KM]?W)?");
QString optional_num_pattern = QString("(?<num>(?<=SNR|HEARING)\\s?[-+]?(?:3[01]|[0-2]?[0-9]))?"); QString optional_num_pattern = QString("(?<num>(?<=SNR|HEARING)\\s?[-+]?(?:3[01]|[0-2]?[0-9]))?");
@@ -84,9 +85,9 @@ QRegularExpression directed_re("^" +
optional_pwr_pattern + optional_pwr_pattern +
optional_num_pattern); optional_num_pattern);
QRegularExpression beacon_re(R"(^(?<type>CQCQCQ|BEACON)(?:\s(?<grid>[A-Z]{2}[0-9]{2}))?\b)"); QRegularExpression beacon_re(R"(^\s*(?<type>CQCQCQ|BEACON)(?:\s(?<grid>[A-R]{2}[0-9]{2}))?\b)");
QRegularExpression compound_re("^[<]" + QRegularExpression compound_re("^\\s*[<]" +
callsign_pattern + callsign_pattern +
"(?<extra>" + "(?<extra>" +
optional_grid_pattern + optional_grid_pattern +
@@ -1197,12 +1198,15 @@ QStringList Varicode::unpackBeaconMessage(const QString &text, quint8 *pType, bo
QString Varicode::packCompoundMessage(QString const &text, int *n){ QString Varicode::packCompoundMessage(QString const &text, int *n){
QString frame; QString frame;
qDebug() << "trying to pack compound message" << text;
auto parsedText = compound_re.match(text); auto parsedText = compound_re.match(text);
if(!parsedText.hasMatch()){ if(!parsedText.hasMatch()){
if(n) *n = 0; if(n) *n = 0;
return frame; return frame;
} }
qDebug() << parsedText.capturedTexts();
QString callsign = parsedText.captured("callsign"); QString callsign = parsedText.captured("callsign");
QString grid = parsedText.captured("grid"); QString grid = parsedText.captured("grid");
QString cmd = parsedText.captured("cmd"); QString cmd = parsedText.captured("cmd");
+4 -8
View File
@@ -16,14 +16,10 @@ class Varicode
public: public:
// frame type transmitted via itype and decoded by the ft8 decoded // frame type transmitted via itype and decoded by the ft8 decoded
enum TransmissionType { enum TransmissionType {
FT8 = 0, // [000] FT8Call = 0, // [000] <- any other frame of the message
FT8Fox = 1, // [001] <- the decoder special cases this one frequently :| FT8CallFirst = 1, // [001] <- the first frame of a message
FT8Call = 2, // [010] FT8CallLast = 2, // [010] <- the last frame of a message
FT8CallLast = 3, // [011] <- used to indicate the last frame in a transmission FT8CallReserved = 4, // [100] <- a reserved flag for future use...
FT8CallFirst = 4, // [100] <- used to indicate the first frmae in a transmission
FT8CallReservedB = 5, // [101]
FT8CallReservedC = 6, // [110]
FT8CallReservedD = 7, // [111]
}; };
enum FrameType { enum FrameType {