Morse code, initial commit. Does not read back WPM and breaking mode

yet, although it can set them.
half-duplex
Elliott Liggett 2023-01-20 22:11:30 -08:00
rodzic 93d20cc1ba
commit 23c191a091
11 zmienionych plików z 442 dodań i 13 usunięć

53
cwsender.cpp 100644
Wyświetl plik

@ -0,0 +1,53 @@
#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);
}
cwSender::~cwSender()
{
delete ui;
}
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();
}
}
void cwSender::on_stopBtn_clicked()
{
emit stopCW();
}
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);
}
void cwSender::on_wpmSpin_valueChanged(int wpm)
{
emit setKeySpeed((unsigned char)wpm);
}

42
cwsender.h 100644
Wyświetl plik

@ -0,0 +1,42 @@
#ifndef CWSENDER_H
#define CWSENDER_H
#include <QMainWindow>
#include <QString>
#include <QFont>
#include "wfviewtypes.h"
namespace Ui {
class cwSender;
}
class cwSender : public QMainWindow
{
Q_OBJECT
public:
explicit cwSender(QWidget *parent = 0);
~cwSender();
signals:
void sendCW(QString cwMessage);
void stopCW();
void setKeySpeed(unsigned char wpm);
void setBreakInMode(unsigned char b);
private slots:
void on_sendBtn_clicked();
void on_stopBtn_clicked();
void on_textToSendEdit_returnPressed();
void on_breakinCombo_activated(int index);
void on_wpmSpin_valueChanged(int arg1);
private:
Ui::cwSender *ui;
};
#endif // CWSENDER_H

196
cwsender.ui 100644
Wyświetl plik

@ -0,0 +1,196 @@
<?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>855</width>
<height>491</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</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="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="text">
<string>Macro 5</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="macro2btn">
<property name="text">
<string>Macro 2</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QPushButton" name="macro4btn">
<property name="text">
<string>Macro 4</string>
</property>
</widget>
</item>
<item row="0" column="5">
<widget class="QCheckBox" name="checkBox">
<property name="text">
<string>Edit Mode</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="macro7btn">
<property name="text">
<string>Macro 7</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="macro3btn">
<property name="text">
<string>Macro 3</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="macro6btn">
<property name="text">
<string>Macro 6</string>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QPushButton" name="macro10btn">
<property name="text">
<string>Macro 10</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QPushButton" name="macro9btn">
<property name="text">
<string>Macro 9</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="macro8btn">
<property name="text">
<string>Macro 8</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QPushButton" name="macro1btn">
<property name="text">
<string>Macro 1</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="stopBtn">
<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="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="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">
<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,7 @@ Q_LOGGING_CATEGORY(logGui, "gui")
Q_LOGGING_CATEGORY(logLogger, "log")
Q_LOGGING_CATEGORY(logUser, "user")
Q_LOGGING_CATEGORY(logRig, "rig")
Q_LOGGING_CATEGORY(logRigcommands, "rigCommands")
Q_LOGGING_CATEGORY(logAudio, "audio")
Q_LOGGING_CATEGORY(logUdp, "udp")
Q_LOGGING_CATEGORY(logUdpServer, "udp.server")

Wyświetl plik

@ -9,6 +9,7 @@ Q_DECLARE_LOGGING_CATEGORY(logGui)
Q_DECLARE_LOGGING_CATEGORY(logLogger)
Q_DECLARE_LOGGING_CATEGORY(logUser)
Q_DECLARE_LOGGING_CATEGORY(logRig)
Q_DECLARE_LOGGING_CATEGORY(rigCommands)
Q_DECLARE_LOGGING_CATEGORY(logAudio)
Q_DECLARE_LOGGING_CATEGORY(logUdp)
Q_DECLARE_LOGGING_CATEGORY(logUdpServer)

Wyświetl plik

@ -1164,6 +1164,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
@ -4558,6 +4604,19 @@ void rigCommander::getBreakIn()
prepDataAndSend(payload);
}
void rigCommander::setKeySpeed(unsigned char wpm)
{
// 0 = 6 WPM
// 255 = 48 WPM
unsigned char wpmRadioSend = (wpm-6) * (6.071);
QByteArray payload;
payload.setRawData("\x14\x0C", 2);
payload.append(wpmRadioSend);
prepDataAndSend(payload);
}
void rigCommander::setManualNotch(bool enabled)
{
QByteArray payload("\x16\x48");
@ -4572,7 +4631,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,7 @@ public slots:
void getVox();
void setBreakIn(unsigned char type);
void getBreakIn();
void setKeySpeed(unsigned char wpm);
void setManualNotch(bool enabled);
void getManualNotch();

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,12 @@ 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(setCWBreakMode(unsigned char)), rig, SLOT(setBreakIn(unsigned char)));
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 +1065,15 @@ 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);});
}
void wfmain::prepareSettingsWindow()
@ -3544,6 +3560,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 +3809,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 +4015,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;
@ -4301,7 +4352,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
@ -4339,7 +4390,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
@ -7339,7 +7390,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: ---------- //
@ -8109,12 +8160,15 @@ void wfmain::messageHandler(QtMsgType type, const QMessageLogContext& context, c
out << context.category << ": " << msg << "\n";
out.flush(); // Clear the buffered data
text.append(context.category);
text.append(": ");
text.append(msg);
logTextMutex.lock();
logStringBuffer.push_front(text);
logTextMutex.unlock();
if(QString(context.category) != QString("rigCommands"))
{
text.append(context.category);
text.append(": ");
text.append(msg);
logTextMutex.lock();
logStringBuffer.push_front(text);
logTextMutex.unlock();
}
}
void wfmain::on_customEdgeBtn_clicked()

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);
@ -889,7 +898,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 +922,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 +1055,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

@ -197,6 +197,7 @@ win32:INCLUDEPATH += ../qcustomplot
INCLUDEPATH += resampler
SOURCES += main.cpp\
cwsender.cpp \
loggingwindow.cpp \
wfmain.cpp \
commhandler.cpp \
@ -234,6 +235,7 @@ SOURCES += main.cpp\
HEADERS += wfmain.h \
colorprefs.h \
commhandler.h \
cwsender.h \
loggingwindow.h \
prefs.h \
rigcommander.h \
@ -278,6 +280,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;