Working on CW keyer

main
PianetaRadio 2025-04-09 23:35:27 +02:00 zatwierdzone przez GitHub
rodzic f617f7adbd
commit 89318e7b71
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
14 zmienionych plików z 759 dodań i 135 usunięć

131
dialogcwkeyer.cpp 100644
Wyświetl plik

@ -0,0 +1,131 @@
/**
** This file is part of the CatRadio project.
** Copyright 2022-2025 Gianfranco Sordetti IZ8EWD <iz8ewd@pianetaradio.it>.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
**/
#include "dialogcwkeyer.h"
#include "ui_dialogcwkeyer.h"
#include "guidata.h"
#include "winkeyer.h"
#include <QSettings>
#include <QFile>
#include <QSerialPortInfo>
#include <QDebug>
#include <QThread>
extern cwKeyerConfig cwKConf;
DialogCWKeyer::DialogCWKeyer(WinKeyer *winkeyer, QWidget *parent)
: QDialog(parent)
, ui(new Ui::DialogCWKeyer)
, wk(winkeyer)
{
ui->setupUi(this);
ui->lineEdit_cwK1->setText(cwKConf.memoryString[0]);
ui->lineEdit_cwK2->setText(cwKConf.memoryString[1]);
ui->lineEdit_cwK3->setText(cwKConf.memoryString[2]);
ui->lineEdit_cwK4->setText(cwKConf.memoryString[3]);
ui->lineEdit_cwK5->setText(cwKConf.memoryString[4]);
if (wk->isOpen) //WinKeyer already open
{
ui->pushButton_Connect->setChecked(true);
ui->label_wkVersion->setText(QString("WinKeyer v. %1").arg(wk->version));
}
//* COM port
ui->comboBox_comPort->clear();
ui->comboBox_comPort->addItem("");
foreach (const QSerialPortInfo &comPort, QSerialPortInfo::availablePorts()) //search available COM port
{
#ifdef Q_OS_WIN
ui->comboBox_comPort->addItem(comPort.portName());
#endif
#ifdef Q_OS_LINUX
ui->comboBox_comPort->addItem("/dev/"+comPort.portName());
#endif
}
ui->comboBox_comPort->setCurrentText(cwKConf.comPort);
}
DialogCWKeyer::~DialogCWKeyer()
{
delete ui;
}
void DialogCWKeyer::on_pushButton_Connect_toggled(bool checked)
{
if (checked && !wk->isOpen) //Connect
{
if (!wk->init(ui->comboBox_comPort->currentText())) //Open serial port
{
//wait 2 seconds, serial port open causes reset in Arduino for K3NG CW keyer
QThread::msleep(2000);
wk->version = wk->open(); //Open WinKeyer host
if (wk->version) //Read WinKeyer version
{
ui->label_wkVersion->setText(QString("WinKeyer v. %1").arg(wk->version));
wk->isOpen = true;
wk->setWpmSpeed(20); //Set default WPM speed
}
else //Winkeyer error
{
ui->label_wkVersion->setText("WinKeyer error");
ui->pushButton_Connect->setChecked(false);
}
}
else //Serial port error
{
ui->label_wkVersion->setText("Serial error");
ui->pushButton_Connect->setChecked(false);
}
}
else if (!checked && wk->isOpen) //Disconnect
{
ui->label_wkVersion->setText("Disconnected");
wk->close();
wk->isOpen = false;
}
}
void DialogCWKeyer::on_buttonBox_accepted()
{
cwKConf.comPort = ui->comboBox_comPort->currentText();
cwKConf.memoryString[0] = ui->lineEdit_cwK1->text().toUtf8();
cwKConf.memoryString[1] = ui->lineEdit_cwK2->text().toUtf8();
cwKConf.memoryString[2] = ui->lineEdit_cwK3->text().toUtf8();
cwKConf.memoryString[3] = ui->lineEdit_cwK4->text().toUtf8();
cwKConf.memoryString[4] = ui->lineEdit_cwK5->text().toUtf8();
//* Save settings in catradio.ini
QSettings configFile(QString("catradio.ini"), QSettings::IniFormat);
configFile.setValue("CWKeyer/comPort", cwKConf.comPort);
configFile.setValue("CWKeyer/cwMemoryString1", cwKConf.memoryString[0]);
configFile.setValue("CWKeyer/cwMemoryString2", cwKConf.memoryString[1]);
configFile.setValue("CWKeyer/cwMemoryString3", cwKConf.memoryString[2]);
configFile.setValue("CWKeyer/cwMemoryString4", cwKConf.memoryString[3]);
configFile.setValue("CWKeyer/cwMemoryString5", cwKConf.memoryString[4]);
}

50
dialogcwkeyer.h 100644
Wyświetl plik

@ -0,0 +1,50 @@
/**
** This file is part of the CatRadio project.
** Copyright 2022-2025 Gianfranco Sordetti IZ8EWD <iz8ewd@pianetaradio.it>.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
**/
#ifndef DIALOGCWKEYER_H
#define DIALOGCWKEYER_H
#include <QDialog>
#include "winkeyer.h"
namespace Ui {
class DialogCWKeyer;
}
class DialogCWKeyer : public QDialog
{
Q_OBJECT
public:
explicit DialogCWKeyer(WinKeyer *winkeyer, QWidget *parent = nullptr);
~DialogCWKeyer();
private slots:
void on_pushButton_Connect_toggled(bool checked);
void on_buttonBox_accepted();
private:
Ui::DialogCWKeyer *ui;
WinKeyer *wk;
};
#endif // DIALOGCWKEYER_H

175
dialogcwkeyer.ui 100644
Wyświetl plik

@ -0,0 +1,175 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DialogCWKeyer</class>
<widget class="QDialog" name="DialogCWKeyer">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>410</height>
</rect>
</property>
<property name="windowTitle">
<string>CW Keyer Setup</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0" colspan="2">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label_cwK1">
<property name="text">
<string>1</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="lineEdit_cwK1"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_cwK2">
<property name="text">
<string>2</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="lineEdit_cwK2"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_cwK3">
<property name="text">
<string>3</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="lineEdit_cwK3"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_cwK4">
<property name="text">
<string>4</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="lineEdit_cwK4"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_cwK5">
<property name="text">
<string>5</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="lineEdit_cwK5"/>
</item>
</layout>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>WinKeyer</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_comPort">
<property name="text">
<string>COM Port</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="comboBox_comPort"/>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="pushButton_Connect">
<property name="text">
<string>Connect</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_wkVersion">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="1">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>DialogCWKeyer</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>DialogCWKeyer</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

Wyświetl plik

@ -1,6 +1,6 @@
/**
** This file is part of the CatRadio project.
** Copyright 2022-2024 Gianfranco Sordetti IZ8EWD <iz8ewd@pianetaradio.it>.
** Copyright 2022-2025 Gianfranco Sordetti IZ8EWD <iz8ewd@pianetaradio.it>.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
@ -38,6 +38,7 @@ DialogSetup::DialogSetup(QWidget *parent) :
if (guiConf.vfoDisplayMode == 1) ui->radioButton_vfoDispMode_UD->setChecked(true);
if (guiConf.darkTheme) ui->radioButton_themeDark->setChecked(true);
if (guiConf.cwKeyerMode == 1) ui->radioButton_cwKeyerMode_Keyer->setChecked(true);
if (guiConf.voiceKeyerMode == 1) ui->radioButton_voiceKeyerMode_CatRadio->setChecked(true);
if (guiConf.peakHold) ui->checkBox_peakHold->setChecked(true);
if (guiConf.debugMode) ui->checkBox_debug->setChecked(true);
@ -62,6 +63,7 @@ void DialogSetup::on_buttonBox_accepted()
guiConf.vfoDisplayMode = ui->radioButton_vfoDispMode_UD->isChecked();
guiConf.darkTheme = ui->radioButton_themeDark->isChecked();
guiConf.cwKeyerMode = ui->radioButton_cwKeyerMode_Keyer->isChecked();
guiConf.voiceKeyerMode = ui->radioButton_voiceKeyerMode_CatRadio->isChecked();
guiConf.peakHold = ui->checkBox_peakHold->isChecked();
guiConf.debugMode = ui->checkBox_debug->isChecked();
@ -70,6 +72,7 @@ void DialogSetup::on_buttonBox_accepted()
QSettings configFile(QString("catradio.ini"), QSettings::IniFormat);
configFile.setValue("vfoDisplayMode", guiConf.vfoDisplayMode);
configFile.setValue("darkTheme", guiConf.darkTheme);
configFile.setValue("cwKeyerMode", guiConf.cwKeyerMode);
configFile.setValue("voiceKeyerMode", guiConf.voiceKeyerMode);
configFile.setValue("peakHold", guiConf.peakHold);
configFile.setValue("debugMode", guiConf.debugMode);

Wyświetl plik

@ -151,6 +151,32 @@
<string>Keyer</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QGroupBox" name="groupBox_cwKeyerMode">
<property name="title">
<string>CW Keyer</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QRadioButton" name="radioButton_cwKeyerMode_Radio">
<property name="text">
<string>Radio</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioButton_cwKeyerMode_Keyer">
<property name="text">
<string>Keyer</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_voiceKeyerMode">
<property name="title">

Wyświetl plik

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>400</width>
<height>409</height>
<height>410</height>
</rect>
</property>
<property name="windowTitle">

Wyświetl plik

@ -22,3 +22,4 @@
guiConfig guiConf;
guiCommand guiCmd;
voiceKeyerConfig voiceKConf;
cwKeyerConfig cwKConf;

Wyświetl plik

@ -39,7 +39,7 @@ typedef struct {
bool darkTheme; //flag for Dark theme
bool peakHold; //meters peak hold
bool debugMode; //flag for debug log
int cwKeyerMode; //0: Radio
int cwKeyerMode; //0: Radio, 1: WinKeyer
int voiceKeyerMode; //0: Radio, 1: CatRadio
} guiConfig;
@ -59,3 +59,10 @@ typedef struct {
QString audioOutput; //Audio output device name
int audioOutputVolume; //Audio output volume integer 0..10
} voiceKeyerConfig;
typedef struct {
QString comPort; //COM port name
QByteArray memoryString[5]; //CW strings
int wpm; //WPM
} cwKeyerConfig;

Wyświetl plik

@ -22,13 +22,16 @@
#include "dialogconfig.h"
#include "dialogsetup.h"
#include "dialogvoicekeyer.h"
#include "dialogcwkeyer.h"
#include "dialogcommand.h"
#include "dialogradioinfo.h"
#include "dialognetrigctl.h"
#include "rigdaemon.h"
#include "rigdata.h"
#include "guidata.h"
#include "rigcommand.h"
#include "winkeyer.h"
#include <QDebug>
#include <QMessageBox>
@ -41,7 +44,7 @@
#include <QCoreApplication>
#include <QDir>
#include <cwchar>
#include <cwchar> //c++ string library
#include <rig.h> //Hamlib
//RIG *my_rig;
@ -54,6 +57,7 @@ extern rigCommand rigCap;
extern guiConfig guiConf;
extern guiCommand guiCmd;
extern voiceKeyerConfig voiceKConf;
extern cwKeyerConfig cwKConf;
int retcode; //Return code from function
int i; //Index
@ -71,6 +75,8 @@ RigDaemon *rigDaemon = new RigDaemon;
QDialog *command = nullptr;
QDialog *radioInfo = nullptr;
WinKeyer *winkeyer = nullptr;
//***** MainWindow *****
@ -82,7 +88,7 @@ MainWindow::MainWindow(QWidget *parent)
//display name and version in the window title
QString version = QString::number(VERSION_MAJ)+"."+QString::number(VERSION_MIN)+"."+QString::number(VERSION_MIC);
this->setWindowTitle("CatRadio v."+version);
this->setWindowTitle("CatRadio v."+version+" (Beta)");
QDir::setCurrent(QCoreApplication::applicationDirPath()); //set current path = application path
@ -111,14 +117,20 @@ MainWindow::MainWindow(QWidget *parent)
workerThread.start();
//* Load settings from catradio.ini
loadGuiConfig("catradio.ini");
loadRigConfig("catradio.ini");
loadGuiConfig("catradio.ini"); //load GUI config
loadRigConfig("catradio.ini"); //load Rig config
//Voice memory
if (guiConf.voiceKeyerMode == 1)
{
ui->action_Voice_Keyer->setEnabled(true); //enable Voice Keyer menu
audioOutputInit("catradio.ini"); //init audio
}
//CW keyer
if (guiConf.cwKeyerMode == 1)
{
ui->actionCW_Keyer->setEnabled(true); //enable CW Keyer menu
loadCwKeyerConfig("catradio.ini"); //load CW Keyer config
}
//* Debug
if (guiConf.debugMode) rig_set_debug_level(RIG_DEBUG_VERBOSE); //debug verbose
@ -209,12 +221,25 @@ MainWindow::~MainWindow()
rigCom.connected = 0;
rig_close(my_rig); //Close the communication to the rig
rig_cleanup(my_rig); //Release rig handle and free associated memory
}
rig_cleanup(my_rig); //Release rig handle and free associated memory
fclose(debugFile); //Close debug.log
if (guiConf.cwKeyerMode == 1)
{
qDebug()<<winkeyer<<"Distructor 5";
if (winkeyer && winkeyer->isOpen) winkeyer->close();
if (winkeyer)
{
delete winkeyer;
qDebug()<<"Delete";
}
}
if (command) delete command; //deallocate *command
if (radioInfo) delete radioInfo; //deallocate *radioInfo
//* Save window settings
QSettings configFile(QString("catradio.ini"), QSettings::IniFormat);
configFile.setValue("WindowSettings/geometry", saveGeometry());
@ -393,7 +418,7 @@ void MainWindow::guiInit()
//* CW
if (!rig_has_set_func(my_rig, RIG_FUNC_FBKIN)) ui->checkBox_BKIN->setEnabled(false);
if (!rig_has_set_func(my_rig, RIG_FUNC_APF)) ui->checkBox_APF->setEnabled(false);
if (!rig_has_set_level(my_rig, RIG_LEVEL_KEYSPD)) ui->spinBox_WPM->setEnabled(false);
if (guiConf.cwKeyerMode == 0 && !rig_has_set_level(my_rig, RIG_LEVEL_KEYSPD)) ui->spinBox_WPM->setEnabled(false);
//* FM
ui->comboBox_toneType->clear();
@ -444,6 +469,7 @@ void MainWindow::loadGuiConfig(QString configFileName)
guiConf.vfoDisplayMode = configFile.value("vfoDisplayMode", 0).toInt();
guiConf.darkTheme = configFile.value("darkTheme", false).toBool();
guiConf.cwKeyerMode = configFile.value("cwKeyerMode", 0).toInt();
guiConf.voiceKeyerMode = configFile.value("voiceKeyerMode", 0).toInt();
guiConf.peakHold = configFile.value("peakHold", true).toBool();
guiConf.debugMode = configFile.value("debugMode", false).toBool();
@ -531,6 +557,25 @@ void MainWindow::audioOutputInit(QString configFileName)
#endif
}
void MainWindow::loadCwKeyerConfig(QString configFileName)
{
QSettings configFile(configFileName, QSettings::IniFormat);
//Set keyer COM port name
cwKConf.comPort = configFile.value("CWKeyer/comPort", "").toString();
//Set CW strings associated to keyer memory buttons
cwKConf.memoryString[0] = configFile.value("CWKeyer/cwMemoryString1", "").toByteArray();
cwKConf.memoryString[1] = configFile.value("CWKeyer/cwMemoryString2", "").toByteArray();
cwKConf.memoryString[2] = configFile.value("CWKeyer/cwMemoryString3", "").toByteArray();
cwKConf.memoryString[3] = configFile.value("CWKeyer/cwMemoryString4", "").toByteArray();
cwKConf.memoryString[4] = configFile.value("CWKeyer/cwMemoryString5", "").toByteArray();
if (!winkeyer) winkeyer = new WinKeyer;
}
void MainWindow::guiUpdate()
{
//* Power button
@ -809,7 +854,7 @@ void MainWindow::guiUpdate()
//* CW
if (!rigCmd.bkin) ui->checkBox_BKIN->setChecked(rigGet.bkin);
if (!rigCmd.apf) ui->checkBox_APF->setChecked(rigGet.apf);
if (!rigCmd.wpm) ui->spinBox_WPM->setValue(rigGet.wpm);
if (guiConf.cwKeyerMode == 0 && !rigCmd.wpm) ui->spinBox_WPM->setValue(rigGet.wpm);
//* FM
if (rigGet.rptShift == RIG_RPT_SHIFT_MINUS && !rigCmd.rptShift) ui->radioButton_RPTshiftMinus->setChecked(true); //-
@ -1199,27 +1244,57 @@ void MainWindow::on_pushButton_BandUp_clicked()
//CW keyer
void MainWindow::on_pushButton_CW1_clicked()
{
send_cw_mem(1);
if (guiConf.cwKeyerMode == 0) send_cw_mem(1); //Radio CW keyer
else if (guiConf.cwKeyerMode == 1 && winkeyer->isOpen && rigCmd.cwSend == 0 && cwKConf.memoryString[0]!="") //WinKeyer
{
rigCmd.cwSend = 1;
winkeyer->sendString(cwKConf.memoryString[0]);
rigCmd.cwSend = 0;
}
}
void MainWindow::on_pushButton_CW2_clicked()
{
send_cw_mem(2);
if (guiConf.cwKeyerMode == 0) send_cw_mem(2);
else if (guiConf.cwKeyerMode == 1 && winkeyer->isOpen && rigCmd.cwSend == 0 && cwKConf.memoryString[1]!="")
{
rigCmd.cwSend = 1;
winkeyer->sendString(cwKConf.memoryString[1]);
rigCmd.cwSend = 0;
}
}
void MainWindow::on_pushButton_CW3_clicked()
{
send_cw_mem(3);
if (guiConf.cwKeyerMode == 0) send_cw_mem(3);
else if (guiConf.cwKeyerMode == 1 && winkeyer->isOpen && rigCmd.cwSend == 0 && cwKConf.memoryString[2]!="")
{
rigCmd.cwSend = 1;
winkeyer->sendString(cwKConf.memoryString[2]);
rigCmd.cwSend = 0;
}
}
void MainWindow::on_pushButton_CW4_clicked()
{
send_cw_mem(4);
if (guiConf.cwKeyerMode == 0) send_cw_mem(4);
else if (guiConf.cwKeyerMode == 1 && winkeyer->isOpen && rigCmd.cwSend == 0 && cwKConf.memoryString[3]!="")
{
rigCmd.cwSend = 1;
winkeyer->sendString(cwKConf.memoryString[3]);
rigCmd.cwSend = 0;
}
}
void MainWindow::on_pushButton_CW5_clicked()
{
send_cw_mem(5);
if (guiConf.cwKeyerMode == 0) send_cw_mem(5);
else if (guiConf.cwKeyerMode == 1 && winkeyer->isOpen && rigCmd.cwSend == 0 && cwKConf.memoryString[4]!="")
{
rigCmd.cwSend = 1;
winkeyer->sendString(cwKConf.memoryString[4]);
rigCmd.cwSend = 0;
}
}
//Voice keyer
@ -1664,11 +1739,15 @@ void MainWindow::on_spinBox_NR_valueChanged(int arg1)
void MainWindow::on_spinBox_WPM_valueChanged(int arg1)
{
if (!rigCmd.wpm)
if (guiConf.cwKeyerMode == 0 && !rigCmd.wpm)
{
rigSet.wpm = arg1;
rigCmd.wpm = 1;
}
else if (guiConf.cwKeyerMode == 1 && winkeyer->isOpen && rigCmd.cwSend == 0)
{
winkeyer->setWpmSpeed(arg1);
}
}
void MainWindow::on_spinBox_RPToffset_valueChanged(int arg1)
@ -1888,6 +1967,13 @@ void MainWindow::on_action_Setup_triggered()
ui->lineEdit_vfoMain->setMode(guiConf.vfoDisplayMode);
ui->lineEdit_vfoSub->setMode(guiConf.vfoDisplayMode);
if (guiConf.cwKeyerMode == 1)
{
ui->actionCW_Keyer->setEnabled(true);
loadCwKeyerConfig("catradio.ini");
}
else ui->action_Voice_Keyer->setEnabled(false);
if (guiConf.voiceKeyerMode == 1)
{
ui->action_Voice_Keyer->setEnabled(true);
@ -1905,6 +1991,15 @@ void MainWindow::on_action_Voice_Keyer_triggered()
audioOutputInit("catradio.ini");
}
void MainWindow::on_actionCW_Keyer_triggered()
{
DialogCWKeyer cwKeyer(winkeyer);
cwKeyer.setModal(true);
cwKeyer.exec();
loadCwKeyerConfig("catradio.ini");
}
void MainWindow::on_action_RadioInfo_triggered()
{
if (!radioInfo) radioInfo = new DialogRadioInfo(my_rig, this);
@ -1996,4 +2091,3 @@ void MainWindow::on_action_CatRadioHomepage_triggered()
QUrl homepage("https://www.pianetaradio.it/blog/catradio/");
QDesktopServices::openUrl(homepage);
}

Wyświetl plik

@ -32,6 +32,7 @@
#include <QSettings>
#include "rig.h"
#include "winkeyer.h"
#define RELEASE_DATE __DATE__
#define VERSION_MAJ 1
@ -74,9 +75,16 @@ private slots:
void on_comboBox_Mode_activated(int index);
void on_comboBox_ModeSub_activated(int index);
void on_comboBox_BW_activated(int index);
void on_comboBox_AGC_activated(int index);
void on_comboBox_Att_activated(int index);
void on_comboBox_Preamp_activated(int index);
void on_comboBox_Ant_activated(int index);
void on_comboBox_Meter_activated(int index);
void on_comboBox_toneType_activated(int index);
void on_comboBox_toneFreq_activated(int index);
void on_pushButton_Fast_toggled(bool checked);
void on_pushButton_Band160_clicked();
void on_pushButton_Band80_clicked();
void on_pushButton_Band60_clicked();
@ -88,133 +96,80 @@ private slots:
void on_pushButton_Band12_clicked();
void on_pushButton_Band10_clicked();
void on_pushButton_Band6_clicked();
void on_pushButton_Tune_clicked();
void on_radioButton_Tuner_toggled(bool checked);
void on_pushButton_Band2_clicked();
void on_pushButton_Band70_clicked();
void on_pushButton_BandGen_clicked();
void on_pushButton_BandDown_clicked();
void on_pushButton_BandUp_clicked();
void on_pushButton_QSplit_clicked();
void on_action_Connection_triggered();
void on_comboBox_BW_activated(int index);
void on_checkBox_NAR_toggled(bool checked);
void on_checkBox_BKIN_toggled(bool checked);
void on_comboBox_AGC_activated(int index);
void on_comboBox_Att_activated(int index);
void on_comboBox_Preamp_activated(int index);
void on_comboBox_Ant_activated(int index);
void on_action_AboutCatRadio_triggered();
void on_checkBox_NB_toggled(bool checked);
void on_checkBox_NR_toggled(bool checked);
void on_checkBox_NF_toggled(bool checked);
void on_comboBox_Meter_activated(int index);
void on_spinBox_NR_valueChanged(int arg1);
void on_horizontalSlider_IFshift_valueChanged(int value);
void on_pushButton_Band2_clicked();
void on_pushButton_Band70_clicked();
void on_pushButton_BandGen_clicked();
void on_action_Setup_triggered();
void on_action_CatRadioHomepage_triggered();
void on_action_AboutQT_triggered();
void on_action_AboutHamLib_triggered();
void on_verticalSlider_AFGain_valueChanged(int value);
void on_verticalSlider_Squelch_valueChanged(int value);
void on_verticalSlider_RFpower_valueChanged(int value);
void on_verticalSlider_RFgain_valueChanged(int value);
void on_spinBox_WPM_valueChanged(int arg1);
void on_checkBox_APF_toggled(bool checked);
void on_radioButton_RPTshiftSimplex_toggled(bool checked);
void on_radioButton_RPTshiftMinus_toggled(bool checked);
void on_radioButton_RPTshiftPlus_toggled(bool checked);
void on_comboBox_toneType_activated(int index);
void on_comboBox_toneFreq_activated(int index);
void on_spinBox_RPToffset_valueChanged(int arg1);
void on_pushButton_Tune_clicked();
void on_pushButton_left_clicked();
void on_pushButton_right_clicked();
void on_checkBox_clar_toggled(bool checked);
void on_pushButton_clarClear_clicked();
void on_horizontalSlider_clar_valueChanged(int value);
void on_radioButton_clarRIT_toggled(bool checked);
void on_radioButton_clarXIT_toggled(bool checked);
void on_verticalSlider_RFpower_sliderReleased();
void on_verticalSlider_RFgain_sliderReleased();
void on_verticalSlider_AFGain_sliderReleased();
void on_verticalSlider_Squelch_sliderReleased();
void on_horizontalSlider_IFshift_sliderReleased();
void on_horizontalSlider_clar_sliderReleased();
void on_checkBox_NB2_toggled(bool checked);
void on_verticalSlider_micGain_valueChanged(int value);
void on_verticalSlider_micGain_sliderReleased();
void on_verticalSlider_micCompressor_valueChanged(int value);
void on_verticalSlider_micCompressor_sliderReleased();
void on_verticalSlider_micMonitor_valueChanged(int value);
void on_verticalSlider_micMonitor_sliderReleased();
void on_checkBox_micCompressor_toggled(bool checked);
void on_checkBox_micMonitor_toggled(bool checked);
void on_action_Command_triggered();
void on_action_RadioInfo_triggered();
void on_action_AboutDarkTheme_triggered();
void on_actionNET_rigctl_triggered();
void on_action_Voice_Keyer_triggered();
void on_pushButton_CW1_clicked();
void on_pushButton_CW2_clicked();
void on_pushButton_CW3_clicked();
void on_pushButton_CW4_clicked();
void on_pushButton_CW5_clicked();
void on_pushButton_VoiceK1_clicked();
void on_pushButton_VoiceK2_clicked();
void on_pushButton_VoiceK3_clicked();
void on_pushButton_VoiceK4_clicked();
void on_pushButton_VoiceK5_clicked();
void on_pushButton_clarClear_clicked();
void on_checkBox_NAR_toggled(bool checked);
void on_checkBox_BKIN_toggled(bool checked);
void on_checkBox_NB_toggled(bool checked);
void on_checkBox_NB2_toggled(bool checked);
void on_checkBox_NR_toggled(bool checked);
void on_checkBox_NF_toggled(bool checked);
void on_checkBox_APF_toggled(bool checked);
void on_checkBox_micCompressor_toggled(bool checked);
void on_checkBox_micMonitor_toggled(bool checked);
void on_checkBox_clar_toggled(bool checked);
void on_spinBox_NR_valueChanged(int arg1);
void on_spinBox_WPM_valueChanged(int arg1);
void on_spinBox_RPToffset_valueChanged(int arg1);
void on_radioButton_Tuner_toggled(bool checked);
void on_radioButton_RPTshiftSimplex_toggled(bool checked);
void on_radioButton_RPTshiftMinus_toggled(bool checked);
void on_radioButton_clarRIT_toggled(bool checked);
void on_radioButton_clarXIT_toggled(bool checked);
void on_radioButton_RPTshiftPlus_toggled(bool checked);
void on_horizontalSlider_IFshift_sliderReleased();
void on_horizontalSlider_clar_sliderReleased();
void on_horizontalSlider_clar_valueChanged(int value);
void on_horizontalSlider_IFshift_valueChanged(int value);
void on_verticalSlider_RFpower_sliderReleased();
void on_verticalSlider_RFgain_sliderReleased();
void on_verticalSlider_AFGain_sliderReleased();
void on_verticalSlider_Squelch_sliderReleased();
void on_verticalSlider_micGain_valueChanged(int value);
void on_verticalSlider_micGain_sliderReleased();
void on_verticalSlider_micCompressor_valueChanged(int value);
void on_verticalSlider_micCompressor_sliderReleased();
void on_verticalSlider_micMonitor_valueChanged(int value);
void on_verticalSlider_micMonitor_sliderReleased();
void on_verticalSlider_AFGain_valueChanged(int value);
void on_verticalSlider_Squelch_valueChanged(int value);
void on_verticalSlider_RFpower_valueChanged(int value);
void on_verticalSlider_RFgain_valueChanged(int value);
void on_action_Connection_triggered();
void on_action_Setup_triggered();
void on_action_CatRadioHomepage_triggered();
void on_action_AboutQT_triggered();
void on_action_AboutHamLib_triggered();
void on_action_Command_triggered();
void on_action_RadioInfo_triggered();
void on_action_AboutDarkTheme_triggered();
void on_actionNET_rigctl_triggered();
void on_action_Voice_Keyer_triggered();
void on_actionCW_Keyer_triggered();
void on_action_AboutCatRadio_triggered();
private:
Ui::MainWindow *ui;
@ -230,12 +185,14 @@ private:
#endif
RIG *my_rig;
//WinKeyer *winkeyer = nullptr;
void guiInit();
void loadGuiConfig(QString configFileName);
void loadRigConfig(QString configFileName);
void audioOutputInit(QString configFileName);
void loadCwKeyerConfig(QString configFileName);
void setSubMeter();

Wyświetl plik

@ -2150,10 +2150,11 @@
<property name="title">
<string>Config</string>
</property>
<addaction name="action_Connection"/>
<addaction name="action_Setup"/>
<addaction name="action_Connection"/>
<addaction name="separator"/>
<addaction name="action_Voice_Keyer"/>
<addaction name="actionCW_Keyer"/>
</widget>
<widget class="QMenu" name="menu_Help">
<property name="title">
@ -2255,6 +2256,14 @@
<string>Voice Keyer</string>
</property>
</action>
<action name="actionCW_Keyer">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>CW Keyer</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>

Wyświetl plik

@ -118,7 +118,7 @@ void RigDaemon::rigUpdate(RIG *my_rig)
}
//* CW memory keyer (rig)
if (rigCmd.cwSend && (rigGet.mode == RIG_MODE_CW || rigGet.mode == RIG_MODE_CWN || rigGet.mode == RIG_MODE_CWR))
if (guiConf.cwKeyerMode == 0 && rigCmd.cwSend && (rigGet.mode == RIG_MODE_CW || rigGet.mode == RIG_MODE_CWN || rigGet.mode == RIG_MODE_CWR))
{
//if (rig_has_get_func(my_rig, RIG_FUNCTION_SEND_MORSE)) rig_send_morse(my_rig, RIG_VFO_CURR, &rigSet.cwMem);
retcode = rig_send_morse(my_rig, RIG_VFO_CURR, &rigSet.cwMem);
@ -205,7 +205,8 @@ void RigDaemon::rigUpdate(RIG *my_rig)
{
guiCmd.bwidthList = 1; //Command update of BW list
guiCmd.tabList = 1; //Command selection of appropriate mode function tab
indexCmd = 0;
guiCmd.dialConf = 1; //Command the tuning dial step configuration
indexCmd = 0; //Update all
//rig_get_mode(my_rig, RIG_VFO_CURR, &rigGet.mode, &rigGet.bwidth); //Get BW
}
rigCmd.mode = 0;
@ -661,6 +662,7 @@ void RigDaemon::rigUpdate(RIG *my_rig)
{
guiCmd.bwidthList = 1; //Command update of BW list
guiCmd.tabList = 1; //Command selection of appropriate mode function tab
guiCmd.dialConf = 1; //Command the tuning dial step configuration
}
rigGet.mode = tempMode;
@ -836,7 +838,7 @@ void RigDaemon::rigUpdate(RIG *my_rig)
{
if (rig_has_get_func(my_rig, RIG_FUNC_FBKIN)) rig_get_func(my_rig, RIG_VFO_CURR, RIG_FUNC_FBKIN, &rigGet.bkin); //Break-in
if (rig_has_get_func(my_rig, RIG_FUNC_APF)) rig_get_func(my_rig, RIG_VFO_CURR, RIG_FUNC_APF, &rigGet.apf); //Audio Peak Filter
if (rig_has_get_level(my_rig, RIG_LEVEL_KEYSPD)) rig_get_level(my_rig, RIG_VFO_CURR, RIG_LEVEL_KEYSPD, &retvalue); //Keyer speed WPM
if (guiConf.cwKeyerMode == 0 && rig_has_get_level(my_rig, RIG_LEVEL_KEYSPD)) rig_get_level(my_rig, RIG_VFO_CURR, RIG_LEVEL_KEYSPD, &retvalue); //Keyer speed WPM
rigGet.wpm = retvalue.i;
}

125
winkeyer.cpp 100644
Wyświetl plik

@ -0,0 +1,125 @@
/**
** This file is part of the CatRadio project.
** Copyright 2022-2025 Gianfranco Sordetti IZ8EWD <iz8ewd@pianetaradio.it>.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
**/
#include "winkeyer.h"
#include <QSerialPort>
#include <QDebug>
int WinKeyer::init(QString portName) //Serial port init
{
serial = new QSerialPort();
if (serial && !serial->isOpen())
{
//Set serial port parameters
serial->setPortName(portName);
serial->setBaudRate(QSerialPort::Baud1200);
serial->setDataBits(QSerialPort::Data8);
serial->setParity(QSerialPort::NoParity);
serial->setStopBits(QSerialPort::OneStop);
serial->setFlowControl(QSerialPort::NoFlowControl);
//Open the serial port
serial->open(QIODevice::ReadWrite);
return serial->error();
}
return QSerialPort::OpenError;
}
int WinKeyer::open() //Open WK
{
if (serial->isOpen())
{
//Command mode \x00 and Host open \x02
QByteArray dataToSend = QByteArray::fromRawData("\x00\x02", 2);
serial->write(dataToSend);
if (serial->waitForBytesWritten(1000))
{
if (serial->waitForReadyRead(1000))
{
QByteArray receivedData = serial->readAll(); //receive the WK revision code
bool okInt;
int intValue = receivedData.toHex().toInt(&okInt, 16);
if (okInt)
{
isOpen = true;
return intValue;
}
else
{
isOpen = false;
return 0;
}
}
}
}
return 0;
}
void WinKeyer::close() //Close WK and serial port
{
if (serial->isOpen())
{
//Command mode x00 and Host close \x03
QByteArray dataToSend = QByteArray::fromRawData("\x00\x03", 2);
serial->write(dataToSend);
//Close the serial port
serial->close();
delete serial;
serial = nullptr;
isOpen = false;
}
}
void WinKeyer::setWpmSpeed(int wpm)
{
if (serial->isOpen())
{
if (wpm < 5) wpm = 5;
else if (wpm > 99) wpm = 99;
//Set WPM speed \x02 + \xnn WPM
QByteArray dataToSend = QByteArray::fromRawData("\x02", 1);
dataToSend.append(intToByte(wpm));
serial->write(dataToSend);
}
}
void WinKeyer::sendString(QByteArray string)
{
if (serial->isOpen())
{
serial->write(string.toUpper());
}
}
QByteArray WinKeyer::intToByte (int value)
{
QByteArray byteArray;
byteArray.append(static_cast<char>(value & 0xFF));
return byteArray;
}

44
winkeyer.h 100644
Wyświetl plik

@ -0,0 +1,44 @@
/**
** This file is part of the CatRadio project.
** Copyright 2022-2025 Gianfranco Sordetti IZ8EWD <iz8ewd@pianetaradio.it>.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
**/
#ifndef WINKEYER_H
#define WINKEYER_H
#include <QSerialPort>
class WinKeyer
{
public:
int version; //WinKeyer version
bool isOpen; //WinKeyer open flag
int init(QString portName);
int open();
void close();
void setWpmSpeed(int wpm);
void sendString(QByteArray string);
private:
QSerialPort *serial = nullptr;
QByteArray intToByte (int value); //Convert int (0 - 255) into a 1 byte QByteArray
};
#endif // WINKEYER_H