mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2024-11-25 13:48:42 -05:00
Add FrequencyList methods to retrieve band name sets
Start to rationalize the new WSPR code with the data models. git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@5475 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
parent
fd06da1432
commit
4a445b0779
26
Bands.cpp
26
Bands.cpp
@ -195,3 +195,29 @@ QVariant Bands::headerData (int section, Qt::Orientation orientation, int role)
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QString Bands::const_iterator::operator * ()
|
||||
{
|
||||
return ADIF_bands[row_].name_;
|
||||
}
|
||||
|
||||
bool Bands::const_iterator::operator != (const_iterator const& rhs) const
|
||||
{
|
||||
return row_ != rhs.row_;
|
||||
}
|
||||
|
||||
auto Bands::const_iterator::operator ++ () -> const_iterator&
|
||||
{
|
||||
++row_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto Bands::begin () const -> Bands::const_iterator
|
||||
{
|
||||
return const_iterator (0);
|
||||
}
|
||||
|
||||
auto Bands::end () const -> Bands::const_iterator
|
||||
{
|
||||
return const_iterator (table_rows ());
|
||||
}
|
||||
|
21
Bands.hpp
21
Bands.hpp
@ -32,6 +32,23 @@ class Bands final
|
||||
public:
|
||||
using Frequency = Radio::Frequency;
|
||||
|
||||
// an iterator that meets the requirements of the C++ for range statement
|
||||
class const_iterator
|
||||
{
|
||||
public:
|
||||
const_iterator (int row)
|
||||
: row_ {row}
|
||||
{
|
||||
}
|
||||
|
||||
QString operator * ();
|
||||
bool operator != (const_iterator const&) const;
|
||||
const_iterator& operator ++ ();
|
||||
|
||||
private:
|
||||
int row_;
|
||||
};
|
||||
|
||||
explicit Bands (QObject * parent = nullptr);
|
||||
|
||||
//
|
||||
@ -40,6 +57,10 @@ public:
|
||||
QString find (Frequency) const; // find band Frequency is in
|
||||
static QString const& oob ();
|
||||
|
||||
// Iterators
|
||||
const_iterator begin () const;
|
||||
const_iterator end () const;
|
||||
|
||||
// Custom role for sorting.
|
||||
static int constexpr SortRole = Qt::UserRole;
|
||||
|
||||
|
@ -173,8 +173,26 @@ int FrequencyList::best_working_frequency (Frequency f) const
|
||||
auto const& target_band = m_->bands_->find (f);
|
||||
if (!target_band.isEmpty ())
|
||||
{
|
||||
// find a frequency in the same band that is allowed for the
|
||||
// target mode
|
||||
// find a frequency in the same band that is allowed
|
||||
for (int row = 0; row < rowCount (); ++row)
|
||||
{
|
||||
auto const& source_row = mapToSource (index (row, 0)).row ();
|
||||
auto const& band = m_->bands_->find (m_->frequency_list_[source_row].frequency_);
|
||||
if (band == target_band)
|
||||
{
|
||||
return row;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int FrequencyList::best_working_frequency (QString const& target_band) const
|
||||
{
|
||||
int result {-1};
|
||||
if (!target_band.isEmpty ())
|
||||
{
|
||||
// find a frequency in the same band that is allowed
|
||||
for (int row = 0; row < rowCount (); ++row)
|
||||
{
|
||||
auto const& source_row = mapToSource (index (row, 0)).row ();
|
||||
@ -553,3 +571,23 @@ auto FrequencyList::end () const -> FrequencyList::const_iterator
|
||||
{
|
||||
return const_iterator (this, rowCount ());
|
||||
}
|
||||
|
||||
auto FrequencyList::all_bands () const -> BandSet
|
||||
{
|
||||
BandSet result;
|
||||
for (auto const& item : m_->frequency_list_)
|
||||
{
|
||||
result << m_->bands_->find (item.frequency_);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
auto FrequencyList::filtered_bands () const -> BandSet
|
||||
{
|
||||
BandSet result;
|
||||
for (auto const& item : *this)
|
||||
{
|
||||
result << m_->bands_->find (item.frequency_);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -14,18 +14,21 @@ class Bands;
|
||||
//
|
||||
// Class FrequencyList
|
||||
//
|
||||
// Encapsulates a collection of frequencies. The implementation is a
|
||||
// table containing the list of Frequency type elements which is
|
||||
// editable and a second column which is an immutable double
|
||||
// representation of the corresponding Frequency item scaled to
|
||||
// mega-Hertz.
|
||||
// Encapsulates a collection of frequencies with associated modes.
|
||||
// The implementation is a table containing the list of Frequency and
|
||||
// mode tuples which are editable. A third column is modeled in the
|
||||
// model which is an immutable double representation of the
|
||||
// corresponding Frequency item scaled to mega-Hertz.
|
||||
//
|
||||
// The list is ordered.
|
||||
// The list is ordered. A filter on mode is available and is set by
|
||||
// the filter(Mode) method. The Mode value Modes::NULL_MODE passes
|
||||
// all rows in the filter.
|
||||
//
|
||||
// Responsibilities
|
||||
//
|
||||
// Stores internally a list of unique frequencies. Provides methods
|
||||
// to add and delete list elements.
|
||||
// Stores internally a list of unique frequency mode tuples.
|
||||
// Provides methods to add and delete list elements. Provides range
|
||||
// iterators for a filtered view of the underlying table.
|
||||
//
|
||||
// Collaborations
|
||||
//
|
||||
@ -47,6 +50,7 @@ public:
|
||||
Mode mode_;
|
||||
};
|
||||
using FrequencyItems = QList<Item>;
|
||||
using BandSet = QSet<QString>;
|
||||
|
||||
enum Column {mode_column, frequency_column, frequency_mhz_column};
|
||||
|
||||
@ -81,16 +85,26 @@ public:
|
||||
// Note that these iterators are on the final sorted and filtered
|
||||
// rows, if you need to access the underlying unfiltered and
|
||||
// unsorted frequencies then use the frequency_list() member to
|
||||
// access the underlying list of rows
|
||||
// access the underlying list of rows.
|
||||
const_iterator begin () const;
|
||||
const_iterator end () const;
|
||||
|
||||
// Bands of the frequencies
|
||||
BandSet all_bands () const;
|
||||
BandSet filtered_bands () const;
|
||||
|
||||
// Find the row of the nearest best working frequency given a
|
||||
// frequency and mode
|
||||
// frequency. Returns -1 if no suitable working frequency is found
|
||||
// in the list.
|
||||
int best_working_frequency (Frequency) const;
|
||||
|
||||
// Find the row of the nearest best working frequency given a band
|
||||
// name. Returns -1 if no suitable working frequency is found in the
|
||||
// list.
|
||||
int best_working_frequency (QString const& band) const;
|
||||
|
||||
// Set filter
|
||||
void filter (Mode);
|
||||
Q_SLOT void filter (Mode);
|
||||
|
||||
// Reset
|
||||
Q_SLOT void reset_to_defaults ();
|
||||
|
113
mainwindow.cpp
113
mainwindow.cpp
@ -52,6 +52,9 @@ namespace
|
||||
Radio::Frequency constexpr default_frequency {14076000};
|
||||
QRegExp message_alphabet {"[- @A-Za-z0-9+./?#]*"};
|
||||
|
||||
// These 10 bands are the hopping candidates and are globally coordinated
|
||||
QStringList const hopping_bands = {"160m","80m","60m","40m","30m","20m","17m","15m","12m","10m"};
|
||||
|
||||
bool message_is_73 (int type, QStringList const& msg_parts)
|
||||
{
|
||||
return type >= 0
|
||||
@ -390,20 +393,8 @@ MainWindow::MainWindow(bool multiple, QSettings * settings, QSharedMemory *shdme
|
||||
m_uploading=false;
|
||||
m_hopTest=false;
|
||||
m_bTxTime=false;
|
||||
m_band00=-1;
|
||||
m_rxDone=false;
|
||||
|
||||
m_fWSPR["160"]=1.8366; //WSPR frequencies
|
||||
m_fWSPR["80"]=3.5926;
|
||||
m_fWSPR["60"]=5.2872;
|
||||
m_fWSPR["40"]=7.0386;
|
||||
m_fWSPR["30"]=10.1387;
|
||||
m_fWSPR["20"]=14.0956;
|
||||
m_fWSPR["17"]=18.1046;
|
||||
m_fWSPR["15"]=21.0946;
|
||||
m_fWSPR["12"]=24.9246;
|
||||
m_fWSPR["10"]=28.1246;
|
||||
|
||||
signalMeter = new SignalMeter(ui->meterFrame);
|
||||
signalMeter->resize(50, 160);
|
||||
|
||||
@ -2224,16 +2215,8 @@ void MainWindow::startTx2()
|
||||
transmit (snr);
|
||||
signalMeter->setValue(0);
|
||||
if(m_mode.mid(0,4)=="WSPR" and !m_tune) {
|
||||
<<<<<<< variant A
|
||||
t = " Transmitting " + m_mode + " ----------------------- " +
|
||||
QString {m_config.bands ()->find (m_dialFreq)->name_};
|
||||
>>>>>>> variant B
|
||||
t = " Transmiting " + m_mode + " ----------------------- " +
|
||||
m_config.bands ()->find (m_dialFreq);
|
||||
####### Ancestor
|
||||
t = " Transmiting " + m_mode + " ----------------------- " +
|
||||
QString {m_config.bands ()->find (m_dialFreq)->name_};
|
||||
======= end
|
||||
ui->decodedTextBrowser->append(t.rightJustified (71, '-'));
|
||||
|
||||
QFile f {m_dataDir.absoluteFilePath ("ALL_WSPR.TXT")};
|
||||
@ -3821,14 +3804,15 @@ void MainWindow::pskSetLocal ()
|
||||
{
|
||||
// find the station row, if any, that matches the band we are on
|
||||
auto stations = m_config.stations ();
|
||||
auto matches = stations->match (stations->index (0, 0)
|
||||
auto matches = stations->match (stations->index (0, StationList::band_column)
|
||||
, Qt::DisplayRole
|
||||
, ui->bandComboBox->currentText ()
|
||||
, 1
|
||||
, Qt::MatchExactly);
|
||||
QString antenna_description;
|
||||
if (!matches.isEmpty ()) {
|
||||
antenna_description = stations->index (matches.first ().row (), 2).data ().toString ();
|
||||
antenna_description = stations->index (matches.first ().row ()
|
||||
, StationList::description_column).data ().toString ();
|
||||
}
|
||||
psk_Reporter->setLocalStation(m_config.my_callsign (), m_config.my_grid (),
|
||||
antenna_description, QString {"WSJT-X v" + version() + " " +
|
||||
@ -4274,7 +4258,6 @@ void MainWindow::on_cbBandHop_toggled(bool b)
|
||||
|
||||
void MainWindow::bandHopping()
|
||||
{
|
||||
QString bandName[]={"160","80","60","40","30","20","17","15","12","10"};
|
||||
QDateTime t = QDateTime::currentDateTimeUtc();
|
||||
QString date = t.date().toString("yyyy MMM dd").trimmed();
|
||||
QString utc = t.time().toString().trimmed();
|
||||
@ -4286,9 +4269,8 @@ void MainWindow::bandHopping()
|
||||
float sec=t.time().second() + 0.001*t.time().msec();
|
||||
float uth=nhr + nmin/60.0 + sec/3600.0;
|
||||
int isun;
|
||||
int iband0,iband;
|
||||
int iband0;
|
||||
int ntxnext;
|
||||
int i,j;
|
||||
|
||||
static int icall=0;
|
||||
if(m_hopTest) uth+= 2.0*icall/60.0;
|
||||
@ -4296,7 +4278,7 @@ void MainWindow::bandHopping()
|
||||
|
||||
// Find grayline status, isun: 0=Sunrise, 1=Day, 2=Sunset, 3=Night
|
||||
hopping_(&nyear, &month, &nday, &uth,
|
||||
const_cast <char *> (m_config.my_grid ().toLatin1().constData()),
|
||||
m_config.my_grid ().toLatin1().constData(),
|
||||
&m_grayDuration, &m_pctx, &isun, &iband0, &ntxnext, 6);
|
||||
|
||||
|
||||
@ -4307,96 +4289,71 @@ void MainWindow::bandHopping()
|
||||
}
|
||||
|
||||
if( m_bandHopping ) {
|
||||
QString bname;
|
||||
QStringList s;
|
||||
if(isun==0) s=m_sunriseBands;
|
||||
if(isun==1) s=m_dayBands;
|
||||
if(isun==2) s=m_sunsetBands;
|
||||
if(isun==3) s=m_nightBands;
|
||||
|
||||
Frequency f0=0;
|
||||
iband=-1;
|
||||
for(i=0; i<s.length(); i++) { //See if designated band is active
|
||||
if(s.at(i)==bandName[iband0]) {
|
||||
f0=(Frequency)1000000*m_fWSPR[bandName[iband0]]+0.5;
|
||||
bname=s.at(i);
|
||||
iband=iband0;
|
||||
QString new_band;
|
||||
if (s.contains (hopping_bands[iband0])) { //See if designated band is active
|
||||
new_band = hopping_bands[iband0];
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
// If designated band is not active, choose one that is active
|
||||
if(iband==-1) {
|
||||
for(i=0; i<s.length(); i++) {
|
||||
j=qrand() % s.length();
|
||||
bname=s.at(j);
|
||||
f0=(Frequency)1000000*m_fWSPR[bname]+0.5;
|
||||
if(s.at(j)!=bandName[m_band00]) break;
|
||||
}
|
||||
for(i=0; i<10; i++) {
|
||||
if(bname==bandName[i]) {
|
||||
iband=i;
|
||||
// and in the hopping list
|
||||
for (auto i = 0; i < s.size (); ++i) { // arbitrary number of iterations
|
||||
auto const& bname = s[qrand() % s.size ()]; // pick a random band
|
||||
if (bname != m_band00 && hopping_bands.contains (bname)) {
|
||||
new_band = bname;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
qDebug () << "bandHopping: m_band00:" << m_band00 << "new candidate band:" << new_band;
|
||||
|
||||
QThread::msleep(1500);
|
||||
|
||||
// qDebug() << nhr << nmin << int(sec) << bname << f0 << 0.000001*f0;
|
||||
// qDebug() << nhr << nmin << int(sec) << m_band00 << f0 << 0.000001*f0;
|
||||
|
||||
m_band00=iband;
|
||||
auto frequencies = m_config.frequencies ();
|
||||
// Iterate the filtered-by-mode FrequencyList model
|
||||
for (int row = 0; row < frequencies->rowCount (); ++row) {
|
||||
// Lookup the underlying source model index from the filtered model index
|
||||
auto const& source_index = frequencies->mapToSource (frequencies->index (row, FrequencyList::frequency_column));
|
||||
// and use it to directly access the list of frequencies that the
|
||||
// FrequencyList model wraps (we could also use the model data()
|
||||
// member using the EditRole of the frequency_column but this way
|
||||
// avoids going via a QVariant item)
|
||||
auto const& f = frequencies->frequency_list ()[source_index.row ()].frequency_;
|
||||
if(f==f0) {
|
||||
on_bandComboBox_activated(row); //Set new band
|
||||
// qDebug() << nhr << nmin << int(sec) << "Band selected" << i << 0.000001*f0 << 0.000001*f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
auto const& row = m_config.frequencies ()->best_working_frequency (new_band);
|
||||
if (row >= 0) { // band is configured
|
||||
m_band00 = new_band;
|
||||
ui->bandComboBox->setCurrentIndex (row);
|
||||
on_bandComboBox_activated (row);
|
||||
|
||||
m_cmnd="";
|
||||
QFile f1 {m_appDir + "/user_hardware.bat"};
|
||||
if(f1.exists()) {
|
||||
m_cmnd=QDir::toNativeSeparators (m_appDir + "/user_hardware.bat ") + bname;
|
||||
m_cmnd=QDir::toNativeSeparators (m_appDir + "/user_hardware.bat ") + m_band00;
|
||||
}
|
||||
QFile f2 {m_appDir + "/user_hardware.cmd"};
|
||||
if(f2.exists()) {
|
||||
m_cmnd=QDir::toNativeSeparators (m_appDir + "/user_hardware.cmd ") + bname;
|
||||
m_cmnd=QDir::toNativeSeparators (m_appDir + "/user_hardware.cmd ") + m_band00;
|
||||
}
|
||||
QFile f3 {m_appDir + "/user_hardware.exe"};
|
||||
if(f3.exists()) {
|
||||
m_cmnd=QDir::toNativeSeparators (m_appDir + "/user_hardware.exe ") + bname;
|
||||
m_cmnd=QDir::toNativeSeparators (m_appDir + "/user_hardware.exe ") + m_band00;
|
||||
}
|
||||
QFile f4 {m_appDir + "/user_hardware"};
|
||||
if(f4.exists()) {
|
||||
m_cmnd=QDir::toNativeSeparators (m_appDir + "/user_hardware ") + bname;
|
||||
m_cmnd=QDir::toNativeSeparators (m_appDir + "/user_hardware ") + m_band00;
|
||||
}
|
||||
if(m_cmnd!="") p3.start(m_cmnd); // Execute user's hardware controller
|
||||
|
||||
// Displat grayline status
|
||||
QString dailySequence[4]={"Sunrise grayline","Day","Sunset grayline","Night"};
|
||||
auto_tx_label->setText(dailySequence[isun]);
|
||||
|
||||
// Produce a short tuneup signal
|
||||
s=m_tuneBands;
|
||||
m_tuneup = false;
|
||||
for(int i=0; i<s.length(); i++) {
|
||||
if(s.at(i)==bname) m_tuneup=true;
|
||||
}
|
||||
if(m_tuneup) {
|
||||
if (m_tuneBands.contains (m_band00)) {
|
||||
m_tuneup = true;
|
||||
on_tuneButton_clicked (true);
|
||||
tuneATU_Timer->start (2500);
|
||||
}
|
||||
} //endif m_bandHopping
|
||||
}
|
||||
|
||||
// Display grayline status
|
||||
QString dailySequence[4]={"Sunrise grayline","Day","Sunset grayline","Night"};
|
||||
auto_tx_label->setText(dailySequence[isun]);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_pushButton_clicked()
|
||||
|
@ -328,7 +328,7 @@ private:
|
||||
qint32 m_pctx;
|
||||
qint32 m_nseq;
|
||||
qint32 m_grayDuration;
|
||||
qint32 m_band00;
|
||||
QString m_band00;
|
||||
|
||||
bool m_btxok; //True if OK to transmit
|
||||
bool m_diskData;
|
||||
@ -454,8 +454,6 @@ private:
|
||||
QStringList m_nightBands;
|
||||
QStringList m_tuneBands;
|
||||
|
||||
QMap<QString,double> m_fWSPR;
|
||||
|
||||
QHash<QString,bool> m_pfx;
|
||||
QHash<QString,bool> m_sfx;
|
||||
|
||||
@ -552,7 +550,7 @@ extern "C" {
|
||||
void wspr_downsample_(short int d2[], int* k);
|
||||
void savec2_(char* fname, int* m_TRseconds, double* m_dialFreq, int len1);
|
||||
|
||||
void hopping_(int* nyear, int* month, int* nday, float* uth, char* MyGrid,
|
||||
void hopping_(int* nyear, int* month, int* nday, float* uth, char const * MyGrid,
|
||||
int* nduration, int* npctx, int* isun, int* iband,
|
||||
int* ntxnext, int len);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user