Merge remote-tracking branch 'origin/cwcw' into filterwidth

half-duplex
Phil Taylor 2023-01-24 00:40:08 +00:00
commit 525f984f01
13 zmienionych plików z 1052 dodań i 38 usunięć

281
cwsender.cpp 100644
Wyświetl plik

@ -0,0 +1,281 @@
#include "cwsender.h"
#include "ui_cwsender.h"
cwSender::cwSender(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::cwSender)
{
ui->setupUi(this);
this->setWindowTitle("CW Sender");
ui->textToSendEdit->setFocus();
QFont f = QFont("Monospace");
f.setStyleHint(QFont::TypeWriter);
ui->textToSendEdit->setFont(f);
ui->transcriptText->setFont(f);
ui->textToSendEdit->setFocus();
ui->statusbar->setToolTipDuration(3000);
this->setToolTipDuration(3000);
}
cwSender::~cwSender()
{
qDebug(logCW()) << "Running CW Sender destructor.";
delete ui;
}
void cwSender::showEvent(QShowEvent *event)
{
emit getCWSettings();
(void)event;
}
void cwSender::handleKeySpeed(unsigned char wpm)
{
//qDebug(logCW()) << "Told that current WPM is" << wpm;
if((wpm >= 6) && (wpm <=48))
{
//qDebug(logCW()) << "Setting WPM UI control to" << wpm;
ui->wpmSpin->blockSignals(true);
ui->wpmSpin->setValue(wpm);
ui->wpmSpin->blockSignals(false);
}
}
void cwSender::handleBreakInMode(unsigned char b)
{
if(b < 3)
{
ui->breakinCombo->blockSignals(true);
ui->breakinCombo->setCurrentIndex(b);
ui->breakinCombo->blockSignals(false);
}
}
void cwSender::handleCurrentModeUpdate(mode_kind mode)
{
this->currentMode = mode;
if( (currentMode==modeCW) || (currentMode==modeCW_R) )
{
} else {
ui->statusbar->showMessage("Note: Mode needs to be set to CW or CW-R to send CW.", 3000);
}
}
void cwSender::on_sendBtn_clicked()
{
if( (ui->textToSendEdit->text().length() > 0) &&
(ui->textToSendEdit->text().length() <= 30) )
{
emit sendCW(ui->textToSendEdit->text());
ui->transcriptText->appendPlainText(ui->textToSendEdit->text());
ui->textToSendEdit->clear();
ui->textToSendEdit->setFocus();
ui->statusbar->showMessage("Sending CW", 3000);
}
if( (currentMode==modeCW) || (currentMode==modeCW_R) )
{
} else {
ui->statusbar->showMessage("Note: Mode needs to be set to CW or CW-R to send CW.", 3000);
}
}
void cwSender::on_stopBtn_clicked()
{
emit stopCW();
ui->textToSendEdit->setFocus();
ui->statusbar->showMessage("Stopping CW transmission.", 3000);
}
void cwSender::on_textToSendEdit_returnPressed()
{
on_sendBtn_clicked();
}
void cwSender::on_breakinCombo_activated(int brkmode)
{
// 0 = off, 1 = semi, 2 = full
emit setBreakInMode((unsigned char)brkmode);
ui->textToSendEdit->setFocus();
}
void cwSender::on_wpmSpin_valueChanged(int wpm)
{
emit setKeySpeed((unsigned char)wpm);
}
void cwSender::on_macro1btn_clicked()
{
processMacroButton(1, ui->macro1btn);
}
void cwSender::on_macro2btn_clicked()
{
processMacroButton(2, ui->macro2btn);
}
void cwSender::on_macro3btn_clicked()
{
processMacroButton(3, ui->macro3btn);
}
void cwSender::on_macro4btn_clicked()
{
processMacroButton(4, ui->macro4btn);
}
void cwSender::on_macro5btn_clicked()
{
processMacroButton(5, ui->macro5btn);
}
void cwSender::on_macro6btn_clicked()
{
processMacroButton(6, ui->macro6btn);
}
void cwSender::on_macro7btn_clicked()
{
processMacroButton(7, ui->macro7btn);
}
void cwSender::on_macro8btn_clicked()
{
processMacroButton(8, ui->macro8btn);
}
void cwSender::on_macro9btn_clicked()
{
processMacroButton(9, ui->macro9btn);
}
void cwSender::on_macro10btn_clicked()
{
processMacroButton(10, ui->macro10btn);
}
void cwSender::processMacroButton(int buttonNumber, QPushButton *btn)
{
if(ui->macroEditChk->isChecked())
{
editMacroButton(buttonNumber, btn);
} else {
runMacroButton(buttonNumber);
}
ui->textToSendEdit->setFocus();
}
void cwSender::runMacroButton(int buttonNumber)
{
if(macroText[buttonNumber].isEmpty())
return;
QString outText;
if(macroText[buttonNumber].contains("\%1"))
{
outText = macroText[buttonNumber].arg(sequenceNumber, 3, 10, QChar('0'));
sequenceNumber++;
ui->sequenceSpin->blockSignals(true);
ui->sequenceSpin->setValue(sequenceNumber);
ui->sequenceSpin->blockSignals(false);
} else {
outText = macroText[buttonNumber];
}
emit sendCW(outText);
ui->transcriptText->appendPlainText(outText);
ui->textToSendEdit->setFocus();
if( (currentMode==modeCW) || (currentMode==modeCW_R) )
{
ui->statusbar->showMessage(QString("Sending CW macro %1").arg(buttonNumber));
} else {
ui->statusbar->showMessage("Note: Mode needs to be set to CW or CW-R to send CW.");
}
}
void cwSender::editMacroButton(int buttonNumber, QPushButton* btn)
{
bool ok;
QString promptFirst = QString("Please enter the text for macro %1,\n"
"up to 30 characters.\n").arg(buttonNumber);
QString promptSecond = QString("You may use \"\%1\" to insert a sequence number.");
QString prompt = promptFirst+promptSecond;
QString newMacroText = QInputDialog::getText(this, "Macro Edit",
prompt,
QLineEdit::Normal, macroText[buttonNumber], &ok);
if(!ok)
return;
if(newMacroText.length() > 30)
{
QMessageBox msgBox;
msgBox.setText(QString("The text entered was too long \n"
"(max length is 30 characters).\n"
"Your input was %1 characters.").arg(newMacroText.length()));
msgBox.exec();
this->raise();
return;
}
macroText[buttonNumber] = newMacroText;
setMacroButtonText(newMacroText, btn);
}
void cwSender::setMacroButtonText(QString btnText, QPushButton *btn)
{
if(btn==Q_NULLPTR)
return;
if(btnText.isEmpty())
return;
QString shortBtnName;
if(btnText.length() <= 8)
{
shortBtnName = btnText;
} else {
shortBtnName = btnText.left(7);
shortBtnName.append("");
}
btn->setText(shortBtnName);
}
void cwSender::on_sequenceSpin_valueChanged(int newSeq)
{
sequenceNumber = newSeq;
ui->textToSendEdit->setFocus();
}
QStringList cwSender::getMacroText()
{
// This is for preference saving:
QStringList mlist;
for(int i=1; i < 11; i++)
{
mlist << macroText[i];
}
return mlist;
}
void cwSender::setMacroText(QStringList macros)
{
if(macros.length() != 10)
{
qCritical(logCW()) << "Macro list must be exactly 10. Rejecting macro text load.";
return;
}
for(int i=0; i < 10; i++)
{
macroText[i+1] = macros.at(i);
}
setMacroButtonText(macroText[1], ui->macro1btn);
setMacroButtonText(macroText[2], ui->macro2btn);
setMacroButtonText(macroText[3], ui->macro3btn);
setMacroButtonText(macroText[4], ui->macro4btn);
setMacroButtonText(macroText[5], ui->macro5btn);
setMacroButtonText(macroText[6], ui->macro6btn);
setMacroButtonText(macroText[7], ui->macro7btn);
setMacroButtonText(macroText[8], ui->macro8btn);
setMacroButtonText(macroText[9], ui->macro9btn);
setMacroButtonText(macroText[10], ui->macro10btn);
}

83
cwsender.h 100644
Wyświetl plik

@ -0,0 +1,83 @@
#ifndef CWSENDER_H
#define CWSENDER_H
#include <QMainWindow>
#include <QString>
#include <QFont>
#include <QInputDialog>
#include <QMessageBox>
#include "wfviewtypes.h"
#include "logcategories.h"
namespace Ui {
class cwSender;
}
class cwSender : public QMainWindow
{
Q_OBJECT
public:
explicit cwSender(QWidget *parent = 0);
~cwSender();
QStringList getMacroText();
void setMacroText(QStringList macros);
signals:
void sendCW(QString cwMessage);
void stopCW();
void setKeySpeed(unsigned char wpm);
void setBreakInMode(unsigned char b);
void getCWSettings();
public slots:
void handleKeySpeed(unsigned char wpm);
void handleBreakInMode(unsigned char b);
void handleCurrentModeUpdate(mode_kind mode);
private slots:
void on_sendBtn_clicked();
void showEvent(QShowEvent* event);
void on_stopBtn_clicked();
void on_textToSendEdit_returnPressed();
void on_breakinCombo_activated(int index);
void on_wpmSpin_valueChanged(int arg1);
void on_macro1btn_clicked();
void on_macro2btn_clicked();
void on_macro3btn_clicked();
void on_macro4btn_clicked();
void on_macro5btn_clicked();
void on_macro6btn_clicked();
void on_macro7btn_clicked();
void on_macro8btn_clicked();
void on_macro9btn_clicked();
void on_macro10btn_clicked();
void on_sequenceSpin_valueChanged(int arg1);
private:
Ui::cwSender *ui;
QString macroText[11];
int sequenceNumber = 1;
mode_kind currentMode;
void processMacroButton(int buttonNumber, QPushButton *btn);
void runMacroButton(int buttonNumber);
void editMacroButton(int buttonNumber, QPushButton *btn);
void setMacroButtonText(QString btnText, QPushButton *btn);
};
#endif // CWSENDER_H

283
cwsender.ui 100644
Wyświetl plik

@ -0,0 +1,283 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>cwSender</class>
<widget class="QMainWindow" name="cwSender">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>681</width>
<height>451</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<property name="toolTip">
<string>Send the text in the edit box</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="5">
<widget class="QLabel" name="label">
<property name="text">
<string>WPM:</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="8">
<widget class="QPlainTextEdit" name="transcriptText">
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="toolTip">
<string>CW Transmission Transcript</string>
</property>
<property name="undoRedoEnabled">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0" colspan="8">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Macros</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="4">
<widget class="QPushButton" name="macro5btn">
<property name="toolTip">
<string>Macro Access Button</string>
</property>
<property name="text">
<string>Macro 5</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="macro2btn">
<property name="toolTip">
<string>Macro Access Button</string>
</property>
<property name="text">
<string>Macro 2</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QPushButton" name="macro4btn">
<property name="toolTip">
<string>Macro Access Button</string>
</property>
<property name="text">
<string>Macro 4</string>
</property>
</widget>
</item>
<item row="0" column="5">
<widget class="QCheckBox" name="macroEditChk">
<property name="toolTip">
<string>Check this box to enter edit mode, where you can then press the macro buttons to edit the macros.</string>
</property>
<property name="text">
<string>Edit Mode</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="macro7btn">
<property name="toolTip">
<string>Macro Access Button</string>
</property>
<property name="text">
<string>Macro 7</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="macro3btn">
<property name="toolTip">
<string>Macro Access Button</string>
</property>
<property name="text">
<string>Macro 3</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="macro6btn">
<property name="toolTip">
<string>Macro Access Button</string>
</property>
<property name="text">
<string>Macro 6</string>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QPushButton" name="macro10btn">
<property name="toolTip">
<string>Macro Access Button</string>
</property>
<property name="text">
<string>Macro 10</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QPushButton" name="macro9btn">
<property name="toolTip">
<string>Macro Access Button</string>
</property>
<property name="text">
<string>Macro 9</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="macro8btn">
<property name="toolTip">
<string>Macro Access Button</string>
</property>
<property name="text">
<string>Macro 8</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QPushButton" name="macro1btn">
<property name="toolTip">
<string>Macro Access Button</string>
</property>
<property name="text">
<string>Macro 1</string>
</property>
</widget>
</item>
<item row="1" column="5">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Seq</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="sequenceSpin">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Sequence number, for contests. &lt;/p&gt;&lt;p&gt;Substitute &amp;quot;%1&amp;quot; in your macro text to use it. &lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>99999</number>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="stopBtn">
<property name="toolTip">
<string>Stop sending CW</string>
</property>
<property name="text">
<string>Stop</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Break In</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLineEdit" name="textToSendEdit">
<property name="minimumSize">
<size>
<width>25</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>400</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Type the text you wish to send as CW here.</string>
</property>
<property name="maxLength">
<number>30</number>
</property>
<property name="placeholderText">
<string>Type here...</string>
</property>
</widget>
</item>
<item row="1" column="6">
<widget class="QSpinBox" name="wpmSpin">
<property name="toolTip">
<string>Set the Words Per Minute</string>
</property>
<property name="minimum">
<number>6</number>
</property>
<property name="maximum">
<number>48</number>
</property>
<property name="value">
<number>20</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="sendBtn">
<property name="text">
<string>Send</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QComboBox" name="breakinCombo">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Set the desired break-in mode:&lt;/p&gt;&lt;p&gt;1. None: You must manually key and unkey the radio.&lt;/p&gt;&lt;p&gt;2. Semi: Transmit is automatic and switches to receive at the end of the text.&lt;/p&gt;&lt;p&gt;3. Full: Same as semi, but with breaks between characters when possible.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<item>
<property name="text">
<string>Off</string>
</property>
</item>
<item>
<property name="text">
<string>Semi</string>
</property>
</item>
<item>
<property name="text">
<string>Full</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>

Wyświetl plik

@ -6,6 +6,8 @@ Q_LOGGING_CATEGORY(logGui, "gui")
Q_LOGGING_CATEGORY(logLogger, "log")
Q_LOGGING_CATEGORY(logUser, "user")
Q_LOGGING_CATEGORY(logRig, "rig")
Q_LOGGING_CATEGORY(logRigTraffic, "rigTraffic")
Q_LOGGING_CATEGORY(logCW, "cw")
Q_LOGGING_CATEGORY(logAudio, "audio")
Q_LOGGING_CATEGORY(logUdp, "udp")
Q_LOGGING_CATEGORY(logUdpServer, "udp.server")

Wyświetl plik

@ -9,6 +9,8 @@ Q_DECLARE_LOGGING_CATEGORY(logGui)
Q_DECLARE_LOGGING_CATEGORY(logLogger)
Q_DECLARE_LOGGING_CATEGORY(logUser)
Q_DECLARE_LOGGING_CATEGORY(logRig)
Q_DECLARE_LOGGING_CATEGORY(logRigTraffic)
Q_DECLARE_LOGGING_CATEGORY(logCW)
Q_DECLARE_LOGGING_CATEGORY(logAudio)
Q_DECLARE_LOGGING_CATEGORY(logUdp)
Q_DECLARE_LOGGING_CATEGORY(logUdpServer)

42
printhex.h 100644
Wyświetl plik

@ -0,0 +1,42 @@
#ifndef PRINTHEX_H
#define PRINTHEX_H
#include <QByteArray>
#include <QString>
#include "logcategories.h"
QString inline getHex(const QByteArray &pdata)
{
QString head = "---- Begin hex dump -----:\n";
QString sdata("DATA: ");
QString index("INDEX: ");
for(int i=0; i < pdata.length(); i++)
{
sdata.append(QString("%1 ").arg((unsigned char)pdata[i], 2, 16, QChar('0')) );
index.append(QString("%1 ").arg(i, 2, 10, QChar('0')));
}
sdata.append("\n");
index.append("\n");
QString tail = "---- End hex dump -----\n";
return head + sdata + index + tail;
}
void inline printHexNow(const QByteArray &pdata, const QLoggingCategory &cat)
{
QString d = getHex(pdata);
// These lines are needed to keep the formatting as expected in the log file
if(d.endsWith("\n"))
{
d.chop(1);
}
QStringList s = d.split("\n");
for(int i=0; i < s.length(); i++)
{
qDebug(cat) << s.at(i);
}
}
#endif // PRINTHEX_H

Wyświetl plik

@ -3,6 +3,7 @@
#include "rigidentities.h"
#include "logcategories.h"
#include "printhex.h"
// Copyright 2017-2020 Elliott H. Liggett
@ -307,8 +308,10 @@ void rigCommander::prepDataAndSend(QByteArray data)
if(data[4] != '\x15')
{
// We don't print out requests for meter levels
qDebug(logRig()) << "Final payload in rig commander to be sent to rig: ";
printHex(data);
qDebug(logRigTraffic()) << "Final payload in rig commander to be sent to rig: ";
//printHex(data);
//printHex(data, logRigTraffic());
printHexNow(data, logRigTraffic());
}
emit dataForComm(data);
@ -1164,6 +1167,52 @@ void rigCommander::setPTT(bool pttOn)
}
}
void rigCommander::sendCW(QString textToSend)
{
if(textToSend.length() >30)
{
qCritical(logRig()).nospace() << "Cannot send CW message, length > 30 characters (" << textToSend.length() << ")";
return;
}
QByteArray textData = textToSend.toLocal8Bit();
unsigned char p=0;
for(int c=0; c < textData.length(); c++)
{
p = textData.at(c);
if( ( (p >= 0x30) && (p <= 0x39) ) ||
( (p >= 0x41) && (p <= 0x5A) ) ||
( (p >= 0x61) && (p <= 0x7A) ) ||
(p==0x2F) || (p==0x3F) || (p==0x2E) ||
(p==0x2D) || (p==0x2C) || (p==0x3A) ||
(p==0x27) || (p==0x28) || (p==0x29) ||
(p==0x3D) || (p==0x2B) || (p==0x22) ||
(p==0x40) || (p==0x20) )
{
// Allowed character, continue
} else {
qWarning(logRig()) << "Invalid character detected in CW message at position " << c << ", the character is " << textToSend.at(c);
printHex(textData);
textData[c] = 0x3F; // "?"
}
}
if(pttAllowed)
{
QByteArray payload("\x17", 1);
payload.append(textData);
prepDataAndSend(payload);
}
// Does it need to end in "FF" or is that implicit at the end of a message?
}
void rigCommander::sendStopCW()
{
QByteArray payload("\x17", 1);
payload.append("\xFF");
prepDataAndSend(payload);
}
void rigCommander::setCIVAddr(unsigned char civAddr)
{
// Note: This sets the radio's CIV address
@ -1344,7 +1393,8 @@ void rigCommander::parseCommand()
{
// We do not log spectrum and meter data,
// as they tend to clog up any useful logging.
printHex(payloadIn);
qDebug(logRigTraffic()) << "Received from radio:";
printHexNow(payloadIn, logRigTraffic());
}
switch(payloadIn[00])
@ -1539,8 +1589,9 @@ void rigCommander::parseLevels()
state.set(MICGAIN, level, false);
break;
case '\x0C':
// CW Keying Speed - ignore for now
state.set(KEYSPD, level, false);
//qInfo(logRig()) << "Have received key speed in RC, raw level: " << level << ", WPM: " << (level/6.071)+6 << ", rounded: " << round((level/6.071)+6);
emit haveKeySpeed(round((level/6.071)+6));
break;
case '\x0D':
// Notch filder setting - ignore for now
@ -2740,6 +2791,7 @@ void rigCommander::parseRegister16()
state.set(FBKINFUNC, true, false);
state.set(SBKINFUNC, false, false);
}
emit haveCWBreakMode(payloadIn.at(2));
break;
case '\x48': // Manual Notch
state.set(MNFUNC, payloadIn.at(2) != 0, false);
@ -3070,20 +3122,20 @@ void rigCommander::parseWFData()
isSub = payloadIn.at(2)==0x01;
freqSpan = parseFrequency(payloadIn, 6);
emit haveScopeSpan(freqSpan, isSub);
qInfo(logRig()) << "Received 0x15 center span data: for frequency " << freqSpan.Hz;
//qInfo(logRig()) << "Received 0x15 center span data: for frequency " << freqSpan.Hz;
//printHex(payloadIn, false, true);
break;
case 0x16:
// read edge mode center in edge mode
emit haveScopeEdge((char)payloadIn[2]);
qInfo(logRig()) << "Received 0x16 edge in center mode:";
//qInfo(logRig()) << "Received 0x16 edge in center mode:";
printHex(payloadIn, false, true);
// [1] 0x16
// [2] 0x01, 0x02, 0x03: Edge 1,2,3
break;
case 0x17:
// Hold status (only 9700?)
qInfo(logRig()) << "Received 0x17 hold status - need to deal with this!";
qDebug(logRig()) << "Received 0x17 hold status - need to deal with this!";
printHex(payloadIn, false, true);
break;
case 0x19:
@ -4558,6 +4610,26 @@ void rigCommander::getBreakIn()
prepDataAndSend(payload);
}
void rigCommander::setKeySpeed(unsigned char wpm)
{
// 0 = 6 WPM
// 255 = 48 WPM
unsigned char wpmRadioSend = round((wpm-6) * (6.071));
//qInfo(logRig()) << "Setting keyspeed to " << wpm << "WPM, via command value" << wpmRadioSend;
QByteArray payload;
payload.setRawData("\x14\x0C", 2);
payload.append(bcdEncodeInt(wpmRadioSend));
prepDataAndSend(payload);
}
void rigCommander::getKeySpeed()
{
QByteArray payload;
payload.setRawData("\x14\x0C", 2);
prepDataAndSend(payload);
}
void rigCommander::setManualNotch(bool enabled)
{
QByteArray payload("\x16\x48");
@ -4572,7 +4644,6 @@ void rigCommander::getManualNotch()
prepDataAndSend(payload);
}
void rigCommander::getRigID()
{
QByteArray payload;

Wyświetl plik

@ -86,6 +86,8 @@ public slots:
// PTT, ATU, ATT, Antenna, and Preamp:
void getPTT();
void setPTT(bool pttOn);
void sendCW(QString textToSend);
void sendStopCW();
void startATU();
void setATU(bool enabled);
void getATUStatus();
@ -113,6 +115,8 @@ public slots:
void getVox();
void setBreakIn(unsigned char type);
void getBreakIn();
void setKeySpeed(unsigned char wpm);
void getKeySpeed();
void setManualNotch(bool enabled);
void getManualNotch();
@ -339,6 +343,11 @@ signals:
void havePreamp(unsigned char pre);
void haveAntenna(unsigned char ant,bool rx);
// CW:
void haveKeySpeed(unsigned char wpm);
void haveCWBreakMode(unsigned char bmode);
// Rig State
void stateInfo(rigstate* state);

Wyświetl plik

@ -48,6 +48,7 @@ wfmain::wfmain(const QString settingsFile, const QString logFile, bool debugMode
rpt = new repeaterSetup();
sat = new satelliteSetup();
trxadj = new transceiverAdjustments();
cw = new cwSender();
shut = new controllerSetup();
abtBox = new aboutbox();
selRad = new selectRadio();
@ -341,6 +342,18 @@ void wfmain::rigConnections()
connect(rig, SIGNAL(havePTTStatus(bool)), this, SLOT(receivePTTstatus(bool)));
connect(this, SIGNAL(setPTT(bool)), rig, SLOT(setPTT(bool)));
connect(this, SIGNAL(getPTT()), rig, SLOT(getPTT()));
connect(this, SIGNAL(sendCW(QString)), rig, SLOT(sendCW(QString)));
connect(this, SIGNAL(stopCW()), rig, SLOT(sendStopCW()));
connect(this, SIGNAL(setKeySpeed(unsigned char)), rig, SLOT(setKeySpeed(unsigned char)));
connect(this, SIGNAL(getKeySpeed()), rig, SLOT(getKeySpeed()));
connect(this, SIGNAL(setCWBreakMode(unsigned char)), rig, SLOT(setBreakIn(unsigned char)));
connect(this, SIGNAL(getCWBreakMode()), rig, SLOT(getBreakIn()));
connect(this->rig, &rigCommander::haveKeySpeed,
[=](const unsigned char &wpm) { cw->handleKeySpeed(wpm);});
connect(this->rig, &rigCommander::haveCWBreakMode,
[=](const unsigned char &bm) { cw->handleBreakInMode(bm);});
connect(rig, SIGNAL(haveBandStackReg(freqt,char,char,bool)), this, SLOT(receiveBandStackReg(freqt,char,char,bool)));
connect(this, SIGNAL(setRitEnable(bool)), rig, SLOT(setRitEnable(bool)));
connect(this, SIGNAL(setRitValue(int)), rig, SLOT(setRitValue(int)));
@ -1058,6 +1071,19 @@ void wfmain::setupMainUI()
connect(this->trxadj, &transceiverAdjustments::setPassband,
[=](const quint16 &passbandHz) { issueCmdUniquePriority(cmdSetPassband, passbandHz);}
);
connect(this->cw, &cwSender::sendCW,
[=](const QString &cwMessage) { issueCmd(cmdSendCW, cwMessage);});
connect(this->cw, &cwSender::stopCW,
[=]() { issueDelayedCommand(cmdStopCW);});
connect(this->cw, &cwSender::setBreakInMode,
[=](const unsigned char &bmode) { issueCmd(cmdSetBreakMode, bmode);});
connect(this->cw, &cwSender::setKeySpeed,
[=](const unsigned char &wpm) { issueCmd(cmdSetKeySpeed, wpm);});
connect(this->cw, &cwSender::getCWSettings,
[=]() { issueDelayedCommand(cmdGetKeySpeed);
issueDelayedCommand(cmdGetBreakMode);});
}
void wfmain::prepareSettingsWindow()
@ -1460,12 +1486,97 @@ void wfmain::setupKeyShortcuts()
keyM->setKey(Qt::Key_M);
connect(keyM, SIGNAL(activated()), this, SLOT(shortcutM()));
// Alternate for plus:
keyK = new QShortcut(this);
keyK->setKey(Qt::Key_K);
connect(keyK, &QShortcut::activated,
[=]() {
if (freqLock) return;
this->shortcutPlus();
});
// Alternate for minus:
keyJ = new QShortcut(this);
keyJ->setKey(Qt::Key_J);
connect(keyJ, &QShortcut::activated,
[=]() {
if (freqLock) return;
this->shortcutMinus();
});
keyShiftK = new QShortcut(this);
keyShiftK->setKey(Qt::SHIFT + Qt::Key_K);
connect(keyShiftK, &QShortcut::activated,
[=]() {
if (freqLock) return;
this->shortcutShiftPlus();
});
keyShiftJ = new QShortcut(this);
keyShiftJ->setKey(Qt::SHIFT + Qt::Key_J);
connect(keyShiftJ, &QShortcut::activated,
[=]() {
if (freqLock) return;
this->shortcutShiftMinus();
});
keyControlK = new QShortcut(this);
keyControlK->setKey(Qt::CTRL + Qt::Key_K);
connect(keyControlK, &QShortcut::activated,
[=]() {
if (freqLock) return;
this->shortcutControlPlus();
});
keyControlJ = new QShortcut(this);
keyControlJ->setKey(Qt::CTRL + Qt::Key_J);
connect(keyControlJ, &QShortcut::activated,
[=]() {
if (freqLock) return;
this->shortcutControlMinus();
});
// Move the tuning knob by the tuning step selected:
// H = Down
keyH = new QShortcut(this);
keyH->setKey(Qt::Key_H);
connect(keyH, &QShortcut::activated,
[=]() {
if (freqLock) return;
freqt f;
f.Hz = roundFrequencyWithStep(freq.Hz, -1, tsKnobHz);
f.MHzDouble = f.Hz / (double)1E6;
freq.Hz = f.Hz;
freq.MHzDouble = f.MHzDouble;
setUIFreq();
issueCmd(cmdSetFreq, f);
});
// L = Up
keyL = new QShortcut(this);
keyL->setKey(Qt::Key_L);
connect(keyL, &QShortcut::activated,
[=]() {
if (freqLock) return;
freqt f;
f.Hz = roundFrequencyWithStep(freq.Hz, 1, tsKnobHz);
f.MHzDouble = f.Hz / (double)1E6;
ui->freqLabel->setText(QString("%1").arg(f.MHzDouble, 0, 'f'));
freq.Hz = f.Hz;
freq.MHzDouble = f.MHzDouble;
setUIFreq();
issueCmd(cmdSetFreq, f);
});
keyDebug = new QShortcut(this);
#if (QT_VERSION < QT_VERSION_CHECK(6,0,0))
keyDebug->setKey(Qt::CTRL + Qt::SHIFT + Qt::Key_D);
#else
keyDebug->setKey(Qt::CTRL + Qt::Key_D);
#endif
#endif
connect(keyDebug, SIGNAL(activated()), this, SLOT(on_debugBtn_clicked()));
}
@ -2124,8 +2235,24 @@ void wfmain::loadSettings()
ui->clusterTimeoutLineEdit->setEnabled(false);
}
settings->endArray();
settings->endGroup();
// CW Memory Load:
settings->beginGroup("Keyer");
int numMemories = settings->beginReadArray("macros");
if(numMemories==10)
{
QStringList macroList;
for(int m=0; m < 10; m++)
{
settings->setArrayIndex(m);
macroList << settings->value("macroText", "").toString();
}
cw->setMacroText(macroList);
}
settings->endArray();
settings->endGroup();
#if defined (USB_CONTROLLER)
/* Load USB buttons*/
settings->beginGroup("USB");
@ -2679,7 +2806,22 @@ void wfmain::saveSettings()
}
settings->endArray();
settings->endGroup();
settings->beginGroup("Keyer");
QStringList macroList = cw->getMacroText();
if(macroList.length() == 10)
{
settings->beginWriteArray("macros");
for(int m=0; m < 10; m++)
{
settings->setArrayIndex(m);
settings->setValue("macroText", macroList.at(m));
}
settings->endArray();
} else {
qDebug(logSystem()) << "Error, CW macro list is wrong length: " << macroList.length();
}
settings->endGroup();
#if defined(USB_CONTROLLER)
@ -3021,12 +3163,13 @@ void wfmain::shortcutMinus()
freqt f;
f.Hz = roundFrequencyWithStep(freq.Hz, -1, tsPlusHz);
f.MHzDouble = f.Hz / (double)1E6;
freq.Hz = f.Hz;
freq.MHzDouble = f.MHzDouble;
setUIFreq();
//issueCmd(cmdSetFreq, f);
issueCmdUniquePriority(cmdSetFreq, f);
issueDelayedCommandUnique(cmdGetFreq);
//issueDelayedCommandUnique(cmdGetFreq);
}
void wfmain::shortcutPlus()
@ -3035,12 +3178,13 @@ void wfmain::shortcutPlus()
freqt f;
f.Hz = roundFrequencyWithStep(freq.Hz, 1, tsPlusHz);
f.MHzDouble = f.Hz / (double)1E6;
freq.Hz = f.Hz;
freq.MHzDouble = f.MHzDouble;
setUIFreq();
//issueCmd(cmdSetFreq, f);
issueCmdUniquePriority(cmdSetFreq, f);
issueDelayedCommandUnique(cmdGetFreq);
//issueDelayedCommandUnique(cmdGetFreq);
}
void wfmain::shortcutStepMinus()
@ -3075,12 +3219,13 @@ void wfmain::shortcutShiftMinus()
freqt f;
f.Hz = roundFrequencyWithStep(freq.Hz, -1, tsPlusShiftHz);
f.MHzDouble = f.Hz / (double)1E6;
freq.Hz = f.Hz;
freq.MHzDouble = f.MHzDouble;
setUIFreq();
//emit setFrequency(0,f);
issueCmd(cmdSetFreq, f);
issueDelayedCommandUnique(cmdGetFreq);
//issueDelayedCommandUnique(cmdGetFreq);
}
void wfmain::shortcutShiftPlus()
@ -3089,12 +3234,13 @@ void wfmain::shortcutShiftPlus()
freqt f;
f.Hz = roundFrequencyWithStep(freq.Hz, 1, tsPlusShiftHz);
f.MHzDouble = f.Hz / (double)1E6;
freq.Hz = f.Hz;
freq.MHzDouble = f.MHzDouble;
setUIFreq();
//emit setFrequency(0,f);
issueCmd(cmdSetFreq, f);
issueDelayedCommandUnique(cmdGetFreq);
//issueDelayedCommandUnique(cmdGetFreq);
}
void wfmain::shortcutControlMinus()
@ -3103,12 +3249,12 @@ void wfmain::shortcutControlMinus()
freqt f;
f.Hz = roundFrequencyWithStep(freq.Hz, -1, tsPlusControlHz);
f.MHzDouble = f.Hz / (double)1E6;
freq.Hz = f.Hz;
freq.MHzDouble = f.MHzDouble;
setUIFreq();
//emit setFrequency(0,f);
issueCmd(cmdSetFreq, f);
issueDelayedCommandUnique(cmdGetFreq);
//issueDelayedCommandUnique(cmdGetFreq);
}
void wfmain::shortcutControlPlus()
@ -3117,12 +3263,12 @@ void wfmain::shortcutControlPlus()
freqt f;
f.Hz = roundFrequencyWithStep(freq.Hz, 1, tsPlusControlHz);
f.MHzDouble = f.Hz / (double)1E6;
freq.Hz = f.Hz;
freq.MHzDouble = f.MHzDouble;
setUIFreq();
//emit setFrequency(0,f);
issueCmd(cmdSetFreq, f);
issueDelayedCommandUnique(cmdGetFreq);
//issueDelayedCommandUnique(cmdGetFreq);
}
void wfmain::shortcutPageUp()
@ -3131,12 +3277,12 @@ void wfmain::shortcutPageUp()
freqt f;
f.Hz = freq.Hz + tsPageHz;
f.MHzDouble = f.Hz / (double)1E6;
freq.Hz = f.Hz;
freq.MHzDouble = f.MHzDouble;
setUIFreq();
//emit setFrequency(0,f);
issueCmd(cmdSetFreq, f);
issueDelayedCommandUnique(cmdGetFreq);
//issueDelayedCommandUnique(cmdGetFreq);
}
void wfmain::shortcutPageDown()
@ -3145,12 +3291,12 @@ void wfmain::shortcutPageDown()
freqt f;
f.Hz = freq.Hz - tsPageHz;
f.MHzDouble = f.Hz / (double)1E6;
freq.Hz = f.Hz;
freq.MHzDouble = f.MHzDouble;
setUIFreq();
//emit setFrequency(0,f);
issueCmd(cmdSetFreq, f);
issueDelayedCommandUnique(cmdGetFreq);
//issueDelayedCommandUnique(cmdGetFreq);
}
void wfmain::shortcutF()
@ -3544,6 +3690,24 @@ void wfmain::doCmd(commandtype cmddata)
}
break;
}
case cmdSendCW:
{
QString messageText = (*std::static_pointer_cast<QString>(data));
emit sendCW(messageText);
break;
}
case cmdSetBreakMode:
{
unsigned char bmode = (*std::static_pointer_cast<unsigned char>(data));
emit setCWBreakMode(bmode);
break;
}
case cmdSetKeySpeed:
{
unsigned char wpm = (*std::static_pointer_cast<unsigned char>(data));
emit setKeySpeed(wpm);
break;
}
case cmdSetATU:
{
bool atuOn = (*std::static_pointer_cast<bool>(data));
@ -3775,12 +3939,21 @@ void wfmain::doCmd(cmds cmd)
break;
case cmdGetALCMeter:
if(amTransmitting)
emit getMeters(meterALC);
emit getMeters(meterALC);
break;
case cmdGetCompMeter:
if(amTransmitting)
emit getMeters(meterComp);
break;
case cmdGetKeySpeed:
emit getKeySpeed();
break;
case cmdGetBreakMode:
emit getCWBreakMode();
break;
case cmdStopCW:
emit stopCW();
break;
case cmdStartRegularPolling:
runPeriodicCommands = true;
break;
@ -3972,6 +4145,14 @@ void wfmain::issueCmd(cmds cmd, qint16 c)
delayedCmdQue.push_back(cmddata);
}
void wfmain::issueCmd(cmds cmd, QString s)
{
commandtype cmddata;
cmddata.cmd = cmd;
cmddata.data = std::shared_ptr<QString>(new QString(s));
delayedCmdQue.push_back(cmddata);
}
void wfmain::issueCmdUniquePriority(cmds cmd, bool b)
{
commandtype cmddata;
@ -4314,7 +4495,7 @@ void wfmain::initPeriodicCommands()
}
}
void wfmain::insertPeriodicCommand(cmds cmd, unsigned char priority)
void wfmain::insertPeriodicCommand(cmds cmd, unsigned char priority=100)
{
// TODO: meaningful priority
// These commands get run at the fastest pace possible
@ -4352,7 +4533,7 @@ void wfmain::removePeriodicCommand(cmds cmd)
}
void wfmain::insertSlowPeriodicCommand(cmds cmd, unsigned char priority)
void wfmain::insertSlowPeriodicCommand(cmds cmd, unsigned char priority=100)
{
// TODO: meaningful priority
// These commands are run every 20 "ticks" of the primary radio command loop
@ -4579,7 +4760,7 @@ void wfmain::receiveSpectrumData(QByteArray spectrum, double startFreq, double e
wfRow = wfimage.at(row);
for(int col = 0; col < spectWidth; col++)
{
colorMap->data()->setCell( col, row, wfRow.at(col));
colorMap->data()->setCell( col, row, (unsigned char)wfRow.at(col));
}
}
if(updateRange)
@ -5023,6 +5204,7 @@ void wfmain::receiveMode(unsigned char mode, unsigned char filter)
}
currentModeIndex = mode;
currentModeInfo.mk = (mode_kind)mode;
cw->handleCurrentModeUpdate((mode_kind)mode);
currentModeInfo.filter = filter;
switch (currentModeInfo.mk) {
@ -7338,7 +7520,7 @@ void wfmain::on_underlayAverageBuffer_toggled(bool checked)
void wfmain::on_debugBtn_clicked()
{
qInfo(logSystem()) << "Debug button pressed.";
emit getRigID();
cw->show();
}
// ---------- color helper functions: ---------- //
@ -8114,6 +8296,7 @@ void wfmain::messageHandler(QtMsgType type, const QMessageLogContext& context, c
logTextMutex.lock();
logStringBuffer.push_front(text);
logTextMutex.unlock();
}
void wfmain::on_customEdgeBtn_clicked()
@ -8507,3 +8690,16 @@ void wfmain::on_autoSSBchk_clicked(bool checked)
{
prefs.automaticSidebandSwitching = checked;
}
void wfmain::on_cwButton_clicked()
{
if(cw->isMinimized())
{
cw->raise();
cw->activateWindow();
return;
}
cw->show();
cw->raise();
cw->activateWindow();
}

Wyświetl plik

@ -35,6 +35,7 @@
#include "repeatersetup.h"
#include "satellitesetup.h"
#include "transceiveradjustments.h"
#include "cwsender.h"
#include "udpserver.h"
#include "qledlabel.h"
#include "rigctld.h"
@ -158,7 +159,7 @@ signals:
// PTT, ATU, ATT, Antenna, Preamp:
void getPTT();
void setPTT(bool pttOn);
void setPTT(bool pttOn);
void getAttenuator();
void getPreamp();
void getAntenna();
@ -169,6 +170,14 @@ signals:
void setATU(bool atuEnabled);
void getATUStatus();
// CW Keying:
void sendCW(QString message);
void stopCW();
void getKeySpeed();
void setKeySpeed(unsigned char wpm);
void setCWBreakMode(unsigned char breakMode);
void getCWBreakMode();
// Time and date:
void setTime(timekind t);
void setDate(datekind d);
@ -720,6 +729,8 @@ private slots:
void on_autoSSBchk_clicked(bool checked);
void on_cwButton_clicked();
private:
Ui::wfmain *ui;
void closeEvent(QCloseEvent *event);
@ -796,6 +807,17 @@ private:
QShortcut *keyF;
QShortcut *keyM;
QShortcut *keyH;
QShortcut *keyK; // alternate +
QShortcut *keyJ; // alternate -
QShortcut *keyL;
QShortcut *keyShiftK;
QShortcut *keyShiftJ;
QShortcut *keyControlK;
QShortcut *keyControlJ;
QShortcut *keyDebug;
@ -889,7 +911,7 @@ private:
cmdGetVdMeter, cmdGetIdMeter, cmdGetSMeter, cmdGetCenterMeter, cmdGetPowerMeter,
cmdGetSWRMeter, cmdGetALCMeter, cmdGetCompMeter, cmdGetTxRxMeter,
cmdGetTone, cmdGetTSQL, cmdGetDTCS, cmdGetRptAccessMode, cmdGetPreamp, cmdGetAttenuator, cmdGetAntenna,
cmdGetBandStackReg,
cmdGetBandStackReg, cmdGetKeySpeed, cmdSetKeySpeed, cmdGetBreakMode, cmdSetBreakMode, cmdSendCW, cmdStopCW,
cmdSetTime, cmdSetDate, cmdSetUTCOffset};
struct commandtype {
@ -913,6 +935,7 @@ private:
void issueCmd(cmds cmd, bool b);
void issueCmd(cmds cmd, quint16 c);
void issueCmd(cmds cmd, qint16 c);
void issueCmd(cmds cmd, QString s);
// These commands pop_front and remove similar commands:
void issueCmdUniquePriority(cmds cmd, bool b);
@ -1045,10 +1068,12 @@ private:
unsigned char usbGain=0;
unsigned char lanGain=0;
// Widgets and Special Windows:
calibrationWindow *cal;
repeaterSetup *rpt;
satelliteSetup *sat;
transceiverAdjustments *trxadj;
cwSender *cw;
controllerSetup* shut;
aboutbox *abtBox;
selectRadio *selRad;

Wyświetl plik

@ -18,7 +18,7 @@
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>3</number>
<number>0</number>
</property>
<widget class="QWidget" name="mainTab">
<attribute name="title">
@ -1041,6 +1041,16 @@
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="cwButton">
<property name="toolTip">
<string>Press to bring up the CW Sender</string>
</property>
<property name="text">
<string>CW</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="rptSetupBtn">
<property name="toolTip">

Wyświetl plik

@ -197,6 +197,7 @@ win32:INCLUDEPATH += ../qcustomplot
INCLUDEPATH += resampler
SOURCES += main.cpp\
cwsender.cpp \
loggingwindow.cpp \
wfmain.cpp \
commhandler.cpp \
@ -234,8 +235,10 @@ SOURCES += main.cpp\
HEADERS += wfmain.h \
colorprefs.h \
commhandler.h \
cwsender.h \
loggingwindow.h \
prefs.h \
printhex.h \
rigcommander.h \
freqmemory.h \
rigidentities.h \
@ -278,6 +281,7 @@ HEADERS += wfmain.h \
FORMS += wfmain.ui \
calibrationwindow.ui \
cwsender.ui \
loggingwindow.ui \
satellitesetup.ui \
selectradio.ui \

Wyświetl plik

@ -59,6 +59,12 @@ enum mode_kind {
modeDCR
};
enum breakIn_t {
brkinOff = 0x00,
brkinSemi = 0x01,
brkinFull = 0x02
};
struct freqt {
quint64 Hz;
double MHzDouble;