2018-06-19 12:58:52 -07:00
# include "rigcommander.h"
# include <QDebug>
2018-11-24 00:10:05 -08:00
# include "rigidentities.h"
2021-02-23 21:21:22 +00:00
# include "logcategories.h"
2023-01-21 13:38:39 -08:00
# include "printhex.h"
2018-11-24 00:10:05 -08:00
2023-04-24 08:37:10 +01:00
// Copyright 2017-2023 Elliott H. Liggett W6EL and Phil E. Taylor M0VSE
2018-11-16 14:08:21 -08:00
// This file parses data from the radio and also forms commands to the radio.
// The radio physical interface is handled by the commHandler() instance "comm"
2018-06-19 12:58:52 -07:00
//
// See here for a wonderful CI-V overview:
// http://www.plicht.de/ekki/civ/civ-p0a.html
//
// The IC-7300 "full" manual also contains a command reference.
// How to make spectrum display stop using rigctl:
2021-02-27 21:18:26 +01:00
// echo "w \0xFE\0xFE\0x94\0xE0\0x27\0x11\0x00\0xFD" | rigctl -m 3073 -r /dev/ttyUSB0 -s 115200 -vvvvv
2018-06-19 12:58:52 -07:00
// Note: When sending \x00, must use QByteArray.setRawData()
2022-05-08 19:31:05 +01:00
rigCommander : : rigCommander ( QObject * parent ) : QObject ( parent )
2021-02-10 17:32:56 +00:00
{
2023-05-01 21:56:52 +01:00
2022-01-26 09:49:52 +00:00
qInfo ( logRig ( ) ) < < " creating instance of rigCommander() " ;
2023-05-12 00:24:01 +01:00
2022-01-26 09:49:52 +00:00
}
2022-05-08 19:31:05 +01:00
rigCommander : : rigCommander ( quint8 guid [ GUIDLEN ] , QObject * parent ) : QObject ( parent )
2022-01-26 09:49:52 +00:00
{
2023-05-01 21:56:52 +01:00
2022-01-26 09:49:52 +00:00
qInfo ( logRig ( ) ) < < " creating instance of rigCommander() " ;
2022-01-29 22:50:58 +00:00
memcpy ( this - > guid , guid , GUIDLEN ) ;
2023-05-12 00:24:01 +01:00
// Add some commands that is a minimum for rig detection
2021-02-10 17:32:56 +00:00
}
rigCommander : : ~ rigCommander ( )
{
2022-01-26 09:49:52 +00:00
qInfo ( logRig ( ) ) < < " closing instance of rigCommander() " ;
2023-12-18 10:47:16 +00:00
queue - > setRigCaps ( Q_NULLPTR ) ; // Remove access to rigCaps
2021-02-10 17:32:56 +00:00
closeComm ( ) ;
}
2018-06-19 12:58:52 -07:00
2021-02-10 17:32:56 +00:00
2023-04-23 21:29:44 +01:00
void rigCommander : : commSetup ( QHash < unsigned char , QString > rigList , unsigned char rigCivAddr , QString rigSerialPort , quint32 rigBaudRate , QString vsp , quint16 tcpPort , quint8 wf )
2018-06-19 12:58:52 -07:00
{
// construct
2023-05-12 00:24:01 +01:00
2018-11-07 15:54:03 -08:00
// TODO: Bring this parameter and the comm port from the UI.
2018-11-26 23:10:23 -08:00
// Keep in hex in the UI as is done with other CIV apps.
2023-04-23 21:29:44 +01:00
this - > rigList = rigList ;
2023-05-12 00:24:01 +01:00
civAddr = rigCivAddr ; // address of the radio.
2021-02-10 17:32:56 +00:00
usingNativeLAN = false ;
2022-04-18 20:29:50 +01:00
2021-02-10 17:32:56 +00:00
this - > rigSerialPort = rigSerialPort ;
this - > rigBaudRate = rigBaudRate ;
2022-01-26 09:49:52 +00:00
rigCaps . baudRate = rigBaudRate ;
2018-11-26 23:10:23 -08:00
2022-05-08 19:31:05 +01:00
comm = new commHandler ( rigSerialPort , rigBaudRate , wf , this ) ;
ptty = new pttyHandler ( vsp , this ) ;
2018-06-19 12:58:52 -07:00
2022-04-08 14:40:05 +01:00
if ( tcpPort > 0 ) {
tcp = new tcpServer ( this ) ;
tcp - > startServer ( tcpPort ) ;
}
2022-03-23 10:12:42 +00:00
2018-06-19 12:58:52 -07:00
// data from the comm port to the program:
connect ( comm , SIGNAL ( haveDataFromPort ( QByteArray ) ) , this , SLOT ( handleNewData ( QByteArray ) ) ) ;
2021-03-04 20:19:05 +00:00
// data from the ptty to the rig:
connect ( ptty , SIGNAL ( haveDataFromPort ( QByteArray ) ) , comm , SLOT ( receiveDataFromUserToRig ( QByteArray ) ) ) ;
2022-03-23 10:12:42 +00:00
2018-06-19 12:58:52 -07:00
// data from the program to the comm port:
connect ( this , SIGNAL ( dataForComm ( QByteArray ) ) , comm , SLOT ( receiveDataFromUserToRig ( QByteArray ) ) ) ;
2023-05-08 13:26:45 +01:00
// Whether radio is half duplex only
connect ( this , SIGNAL ( setHalfDuplex ( bool ) ) , comm , SLOT ( setHalfDuplex ( bool ) ) ) ;
2022-04-08 14:40:05 +01:00
if ( tcpPort > 0 ) {
// data from the tcp port to the rig:
connect ( tcp , SIGNAL ( receiveData ( QByteArray ) ) , comm , SLOT ( receiveDataFromUserToRig ( QByteArray ) ) ) ;
connect ( comm , SIGNAL ( haveDataFromPort ( QByteArray ) ) , tcp , SLOT ( sendData ( QByteArray ) ) ) ;
}
2021-11-05 23:21:36 -07:00
connect ( this , SIGNAL ( toggleRTS ( bool ) ) , comm , SLOT ( setRTS ( bool ) ) ) ;
2018-06-19 12:58:52 -07:00
2021-03-04 20:19:05 +00:00
// data from the rig to the ptty:
2021-03-05 12:53:23 +00:00
connect ( comm , SIGNAL ( haveDataFromPort ( QByteArray ) ) , ptty , SLOT ( receiveDataFromRigToPtty ( QByteArray ) ) ) ;
2021-03-04 20:19:05 +00:00
2023-01-05 19:37:53 +00:00
connect ( comm , SIGNAL ( havePortError ( errorType ) ) , this , SLOT ( handlePortError ( errorType ) ) ) ;
2023-01-07 11:36:53 +00:00
connect ( ptty , SIGNAL ( havePortError ( errorType ) ) , this , SLOT ( handlePortError ( errorType ) ) ) ;
2021-02-10 17:32:56 +00:00
2018-06-19 12:58:52 -07:00
connect ( this , SIGNAL ( getMoreDebug ( ) ) , comm , SLOT ( debugThis ( ) ) ) ;
2021-03-04 20:19:05 +00:00
connect ( this , SIGNAL ( getMoreDebug ( ) ) , ptty , SLOT ( debugThis ( ) ) ) ;
2021-08-29 00:16:31 +01:00
2023-05-12 00:24:01 +01:00
commonSetup ( ) ;
2021-02-10 17:32:56 +00:00
}
2023-04-23 21:29:44 +01:00
void rigCommander : : commSetup ( QHash < unsigned char , QString > rigList , unsigned char rigCivAddr , udpPreferences prefs , audioSetup rxSetup , audioSetup txSetup , QString vsp , quint16 tcpPort )
2021-02-10 17:32:56 +00:00
{
// construct
// TODO: Bring this parameter and the comm port from the UI.
// Keep in hex in the UI as is done with other CIV apps.
2023-04-23 21:29:44 +01:00
this - > rigList = rigList ;
2023-05-12 00:24:01 +01:00
civAddr = rigCivAddr ; // address of the radio
2021-02-10 17:32:56 +00:00
usingNativeLAN = true ;
2022-03-23 10:12:42 +00:00
2021-02-10 17:32:56 +00:00
if ( udp = = Q_NULLPTR ) {
2021-02-21 14:53:42 +00:00
2021-06-04 08:24:26 +01:00
udp = new udpHandler ( prefs , rxSetup , txSetup ) ;
2021-02-21 14:53:42 +00:00
udpHandlerThread = new QThread ( this ) ;
2022-05-02 16:11:35 +01:00
udpHandlerThread - > setObjectName ( " udpHandler() " ) ;
2021-02-21 14:53:42 +00:00
udp - > moveToThread ( udpHandlerThread ) ;
connect ( this , SIGNAL ( initUdpHandler ( ) ) , udp , SLOT ( init ( ) ) ) ;
connect ( udpHandlerThread , SIGNAL ( finished ( ) ) , udp , SLOT ( deleteLater ( ) ) ) ;
udpHandlerThread - > start ( ) ;
emit initUdpHandler ( ) ;
2021-03-05 12:53:23 +00:00
//this->rigSerialPort = rigSerialPort;
//this->rigBaudRate = rigBaudRate;
2021-03-04 20:19:05 +00:00
2022-05-08 19:31:05 +01:00
ptty = new pttyHandler ( vsp , this ) ;
2021-03-04 20:19:05 +00:00
2022-04-08 14:40:05 +01:00
if ( tcpPort > 0 ) {
tcp = new tcpServer ( this ) ;
tcp - > startServer ( tcpPort ) ;
}
2021-03-05 12:53:23 +00:00
// Data from UDP to the program
2021-02-10 17:32:56 +00:00
connect ( udp , SIGNAL ( haveDataFromPort ( QByteArray ) ) , this , SLOT ( handleNewData ( QByteArray ) ) ) ;
2021-03-05 12:53:23 +00:00
2021-03-04 20:19:05 +00:00
// data from the rig to the ptty:
connect ( udp , SIGNAL ( haveDataFromPort ( QByteArray ) ) , ptty , SLOT ( receiveDataFromRigToPtty ( QByteArray ) ) ) ;
2021-03-05 12:53:23 +00:00
// Audio from UDP
2021-03-01 19:53:12 +00:00
connect ( udp , SIGNAL ( haveAudioData ( audioPacket ) ) , this , SLOT ( receiveAudioData ( audioPacket ) ) ) ;
2021-02-10 17:32:56 +00:00
2021-03-05 12:53:23 +00:00
// data from the program to the rig:
2021-02-10 17:32:56 +00:00
connect ( this , SIGNAL ( dataForComm ( QByteArray ) ) , udp , SLOT ( receiveDataFromUserToRig ( QByteArray ) ) ) ;
2021-03-05 12:53:23 +00:00
2021-03-04 20:19:05 +00:00
// data from the ptty to the rig:
connect ( ptty , SIGNAL ( haveDataFromPort ( QByteArray ) ) , udp , SLOT ( receiveDataFromUserToRig ( QByteArray ) ) ) ;
2022-04-08 14:40:05 +01:00
if ( tcpPort > 0 ) {
// data from the tcp port to the rig:
connect ( tcp , SIGNAL ( receiveData ( QByteArray ) ) , udp , SLOT ( receiveDataFromUserToRig ( QByteArray ) ) ) ;
connect ( udp , SIGNAL ( haveDataFromPort ( QByteArray ) ) , tcp , SLOT ( sendData ( QByteArray ) ) ) ;
}
2022-03-23 10:12:42 +00:00
2021-02-27 00:37:00 +00:00
connect ( this , SIGNAL ( haveChangeLatency ( quint16 ) ) , udp , SLOT ( changeLatency ( quint16 ) ) ) ;
2021-03-22 18:53:34 +00:00
connect ( this , SIGNAL ( haveSetVolume ( unsigned char ) ) , udp , SLOT ( setVolume ( unsigned char ) ) ) ;
2021-05-21 16:30:52 +01:00
connect ( udp , SIGNAL ( haveBaudRate ( quint32 ) ) , this , SLOT ( receiveBaudRate ( quint32 ) ) ) ;
2021-02-10 17:32:56 +00:00
// Connect for errors/alerts
2023-01-05 19:37:53 +00:00
connect ( udp , SIGNAL ( haveNetworkError ( errorType ) ) , this , SLOT ( handlePortError ( errorType ) ) ) ;
2022-01-22 15:12:36 +00:00
connect ( udp , SIGNAL ( haveNetworkStatus ( networkStatus ) ) , this , SLOT ( handleStatusUpdate ( networkStatus ) ) ) ;
2022-08-23 22:24:05 -07:00
connect ( udp , SIGNAL ( haveNetworkAudioLevels ( networkAudioLevels ) ) , this , SLOT ( handleNetworkAudioLevels ( networkAudioLevels ) ) ) ;
2021-03-04 20:19:05 +00:00
2023-01-05 19:37:53 +00:00
connect ( ptty , SIGNAL ( havePortError ( errorType ) ) , this , SLOT ( handlePortError ( errorType ) ) ) ;
2021-03-04 20:19:05 +00:00
connect ( this , SIGNAL ( getMoreDebug ( ) ) , ptty , SLOT ( debugThis ( ) ) ) ;
2021-07-05 16:45:19 -07:00
2022-01-21 19:23:32 +00:00
connect ( udp , SIGNAL ( requestRadioSelection ( QList < radio_cap_packet > ) ) , this , SLOT ( radioSelection ( QList < radio_cap_packet > ) ) ) ;
2023-12-18 15:48:17 +00:00
connect ( udp , SIGNAL ( setRadioUsage ( quint8 , bool , quint8 , QString , QString ) ) , this , SLOT ( radioUsage ( quint8 , bool , quint8 , QString , QString ) ) ) ;
2022-01-23 17:54:40 +00:00
connect ( this , SIGNAL ( selectedRadio ( quint8 ) ) , udp , SLOT ( setCurrentRadio ( quint8 ) ) ) ;
2023-07-06 10:36:11 +01:00
2021-07-05 16:45:19 -07:00
emit haveAfGain ( rxSetup . localAFgain ) ;
2022-01-04 18:34:34 +00:00
localVolume = rxSetup . localAFgain ;
2021-02-10 17:32:56 +00:00
2023-05-12 00:24:01 +01:00
}
2021-02-10 17:32:56 +00:00
2023-05-12 00:24:01 +01:00
commonSetup ( ) ;
2021-02-10 17:32:56 +00:00
2018-06-19 12:58:52 -07:00
}
2021-02-10 17:32:56 +00:00
void rigCommander : : closeComm ( )
{
2021-05-22 17:02:51 +01:00
qDebug ( logRig ( ) ) < < " Closing rig comms " ;
2021-02-10 17:32:56 +00:00
if ( comm ! = Q_NULLPTR ) {
delete comm ;
}
comm = Q_NULLPTR ;
2021-02-21 14:53:42 +00:00
if ( udpHandlerThread ! = Q_NULLPTR ) {
udpHandlerThread - > quit ( ) ;
udpHandlerThread - > wait ( ) ;
2021-02-10 17:32:56 +00:00
}
udp = Q_NULLPTR ;
2021-03-04 20:19:05 +00:00
if ( ptty ! = Q_NULLPTR ) {
delete ptty ;
}
2021-03-05 12:53:23 +00:00
ptty = Q_NULLPTR ;
2021-02-10 17:32:56 +00:00
}
2023-05-12 00:24:01 +01:00
void rigCommander : : commonSetup ( )
2018-06-19 12:58:52 -07:00
{
2023-05-12 00:24:01 +01:00
2021-02-10 17:32:56 +00:00
// common elements between the two constructors go here:
setCIVAddr ( civAddr ) ;
spectSeqMax = 0 ; // this is now set after rig ID determined
2021-05-30 15:08:22 -07:00
2021-02-10 17:32:56 +00:00
payloadSuffix = QByteArray ( " \xFD " ) ;
2023-05-12 00:24:01 +01:00
lookingForRig = true ;
2021-02-10 17:32:56 +00:00
foundRig = false ;
2023-05-12 00:24:01 +01:00
2023-05-15 10:53:52 +01:00
// Add the below commands so we can get a response until we have received rigCaps
2023-05-12 00:24:01 +01:00
rigCaps . commands . clear ( ) ;
rigCaps . commandsReverse . clear ( ) ;
2023-05-25 23:17:54 +01:00
rigCaps . commands . insert ( funcTransceiverId , funcType ( funcTransceiverId , QString ( " Transceiver ID " ) , QByteArrayLiteral ( " \x19 \x00 " ) , 0 , 0 , false ) ) ;
2023-05-12 00:24:01 +01:00
rigCaps . commandsReverse . insert ( QByteArrayLiteral ( " \x19 \x00 " ) , funcTransceiverId ) ;
2023-06-08 08:20:50 +01:00
this - > setObjectName ( " Rig Commander " ) ;
2023-05-12 00:24:01 +01:00
queue = cachingQueue : : getInstance ( this ) ;
2024-01-27 22:13:47 +00:00
connect ( queue , SIGNAL ( haveCommand ( funcs , QVariant , uchar ) ) , this , SLOT ( receiveCommand ( funcs , QVariant , uchar ) ) ) ;
2021-02-28 21:41:27 -08:00
oldScopeMode = spectModeUnknown ;
2021-02-10 17:32:56 +00:00
pttAllowed = true ; // This is for developing, set to false for "safe" debugging. Set to true for deployment.
2023-05-12 00:24:01 +01:00
emit commReady ( ) ;
2018-06-19 12:58:52 -07:00
}
2021-05-30 15:08:22 -07:00
2018-06-19 12:58:52 -07:00
void rigCommander : : process ( )
{
2021-02-10 17:32:56 +00:00
// new thread enters here. Do nothing but do check for errors.
if ( comm ! = Q_NULLPTR & & comm - > serialError )
{
2023-01-05 19:37:53 +00:00
emit havePortError ( errorType ( rigSerialPort , QString ( " Error from commhandler. Check serial port. " ) ) ) ;
2021-02-10 17:32:56 +00:00
}
}
2023-01-05 19:37:53 +00:00
void rigCommander : : handlePortError ( errorType err )
2021-02-10 17:32:56 +00:00
{
2023-01-05 19:37:53 +00:00
qInfo ( logRig ( ) ) < < " Error using port " < < err . device < < " message: " < < err . message ;
emit havePortError ( err ) ;
2021-02-10 17:32:56 +00:00
}
2022-01-22 15:12:36 +00:00
void rigCommander : : handleStatusUpdate ( const networkStatus status )
2021-02-10 17:32:56 +00:00
{
2022-01-22 15:12:36 +00:00
emit haveStatusUpdate ( status ) ;
2021-02-10 17:32:56 +00:00
}
2022-08-23 22:24:05 -07:00
void rigCommander : : handleNetworkAudioLevels ( networkAudioLevels l )
{
emit haveNetworkAudioLevels ( l ) ;
}
2021-04-30 22:15:30 -07:00
bool rigCommander : : usingLAN ( )
{
return usingNativeLAN ;
}
2021-05-21 16:30:52 +01:00
void rigCommander : : receiveBaudRate ( quint32 baudrate ) {
2022-01-26 09:49:52 +00:00
rigCaps . baudRate = baudrate ;
2021-05-21 16:30:52 +01:00
emit haveBaudRate ( baudrate ) ;
}
2022-01-04 18:34:34 +00:00
void rigCommander : : setRTSforPTT ( bool enabled )
{
if ( ! usingNativeLAN )
{
useRTSforPTT_isSet = true ;
useRTSforPTT_manual = enabled ;
if ( comm ! = NULL )
{
rigCaps . useRTSforPTT = enabled ;
comm - > setUseRTSforPTT ( enabled ) ;
}
}
}
2021-02-10 17:32:56 +00:00
void rigCommander : : findRigs ( )
{
// This function sends data to 0x00 ("broadcast") to look for any connected rig.
lookingForRig = true ;
foundRig = false ;
QByteArray data ;
QByteArray data2 ;
//data.setRawData("\xFE\xFE\xa2", 3);
data . setRawData ( " \xFE \xFE \x00 " , 3 ) ;
2021-02-22 11:11:08 +00:00
data . append ( ( char ) compCivAddr ) ; // wfview's address, 0xE1
2021-02-10 17:32:56 +00:00
data2 . setRawData ( " \x19 \x00 " , 2 ) ; // get rig ID
data . append ( data2 ) ;
data . append ( payloadSuffix ) ;
emit dataForComm ( data ) ;
2023-05-03 19:19:58 +01:00
// HACK for testing radios that do not respond to rig ID queries:
2021-11-04 20:17:50 -07:00
//this->model = model736;
//this->determineRigCaps();
2021-02-10 17:32:56 +00:00
return ;
2018-06-19 12:58:52 -07:00
}
void rigCommander : : prepDataAndSend ( QByteArray data )
2023-05-12 00:24:01 +01:00
{
2018-06-19 12:58:52 -07:00
data . prepend ( payloadPrefix ) ;
data . append ( payloadSuffix ) ;
2021-05-15 18:53:16 +01:00
2021-03-02 22:11:01 -08:00
if ( data [ 4 ] ! = ' \x15 ' )
{
// We don't print out requests for meter levels
2023-01-21 13:38:39 -08:00
qDebug ( logRigTraffic ( ) ) < < " Final payload in rig commander to be sent to rig: " ;
printHexNow ( data , logRigTraffic ( ) ) ;
2021-03-02 22:11:01 -08:00
}
2024-02-07 13:06:23 +00:00
lastCommandToRig = data ;
2018-06-19 12:58:52 -07:00
emit dataForComm ( data ) ;
}
2024-03-30 20:40:27 +00:00
bool rigCommander : : getCommand ( funcs func , QByteArray & payload , int value , uchar receiver )
2023-04-25 08:56:06 +01:00
{
2023-04-28 01:01:57 +01:00
// Value is set to INT_MIN by default as this should be outside any "real" values
2023-04-25 08:56:06 +01:00
auto it = rigCaps . commands . find ( func ) ;
if ( it ! = rigCaps . commands . end ( ) )
{
2023-04-28 01:01:57 +01:00
if ( value = = INT_MIN | | ( value > = it . value ( ) . minVal & & value < = it . value ( ) . maxVal ) )
2023-04-25 08:56:06 +01:00
{
2024-02-12 10:06:08 -08:00
/*
2023-04-28 01:01:57 +01:00
if ( value = = INT_MIN )
2023-04-25 15:56:28 +01:00
qDebug ( logRig ( ) ) < < QString ( " %0 with no value (get) " ) . arg ( funcString [ func ] ) ;
else
qDebug ( logRig ( ) ) < < QString ( " %0 with value %1 (Range: %2-%3) " ) . arg ( funcString [ func ] ) . arg ( value ) . arg ( it . value ( ) . minVal ) . arg ( it . value ( ) . maxVal ) ;
2024-02-12 10:06:08 -08:00
*/
2023-05-25 23:17:54 +01:00
if ( rigCaps . hasCommand29 & & it . value ( ) . cmd29 )
{
// This can use cmd29 so add sub/main to the command
payload . append ( ' \x29 ' ) ;
2024-03-30 20:40:27 +00:00
payload . append ( static_cast < uchar > ( receiver ) ) ;
} else if ( ! rigCaps . hasCommand29 & & receiver )
2023-07-23 11:17:10 +01:00
{
// We don't have command29 so can't select sub
2024-03-30 20:40:27 +00:00
qInfo ( logRig ( ) ) < < " Rig has no Command29, removing command: " < < funcString [ func ] < < " VFO " < < receiver ;
queue - > del ( func , receiver ) ;
2023-07-23 11:17:10 +01:00
return false ;
2023-05-25 23:17:54 +01:00
}
2023-04-25 08:56:06 +01:00
payload . append ( it . value ( ) . data ) ;
return true ;
}
2023-04-28 01:01:57 +01:00
else if ( value ! = INT_MIN )
2023-04-25 08:56:06 +01:00
{
2024-02-12 10:06:08 -08:00
qDebug ( logRig ( ) ) < < QString ( " Value %0 for %1 is outside of allowed range (%2-%3) " ) . arg ( value ) . arg ( funcString [ func ] ) . arg ( it . value ( ) . minVal ) . arg ( it . value ( ) . maxVal ) ;
2023-04-25 08:56:06 +01:00
}
2023-06-05 21:53:17 +01:00
} else {
// Don't try this command again as the rig doesn't support it!
2024-03-30 20:40:27 +00:00
qDebug ( logRig ( ) ) < < " Removing unsupported command from queue " < < funcString [ func ] < < " VFO " < < receiver ;
queue - > del ( func , receiver ) ;
2023-04-25 08:56:06 +01:00
}
return false ;
}
2021-04-19 22:55:39 -07:00
void rigCommander : : powerOn ( )
{
QByteArray payload ;
2022-01-04 18:34:34 +00:00
int numFE = 150 ;
2023-05-09 18:27:13 +01:00
2022-01-04 18:34:34 +00:00
switch ( this - > rigBaudRate ) {
case 57600 :
numFE = 75 ;
break ;
case 38400 :
numFE = 50 ;
break ;
case 19200 :
numFE = 25 ;
break ;
case 9600 :
numFE = 13 ;
break ;
case 4800 :
numFE = 7 ;
break ;
}
2023-05-12 00:24:01 +01:00
if ( ! usingNativeLAN | | ! rigCaps . hasLan ) {
for ( int i = 0 ; i < numFE ; i + + )
{
payload . append ( " \xFE " ) ;
}
2021-04-19 22:55:39 -07:00
}
2023-04-25 08:56:06 +01:00
unsigned char cmd = 0x01 ;
2023-05-09 18:27:13 +01:00
payload . append ( payloadPrefix ) ;
2023-05-09 17:28:55 +01:00
if ( getCommand ( funcPowerControl , payload , cmd ) )
2023-04-23 21:29:44 +01:00
{
payload . append ( cmd ) ;
2023-05-09 18:27:13 +01:00
payload . append ( payloadSuffix ) ; // FD
2023-04-25 08:56:06 +01:00
}
else
{
2023-04-23 21:29:44 +01:00
// We may not know the command to turn the radio on so here it is:
payload . append ( " \x18 \x01 " ) ;
payload . append ( payloadSuffix ) ; // FD
}
2021-04-19 22:55:39 -07:00
qDebug ( logRig ( ) ) < < " Power ON command in rigcommander to be sent to rig: " ;
printHex ( payload ) ;
emit dataForComm ( payload ) ;
}
void rigCommander : : powerOff ( )
{
2023-04-25 08:56:06 +01:00
QByteArray payload ;
unsigned char cmd = ' \x00 ' ;
2023-05-09 17:28:55 +01:00
if ( getCommand ( funcPowerControl , payload , cmd ) )
2023-04-23 21:29:44 +01:00
{
payload . append ( cmd ) ;
2023-04-19 14:51:23 +01:00
prepDataAndSend ( payload ) ;
}
2021-04-19 22:55:39 -07:00
}
2023-01-27 12:44:23 -08:00
2021-03-22 00:11:43 -07:00
QByteArray rigCommander : : makeFreqPayload ( freqt freq )
{
QByteArray result ;
quint64 freqInt = freq . Hz ;
unsigned char a ;
int numchars = 5 ;
2023-09-22 19:06:09 +01:00
if ( freq . Hz > = 1E10 )
numchars = 6 ;
2021-03-22 00:11:43 -07:00
for ( int i = 0 ; i < numchars ; i + + ) {
a = 0 ;
a | = ( freqInt ) % 10 ;
freqInt / = 10 ;
a | = ( ( freqInt ) % 10 ) < < 4 ;
freqInt / = 10 ;
result . append ( a ) ;
//printHex(result, false, true);
}
return result ;
}
2018-06-19 12:58:52 -07:00
QByteArray rigCommander : : makeFreqPayload ( double freq )
{
quint64 freqInt = ( quint64 ) ( freq * 1E6 ) ;
QByteArray result ;
unsigned char a ;
int numchars = 5 ;
2023-09-22 19:06:09 +01:00
if ( freqInt > = 1E10 )
numchars = 6 ;
2018-06-19 12:58:52 -07:00
for ( int i = 0 ; i < numchars ; i + + ) {
a = 0 ;
a | = ( freqInt ) % 10 ;
freqInt / = 10 ;
a | = ( ( freqInt ) % 10 ) < < 4 ;
freqInt / = 10 ;
result . append ( a ) ;
//printHex(result, false, true);
}
2021-05-15 18:53:16 +01:00
//qInfo(logRig()) << "encoded frequency for " << freq << " as int " << freqInt;
2018-06-19 12:58:52 -07:00
//printHex(result, false, true);
return result ;
}
2021-04-24 00:31:51 -07:00
2023-11-26 14:47:17 +00:00
QByteArray rigCommander : : encodeTone ( quint16 tone )
2021-04-24 00:31:51 -07:00
{
2023-11-26 14:47:17 +00:00
return encodeTone ( tone , false , false ) ;
2021-04-24 00:31:51 -07:00
}
2023-11-26 14:47:17 +00:00
QByteArray rigCommander : : encodeTone ( quint16 tone , bool tinv , bool rinv )
2021-04-24 00:31:51 -07:00
{
2023-11-26 14:47:17 +00:00
// This function is fine to use for DTCS and TONE
QByteArray enct ;
2021-04-24 00:31:51 -07:00
2023-11-26 14:47:17 +00:00
unsigned char inv = 0 ;
inv = inv | ( unsigned char ) rinv ;
inv = inv | ( ( unsigned char ) tinv ) < < 4 ;
2021-04-24 00:31:51 -07:00
2023-11-26 14:47:17 +00:00
enct . append ( inv ) ;
2021-06-25 23:56:19 -07:00
2023-11-26 14:47:17 +00:00
unsigned char hundreds = tone / 1000 ;
unsigned char tens = ( tone - ( hundreds * 1000 ) ) / 100 ;
unsigned char ones = ( tone - ( hundreds * 1000 ) - ( tens * 100 ) ) / 10 ;
unsigned char dec = ( tone - ( hundreds * 1000 ) - ( tens * 100 ) - ( ones * 10 ) ) ;
2021-06-25 23:56:19 -07:00
2023-11-26 14:47:17 +00:00
enct . append ( tens | ( hundreds < < 4 ) ) ;
enct . append ( dec | ( ones < < 4 ) ) ;
2021-05-07 15:46:47 -07:00
2023-11-26 14:47:17 +00:00
return enct ;
2018-06-19 12:58:52 -07:00
}
2018-11-07 15:54:03 -08:00
2023-11-26 14:47:17 +00:00
toneInfo rigCommander : : decodeTone ( QByteArray eTone )
2021-04-04 23:33:56 -07:00
{
// index: 00 01 02 03 04
// CTCSS: 1B 01 00 12 73 = PL 127.3, decode as 1273
// D(T)CS: 1B 01 TR 01 23 = T/R Invert bits + DCS code 123
2023-05-15 10:53:52 +01:00
toneInfo t ;
2024-02-12 22:26:25 +00:00
if ( eTone . length ( ) < 3 ) {
2023-05-15 10:53:52 +01:00
return t ;
2021-06-01 00:25:20 +01:00
}
2021-04-04 23:33:56 -07:00
2024-02-12 22:26:25 +00:00
if ( ( eTone . at ( 0 ) & 0x01 ) = = 0x01 )
2023-05-15 10:53:52 +01:00
t . tinv = true ;
2024-02-12 22:26:25 +00:00
if ( ( eTone . at ( 0 ) & 0x10 ) = = 0x10 )
2023-05-15 10:53:52 +01:00
t . rinv = true ;
2021-04-04 23:33:56 -07:00
2024-02-12 22:26:25 +00:00
t . tone + = ( eTone . at ( 2 ) & 0x0f ) ;
t . tone + = ( ( eTone . at ( 2 ) & 0xf0 ) > > 4 ) * 10 ;
t . tone + = ( eTone . at ( 1 ) & 0x0f ) * 100 ;
t . tone + = ( ( eTone . at ( 1 ) & 0xf0 ) > > 4 ) * 1000 ;
2021-04-04 23:33:56 -07:00
2023-05-15 10:53:52 +01:00
return t ;
2021-04-04 00:36:21 -07:00
}
2023-11-26 14:47:17 +00:00
void rigCommander : : setCIVAddr ( unsigned char civAddr )
2021-04-04 00:36:21 -07:00
{
2023-11-26 14:47:17 +00:00
// Note: This sets the radio's CIV address
// the computer's CIV address is defined in the header file.
2021-04-04 00:36:21 -07:00
2023-11-26 14:47:17 +00:00
this - > civAddr = civAddr ;
payloadPrefix = QByteArray ( " \xFE \xFE " ) ;
payloadPrefix . append ( civAddr ) ;
payloadPrefix . append ( ( char ) compCivAddr ) ;
2021-04-04 00:36:21 -07:00
}
2023-11-26 14:47:17 +00:00
void rigCommander : : handleNewData ( const QByteArray & data )
2021-04-04 00:36:21 -07:00
{
2023-11-26 14:47:17 +00:00
emit haveDataForServer ( data ) ;
parseData ( data ) ;
2021-04-04 00:36:21 -07:00
}
2023-11-26 14:47:17 +00:00
void rigCommander : : receiveAudioData ( const audioPacket & data )
2021-04-04 00:36:21 -07:00
{
2023-11-26 14:47:17 +00:00
emit haveAudioData ( data ) ;
2021-04-04 00:36:21 -07:00
}
2023-11-26 14:47:17 +00:00
void rigCommander : : parseData ( QByteArray dataInput )
2023-01-27 14:05:50 -08:00
{
2023-11-26 14:47:17 +00:00
// TODO: Clean this up.
// It finally works very nicely, needs to be streamlined.
//
2023-01-27 14:05:50 -08:00
2023-11-26 14:47:17 +00:00
int index = 0 ;
volatile int count = 0 ; // debug purposes
2023-01-31 21:52:24 -08:00
2023-11-26 14:47:17 +00:00
// use this:
QList < QByteArray > dataList = dataInput . split ( ' \xFD ' ) ;
QByteArray data ;
// qInfo(logRig()) << "data list has this many elements: " << dataList.size();
if ( dataList . last ( ) . isEmpty ( ) )
2023-04-25 08:56:06 +01:00
{
2023-11-26 14:47:17 +00:00
dataList . removeLast ( ) ; // if the original ended in FD, then there is a blank entry at the end.
2023-04-25 08:56:06 +01:00
}
2023-11-26 14:47:17 +00:00
// Only thing is, each frame is missing '\xFD' at the end. So append! Keeps the frames intact.
for ( index = 0 ; index < dataList . count ( ) ; index + + )
2023-01-31 14:03:51 -08:00
{
2023-11-26 14:47:17 +00:00
data = dataList [ index ] ;
data . append ( ' \xFD ' ) ; // because we expect it to be there.
2023-01-31 14:03:51 -08:00
2023-11-26 14:47:17 +00:00
count + + ;
// Data echo'd back from the rig start with this:
// fe fe 94 e0 ...... fd
// Data from the rig that is not an echo start with this:
// fe fe e0 94 ...... fd (for example, a reply to a query)
// Data from the rig that was not asked for is sent to controller 0x00:
// fe fe 00 94 ...... fd (for example, user rotates the tune control or changes the mode)
//qInfo(logRig()) << "Data received: ";
//printHex(data, false, true);
if ( data . length ( ) < 4 )
2023-04-25 08:56:06 +01:00
{
2023-11-26 14:47:17 +00:00
if ( data . length ( ) )
2023-01-31 21:52:24 -08:00
{
2023-11-26 14:47:17 +00:00
// Finally this almost never happens
// qInfo(logRig()) << "Data length too short: " << data.length() << " bytes. Data:";
//printHex(data, false, true);
2023-01-31 21:52:24 -08:00
}
2023-11-26 14:47:17 +00:00
// no
//return;
// maybe:
// continue;
2023-04-25 08:56:06 +01:00
}
2023-11-26 14:47:17 +00:00
if ( ! data . startsWith ( " \xFE \xFE " ) )
2023-04-25 08:56:06 +01:00
{
2023-11-26 14:47:17 +00:00
// qInfo(logRig()) << "Warning: Invalid data received, did not start with FE FE.";
// find 94 e0 and shift over,
// or look inside for a second FE FE
// Often a local echo will miss a few bytes at the beginning.
if ( data . startsWith ( ' \xFE ' ) )
2023-04-23 21:29:44 +01:00
{
2023-11-26 14:47:17 +00:00
data . prepend ( ' \xFE ' ) ;
// qInfo(logRig()) << "Warning: Working with prepended data stream.";
parseData ( payloadIn ) ;
return ;
} else {
//qInfo(logRig()) << "Error: Could not reconstruct corrupted data: ";
//printHex(data, false, true);
// data.right(data.length() - data.find('\xFE\xFE'));
// if found do not return and keep going.
return ;
2023-04-25 08:56:06 +01:00
}
}
2023-11-26 14:47:17 +00:00
if ( ( unsigned char ) data [ 02 ] = = civAddr )
2023-04-25 08:56:06 +01:00
{
2023-11-26 14:47:17 +00:00
// data is or begins with an echoback from what we sent
// find the first 'fd' and cut it. Then continue.
//payloadIn = data.right(data.length() - data.indexOf('\xfd')-1);
// qInfo(logRig()) << "[FOUND] Trimmed off echo:";
//printHex(payloadIn, false, true);
//parseData(payloadIn);
//return;
2023-01-31 14:03:51 -08:00
}
2023-01-27 21:42:57 -08:00
2023-11-26 14:47:17 +00:00
incomingCIVAddr = data [ 03 ] ; // track the CIV of the sender.
2023-05-01 21:56:52 +01:00
2023-11-26 14:47:17 +00:00
switch ( data [ 02 ] )
{
// case civAddr: // can't have a variable here :-(
// // data is or begins with an echoback from what we sent
// // find the first 'fd' and cut it. Then continue.
// payloadIn = data.right(data.length() - data.indexOf('\xfd')-1);
// //qInfo(logRig()) << "Trimmed off echo:";
// //printHex(payloadIn, false, true);
// parseData(payloadIn);
// break;
// case '\xE0':
2023-05-06 12:36:05 +01:00
2023-11-26 14:47:17 +00:00
case ( char ) 0xE0 :
case ( char ) compCivAddr :
// data is a reply to some query we sent
// extract the payload out and parse.
// payload = getpayload(data); // or something
// parse (payload); // recursive ok?
payloadIn = data . right ( data . length ( ) - 4 ) ;
if ( payloadIn . contains ( " \xFE " ) )
{
//qDebug(logRig()) << "Corrupted data contains FE within message body: ";
//printHex(payloadIn);
break ;
2023-05-06 12:36:05 +01:00
}
2023-11-26 14:47:17 +00:00
parseCommand ( ) ;
break ;
case ' \x00 ' :
// data send initiated by the rig due to user control
// extract the payload out and parse.
if ( ( unsigned char ) data [ 03 ] = = compCivAddr )
2023-05-06 12:36:05 +01:00
{
2023-11-26 14:47:17 +00:00
// This is an echo of our own broadcast request.
// The data are "to 00" and "from E1"
// Don't use it!
qDebug ( logRig ( ) ) < < " Caught it! Found the echo'd broadcast request from us! Rig has not responded to broadcast query yet. " ;
} else {
payloadIn = data . right ( data . length ( ) - 4 ) ; // Removes FE FE E0 94 part
if ( payloadIn . contains ( " \xFE " ) )
{
//qDebug(logRig()) << "Corrupted data contains FE within message body: ";
//printHex(payloadIn);
break ;
}
parseCommand ( ) ;
2023-05-06 12:36:05 +01:00
}
break ;
default :
2023-11-26 14:47:17 +00:00
// could be for other equipment on the CIV network.
// just drop for now.
// relaySendOutData(data);
2023-05-06 12:36:05 +01:00
break ;
2023-05-02 21:18:41 +01:00
}
2023-05-01 21:56:52 +01:00
}
2023-11-26 14:47:17 +00:00
/*
if ( dataList . length ( ) > 1 )
{
qInfo ( logRig ( ) ) < < " Recovered " < < count < < " frames from single data with size " < < dataList . count ( ) ;
}
*/
2023-05-01 21:56:52 +01:00
}
2023-11-26 14:47:17 +00:00
void rigCommander : : parseCommand ( )
2023-05-04 21:55:40 +01:00
{
2023-11-26 14:47:17 +00:00
# ifdef DEBUG_PARSE
QElapsedTimer performanceTimer ;
performanceTimer . start ( ) ;
# endif
funcs func = funcNone ;
2024-03-30 20:40:27 +00:00
uchar receiver = 0 ;
2023-11-26 14:47:17 +00:00
if ( payloadIn . endsWith ( ( char ) 0xfd ) )
2023-05-04 21:55:40 +01:00
{
2023-11-26 14:47:17 +00:00
payloadIn . chop ( 1 ) ;
2023-05-04 21:55:40 +01:00
}
2023-11-26 14:47:17 +00:00
if ( rigCaps . hasCommand29 & & payloadIn [ 0 ] = = ' \x29 ' )
{
2024-03-30 20:40:27 +00:00
receiver = static_cast < uchar > ( payloadIn [ 1 ] ) ;
2024-02-12 22:26:25 +00:00
payloadIn . remove ( 0 , 2 ) ;
2023-11-26 14:47:17 +00:00
}
2023-05-09 17:03:03 +01:00
2023-11-26 14:47:17 +00:00
// As some commands bave both single and multi-byte options, start at 4 characters and work down to 1.
// This is quite wasteful as many commands are single-byte, but I can't think of an easier way?
int count = 0 ;
for ( int i = 4 ; i > 0 ; i - - )
{
auto it = rigCaps . commandsReverse . find ( payloadIn . left ( i ) ) ;
if ( it ! = rigCaps . commandsReverse . end ( ) )
{
func = it . value ( ) ;
count = i ;
break ;
}
}
2023-05-01 21:56:52 +01:00
2023-11-26 14:47:17 +00:00
// Remove the command so all we are left with is the data.
payloadIn . remove ( 0 , count ) ;
# ifdef DEBUG_PARSE
int currentParse = performanceTimer . nsecsElapsed ( ) ;
# endif
2023-05-04 21:55:40 +01:00
2023-11-26 14:47:17 +00:00
if ( ! rigCaps . commands . contains ( func ) ) {
// Don't warn if we haven't received rigCaps yet
if ( haveRigCaps )
qInfo ( logRig ( ) ) < < " Unsupported command received from rig " < < payloadIn . toHex ( ) . mid ( 0 , 10 ) < < " Check rig file " ;
return ;
}
freqt test ;
QVector < memParserFormat > memParser ;
QVariant value ;
switch ( func )
{
case funcFreqGet :
case funcFreqTR :
case funcReadTXFreq :
2023-05-01 21:56:52 +01:00
{
2024-03-30 20:40:27 +00:00
value . setValue ( parseFreqData ( payloadIn , receiver ) ) ;
2023-11-26 14:47:17 +00:00
break ;
2023-05-04 21:55:40 +01:00
}
2023-11-26 14:47:17 +00:00
case funcVFODualWatch :
value . setValue ( static_cast < bool > ( bool ( payloadIn [ 0 ] ) ) ) ;
break ;
# if defined __GNUC__
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
# endif
2024-03-30 20:40:27 +00:00
case funcSubFreq :
receiver = 1 ;
2023-11-26 14:47:17 +00:00
case funcSelectedFreq :
2024-03-30 20:40:27 +00:00
case funcUnselectedFreq :
case funcMainFreq :
2023-05-04 21:55:40 +01:00
{
2024-03-30 20:40:27 +00:00
//qInfo(logRig()) << "Freq len:" << payloadIn.size() << "receiver=" << receiver << "data:" << payloadIn.toHex(' ');
value . setValue ( parseFreqData ( payloadIn , receiver ) ) ;
2023-11-26 14:47:17 +00:00
break ;
2023-05-04 21:55:40 +01:00
}
2023-11-26 14:47:17 +00:00
case funcModeGet :
case funcModeTR :
{
modeInfo m ;
2024-03-30 20:40:27 +00:00
m = parseMode ( payloadIn [ 0 ] , m . filter , receiver ) ;
2023-05-04 21:55:40 +01:00
2023-11-26 14:47:17 +00:00
if ( payloadIn . size ( ) > 1 )
2023-05-04 21:55:40 +01:00
{
2023-11-26 14:47:17 +00:00
m . filter = payloadIn [ 1 ] ;
} else {
m . filter = 0 ;
2023-05-02 21:18:41 +01:00
}
2023-11-26 14:47:17 +00:00
value . setValue ( m ) ;
break ;
2023-05-01 21:56:52 +01:00
}
2024-03-30 20:40:27 +00:00
case funcSubMode :
receiver = 1 ;
2023-11-26 14:47:17 +00:00
case funcSelectedMode :
2024-03-30 20:40:27 +00:00
case funcUnselectedMode :
case funcMainMode :
2023-05-01 21:56:52 +01:00
{
2023-11-26 14:47:17 +00:00
modeInfo m ;
// New format payload with mode+datamode+filter
2024-03-30 20:40:27 +00:00
m = parseMode ( bcdHexToUChar ( payloadIn [ 0 ] ) , bcdHexToUChar ( payloadIn [ 2 ] ) , receiver ) ;
2023-11-26 14:47:17 +00:00
m . data = bcdHexToUChar ( payloadIn [ 1 ] ) ;
2024-03-30 20:40:27 +00:00
m . VFO = selVFO_t ( receiver ) ;
2023-11-26 14:47:17 +00:00
value . setValue ( m ) ;
break ;
2023-05-01 21:56:52 +01:00
}
2023-05-06 12:36:05 +01:00
2023-11-26 14:47:17 +00:00
case funcVFOBandMS :
2023-11-26 16:23:16 +00:00
value . setValue ( static_cast < bool > ( payloadIn [ 0 ] ) ) ;
2023-11-26 14:47:17 +00:00
break ;
case funcSatelliteMemory :
memParser = rigCaps . satParser ;
case funcMemoryContents :
2023-05-06 12:36:05 +01:00
{
2023-11-26 14:47:17 +00:00
memoryType mem ;
if ( memParser . isEmpty ( ) ) {
memParser = rigCaps . memParser ;
mem . sat = false ;
} else {
mem . sat = true ;
2023-05-06 12:36:05 +01:00
}
2018-11-07 15:54:03 -08:00
2023-11-26 14:47:17 +00:00
if ( parseMemory ( & memParser , & mem ) ) {
value . setValue ( mem ) ;
}
break ;
2023-04-23 21:29:44 +01:00
}
2023-11-26 14:47:17 +00:00
# if defined __GNUC__
# pragma GCC diagnostic pop
# endif
case funcMemoryClear :
case funcMemoryKeyer :
case funcMemoryToVFO :
case funcMemoryWrite :
break ;
case funcScanning :
break ;
case funcReadFreqOffset :
2024-03-30 20:40:27 +00:00
value . setValue ( parseFreqData ( payloadIn , receiver ) ) ;
2023-11-26 14:47:17 +00:00
break ;
// These return a single byte that we convert to a uchar (0-99)
case funcTuningStep :
case funcAttenuator :
value . setValue ( bcdHexToUChar ( payloadIn [ 0 ] ) ) ;
break ;
// Return a duplexMode_t for split or duplex (same function)
case funcSplitStatus :
value . setValue ( static_cast < duplexMode_t > ( uchar ( payloadIn [ 0 ] ) ) ) ;
break ;
case funcAntenna :
2018-11-07 15:54:03 -08:00
{
2023-11-26 14:47:17 +00:00
antennaInfo ant ;
ant . antenna = bcdHexToUChar ( payloadIn [ 0 ] ) ;
ant . rx = static_cast < bool > ( payloadIn [ 1 ] ) ;
value . setValue ( ant ) ;
break ;
// Register 13 (speech) has no get values
// Register 14 (levels) starts here:
2018-11-07 15:54:03 -08:00
}
2023-11-26 14:47:17 +00:00
case funcAfGain :
if ( udp = = Q_NULLPTR ) {
value . setValue ( bcdHexToUChar ( payloadIn [ 0 ] , payloadIn [ 1 ] ) ) ;
} else {
value . setValue ( localVolume ) ;
2023-01-20 22:11:30 -08:00
}
2023-11-26 14:47:17 +00:00
break ;
// The following group are 2 bytes converted to uchar (0-255)
case funcKeySpeed : {
uchar level = bcdHexToUChar ( payloadIn [ 0 ] , payloadIn [ 1 ] ) ;
value . setValue < ushort > ( round ( ( level / 6.071 ) + 6 ) ) ;
break ;
2023-04-23 21:29:44 +01:00
}
2021-05-30 15:08:22 -07:00
2023-11-26 14:47:17 +00:00
case funcAGCTime :
case funcRfGain :
case funcSquelch :
case funcAPFLevel :
case funcNRLevel :
case funcPBTInner :
case funcPBTOuter :
case funcIFShift :
case funcCwPitch :
case funcRFPower :
case funcMicGain :
case funcNotchFilter :
case funcCompressorLevel :
case funcBreakInDelay :
case funcNBLevel :
case funcDigiSelShift :
case funcDriveGain :
case funcMonitorGain :
case funcVoxGain :
case funcAntiVoxGain :
// 0x15 Meters
case funcSMeter :
case funcCenterMeter :
case funcPowerMeter :
case funcSWRMeter :
case funcALCMeter :
case funcCompMeter :
case funcVdMeter :
case funcIdMeter :
value . setValue ( bcdHexToUChar ( payloadIn [ 0 ] , payloadIn [ 1 ] ) ) ;
break ;
// These are 2 byte commands that return a single byte (0-99) from position 2
case funcBreakIn : // This is 0,1 or 2
case funcPreamp :
case funcManualNotchWidth :
case funcSSBTXBandwidth :
case funcDSPIFFilter :
value . setValue ( bcdHexToUChar ( payloadIn [ 0 ] ) ) ;
break ;
// The following group ALL return bool
case funcNoiseBlanker :
case funcAudioPeakFilter :
case funcNoiseReduction :
case funcAutoNotch :
case funcRepeaterTone :
case funcRepeaterTSQL :
case funcRepeaterDTCS :
case funcRepeaterCSQL :
case funcCompressor :
case funcMonitor :
case funcVox :
case funcManualNotch :
case funcDigiSel :
case funcTwinPeakFilter :
case funcDialLock :
case funcOverflowStatus :
case funcSMeterSqlStatus :
case funcVariousSql :
case funcRXAntenna :
value . setValue ( static_cast < bool > ( payloadIn [ 0 ] ) ) ;
break ;
case funcMainSubTracking :
case funcToneSquelchType :
emit haveRptAccessMode ( ( rptAccessTxRx_t ) payloadIn . at ( 0 ) ) ;
break ;
case funcIPPlus :
break ;
// 0x17 is CW send and 0x18 is power control (no reply)
// 0x19 it automatically added.
case funcTransceiverId :
2023-11-27 19:11:38 +00:00
if ( ! rigCaps . modelID )
2022-01-04 18:34:34 +00:00
{
2024-02-05 09:33:42 -08:00
if ( payloadIn [ 0 ] = = ( char ) 0x0 & & payloadIn . size ( ) > 1 )
2023-11-27 19:11:38 +00:00
{
payloadIn . remove ( 0 , 1 ) ; // Remove spurious response.
}
value . setValue ( static_cast < uchar > ( payloadIn [ 0 ] ) ) ;
if ( rigList . contains ( uchar ( payloadIn [ 0 ] ) ) )
{
this - > model = rigList . find ( uchar ( payloadIn [ 0 ] ) ) . key ( ) ;
}
//model = determineRadioModel(payloadIn[2]); // verify this is the model not the CIV
rigCaps . modelID = payloadIn [ 0 ] ;
determineRigCaps ( ) ;
qInfo ( logRig ( ) ) < < " Have rig ID: " < < QString : : number ( rigCaps . modelID , 16 ) ;
}
else {
qWarning ( logRig ( ) ) < < " Received transceiverID when we already have rigcaps: " < < payloadIn . toHex ( ' ' ) ;
2022-01-04 18:34:34 +00:00
}
2023-11-26 14:47:17 +00:00
break ;
// 0x1a
case funcBandStackReg :
2021-02-10 17:32:56 +00:00
{
2023-11-26 14:47:17 +00:00
bandStackType bsr ;
bsr . band = payloadIn [ 0 ] ;
bsr . regCode = payloadIn [ 1 ] ;
int freqLen = 5 ;
// PET I want to find a better way to do this!
if ( rigCaps . modelID = = 0xAC & & bsr . band = = 6 ) {
freqLen = 6 ;
2021-05-15 16:57:08 -07:00
}
2024-03-30 20:40:27 +00:00
bsr . freq = parseFreqData ( payloadIn . mid ( 2 , freqLen ) , receiver ) ;
2023-11-26 14:47:17 +00:00
// The Band Stacking command returns the regCode in the position that VFO is expected.
// As BSR is always on the active VFO, just set that.
bsr . freq . VFO = selVFO_t : : activeVFO ;
bsr . mode = payloadIn [ freqLen + 2 ] ;
bsr . filter = payloadIn [ freqLen + 3 ] ;
bsr . data = ( payloadIn [ freqLen + 4 ] & 0x10 ) > > 4 ; // not sure...
//qInfo(logRig()) << QString("BSR: (%0) band:%1 regcode: %2 freq: %3: data: %4 mode: %5 filter %6")
// .arg(payloadIn.toHex(' ')).arg(bsr.band).arg(bsr.regCode).arg(bsr.freq.Hz).arg(bsr.data).arg(bsr.mode).arg(bsr.filter);
value . setValue ( bsr ) ;
break ;
2023-09-23 11:37:55 +01:00
}
2023-11-26 14:47:17 +00:00
case funcFilterWidth :
2018-06-19 12:58:52 -07:00
{
2023-11-26 14:47:17 +00:00
quint16 calc ;
quint8 pass = bcdHexToUChar ( ( quint8 ) payloadIn [ 0 ] ) ;
modeInfo m ;
2024-03-30 20:40:27 +00:00
m = queue - > getCache ( ( receiver ? funcSubMode : funcMainMode ) , receiver ) . value . value < modeInfo > ( ) ;
2021-02-10 17:32:56 +00:00
2023-11-26 14:47:17 +00:00
if ( m . mk = = modeAM )
2023-09-23 12:15:02 +01:00
{
2023-11-26 14:47:17 +00:00
calc = 200 + ( pass * 200 ) ;
2023-09-23 12:15:02 +01:00
}
2023-11-26 14:47:17 +00:00
else if ( pass < = 10 )
2021-02-10 17:32:56 +00:00
{
2023-11-26 14:47:17 +00:00
calc = 50 + ( pass * 50 ) ;
2023-02-04 09:57:12 -08:00
}
2023-11-26 14:47:17 +00:00
else {
calc = 600 + ( ( pass - 10 ) * 100 ) ;
2018-06-19 12:58:52 -07:00
}
2023-11-26 14:47:17 +00:00
value . setValue ( calc ) ;
2024-03-30 20:40:27 +00:00
//qInfo() << "Got filter width" << calc << "VFO" << receiver;
2023-11-26 14:47:17 +00:00
break ;
}
case funcDataModeWithFilter :
{
modeInfo m ;
// New format payload with mode+datamode+filter
2024-03-30 20:40:27 +00:00
m = parseMode ( uchar ( payloadIn [ 0 ] ) , uchar ( payloadIn [ 2 ] ) , receiver ) ;
2023-11-26 14:47:17 +00:00
m . data = uchar ( payloadIn [ 1 ] ) ;
2024-03-30 20:40:27 +00:00
m . VFO = selVFO_t ( receiver & 0x01 ) ;
2023-11-26 14:47:17 +00:00
value . setValue ( m ) ;
break ;
}
case funcAFMute :
// TODO add AF Mute
break ;
// 0x1a 0x05 various registers below are 2 byte (0-255) as uchar
case funcREFAdjust :
case funcREFAdjustFine :
case funcACCAModLevel :
case funcACCBModLevel :
case funcUSBModLevel :
case funcLANModLevel :
case funcSPDIFModLevel :
value . setValue ( bcdHexToUChar ( payloadIn [ 0 ] , payloadIn [ 1 ] ) ) ;
break ;
// Singla byte returned as uchar (0-99)
case funcDATAOffMod :
case funcDATA1Mod :
case funcDATA2Mod :
case funcDATA3Mod :
{
2023-12-17 19:41:22 +00:00
for ( auto & r : rigCaps . inputs )
2021-02-10 17:32:56 +00:00
{
2023-11-26 14:47:17 +00:00
if ( r . reg = = bcdHexToUChar ( payloadIn [ 0 ] ) )
{
value . setValue ( r ) ;
break ;
}
2021-02-10 17:32:56 +00:00
}
2023-11-26 14:47:17 +00:00
break ;
2023-05-15 10:53:52 +01:00
}
2023-11-26 14:47:17 +00:00
case funcDashRatio :
value . setValue ( bcdHexToUChar ( payloadIn [ 0 ] ) ) ;
break ;
// 0x1b register (tones)
case funcToneFreq :
case funcTSQLFreq :
case funcDTCSCode :
case funcCSQLCode :
value . setValue ( decodeTone ( payloadIn ) ) ;
break ;
// 0x1c register (bool)
case funcRitStatus :
case funcTransceiverStatus :
value . setValue ( static_cast < bool > ( payloadIn [ 0 ] ) ) ;
break ;
// tuner is 0-2
case funcTunerStatus :
value . setValue ( bcdHexToUChar ( payloadIn [ 0 ] ) ) ;
break ;
// 0x21 RIT:
case funcRITFreq :
2018-06-19 12:58:52 -07:00
{
2023-11-26 14:47:17 +00:00
/* PET NEEEDS FIXING */
short ritHz = 0 ;
freqt f ;
QByteArray longfreq ;
longfreq = payloadIn . mid ( 2 , 2 ) ;
longfreq . append ( QByteArray ( 3 , ' \x00 ' ) ) ;
f = parseFrequency ( longfreq , 3 ) ;
if ( payloadIn . length ( ) < 5 )
break ;
ritHz = f . Hz * ( ( payloadIn . at ( 4 ) = = ' \x01 ' ) ? - 1 : 1 ) ;
value . setValue ( ritHz ) ;
break ;
}
// 0x27
case funcScopeSubWaveData :
case funcScopeMainWaveData :
2018-06-19 12:58:52 -07:00
{
2023-11-26 14:47:17 +00:00
scopeData d ;
2024-03-30 20:40:27 +00:00
if ( parseSpectrum ( d , receiver ) )
2023-11-26 14:47:17 +00:00
value . setValue ( d ) ;
break ;
2018-06-19 12:58:52 -07:00
}
2023-11-26 14:47:17 +00:00
case funcScopeOnOff :
// confirming scope is on
case funcScopeDataOutput :
// confirming output enabled/disabled of wf data.
case funcScopeMainSub :
// This tells us whether we are receiving main or sub data
case funcScopeSingleDual :
// This tells us whether we are receiving single or dual scopes
2024-03-30 20:40:27 +00:00
//qInfo(logRig()) << "funcScopeSingleDual (" << receiver <<") " << static_cast<bool>(payloadIn[0]);
2023-11-26 14:47:17 +00:00
value . setValue ( static_cast < bool > ( payloadIn [ 0 ] ) ) ;
break ;
# if defined __GNUC__
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
# endif
case funcScopeSubMode :
2024-03-30 20:40:27 +00:00
receiver = 1 ;
2023-11-26 14:47:17 +00:00
case funcScopeMainMode :
// fixed or center
// [1] 0x14
// [2] 0x00
// [3] 0x00 (center), 0x01 (fixed), 0x02, 0x03
value . setValue ( static_cast < spectrumMode_t > ( uchar ( payloadIn [ 0 ] ) ) ) ;
break ;
case funcScopeSubSpan :
2024-03-30 20:40:27 +00:00
receiver = 1 ;
2023-11-26 14:47:17 +00:00
case funcScopeMainSpan :
{
freqt f = parseFrequency ( payloadIn , 3 ) ;
2023-12-17 19:41:22 +00:00
for ( auto & s : rigCaps . scopeCenterSpans )
2023-11-26 14:47:17 +00:00
{
if ( s . freq = = f . Hz )
{
value . setValue ( s ) ;
}
}
break ;
2023-09-23 11:37:55 +01:00
}
2023-11-26 14:47:17 +00:00
case funcScopeSubEdge :
2024-03-30 20:40:27 +00:00
receiver = 1 ;
2023-11-26 14:47:17 +00:00
case funcScopeMainEdge :
// read edge mode center in edge mode
// [1] 0x16
// [2] 0x01, 0x02, 0x03: Edge 1,2,3
value . setValue ( bcdHexToUChar ( payloadIn [ 0 ] ) ) ;
//emit haveScopeEdge((char)payloadIn[2]);
break ;
case funcScopeSubHold :
2024-03-30 20:40:27 +00:00
receiver = 1 ;
2023-11-26 14:47:17 +00:00
case funcScopeMainHold :
value . setValue ( static_cast < bool > ( payloadIn [ 0 ] ) ) ;
break ;
case funcScopeSubRef :
2024-03-30 20:40:27 +00:00
receiver = 1 ;
2023-11-26 14:47:17 +00:00
case funcScopeMainRef :
{
// scope reference level
// [1] 0x19
// [2] 0x00
// [3] 10dB digit, 1dB digit
// [4] 0.1dB digit, 0
// [5] 0x00 = +, 0x01 = -
unsigned char negative = payloadIn [ 2 ] ;
short ref = bcdHexToUInt ( payloadIn [ 0 ] , payloadIn [ 1 ] ) ;
ref = ref / 10 ;
if ( negative ) {
ref * = ( - 1 * negative ) ;
}
value . setValue ( ref ) ;
break ;
}
case funcScopeSubSpeed :
2024-03-30 20:40:27 +00:00
receiver = 1 ;
2023-11-26 14:47:17 +00:00
case funcScopeMainSpeed :
value . setValue ( static_cast < uchar > ( payloadIn [ 0 ] ) ) ;
break ;
case funcScopeSubVBW :
2024-03-30 20:40:27 +00:00
receiver = 1 ;
2023-11-26 14:47:17 +00:00
case funcScopeMainVBW :
break ;
case funcScopeSubRBW :
2024-03-30 20:40:27 +00:00
receiver = 1 ;
2023-11-26 14:47:17 +00:00
case funcScopeMainRBW :
break ;
# if defined __GNUC__
# pragma GCC diagnostic pop
# endif
case funcScopeFixedEdgeFreq :
case funcScopeDuringTX :
case funcScopeCenterType :
break ;
// 0x28
case funcVoiceTX :
break ;
//0x29 - Prefix certain commands with this to get/set certain values without changing current VFO
// If we use it for get commands, need to parse the \x29\x<VFO> first.
case funcMainSubPrefix :
break ;
case funcFB :
break ;
case funcFA :
2024-02-07 13:06:23 +00:00
{
qWarning ( logRig ( ) ) < < " Error (FA) received from rig, last command sent: " ;
QStringList messages = getHexArray ( lastCommandToRig ) ;
foreach ( auto msg , messages )
qWarning ( logRig ( ) ) < < msg ;
2023-11-26 14:47:17 +00:00
break ;
2024-02-07 13:06:23 +00:00
}
2023-11-26 14:47:17 +00:00
default :
qWarning ( logRig ( ) ) < < " Unhandled command received from rig " < < payloadIn . toHex ( ) . mid ( 0 , 10 ) < < " Contact support! " ;
break ;
2021-02-15 22:33:21 -08:00
}
2021-02-11 00:33:25 -08:00
2023-11-26 14:47:17 +00:00
if ( func ! = funcScopeMainWaveData
& & func ! = funcScopeSubWaveData
& & func ! = funcSMeter
& & func ! = funcCenterMeter
& & func ! = funcPowerMeter
& & func ! = funcSWRMeter
& & func ! = funcALCMeter
& & func ! = funcCompMeter
& & func ! = funcVdMeter
& & func ! = funcIdMeter )
2021-02-11 00:33:25 -08:00
{
2023-11-26 14:47:17 +00:00
// We do not log spectrum and meter data,
// as they tend to clog up any useful logging.
qDebug ( logRigTraffic ( ) ) < < " Received from radio: " ;
printHexNow ( payloadIn , logRigTraffic ( ) ) ;
2021-02-11 00:33:25 -08:00
}
2023-11-26 14:47:17 +00:00
# ifdef DEBUG_PARSE
averageParseTime + = currentParse ;
if ( lowParse > currentParse )
lowParse = currentParse ;
else if ( highParse < currentParse )
highParse = currentParse ;
2021-02-11 00:33:25 -08:00
2023-11-26 14:47:17 +00:00
numParseSamples + + ;
if ( lastParseReport . msecsTo ( QTime : : currentTime ( ) ) > = 10000 )
2023-05-12 00:24:01 +01:00
{
2023-11-26 14:47:17 +00:00
qInfo ( logRig ( ) ) < < QString ( " 10 second average command parse time %0 ns (low=%1, high=%2, num=%3: " ) . arg ( averageParseTime / numParseSamples ) . arg ( lowParse ) . arg ( highParse ) . arg ( numParseSamples ) ;
averageParseTime = 0 ;
numParseSamples = 0 ;
lowParse = 9999 ;
highParse = 0 ;
lastParseReport = QTime : : currentTime ( ) ;
2023-05-12 00:24:01 +01:00
}
2023-11-26 14:47:17 +00:00
# endif
2023-05-12 00:24:01 +01:00
2023-11-26 14:47:17 +00:00
if ( value . isValid ( ) & & queue ! = Q_NULLPTR ) {
2024-03-30 20:40:27 +00:00
queue - > receiveValue ( func , value , receiver ) ;
2023-11-26 14:47:17 +00:00
}
2023-05-12 00:24:01 +01:00
}
2023-11-26 14:47:17 +00:00
void rigCommander : : determineRigCaps ( )
2018-06-19 12:58:52 -07:00
{
2023-11-26 14:47:17 +00:00
// First clear all of the current settings
rigCaps . preamps . clear ( ) ;
rigCaps . attenuators . clear ( ) ;
rigCaps . inputs . clear ( ) ;
rigCaps . scopeCenterSpans . clear ( ) ;
rigCaps . bands . clear ( ) ;
rigCaps . modes . clear ( ) ;
rigCaps . commands . clear ( ) ;
rigCaps . commandsReverse . clear ( ) ;
rigCaps . antennas . clear ( ) ;
rigCaps . filters . clear ( ) ;
rigCaps . steps . clear ( ) ;
rigCaps . memParser . clear ( ) ;
rigCaps . satParser . clear ( ) ;
2024-02-09 17:08:04 +00:00
rigCaps . periodic . clear ( ) ;
2023-11-26 14:47:17 +00:00
// modelID should already be set!
while ( ! rigList . contains ( rigCaps . modelID ) )
2021-04-25 00:23:52 -07:00
{
2023-11-26 14:47:17 +00:00
if ( ! rigCaps . modelID ) {
qWarning ( logRig ( ) ) < < " No default rig definition found, cannot continue (sorry!) " ;
return ;
}
// Unknown rig, load default
qInfo ( logRig ( ) ) < < QString ( " No rig definition found for CI-V address: 0x%0, using defaults (some functions may not be available) " ) . arg ( rigCaps . modelID , 2 , 16 ) ;
rigCaps . modelID = 0 ;
2021-04-25 00:23:52 -07:00
}
2023-11-26 14:47:17 +00:00
rigCaps . filename = rigList . find ( rigCaps . modelID ) . value ( ) ;
QSettings * settings = new QSettings ( rigCaps . filename , QSettings : : Format : : IniFormat ) ;
2024-02-11 09:29:30 +00:00
# if (QT_VERSION < QT_VERSION_CHECK(6,0,0))
settings - > setIniCodec ( " UTF-8 " ) ;
# endif
2023-11-26 14:47:17 +00:00
if ( ! settings - > childGroups ( ) . contains ( " Rig " ) )
2023-03-17 23:35:40 +00:00
{
2023-11-26 14:47:17 +00:00
qWarning ( logRig ( ) ) < < rigCaps . filename < < " Cannot be loaded! " ;
return ;
2023-03-17 23:35:40 +00:00
}
2023-11-26 14:47:17 +00:00
settings - > beginGroup ( " Rig " ) ;
// Populate rigcaps
2021-03-22 00:11:43 -07:00
2023-11-26 14:47:17 +00:00
rigCaps . modelName = settings - > value ( " Model " , " " ) . toString ( ) ;
qInfo ( logRig ( ) ) < < QString ( " Loading Rig: %0 from %1 " ) . arg ( rigCaps . modelName , rigCaps . filename ) ;
2021-03-22 00:11:43 -07:00
2024-03-30 20:40:27 +00:00
rigCaps . numReceiver = settings - > value ( " NumberOfReceivers " , 1 ) . toUInt ( ) ;
2024-01-27 22:13:47 +00:00
rigCaps . numVFO = settings - > value ( " NumberOfVFOs " , 1 ) . toUInt ( ) ;
2023-11-26 14:47:17 +00:00
rigCaps . spectSeqMax = settings - > value ( " SpectrumSeqMax " , 0 ) . toUInt ( ) ;
rigCaps . spectAmpMax = settings - > value ( " SpectrumAmpMax " , 0 ) . toUInt ( ) ;
rigCaps . spectLenMax = settings - > value ( " SpectrumLenMax " , 0 ) . toUInt ( ) ;
2018-06-19 12:58:52 -07:00
2023-11-26 14:47:17 +00:00
rigCaps . hasSpectrum = settings - > value ( " HasSpectrum " , false ) . toBool ( ) ;
rigCaps . hasLan = settings - > value ( " HasLAN " , false ) . toBool ( ) ;
rigCaps . hasEthernet = settings - > value ( " HasEthernet " , false ) . toBool ( ) ;
rigCaps . hasWiFi = settings - > value ( " HasWiFi " , false ) . toBool ( ) ;
rigCaps . hasQuickSplitCommand = settings - > value ( " HasQuickSplit " , false ) . toBool ( ) ;
rigCaps . hasDD = settings - > value ( " HasDD " , false ) . toBool ( ) ;
rigCaps . hasDV = settings - > value ( " HasDV " , false ) . toBool ( ) ;
rigCaps . hasTransmit = settings - > value ( " HasTransmit " , false ) . toBool ( ) ;
rigCaps . hasFDcomms = settings - > value ( " HasFDComms " , false ) . toBool ( ) ;
rigCaps . hasCommand29 = settings - > value ( " HasCommand29 " , false ) . toBool ( ) ;
rigCaps . useRTSforPTT = settings - > value ( " UseRTSforPTT " , false ) . toBool ( ) ;
2018-06-19 12:58:52 -07:00
2023-11-26 14:47:17 +00:00
rigCaps . memGroups = settings - > value ( " MemGroups " , 0 ) . toUInt ( ) ;
rigCaps . memories = settings - > value ( " Memories " , 0 ) . toUInt ( ) ;
rigCaps . memStart = settings - > value ( " MemStart " , 1 ) . toUInt ( ) ;
rigCaps . memFormat = settings - > value ( " MemFormat " , " " ) . toString ( ) ;
rigCaps . satMemories = settings - > value ( " SatMemories " , 0 ) . toUInt ( ) ;
rigCaps . satFormat = settings - > value ( " SatFormat " , " " ) . toString ( ) ;
2023-09-22 19:06:09 +01:00
2023-11-26 14:47:17 +00:00
// If rig doesn't have FD comms, tell the commhandler early.
emit setHalfDuplex ( ! rigCaps . hasFDcomms ) ;
2023-05-03 13:38:06 +01:00
2023-11-26 14:47:17 +00:00
// Temporary QList to hold the function string lookup // I would still like to find a better way of doing this!
QHash < QString , funcs > funcsLookup ;
for ( int i = 0 ; i < NUMFUNCS ; i + + )
2023-05-03 13:38:06 +01:00
{
2023-11-26 14:47:17 +00:00
funcsLookup . insert ( funcString [ i ] . toUpper ( ) , funcs ( i ) ) ;
2023-05-03 13:38:06 +01:00
}
2023-11-26 14:47:17 +00:00
int numCommands = settings - > beginReadArray ( " Commands " ) ;
if ( numCommands = = 0 ) {
settings - > endArray ( ) ;
}
else {
for ( int c = 0 ; c < numCommands ; c + + )
{
settings - > setArrayIndex ( c ) ;
if ( funcsLookup . contains ( settings - > value ( " Type " , " **** " ) . toString ( ) . toUpper ( ) ) )
{
funcs func = funcsLookup . find ( settings - > value ( " Type " , " " ) . toString ( ) . toUpper ( ) ) . value ( ) ;
rigCaps . commands . insert ( func , funcType ( func , funcString [ int ( func ) ] ,
QByteArray : : fromHex ( settings - > value ( " String " , " " ) . toString ( ) . toUtf8 ( ) ) ,
settings - > value ( " Min " , 0 ) . toInt ( NULL ) , settings - > value ( " Max " , 0 ) . toInt ( NULL ) ,
settings - > value ( " Command29 " , false ) . toBool ( ) ) ) ;
2023-05-03 13:38:06 +01:00
2023-11-26 14:47:17 +00:00
rigCaps . commandsReverse . insert ( QByteArray : : fromHex ( settings - > value ( " String " , " " ) . toString ( ) . toUtf8 ( ) ) , func ) ;
} else {
qWarning ( logRig ( ) ) < < " **** Function " < < settings - > value ( " Type " , " " ) . toString ( ) < < " Not Found, rig file may be out of date? " ;
}
}
settings - > endArray ( ) ;
}
2023-05-03 13:38:06 +01:00
2024-02-09 17:08:04 +00:00
int numPeriodic = settings - > beginReadArray ( " Periodic " ) ;
if ( numPeriodic = = 0 ) {
qWarning ( logRig ( ) ) < < " No periodic commands defined, please check rigcaps file " ;
settings - > endArray ( ) ;
} else {
for ( int c = 0 ; c < numPeriodic ; c + + )
{
settings - > setArrayIndex ( c ) ;
funcs func = funcsLookup . find ( settings - > value ( " Command " , " " ) . toString ( ) . toUpper ( ) ) . value ( ) ;
if ( ! rigCaps . commands . contains ( func ) ) {
qWarning ( logRig ( ) ) < < " Cannot find periodic command " < < settings - > value ( " Command " , " " ) . toString ( ) < < " in rigcaps, ignoring " ;
} else {
rigCaps . periodic . append ( periodicType ( func ,
settings - > value ( " Priority " , " " ) . toString ( ) , priorityMap [ settings - > value ( " Priority " , " " ) . toString ( ) ] ,
settings - > value ( " VFO " , - 1 ) . toInt ( ) ) ) ;
}
}
settings - > endArray ( ) ;
}
2023-11-26 14:47:17 +00:00
int numModes = settings - > beginReadArray ( " Modes " ) ;
if ( numModes = = 0 ) {
settings - > endArray ( ) ;
}
else {
for ( int c = 0 ; c < numModes ; c + + )
2023-05-15 10:53:52 +01:00
{
2023-11-26 14:47:17 +00:00
settings - > setArrayIndex ( c ) ;
rigCaps . modes . push_back ( modeInfo ( rigMode_t ( settings - > value ( " Num " , 0 ) . toUInt ( ) ) ,
2024-01-28 09:42:50 +00:00
settings - > value ( " Reg " , 0 ) . toString ( ) . toUInt ( ) , settings - > value ( " Name " , " " ) . toString ( ) , settings - > value ( " Min " , 0 ) . toInt ( ) , settings - > value ( " Max " , 0 ) . toInt ( ) ) ) ;
2023-05-15 10:53:52 +01:00
}
2023-11-26 14:47:17 +00:00
settings - > endArray ( ) ;
2023-05-15 10:53:52 +01:00
}
2023-06-05 21:08:01 +01:00
2023-11-26 14:47:17 +00:00
int numSpans = settings - > beginReadArray ( " Spans " ) ;
if ( numSpans = = 0 ) {
settings - > endArray ( ) ;
}
else {
for ( int c = 0 ; c < numSpans ; c + + )
{
settings - > setArrayIndex ( c ) ;
rigCaps . scopeCenterSpans . push_back ( centerSpanData ( centerSpansType ( settings - > value ( " Num " , 0 ) . toUInt ( ) ) ,
settings - > value ( " Name " , " " ) . toString ( ) , settings - > value ( " Freq " , 0 ) . toUInt ( ) ) ) ;
}
settings - > endArray ( ) ;
2023-06-05 21:08:01 +01:00
}
2022-10-28 20:04:14 +01:00
2023-11-26 14:47:17 +00:00
int numInputs = settings - > beginReadArray ( " Inputs " ) ;
if ( numInputs = = 0 ) {
settings - > endArray ( ) ;
}
else {
for ( int c = 0 ; c < numInputs ; c + + )
{
settings - > setArrayIndex ( c ) ;
rigCaps . inputs . append ( rigInput ( inputTypes ( settings - > value ( " Num " , 0 ) . toUInt ( ) ) ,
2024-01-28 09:49:08 +00:00
settings - > value ( " Reg " , 0 ) . toString ( ) . toUInt ( ) , settings - > value ( " Name " , " " ) . toString ( ) ) ) ;
2023-11-26 14:47:17 +00:00
}
settings - > endArray ( ) ;
2023-07-23 11:20:13 +01:00
}
2023-05-24 19:50:01 +01:00
2023-11-26 14:47:17 +00:00
int numSteps = settings - > beginReadArray ( " Tuning Steps " ) ;
if ( numSteps = = 0 ) {
settings - > endArray ( ) ;
}
else {
for ( int c = 0 ; c < numSteps ; c + + )
{
settings - > setArrayIndex ( c ) ;
rigCaps . steps . push_back ( stepType ( settings - > value ( " Num " , 0 ) . toString ( ) . toUInt ( ) ,
settings - > value ( " Name " , " " ) . toString ( ) , settings - > value ( " Hz " , 0ULL ) . toULongLong ( ) ) ) ;
}
settings - > endArray ( ) ;
2023-05-24 19:50:01 +01:00
}
2023-06-05 21:08:01 +01:00
2023-11-26 14:47:17 +00:00
int numPreamps = settings - > beginReadArray ( " Preamps " ) ;
if ( numPreamps = = 0 ) {
settings - > endArray ( ) ;
}
else {
for ( int c = 0 ; c < numPreamps ; c + + )
{
settings - > setArrayIndex ( c ) ;
2024-01-28 09:49:08 +00:00
rigCaps . preamps . push_back ( genericType ( settings - > value ( " Num " , 0 ) . toString ( ) . toUInt ( ) , settings - > value ( " Name " , 0 ) . toString ( ) ) ) ;
2023-11-26 14:47:17 +00:00
}
settings - > endArray ( ) ;
}
2022-10-28 20:04:14 +01:00
2023-11-26 14:47:17 +00:00
int numAntennas = settings - > beginReadArray ( " Antennas " ) ;
if ( numAntennas = = 0 ) {
settings - > endArray ( ) ;
}
else {
for ( int c = 0 ; c < numAntennas ; c + + )
{
settings - > setArrayIndex ( c ) ;
2024-01-28 09:49:08 +00:00
rigCaps . antennas . push_back ( genericType ( settings - > value ( " Num " , 0 ) . toString ( ) . toUInt ( ) , settings - > value ( " Name " , 0 ) . toString ( ) ) ) ;
2022-10-28 20:04:14 +01:00
}
2023-11-26 14:47:17 +00:00
settings - > endArray ( ) ;
}
int numAttenuators = settings - > beginReadArray ( " Attenuators " ) ;
if ( numAttenuators = = 0 ) {
settings - > endArray ( ) ;
}
else {
for ( int c = 0 ; c < numAttenuators ; c + + )
2022-10-28 20:04:14 +01:00
{
2023-11-26 14:47:17 +00:00
settings - > setArrayIndex ( c ) ;
2024-02-07 13:06:23 +00:00
qDebug ( logRig ( ) ) < < " ** GOT ATTENUATOR " < < settings - > value ( " dB " , 0 ) . toString ( ) . toUInt ( ) ;
2023-11-26 14:47:17 +00:00
rigCaps . attenuators . push_back ( ( unsigned char ) settings - > value ( " dB " , 0 ) . toString ( ) . toUInt ( ) ) ;
2022-10-28 20:04:14 +01:00
}
2023-11-26 14:47:17 +00:00
settings - > endArray ( ) ;
}
int numFilters = settings - > beginReadArray ( " Filters " ) ;
if ( numFilters = = 0 ) {
settings - > endArray ( ) ;
}
else {
for ( int c = 0 ; c < numFilters ; c + + )
2022-10-28 20:04:14 +01:00
{
2023-11-26 14:47:17 +00:00
settings - > setArrayIndex ( c ) ;
2024-01-28 09:49:08 +00:00
rigCaps . filters . push_back ( filterType ( settings - > value ( " Num " , 0 ) . toString ( ) . toUInt ( ) , settings - > value ( " Name " , " " ) . toString ( ) , settings - > value ( " Modes " , 0 ) . toUInt ( ) ) ) ;
2022-10-28 20:04:14 +01:00
}
2023-11-26 14:47:17 +00:00
settings - > endArray ( ) ;
}
int numBands = settings - > beginReadArray ( " Bands " ) ;
if ( numBands = = 0 ) {
settings - > endArray ( ) ;
}
else {
for ( int c = 0 ; c < numBands ; c + + )
2022-10-28 20:04:14 +01:00
{
2023-11-26 14:47:17 +00:00
settings - > setArrayIndex ( c ) ;
availableBands band = availableBands ( settings - > value ( " Num " , 0 ) . toInt ( ) ) ;
quint64 start = settings - > value ( " Start " , 0ULL ) . toULongLong ( ) ;
quint64 end = settings - > value ( " End " , 0ULL ) . toULongLong ( ) ;
uchar bsr = static_cast < uchar > ( settings - > value ( " BSR " , 0 ) . toInt ( ) ) ;
double range = settings - > value ( " Range " , 0.0 ) . toDouble ( ) ;
int memGroup = settings - > value ( " MemoryGroup " , - 1 ) . toInt ( ) ;
rigCaps . bands . push_back ( bandType ( band , bsr , start , end , range , memGroup ) ) ;
rigCaps . bsr [ band ] = bsr ;
2024-02-07 13:06:23 +00:00
qDebug ( logRig ( ) ) < < " Adding Band " < < band < < " Start " < < start < < " End " < < end < < " BSR " < < QString : : number ( bsr , 16 ) ;
2022-10-28 20:04:14 +01:00
}
2023-11-26 14:47:17 +00:00
settings - > endArray ( ) ;
}
settings - > endGroup ( ) ;
delete settings ;
// Setup memory formats.
static QRegularExpression memFmtEx ( " %(?<flags>[-+#0]) ? ( ? < pos > \ \ d + | \ \ * ) ? ( ? : \ \ . ( ? < width > \ \ d + | \ \ * ) ) ? ( ? < spec > [ abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ] ) " ) ;
QRegularExpressionMatchIterator i = memFmtEx . globalMatch ( rigCaps . memFormat ) ;
while ( i . hasNext ( ) ) {
QRegularExpressionMatch qmatch = i . next ( ) ;
# if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
if ( qmatch . hasCaptured ( " spec " ) & & qmatch . hasCaptured ( " pos " ) & & qmatch . hasCaptured ( " width " ) ) {
# endif
rigCaps . memParser . append ( memParserFormat ( qmatch . captured ( " spec " ) . at ( 0 ) . toLatin1 ( ) , qmatch . captured ( " pos " ) . toInt ( ) , qmatch . captured ( " width " ) . toInt ( ) ) ) ;
}
# if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
}
# endif
QRegularExpressionMatchIterator i2 = memFmtEx . globalMatch ( rigCaps . satFormat ) ;
while ( i2 . hasNext ( ) ) {
QRegularExpressionMatch qmatch = i2 . next ( ) ;
# if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
if ( qmatch . hasCaptured ( " spec " ) & & qmatch . hasCaptured ( " pos " ) & & qmatch . hasCaptured ( " width " ) ) {
# endif
rigCaps . satParser . append ( memParserFormat ( qmatch . captured ( " spec " ) . at ( 0 ) . toLatin1 ( ) , qmatch . captured ( " pos " ) . toInt ( ) , qmatch . captured ( " width " ) . toInt ( ) ) ) ;
# if (QT_VERSION >= QT_VERSION_CHECK(6,0,0))
2022-10-28 20:04:14 +01:00
}
2023-11-26 14:47:17 +00:00
# endif
2023-06-05 21:08:01 +01:00
}
2023-05-15 10:53:52 +01:00
2023-11-26 14:47:17 +00:00
haveRigCaps = true ;
2023-12-18 10:47:16 +00:00
queue - > setRigCaps ( & rigCaps ) ;
2018-06-19 12:58:52 -07:00
2023-11-26 14:47:17 +00:00
// Copy received guid so we can recognise this radio.
memcpy ( rigCaps . guid , this - > guid , GUIDLEN ) ;
2018-11-16 22:19:44 -08:00
2023-11-26 14:47:17 +00:00
if ( ! usingNativeLAN )
2018-11-16 23:13:59 -08:00
{
2023-11-26 14:47:17 +00:00
if ( useRTSforPTT_isSet )
{
rigCaps . useRTSforPTT = useRTSforPTT_manual ;
}
comm - > setUseRTSforPTT ( rigCaps . useRTSforPTT ) ;
2018-11-16 23:13:59 -08:00
}
2023-11-26 14:47:17 +00:00
if ( lookingForRig )
2023-04-23 21:29:44 +01:00
{
2023-11-26 14:47:17 +00:00
lookingForRig = false ;
foundRig = true ;
2018-11-16 23:13:59 -08:00
2023-11-26 14:47:17 +00:00
qDebug ( logRig ( ) ) < < " ---Rig FOUND from broadcast query: " ;
this - > civAddr = incomingCIVAddr ; // Override and use immediately.
payloadPrefix = QByteArray ( " \xFE \xFE " ) ;
payloadPrefix . append ( civAddr ) ;
payloadPrefix . append ( ( char ) compCivAddr ) ;
// if there is a compile-time error, remove the following line, the "hex" part is the issue:
qInfo ( logRig ( ) ) < < " Using incomingCIVAddr: (int): " < < this - > civAddr < < " hex: " < < QString ( " 0x%1 " ) . arg ( this - > civAddr , 0 , 16 ) ;
emit discoveredRigID ( rigCaps ) ;
} else {
if ( ! foundRig )
{
emit discoveredRigID ( rigCaps ) ;
foundRig = true ;
}
emit haveRigID ( rigCaps ) ;
2023-04-23 21:29:44 +01:00
}
2021-04-07 23:35:24 -07:00
}
2024-03-30 20:40:27 +00:00
bool rigCommander : : parseSpectrum ( scopeData & d , uchar receiver )
2021-04-07 23:35:24 -07:00
{
2023-11-26 14:47:17 +00:00
bool ret = false ;
2021-04-07 23:35:24 -07:00
2023-11-26 14:47:17 +00:00
if ( ! haveRigCaps )
2023-04-23 21:29:44 +01:00
{
2023-11-26 14:47:17 +00:00
qDebug ( logRig ( ) ) < < " Spectrum received in rigCommander, but rigID is incomplete. " ;
return ret ;
2023-04-23 21:29:44 +01:00
}
2023-11-26 14:47:17 +00:00
if ( rigCaps . spectSeqMax = = 0 )
2023-04-23 21:29:44 +01:00
{
2023-11-26 14:47:17 +00:00
// there is a chance this will happen with rigs that support spectrum. Once our RigID query returns, we will parse correctly.
qInfo ( logRig ( ) ) < < " Warning: Spectrum sequence max was zero, yet spectrum was received. " ;
return ret ;
2023-04-23 21:29:44 +01:00
}
2021-04-07 23:35:24 -07:00
2024-03-30 20:40:27 +00:00
if ( receiver )
2023-11-26 14:47:17 +00:00
d = subScopeData ;
else
d = mainScopeData ;
// Here is what to expect:
// payloadIn[00] = '\x27';
// payloadIn[01] = '\x00';
// payloadIn[02] = '\x00';
//
// Example long: (sequences 2-10, 50 pixels)
// "INDEX: 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 "
// "DATA: 27 00 00 07 11 27 13 15 01 00 22 21 09 08 06 19 0e 20 23 25 2c 2d 17 27 29 16 14 1b 1b 21 27 1a 18 17 1e 21 1b 24 21 22 23 13 19 23 2f 2d 25 25 0a 0e 1e 20 1f 1a 0c fd "
// ^--^--(seq 7/11)
// ^-- start waveform data 0x00 to 0xA0, index 05 to 54
//
// Example medium: (sequence #11)
// "INDEX: 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 "
// "DATA: 27 00 00 11 11 0b 13 21 23 1a 1b 22 1e 1a 1d 13 21 1d 26 28 1f 19 1a 18 09 2c 2c 2c 1a 1b fd "
// Example short: (sequence #1) includes center/fixed mode at [05]. No pixels.
// "INDEX: 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 "
// "DATA: 27 00 00 01 11 01 00 00 00 14 00 00 00 35 14 00 00 fd "
// ^-- mode 00 (center) or 01 (fixed)
// ^--14.00 MHz lower edge
// ^-- 14.350 MHz upper edge
// ^-- possibly 00=in range 01 = out of range
// Note, the index used here, -1, matches the ICD in the owner's manual.
// Owner's manual + 1 = our index.
// divs: Mode: Waveinfo: Len: Comment:
// 2-10 var var 56 Minimum wave information w/waveform data
// 11 10 26 31 Minimum wave information w/waveform data
// 1 1 0 18 Only Wave Information without waveform data
freqt fStart ;
freqt fEnd ;
2024-03-30 20:40:27 +00:00
d . receiver = receiver ;
2023-11-26 14:47:17 +00:00
unsigned char sequence = bcdHexToUChar ( payloadIn [ 0 ] ) ;
unsigned char sequenceMax = bcdHexToUChar ( payloadIn [ 1 ] ) ;
int freqLen = 5 ;
// On the IC-905 10GHz+ uses 6 bytes for freq.
if ( rigCaps . modelID = = 0xAC & & ( payloadIn . size ( ) = = 491 | | payloadIn . size ( ) = = 16 ) ) {
freqLen = 6 ;
2023-04-23 21:29:44 +01:00
}
2021-04-07 23:35:24 -07:00
2023-11-26 14:47:17 +00:00
// Sequnce 2, index 05 is the start of data
// Sequence 11. index 05, is the last chunk
// Sequence 11, index 29, is the actual last pixel (it seems)
// It looks like the data length may be variable, so we need to detect it each time.
// start at payloadIn.length()-1 (to override the FD). Never mind, index -1 bad.
// chop off FD.
if ( sequence = = 1 )
2023-04-23 21:29:44 +01:00
{
2023-11-26 14:47:17 +00:00
// This should work on Qt5, but I need to test, use the switch below instead for now.
//d.mode = static_cast<spectrumMode_t>(payloadIn.at(2)); // 0=center, 1=fixed
switch ( payloadIn [ 2 ] )
{
case 0 :
d . mode = spectrumMode_t : : spectModeCenter ;
break ;
case 1 :
d . mode = spectrumMode_t : : spectModeFixed ;
break ;
case 2 :
d . mode = spectrumMode_t : : spectModeScrollC ;
break ;
case 3 :
d . mode = spectrumMode_t : : spectModeScrollF ;
break ;
default :
d . mode = spectrumMode_t : : spectModeUnknown ;
break ;
2023-04-23 21:29:44 +01:00
}
2021-04-07 23:35:24 -07:00
2023-11-26 14:47:17 +00:00
if ( d . mode ! = oldScopeMode )
{
// Modes:
// 0x00 Center
// 0x01 Fixed
// 0x02 Scroll-C
// 0x03 Scroll-F
oldScopeMode = d . mode ;
}
2022-01-04 18:34:34 +00:00
2023-11-26 14:47:17 +00:00
d . oor = ( bool ) payloadIn [ 3 + ( freqLen * 2 ) ] ;
if ( d . oor ) {
d . data = QByteArray ( rigCaps . spectLenMax , ' \0 ' ) ;
d . valid = true ;
return true ;
}
2022-01-04 18:34:34 +00:00
2023-11-26 14:47:17 +00:00
// clear wave information
d . data . clear ( ) ;
// For Fixed, and both scroll modes, the following produces correct information:
2024-03-30 20:40:27 +00:00
fStart = parseFreqData ( payloadIn . mid ( 3 , freqLen ) , receiver ) ;
2023-11-26 14:47:17 +00:00
d . startFreq = fStart . MHzDouble ;
2024-03-30 20:40:27 +00:00
fEnd = parseFreqData ( payloadIn . mid ( 3 + freqLen , freqLen ) , receiver ) ;
2023-11-26 14:47:17 +00:00
d . endFreq = fEnd . MHzDouble ;
if ( d . mode = = spectModeCenter )
{
// "center" mode, start is actual center, end is bandwidth.
d . startFreq - = d . endFreq ;
d . endFreq = d . startFreq + 2 * ( d . endFreq ) ;
}
if ( sequence = = sequenceMax ) // Must be a LAN packet.
{
d . data . append ( payloadIn . right ( payloadIn . length ( ) - 4 - ( freqLen * 2 ) ) ) ;
ret = true ;
}
//qInfo(logRig()) << "Spectrum Data received start:" << d.startFreq << "end:" << d.endFreq << "seq:" << sequence << "/" << sequenceMax << "mode:" << d.mode << "oor" << d.oor << "scopelen:" << d.data.size() << "length:" << payloadIn.length();
}
else if ( ( sequence > 1 ) & & ( sequence < sequenceMax ) )
2023-04-23 21:29:44 +01:00
{
2023-11-26 14:47:17 +00:00
// spectrum from index 05 to index 54, length is 55 per segment. Length is 56 total. Pixel data is 50 pixels.
// sequence numbers 2 through 10, 50 pixels each. Total after sequence 10 is 450 pixels.
d . data . insert ( d . data . length ( ) , payloadIn . right ( payloadIn . length ( ) - 2 ) ) ;
ret = false ;
//qInfo(logRig()) << "sequence: " << sequence << "spec index: " << (sequence-2)*55 << " payloadPosition: " << payloadIn.length() - 2 << " payload length: " << payloadIn.length();
} else if ( sequence = = sequenceMax )
{
// last spectrum, a little bit different (last 25 pixels). Total at end is 475 pixels (7300).
d . data . insert ( d . data . length ( ) , payloadIn . right ( payloadIn . length ( ) - 2 ) ) ;
ret = true ;
//qInfo(logRig()) << "sequence: " << sequence << " spec index: " << (sequence-2)*55 << " payloadPosition: " << payloadIn.length() - 2 << " payload length: " << payloadIn.length();
2023-04-23 21:29:44 +01:00
}
2023-11-26 14:47:17 +00:00
d . valid = ret ;
2022-01-04 18:34:34 +00:00
2023-11-26 14:47:17 +00:00
if ( ! ret ) {
// We need to temporarilly store the scope data somewhere.
2024-03-30 20:40:27 +00:00
if ( receiver )
2023-11-26 14:47:17 +00:00
subScopeData = d ;
else
mainScopeData = d ;
2023-04-23 21:29:44 +01:00
}
2023-11-26 14:47:17 +00:00
return ret ;
2022-01-04 18:34:34 +00:00
}
2023-11-26 14:47:17 +00:00
unsigned char rigCommander : : bcdHexToUChar ( unsigned char in )
2022-01-04 18:34:34 +00:00
{
2023-11-26 14:47:17 +00:00
unsigned char out = 0 ;
out = in & 0x0f ;
out + = ( ( in & 0xf0 ) > > 4 ) * 10 ;
return out ;
2022-01-04 18:34:34 +00:00
}
2023-11-26 14:47:17 +00:00
unsigned int rigCommander : : bcdHexToUInt ( unsigned char hundreds , unsigned char tensunits )
2022-01-04 18:34:34 +00:00
{
2023-11-26 14:47:17 +00:00
// convert:
// hex data: 0x41 0x23
// convert to uint:
// uchar: 4123
unsigned char thousands = ( ( hundreds & 0xf0 ) > > 4 ) ;
unsigned int rtnVal ;
rtnVal = ( hundreds & 0x0f ) * 100 ;
rtnVal + = ( ( tensunits & 0xf0 ) > > 4 ) * 10 ;
rtnVal + = ( tensunits & 0x0f ) ;
rtnVal + = thousands * 1000 ;
return rtnVal ;
2022-01-04 18:34:34 +00:00
}
2023-11-26 14:47:17 +00:00
unsigned char rigCommander : : bcdHexToUChar ( unsigned char hundreds , unsigned char tensunits )
2022-01-04 18:34:34 +00:00
{
2023-11-26 14:47:17 +00:00
// convert:
// hex data: 0x01 0x23
// convert to uchar:
// uchar: 123
unsigned char rtnVal ;
rtnVal = ( hundreds & 0x0f ) * 100 ;
rtnVal + = ( ( tensunits & 0xf0 ) > > 4 ) * 10 ;
rtnVal + = ( tensunits & 0x0f ) ;
return rtnVal ;
2022-01-04 18:34:34 +00:00
}
2023-11-26 14:47:17 +00:00
QByteArray rigCommander : : bcdEncodeInt ( unsigned int num )
2022-01-04 18:34:34 +00:00
{
2023-11-26 14:47:17 +00:00
if ( num > 9999 )
2023-04-23 21:29:44 +01:00
{
2023-11-26 14:47:17 +00:00
qInfo ( logRig ( ) ) < < __FUNCTION__ < < " Error, number is too big for four-digit conversion: " < < num ;
return QByteArray ( ) ;
2023-04-23 21:29:44 +01:00
}
2023-11-26 14:47:17 +00:00
char thousands = num / 1000 ;
char hundreds = ( num - ( 1000 * thousands ) ) / 100 ;
char tens = ( num - ( 1000 * thousands ) - ( 100 * hundreds ) ) / 10 ;
char units = ( num - ( 1000 * thousands ) - ( 100 * hundreds ) - ( 10 * tens ) ) ;
char b0 = hundreds | ( thousands < < 4 ) ;
char b1 = units | ( tens < < 4 ) ;
//qInfo(logRig()) << __FUNCTION__ << " encoding value " << num << " as hex:";
//printHex(QByteArray(b0), false, true);
//printHex(QByteArray(b1), false, true);
QByteArray result ;
result . append ( b0 ) . append ( b1 ) ;
return result ;
2022-01-04 18:34:34 +00:00
}
2023-11-26 14:47:17 +00:00
QByteArray rigCommander : : bcdEncodeChar ( unsigned char num )
2022-01-04 18:34:34 +00:00
{
2023-11-26 14:47:17 +00:00
if ( num > 99 )
2023-04-23 21:29:44 +01:00
{
2023-11-26 14:47:17 +00:00
qInfo ( logRig ( ) ) < < __FUNCTION__ < < " Error, number is too big for two-digit conversion: " < < num ;
return QByteArray ( ) ;
2023-04-23 21:29:44 +01:00
}
2023-11-26 14:47:17 +00:00
uchar tens = num / 10 ;
uchar units = num - ( 10 * tens ) ;
uchar b0 = units | ( tens < < 4 ) ;
//qInfo(logRig()) << __FUNCTION__ << " encoding value " << num << " as hex:";
//printHex(QByteArray(b0), false, true);
//printHex(QByteArray(b1), false, true);
QByteArray result ;
result . append ( b0 ) ;
return result ;
2022-01-04 18:34:34 +00:00
}
2023-11-26 14:47:17 +00:00
freqt rigCommander : : parseFrequency ( )
2022-01-04 18:34:34 +00:00
{
2023-11-26 14:47:17 +00:00
freqt freq ;
freq . Hz = 0 ;
freq . MHzDouble = 0 ;
// process payloadIn, which is stripped.
// float frequencyMhz
// payloadIn[04] = ; // XX MHz
// payloadIn[03] = ; // XX0 KHz
// payloadIn[02] = ; // X.X KHz
// payloadIn[01] = ; // . XX KHz
// printHex(payloadIn, false, true);
frequencyMhz = 0.0 ;
if ( payloadIn . length ( ) = = 7 )
2023-04-23 21:29:44 +01:00
{
2023-11-26 14:47:17 +00:00
// 7300 has these digits too, as zeros.
// IC-705 or IC-9700 with higher frequency data available.
frequencyMhz + = 100 * ( payloadIn [ 05 ] & 0x0f ) ;
frequencyMhz + = ( 1000 * ( ( payloadIn [ 05 ] & 0xf0 ) > > 4 ) ) ;
freq . Hz + = ( payloadIn [ 05 ] & 0x0f ) * 1E6 * 100 ;
freq . Hz + = ( ( payloadIn [ 05 ] & 0xf0 ) > > 4 ) * 1E6 * 1000 ;
2023-04-23 21:29:44 +01:00
}
2023-11-26 14:47:17 +00:00
freq . Hz + = ( payloadIn [ 04 ] & 0x0f ) * 1E6 ;
freq . Hz + = ( ( payloadIn [ 04 ] & 0xf0 ) > > 4 ) * 1E6 * 10 ;
frequencyMhz + = payloadIn [ 04 ] & 0x0f ;
frequencyMhz + = 10 * ( ( payloadIn [ 04 ] & 0xf0 ) > > 4 ) ;
// KHz land:
frequencyMhz + = ( ( payloadIn [ 03 ] & 0xf0 ) > > 4 ) / 10.0 ;
frequencyMhz + = ( payloadIn [ 03 ] & 0x0f ) / 100.0 ;
frequencyMhz + = ( ( payloadIn [ 02 ] & 0xf0 ) > > 4 ) / 1000.0 ;
frequencyMhz + = ( payloadIn [ 02 ] & 0x0f ) / 10000.0 ;
frequencyMhz + = ( ( payloadIn [ 01 ] & 0xf0 ) > > 4 ) / 100000.0 ;
frequencyMhz + = ( payloadIn [ 01 ] & 0x0f ) / 1000000.0 ;
freq . Hz + = payloadIn [ 01 ] & 0x0f ;
freq . Hz + = ( ( payloadIn [ 01 ] & 0xf0 ) > > 4 ) * 10 ;
freq . Hz + = ( payloadIn [ 02 ] & 0x0f ) * 100 ;
freq . Hz + = ( ( payloadIn [ 02 ] & 0xf0 ) > > 4 ) * 1000 ;
freq . Hz + = ( payloadIn [ 03 ] & 0x0f ) * 10000 ;
freq . Hz + = ( ( payloadIn [ 03 ] & 0xf0 ) > > 4 ) * 100000 ;
freq . MHzDouble = frequencyMhz ;
return freq ;
2022-01-04 18:34:34 +00:00
}
2023-11-26 14:47:17 +00:00
freqt rigCommander : : parseFrequencyRptOffset ( QByteArray data )
2022-01-04 18:34:34 +00:00
{
2023-11-26 14:47:17 +00:00
// VHF 600 KHz:
// DATA: 0c 00 60 00 fd
// INDEX: 00 01 02 03 04
// UHF 5 MHz:
// DATA: 0c 00 00 05 fd
// INDEX: 00 01 02 03 04
freqt f ;
f . Hz = 0 ;
f . Hz + = ( data [ 3 ] & 0x0f ) * 1E6 ; // 1 MHz
f . Hz + = ( ( data [ 3 ] & 0xf0 ) > > 4 ) * 1E6 * 10 ; // 10 MHz
f . Hz + = ( data [ 2 ] & 0x0f ) * 10E3 ; // 10 KHz
f . Hz + = ( ( data [ 2 ] & 0xf0 ) > > 4 ) * 100E3 ; // 100 KHz
f . Hz + = ( data [ 1 ] & 0x0f ) * 100 ; // 100 Hz
f . Hz + = ( ( data [ 1 ] & 0xf0 ) > > 4 ) * 1000 ; // 1 KHz
f . MHzDouble = f . Hz / 1E6 ;
f . VFO = activeVFO ;
return f ;
2022-01-04 18:34:34 +00:00
}
2023-11-26 14:47:17 +00:00
freqt rigCommander : : parseFrequency ( QByteArray data , unsigned char lastPosition )
2022-01-04 18:34:34 +00:00
{
2023-11-26 14:47:17 +00:00
// process payloadIn, which is stripped.
// float frequencyMhz
// payloadIn[04] = ; // XX MHz
// payloadIn[03] = ; // XX0 KHz
// payloadIn[02] = ; // X.X KHz
// payloadIn[01] = ; // . XX KHz
//printHex(data, false, true);
// TODO: Check length of data array prior to reading +/- position
// NOTE: This function was written on the IC-7300, which has no need for 100 MHz and 1 GHz.
// Therefore, this function has to go to position +1 to retrieve those numbers for the IC-9700.
freqt freqs ;
freqs . MHzDouble = 0 ;
freqs . Hz = 0 ;
// Does Frequency contain 100 MHz/1 GHz data?
if ( data . length ( ) > lastPosition + 3 )
2023-04-23 21:29:44 +01:00
{
2023-11-26 14:47:17 +00:00
freqs . Hz + = ( data [ lastPosition + 2 ] & 0x0f ) * 1E9 ; // 1 GHz
freqs . Hz + = ( ( data [ lastPosition + 2 ] & 0xf0 ) > > 4 ) * 1E9 * 10 ; // 10 GHz
}
if ( data . length ( ) > = lastPosition + 1 )
{
freqs . Hz + = ( data [ lastPosition + 1 ] & 0x0f ) * 1E6 * 100 ; // 100 MHz
freqs . Hz + = ( ( data [ lastPosition + 1 ] & 0xf0 ) > > 4 ) * 1E6 * 1000 ; // 1000 MHz
2023-04-23 21:29:44 +01:00
}
2022-01-04 18:34:34 +00:00
2023-11-26 14:47:17 +00:00
// Does Frequency contain VFO data? (\x25 command)
if ( lastPosition - 4 > = 0 & & ( quint8 ) data [ lastPosition - 4 ] < 0x02 )
2023-04-23 21:29:44 +01:00
{
2023-11-26 14:47:17 +00:00
freqs . VFO = ( selVFO_t ) ( quint8 ) data [ lastPosition - 4 ] ;
2023-04-23 21:29:44 +01:00
}
2023-11-26 14:47:17 +00:00
freqs . Hz + = ( data [ lastPosition ] & 0x0f ) * 1E6 ;
freqs . Hz + = ( ( data [ lastPosition ] & 0xf0 ) > > 4 ) * 1E6 * 10 ; // 10 MHz
freqs . Hz + = ( data [ lastPosition - 1 ] & 0x0f ) * 10E3 ; // 10 KHz
freqs . Hz + = ( ( data [ lastPosition - 1 ] & 0xf0 ) > > 4 ) * 100E3 ; // 100 KHz
freqs . Hz + = ( data [ lastPosition - 2 ] & 0x0f ) * 100 ; // 100 Hz
freqs . Hz + = ( ( data [ lastPosition - 2 ] & 0xf0 ) > > 4 ) * 1000 ; // 1 KHz
freqs . Hz + = ( data [ lastPosition - 3 ] & 0x0f ) * 1 ; // 1 Hz
freqs . Hz + = ( ( data [ lastPosition - 3 ] & 0xf0 ) > > 4 ) * 10 ; // 10 Hz
freqs . MHzDouble = ( double ) ( freqs . Hz / 1000000.0 ) ;
return freqs ;
2022-01-04 18:34:34 +00:00
}
2023-11-26 14:47:17 +00:00
2024-03-30 20:40:27 +00:00
freqt rigCommander : : parseFreqData ( QByteArray data , uchar receiver )
2022-01-04 18:34:34 +00:00
{
2023-11-26 14:47:17 +00:00
freqt freq ;
freq . Hz = parseFreqDataToInt ( data ) ;
freq . MHzDouble = freq . Hz / 1000000.0 ;
2024-03-30 20:40:27 +00:00
freq . VFO = selVFO_t ( receiver ) ;
2023-11-26 14:47:17 +00:00
return freq ;
2022-01-04 18:34:34 +00:00
}
2023-11-26 14:47:17 +00:00
quint64 rigCommander : : parseFreqDataToInt ( QByteArray data )
2022-01-04 18:34:34 +00:00
{
2023-11-26 14:47:17 +00:00
// Allow raw data to be parsed. Use a lookup table (pow10) for speed
// Should support VERY large or VERY small numbers!
quint64 val = 0 ;
for ( int i = 0 ; i < data . size ( ) * 2 ; i = i + 2 )
2023-04-23 21:29:44 +01:00
{
2023-11-26 14:47:17 +00:00
val + = ( data [ i / 2 ] & 0x0f ) * pow10 [ i ] ;
val + = ( ( data [ i / 2 ] & 0xf0 ) > > 4 ) * ( pow10 [ i + 1 ] ) ;
2023-04-23 21:29:44 +01:00
}
2023-11-26 14:47:17 +00:00
return val ;
2022-01-04 18:34:34 +00:00
}
2023-11-26 14:47:17 +00:00
2024-03-30 20:40:27 +00:00
modeInfo rigCommander : : parseMode ( quint8 mode , quint8 filter , uchar receiver )
2023-04-25 08:56:06 +01:00
{
2023-11-26 14:47:17 +00:00
modeInfo mi ;
bool found = false ;
2023-12-17 19:41:22 +00:00
for ( auto & m : rigCaps . modes )
2023-04-23 21:29:44 +01:00
{
2023-11-26 14:47:17 +00:00
if ( m . reg = = mode )
{
mi = modeInfo ( m ) ;
mi . filter = filter ;
found = true ;
break ;
}
2023-04-23 21:29:44 +01:00
}
2022-01-04 18:34:34 +00:00
2023-11-26 14:47:17 +00:00
if ( ! found ) {
qInfo ( logRig ( ) ) < < QString ( " parseMode() Couldn't find a matching mode %0 with filter %1 " ) . arg ( mode ) . arg ( filter ) ;
2023-04-23 21:29:44 +01:00
}
2022-01-04 18:34:34 +00:00
2023-11-26 14:47:17 +00:00
// We cannot query sub VFO width without command29.
if ( ! rigCaps . hasCommand29 )
2024-03-30 20:40:27 +00:00
receiver = 0 ;
2023-01-20 22:11:30 -08:00
2023-11-26 14:47:17 +00:00
cacheItem item ;
// Does the current mode support filterwidth?
if ( mi . bwMin > 0 & & mi . bwMax > 0 ) {
2024-03-30 20:40:27 +00:00
queue - > getCache ( funcFilterWidth , receiver ) ;
2023-04-23 21:29:44 +01:00
}
2023-01-20 23:23:47 -08:00
2023-11-26 14:47:17 +00:00
if ( item . value . isValid ( ) ) {
mi . pass = item . value . toInt ( ) ;
}
else
2023-04-23 21:29:44 +01:00
{
2023-11-26 14:47:17 +00:00
/* We haven't got a valid passband from the rig yet so we
need to create a ' fake ' one from default values
This will be replaced with a valid one if we get it */
if ( mi . mk = = modeCW | | mi . mk = = modeCW_R | | mi . mk = = modePSK | | mi . mk = = modePSK_R ) {
switch ( filter ) {
case 1 :
mi . pass = 1200 ;
break ;
case 2 :
mi . pass = 500 ;
break ;
case 3 :
mi . pass = 250 ;
break ;
}
}
else if ( mi . mk = = modeRTTY | | mi . mk = = modeRTTY_R )
{
switch ( filter ) {
case 1 :
mi . pass = 2400 ;
break ;
case 2 :
mi . pass = 500 ;
break ;
case 3 :
mi . pass = 250 ;
break ;
}
}
else if ( mi . mk = = modeAM )
{
switch ( filter ) {
case 1 :
mi . pass = 9000 ;
break ;
case 2 :
mi . pass = 6000 ;
break ;
case 3 :
mi . pass = 3000 ;
break ;
}
}
else if ( mi . mk = = modeFM )
{
switch ( filter ) {
case 1 :
mi . pass = 15000 ;
break ;
case 2 :
mi . pass = 10000 ;
break ;
case 3 :
mi . pass = 7000 ;
break ;
}
}
else { // SSB or unknown mode
switch ( filter ) {
case 1 :
mi . pass = 3000 ;
break ;
case 2 :
mi . pass = 2400 ;
break ;
case 3 :
mi . pass = 1800 ;
break ;
}
}
2023-04-23 21:29:44 +01:00
}
2023-11-26 14:47:17 +00:00
return mi ;
2022-01-04 18:34:34 +00:00
}
2023-11-26 14:47:17 +00:00
bool rigCommander : : parseMemory ( QVector < memParserFormat > * memParser , memoryType * mem )
2022-01-04 18:34:34 +00:00
{
2023-11-26 14:47:17 +00:00
// Parse the memory entry into a memoryType, set some defaults so we don't get an unitialized warning.
mem - > frequency . Hz = 0 ;
mem - > frequency . VFO = activeVFO ;
mem - > frequency . MHzDouble = 0.0 ;
mem - > frequencyB = mem - > frequency ;
mem - > duplexOffset = mem - > frequency ;
mem - > duplexOffsetB = mem - > frequency ;
mem - > scan = 0xfe ;
memset ( mem - > UR , 0x0 , sizeof ( mem - > UR ) ) ;
memset ( mem - > URB , 0x0 , sizeof ( mem - > UR ) ) ;
memset ( mem - > R1 , 0x0 , sizeof ( mem - > R1 ) ) ;
memset ( mem - > R1B , 0x0 , sizeof ( mem - > R1B ) ) ;
memset ( mem - > R2 , 0x0 , sizeof ( mem - > R2 ) ) ;
memset ( mem - > R2B , 0x0 , sizeof ( mem - > R2B ) ) ;
memset ( mem - > name , 0x0 , sizeof ( mem - > name ) ) ;
// We need to add 2 characters so that the parser works!
payloadIn . insert ( 0 , " ** " ) ;
2023-12-17 19:41:22 +00:00
for ( auto & parse : * memParser ) {
2023-11-26 14:47:17 +00:00
// non-existant memory is short so send what we have so far.
if ( payloadIn . size ( ) < ( parse . pos + 1 + parse . len ) ) {
return true ;
}
QByteArray data = payloadIn . mid ( parse . pos + 1 , parse . len ) ;
//qInfo(logRig()) << "Parse:" << data.toHex() << "pos" << parse.pos;
switch ( parse . spec )
{
case ' a ' :
if ( parse . len = = 1 ) {
mem - > group = bcdHexToUChar ( data [ 0 ] ) ;
}
else
{
mem - > group = bcdHexToUChar ( data [ 0 ] , data [ 1 ] ) ;
}
break ;
case ' b ' :
mem - > channel = bcdHexToUChar ( data [ 0 ] , data [ 1 ] ) ;
break ;
case ' c ' :
mem - > scan = data [ 0 ] ;
break ;
case ' d ' : // combined split and scan
mem - > split = quint8 ( data [ 0 ] > > 4 & 0x0f ) ;
mem - > scan = quint8 ( data [ 0 ] & 0x0f ) ;
break ;
case ' e ' :
mem - > vfo = data [ 0 ] ;
break ;
case ' E ' :
mem - > vfoB = data [ 0 ] ;
break ;
case ' f ' :
mem - > frequency . Hz = parseFreqDataToInt ( data ) ;
break ;
case ' F ' :
mem - > frequencyB . Hz = parseFreqDataToInt ( data ) ;
break ;
case ' g ' :
mem - > mode = data [ 0 ] ;
break ;
case ' G ' :
mem - > modeB = data [ 0 ] ;
break ;
case ' h ' :
mem - > filter = data [ 0 ] ;
break ;
case ' H ' :
mem - > filterB = data [ 0 ] ;
break ;
case ' i ' : // single datamode
mem - > datamode = data [ 0 ] ;
break ;
case ' I ' : // single datamode
mem - > datamodeB = data [ 0 ] ;
break ;
case ' j ' : // combined duplex and tonemode
mem - > duplex = duplexMode_t ( quint8 ( data [ 0 ] > > 4 & 0x0f ) ) ;
mem - > tonemode = quint8 ( quint8 ( data [ 0 ] & 0x0f ) ) ;
break ;
case ' J ' : // combined duplex and tonemodeB
mem - > duplexB = duplexMode_t ( ( data [ 0 ] > > 4 & 0x0f ) ) ;
mem - > tonemodeB = data [ 0 ] & 0x0f ;
break ;
case ' k ' : // combined datamode and tonemode
mem - > datamode = ( quint8 ( data [ 0 ] > > 4 & 0x0f ) ) ;
mem - > tonemode = data [ 0 ] & 0x0f ;
break ;
case ' K ' : // combined datamode and tonemode
mem - > datamodeB = ( quint8 ( data [ 0 ] > > 4 & 0x0f ) ) ;
mem - > tonemodeB = data [ 0 ] & 0x0f ;
break ;
case ' l ' : // tonemode
mem - > tonemode = data [ 0 ] & 0x0f ;
break ;
case ' L ' : // tonemode
mem - > tonemodeB = data [ 0 ] & 0x0f ;
break ;
case ' m ' :
mem - > dsql = ( quint8 ( data [ 0 ] > > 4 & 0x0f ) ) ;
break ;
case ' M ' :
mem - > dsqlB = ( quint8 ( data [ 0 ] > > 4 & 0x0f ) ) ;
break ;
case ' n ' :
mem - > tone = bcdHexToUInt ( data [ 1 ] , data [ 2 ] ) ; // First byte is not used
break ;
case ' N ' :
mem - > toneB = bcdHexToUInt ( data [ 1 ] , data [ 2 ] ) ; // First byte is not used
break ;
case ' o ' :
mem - > tsql = bcdHexToUInt ( data [ 1 ] , data [ 2 ] ) ; // First byte is not used
break ;
case ' O ' :
mem - > tsqlB = bcdHexToUInt ( data [ 1 ] , data [ 2 ] ) ; // First byte is not used
break ;
case ' p ' :
mem - > dtcsp = ( quint8 ( data [ 0 ] > > 3 & 0x02 ) | quint8 ( data [ 0 ] & 0x01 ) ) ;
break ;
case ' P ' :
mem - > dtcspB = ( quint8 ( data [ 0 ] > > 3 & 0x10 ) | quint8 ( data [ 0 ] & 0x01 ) ) ;
break ;
case ' q ' :
mem - > dtcs = bcdHexToUInt ( data [ 0 ] , data [ 1 ] ) ;
break ;
case ' Q ' :
mem - > dtcsB = bcdHexToUInt ( data [ 0 ] , data [ 1 ] ) ;
break ;
case ' r ' :
mem - > dvsql = bcdHexToUInt ( data [ 0 ] , data [ 1 ] ) ;
break ;
case ' R ' :
mem - > dvsqlB = bcdHexToUInt ( data [ 0 ] , data [ 1 ] ) ;
break ;
case ' s ' :
mem - > duplexOffset . Hz = parseFreqDataToInt ( data ) ;
break ;
case ' S ' :
mem - > duplexOffsetB . Hz = parseFreqDataToInt ( data ) ;
break ;
case ' t ' :
memcpy ( mem - > UR , data , sizeof ( mem - > UR ) ) ;
break ;
case ' T ' :
memcpy ( mem - > URB , data , sizeof ( mem - > UR ) ) ;
break ;
case ' u ' :
memcpy ( mem - > R1 , data , sizeof ( mem - > R1 ) ) ;
break ;
case ' U ' :
memcpy ( mem - > R1B , data , sizeof ( mem - > R1 ) ) ;
break ;
case ' v ' :
memcpy ( mem - > R2 , data , sizeof ( mem - > R2 ) ) ;
break ;
case ' V ' :
memcpy ( mem - > R2B , data , sizeof ( mem - > R2 ) ) ;
break ;
case ' z ' :
if ( mem - > scan = = 0xfe )
mem - > scan = 0 ;
memcpy ( mem - > name , data , sizeof ( mem - > name ) ) ;
break ;
default :
qInfo ( ) < < " Parser didn't match! " < < " spec: " < < parse . spec < < " pos: " < < parse . pos < < " len " < < parse . len ;
break ;
}
2023-04-23 21:29:44 +01:00
}
2023-11-26 14:47:17 +00:00
return true ;
2022-01-04 18:34:34 +00:00
}
2018-11-19 23:42:34 -08:00
void rigCommander : : getRigID ( )
{
2023-04-25 08:56:06 +01:00
QByteArray payload ;
2023-04-26 18:41:38 +01:00
if ( getCommand ( funcTransceiverId , payload ) )
2023-04-23 21:29:44 +01:00
{
prepDataAndSend ( payload ) ;
} else {
// If we haven't got this command yet, need to use the default one!
QByteArray payload = " \x19 \x00 " ;
prepDataAndSend ( payload ) ;
}
2018-11-19 23:42:34 -08:00
}
2021-11-06 23:59:03 -07:00
void rigCommander : : setRigID ( unsigned char rigID )
{
// This function overrides radio model detection.
// It can be used for radios without Rig ID commands,
// or to force a specific radio model
2022-11-23 22:45:29 -08:00
qInfo ( logRig ( ) ) < < " Setting rig ID to: (int) " < < ( int ) rigID ;
2021-11-06 23:59:03 -07:00
lookingForRig = true ;
foundRig = false ;
2021-11-07 00:24:08 -07:00
// needed because this is a fake message and thus the value is uninitialized
// this->civAddr comes from how rigCommander is setup and should be accurate.
this - > incomingCIVAddr = this - > civAddr ;
2023-05-24 19:50:01 +01:00
if ( rigList . contains ( rigID ) ) this - > model = rigID ;
2021-11-06 23:59:03 -07:00
rigCaps . modelID = rigID ;
2023-05-24 19:50:01 +01:00
rigCaps . model = this - > model ;
2021-11-06 23:59:03 -07:00
determineRigCaps ( ) ;
2023-05-24 19:50:01 +01:00
//this->model = determineRadioModel(rigID);
//rigCaps.model = determineRadioModel(rigID);
2021-11-06 23:59:03 -07:00
}
2021-02-27 00:37:00 +00:00
void rigCommander : : changeLatency ( const quint16 value )
2021-02-10 17:32:56 +00:00
{
2021-02-27 00:37:00 +00:00
emit haveChangeLatency ( value ) ;
2021-02-10 17:32:56 +00:00
}
2018-06-19 12:58:52 -07:00
2022-01-21 19:23:32 +00:00
void rigCommander : : radioSelection ( QList < radio_cap_packet > radios )
{
emit requestRadioSelection ( radios ) ;
}
2023-12-18 15:48:17 +00:00
void rigCommander : : radioUsage ( quint8 radio , bool admin , quint8 busy , QString user , QString ip ) {
emit setRadioUsage ( radio , admin , busy , user , ip ) ;
2022-01-21 19:23:32 +00:00
}
2022-01-23 17:54:40 +00:00
void rigCommander : : setCurrentRadio ( quint8 radio ) {
2022-01-21 23:58:18 +00:00
emit selectedRadio ( radio ) ;
}
2022-01-21 19:23:32 +00:00
2023-11-26 16:29:22 +00:00
void rigCommander : : setAfGain ( unsigned char level )
{
if ( udp = = Q_NULLPTR )
{
QByteArray payload ;
if ( getCommand ( funcAfGain , payload , level ) )
{
payload . append ( bcdEncodeInt ( level ) ) ;
prepDataAndSend ( payload ) ;
}
}
else {
emit haveSetVolume ( level ) ;
localVolume = level ;
}
}
2021-08-04 20:49:32 +01:00
2018-06-19 12:58:52 -07:00
void rigCommander : : getDebug ( )
{
// generic debug function for development.
emit getMoreDebug ( ) ;
}
2021-02-17 00:00:28 -08:00
void rigCommander : : printHex ( const QByteArray & pdata )
{
printHex ( pdata , false , true ) ;
}
2018-06-19 12:58:52 -07:00
void rigCommander : : printHex ( const QByteArray & pdata , bool printVert , bool printHoriz )
{
2021-02-23 21:21:22 +00:00
qDebug ( logRig ( ) ) < < " ---- Begin hex dump -----: " ;
2018-06-19 12:58:52 -07:00
QString sdata ( " DATA: " ) ;
QString index ( " INDEX: " ) ;
QStringList strings ;
for ( int i = 0 ; i < pdata . length ( ) ; i + + )
{
strings < < QString ( " [%1]: %2 " ) . arg ( i , 8 , 10 , QChar ( ' 0 ' ) ) . arg ( ( unsigned char ) pdata [ i ] , 2 , 16 , QChar ( ' 0 ' ) ) ;
sdata . append ( QString ( " %1 " ) . arg ( ( unsigned char ) pdata [ i ] , 2 , 16 , QChar ( ' 0 ' ) ) ) ;
index . append ( QString ( " %1 " ) . arg ( i , 2 , 10 , QChar ( ' 0 ' ) ) ) ;
}
if ( printVert )
{
for ( int i = 0 ; i < strings . length ( ) ; i + + )
{
//sdata = QString(strings.at(i));
2021-02-23 21:21:22 +00:00
qDebug ( logRig ( ) ) < < strings . at ( i ) ;
2018-06-19 12:58:52 -07:00
}
}
if ( printHoriz )
{
2021-02-23 21:21:22 +00:00
qDebug ( logRig ( ) ) < < index ;
qDebug ( logRig ( ) ) < < sdata ;
2018-06-19 12:58:52 -07:00
}
2021-02-23 21:21:22 +00:00
qDebug ( logRig ( ) ) < < " ----- End hex dump ----- " ;
2018-06-19 12:58:52 -07:00
}
2021-02-18 09:14:41 +00:00
void rigCommander : : dataFromServer ( QByteArray data )
{
2022-04-20 13:35:23 +01:00
//qInfo(logRig()) << "***************** emit dataForComm()" << data;
2021-02-18 09:14:41 +00:00
emit dataForComm ( data ) ;
}
2022-01-26 09:49:52 +00:00
quint8 * rigCommander : : getGUID ( ) {
return guid ;
}
2018-06-19 12:58:52 -07:00
2024-03-30 20:40:27 +00:00
uchar rigCommander : : makeFilterWidth ( ushort pass , uchar receiver )
2023-05-12 00:24:01 +01:00
{
2023-06-05 21:08:01 +01:00
unsigned char calc ;
2024-03-30 20:40:27 +00:00
modeInfo mi = queue - > getCache ( ( receiver = = 1 ? funcSubMode : funcMainMode ) , receiver ) . value . value < modeInfo > ( ) ;
2023-06-05 21:08:01 +01:00
if ( mi . mk = = modeAM ) { // AM 0-49
calc = quint16 ( ( pass / 200 ) - 1 ) ;
if ( calc > 49 )
calc = 49 ;
}
else if ( pass > = 600 ) // SSB/CW/PSK 10-40 (10-31 for RTTY)
{
calc = quint16 ( ( pass / 100 ) + 4 ) ;
if ( ( ( calc > 31 ) & & ( mi . mk = = modeRTTY | | mi . mk = = modeRTTY_R ) ) )
{
calc = 31 ;
}
else if ( calc > 40 ) {
calc = 40 ;
}
}
else { // SSB etc 0-9
calc = quint16 ( ( pass / 50 ) - 1 ) ;
}
char tens = ( calc / 10 ) ;
char units = ( calc - ( 10 * tens ) ) ;
char b1 = ( units ) | ( tens < < 4 ) ;
return b1 ;
2023-05-12 00:24:01 +01:00
}
2024-03-30 20:40:27 +00:00
void rigCommander : : receiveCommand ( funcs func , QVariant value , uchar receiver )
2023-05-12 00:24:01 +01:00
{
//qInfo() << "Got command:" << funcString[func];
int val = INT_MIN ;
2023-05-24 19:50:01 +01:00
if ( value . isValid ( ) & & value . canConvert < int > ( ) ) {
// Used to validate payload, otherwise ignore.
val = value . value < int > ( ) ;
2023-05-12 00:24:01 +01:00
//qInfo(logRig()) << "Got value" << QString(value.typeName());
2023-05-26 19:11:36 +01:00
if ( func = = funcMemoryContents | | func = = funcMemoryClear | | func = = funcMemoryWrite | | func = = funcMemoryMode )
2023-05-24 19:50:01 +01:00
{
// Strip out group number from memory for validation purposes.
2023-09-22 19:06:09 +01:00
qInfo ( logRig ( ) ) < < " Memory Command " < < funcString [ func ] < < " with valuetype " < < QString ( value . typeName ( ) ) ;
2023-05-24 19:50:01 +01:00
val = val & 0xffff ;
}
}
if ( func = = funcSendCW )
{
val = value . value < QString > ( ) . length ( ) ;
2024-02-05 09:33:42 -08:00
qDebug ( logRig ( ) ) < < " Send CW received " ;
2023-05-24 19:50:01 +01:00
}
if ( func = = funcAfGain & & value . isValid ( ) & & udp ! = Q_NULLPTR ) {
// Ignore the AF Gain command, just queue it for processing
emit haveSetVolume ( static_cast < uchar > ( value . toInt ( ) ) ) ;
2023-05-25 23:17:54 +01:00
queue - > receiveValue ( func , value , false ) ;
2023-05-24 19:50:01 +01:00
return ;
2023-05-12 00:24:01 +01:00
}
2023-05-24 19:50:01 +01:00
// Need to work out what to do with older dual-VFO rigs.
2024-03-30 20:40:27 +00:00
/*
if ( ( func = = funcMainFreq | | func = = funcSubFreq ) & & ! rigCaps . commands . contains ( func ) )
2023-05-24 19:50:01 +01:00
{
if ( value . isValid ( ) )
func = funcFreqSet ;
else
func = funcFreqGet ;
2024-03-30 20:40:27 +00:00
} else if ( ( func = = funcMainMode | | func = = funcSubMode ) & & ! rigCaps . commands . contains ( func ) )
2023-05-24 19:50:01 +01:00
{
if ( value . isValid ( ) )
func = funcModeSet ;
else
func = funcModeGet ;
2024-03-30 20:40:27 +00:00
} else
*/
if ( func = = funcSelectVFO ) {
2023-05-12 00:24:01 +01:00
// Special command
2024-01-29 14:20:31 +00:00
vfo_t v = value . value < vfo_t > ( ) ;
2024-03-30 20:40:27 +00:00
func = ( v = = vfoA ) ? funcVFOASelect : ( v = = vfoB ) ? funcVFOBSelect : ( v = vfoMain ) ? funcVFOMainSelect : funcVFOSubSelect ;
2023-05-12 00:24:01 +01:00
value . clear ( ) ;
2023-05-24 19:50:01 +01:00
val = INT_MIN ;
2023-05-12 00:24:01 +01:00
}
QByteArray payload ;
2024-03-30 20:40:27 +00:00
if ( getCommand ( func , payload , val , receiver ) )
2023-05-12 00:24:01 +01:00
{
if ( value . isValid ( ) )
{
if ( ! strcmp ( value . typeName ( ) , " bool " ) )
{
payload . append ( value . value < bool > ( ) ) ;
}
2023-05-25 23:17:54 +01:00
else if ( ! strcmp ( value . typeName ( ) , " QString " ) )
2023-05-24 19:50:01 +01:00
{
QString text = value . value < QString > ( ) ;
2023-10-30 21:29:09 +00:00
if ( func = = funcSendCW )
2023-05-24 19:50:01 +01:00
{
QByteArray textData = text . 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 ) | |
2023-10-30 21:29:09 +00:00
( p = = 0x40 ) | | ( p = = 0x20 ) | | p = = 0xff )
2023-05-24 19:50:01 +01:00
{
// Allowed character, continue
} else {
qWarning ( logRig ( ) ) < < " Invalid character detected in CW message at position " < < c < < " , the character is " < < text . at ( c ) ;
textData [ c ] = 0x3F ; // "?"
}
}
payload . append ( textData ) ;
2024-02-05 09:33:42 -08:00
qDebug ( logRig ( ) ) < < " Sending CW: payload: " < < payload . toHex ( ' ' ) ;
2023-05-24 19:50:01 +01:00
}
}
2023-05-12 00:24:01 +01:00
else if ( ! strcmp ( value . typeName ( ) , " uchar " ) )
{
2023-11-26 14:16:05 +00:00
payload . append ( bcdEncodeChar ( value . value < uchar > ( ) ) ) ;
2024-02-05 09:33:42 -08:00
qDebug ( logRig ( ) ) < < " **** setting uchar value " < < funcString [ func ] < < " val " < < value . value < uchar > ( ) ;
2023-05-12 00:24:01 +01:00
}
else if ( ! strcmp ( value . typeName ( ) , " ushort " ) )
{
2023-06-05 21:08:01 +01:00
if ( func = = funcFilterWidth ) {
2024-03-30 20:40:27 +00:00
payload . append ( makeFilterWidth ( value . value < ushort > ( ) , receiver ) ) ;
//qInfo() << "Setting filter width" << value.value<ushort>() << "VFO" << receiver << "hex" << payload.toHex();
2023-06-05 21:08:01 +01:00
2023-09-26 12:33:20 +01:00
}
2023-10-30 21:29:09 +00:00
else if ( func = = funcKeySpeed ) {
ushort wpm = round ( ( value . value < ushort > ( ) - 6 ) * ( 6.071 ) ) ;
payload . append ( bcdEncodeInt ( wpm ) ) ;
}
else if ( func = = funcCwPitch ) {
ushort pitch = 0 ;
pitch = ceil ( ( value . value < ushort > ( ) - 300 ) * ( 255.0 / 600.0 ) ) ;
payload . append ( bcdEncodeInt ( pitch ) ) ;
}
2023-09-26 12:33:20 +01:00
else {
2023-05-12 00:24:01 +01:00
payload . append ( bcdEncodeInt ( value . value < ushort > ( ) ) ) ;
2023-09-26 12:33:20 +01:00
}
2023-05-12 00:24:01 +01:00
}
2023-09-26 12:33:20 +01:00
else if ( ! strcmp ( value . typeName ( ) , " short " ) & & func = = funcRITFreq )
2023-05-24 19:50:01 +01:00
{
// Currently only used for RIT (I think)
bool isNegative = false ;
short val = value . value < short > ( ) ;
2024-03-25 19:02:17 +00:00
qDebug ( ) < < " Setting RIT to " < < val ;
2023-05-24 19:50:01 +01:00
if ( val < 0 )
{
isNegative = true ;
val * = - 1 ;
}
freqt f ;
QByteArray freqBytes ;
f . Hz = val ;
freqBytes = makeFreqPayload ( f ) ;
freqBytes . truncate ( 2 ) ;
payload . append ( freqBytes ) ;
payload . append ( QByteArray ( 1 , ( char ) isNegative ) ) ;
}
2023-05-12 00:24:01 +01:00
else if ( ! strcmp ( value . typeName ( ) , " uint " ) & & ( func = = funcMemoryContents | | func = = funcMemoryMode ) )
{
2023-09-22 19:06:09 +01:00
qInfo ( logRig ( ) ) < < " Get Memory Contents " < < ( value . value < uint > ( ) & 0xffff ) ;
2023-12-18 11:22:16 +00:00
qInfo ( logRig ( ) ) < < " Get Memory Group (if exists) " < < ( value . value < uint > ( ) > > 16 & 0xffff ) ;
2023-05-12 00:24:01 +01:00
// Format is different for all radios!
2023-12-18 15:48:17 +00:00
if ( func = = funcMemoryContents ) {
for ( auto & parse : rigCaps . memParser ) {
// If "a" exists, break out of the loop as soon as we have the value.
if ( parse . spec = = ' a ' ) {
if ( parse . len = = 1 ) {
payload . append ( bcdEncodeChar ( value . value < uint > ( ) > > 16 & 0xff ) ) ;
}
else if ( parse . len = = 2 )
{
payload . append ( bcdEncodeInt ( value . value < uint > ( ) > > 16 & 0xffff ) ) ;
}
break ;
2023-05-12 00:24:01 +01:00
}
}
}
payload . append ( bcdEncodeInt ( value . value < uint > ( ) & 0xffff ) ) ;
}
2023-09-22 19:06:09 +01:00
else if ( ! strcmp ( value . typeName ( ) , " memoryType " ) ) {
// We need to iterate through memParser to build the correct format
bool finished = false ;
char nul = 0x0 ;
uchar ffchar = 0xff ;
QVector < memParserFormat > parser ;
memoryType mem = value . value < memoryType > ( ) ;
if ( mem . sat )
{
parser = rigCaps . satParser ;
}
else
{
parser = rigCaps . memParser ;
}
// Format is different for all radios!
2023-12-17 19:41:22 +00:00
for ( auto & parse : parser ) {
2023-09-22 19:06:09 +01:00
switch ( parse . spec )
{
case ' a ' :
if ( parse . len = = 1 ) {
payload . append ( mem . group ) ;
}
else if ( parse . len = = 2 )
{
payload . append ( bcdEncodeInt ( mem . group ) ) ;
}
break ;
case ' b ' :
payload . append ( bcdEncodeInt ( mem . channel ) ) ;
break ;
case ' c ' :
// Are we deleting the memory?
if ( mem . del ) {
payload . append ( ffchar ) ;
finished = true ;
break ;
} else {
payload . append ( mem . scan ) ;
}
break ;
case ' d ' : // combined split and scan
payload . append ( quint8 ( ( mem . split < < 4 & 0xf0 ) | ( mem . scan & 0x0f ) ) ) ;
break ;
case ' e ' :
payload . append ( mem . vfo ) ;
break ;
case ' E ' :
payload . append ( mem . vfoB ) ;
break ;
case ' f ' :
if ( mem . del ) {
payload . append ( ffchar ) ;
finished = true ;
break ;
} else {
payload . append ( makeFreqPayload ( mem . frequency ) ) ;
}
break ;
case ' F ' :
payload . append ( makeFreqPayload ( mem . frequencyB ) ) ;
break ;
case ' g ' :
payload . append ( mem . mode ) ;
break ;
case ' G ' :
payload . append ( mem . modeB ) ;
break ;
case ' h ' :
payload . append ( mem . filter ) ;
break ;
case ' H ' :
payload . append ( mem . filterB ) ;
break ;
case ' i ' : // single datamode
payload . append ( mem . datamode ) ;
break ;
case ' I ' :
payload . append ( mem . datamodeB ) ;
break ;
case ' j ' : // combined duplex and tonemode
payload . append ( ( mem . duplex < < 4 ) | mem . tonemode ) ;
break ;
case ' J ' : // combined duplex and tonemode
payload . append ( ( mem . duplexB < < 4 ) | mem . tonemodeB ) ;
break ;
case ' k ' : // combined datamode and tonemode
payload . append ( ( mem . datamode < < 4 & 0xf0 ) | ( mem . tonemode & 0x0f ) ) ;
break ;
case ' K ' : // combined datamode and tonemode
payload . append ( ( mem . datamodeB < < 4 & 0xf0 ) | ( mem . tonemodeB & 0x0f ) ) ;
break ;
case ' l ' : // tonemode
payload . append ( mem . tonemode ) ;
break ;
case ' L ' :
payload . append ( mem . tonemodeB ) ;
break ;
case ' m ' :
payload . append ( mem . dsql < < 4 ) ;
break ;
case ' M ' :
payload . append ( mem . dsqlB < < 4 ) ;
break ;
case ' n ' :
payload . append ( nul ) ;
payload . append ( bcdEncodeInt ( mem . tone ) ) ;
break ;
case ' N ' :
payload . append ( nul ) ;
payload . append ( bcdEncodeInt ( mem . toneB ) ) ;
break ;
case ' o ' :
payload . append ( nul ) ;
payload . append ( bcdEncodeInt ( mem . tsql ) ) ;
break ;
case ' O ' :
payload . append ( nul ) ;
payload . append ( bcdEncodeInt ( mem . tsqlB ) ) ;
break ;
case ' p ' :
payload . append ( ( mem . dtcsp < < 3 & 0x10 ) | ( mem . dtcsp & 0x01 ) ) ;
break ;
case ' P ' :
payload . append ( ( mem . dtcspB < < 3 & 0x10 ) | ( mem . dtcspB & 0x01 ) ) ;
break ;
case ' q ' :
payload . append ( bcdEncodeInt ( mem . dtcs ) ) ;
break ;
case ' Q ' :
payload . append ( bcdEncodeInt ( mem . dtcsB ) ) ;
break ;
case ' r ' :
payload . append ( mem . dvsql ) ;
break ;
case ' R ' :
payload . append ( mem . dvsqlB ) ;
break ;
case ' s ' :
payload . append ( makeFreqPayload ( mem . duplexOffset ) . mid ( 1 , 3 ) ) ;
break ;
case ' S ' :
payload . append ( makeFreqPayload ( mem . duplexOffsetB ) . mid ( 1 , 3 ) ) ;
break ;
case ' t ' :
payload . append ( QByteArray ( mem . UR ) . leftJustified ( parse . len , ' ' , true ) ) ;
break ;
case ' T ' :
payload . append ( QByteArray ( mem . URB ) . leftJustified ( parse . len , ' ' , true ) ) ;
break ;
case ' u ' :
payload . append ( QByteArray ( mem . R1 ) . leftJustified ( parse . len , ' ' , true ) ) ;
break ;
case ' U ' :
payload . append ( QByteArray ( mem . R1B ) . leftJustified ( parse . len , ' ' , true ) ) ;
break ;
case ' v ' :
payload . append ( QByteArray ( mem . R2 ) . leftJustified ( parse . len , ' ' , true ) ) ;
break ;
case ' V ' :
payload . append ( QByteArray ( mem . R2B ) . leftJustified ( parse . len , ' ' , true ) ) ;
break ;
case ' z ' :
payload . append ( QByteArray ( mem . name ) . leftJustified ( parse . len , ' ' , true ) ) ;
break ;
default :
break ;
}
if ( finished )
break ;
}
qInfo ( logRig ( ) ) < < " Writing memory: " < < payload . toHex ( ' ' ) ;
}
2023-07-16 10:08:28 +01:00
else if ( ! strcmp ( value . typeName ( ) , " int " ) & & ( func = = funcScopeMainRef | | func = = funcScopeSubRef ) )
{
bool isNegative = false ;
int level = value . value < int > ( ) ;
if ( level < 0 )
{
isNegative = true ;
level * = - 1 ;
}
payload . append ( bcdEncodeInt ( level * 10 ) ) ;
payload . append ( static_cast < unsigned char > ( isNegative ) ) ;
}
2023-05-15 13:47:45 +01:00
else if ( ! strcmp ( value . typeName ( ) , " modeInfo " ) )
2023-05-12 00:24:01 +01:00
{
if ( func = = funcDataModeWithFilter )
{
2024-01-28 09:42:50 +00:00
payload . append ( bcdEncodeChar ( value . value < modeInfo > ( ) . data ) ) ;
2023-05-15 13:47:45 +01:00
if ( value . value < modeInfo > ( ) . data ! = 0 )
payload . append ( value . value < modeInfo > ( ) . filter ) ;
2023-05-12 00:24:01 +01:00
} else {
2024-01-28 09:42:50 +00:00
payload . append ( bcdEncodeChar ( value . value < modeInfo > ( ) . reg ) ) ;
2024-03-30 20:40:27 +00:00
if ( func = = funcMainMode | | func = = funcSubMode | | func = = funcSelectedMode | | func = = funcUnselectedMode )
2023-05-15 13:47:45 +01:00
payload . append ( value . value < modeInfo > ( ) . data ) ;
payload . append ( value . value < modeInfo > ( ) . filter ) ;
2023-05-12 00:24:01 +01:00
}
}
else if ( ! strcmp ( value . typeName ( ) , " freqt " ) )
{
if ( func = = funcSendFreqOffset ) {
payload . append ( makeFreqPayload ( value . value < freqt > ( ) ) . mid ( 1 , 3 ) ) ;
} else {
payload . append ( makeFreqPayload ( value . value < freqt > ( ) ) ) ;
}
}
2023-05-15 10:53:52 +01:00
else if ( ! strcmp ( value . typeName ( ) , " antennaInfo " ) )
{
2024-01-28 09:49:08 +00:00
payload . append ( bcdEncodeChar ( value . value < antennaInfo > ( ) . antenna ) ) ;
2023-05-24 19:50:01 +01:00
if ( rigCaps . commands . contains ( funcRXAntenna ) )
payload . append ( value . value < antennaInfo > ( ) . rx ) ;
2023-05-15 10:53:52 +01:00
}
else if ( ! strcmp ( value . typeName ( ) , " rigInput " ) )
{
payload . append ( bcdEncodeChar ( value . value < rigInput > ( ) . reg ) ) ;
}
2023-05-24 19:50:01 +01:00
else if ( ! strcmp ( value . typeName ( ) , " spectrumBounds " ) )
{
spectrumBounds s = value . value < spectrumBounds > ( ) ;
uchar range = 1 ;
2024-01-21 20:36:52 +00:00
for ( const bandType & band : rigCaps . bands )
2023-05-24 19:50:01 +01:00
{
if ( band . range ! = 0.0 & & s . start > band . range )
range + + ;
}
payload . append ( range ) ;
payload . append ( s . edge ) ;
payload . append ( makeFreqPayload ( s . start ) ) ;
payload . append ( makeFreqPayload ( s . end ) ) ;
qInfo ( ) < < " Bounds " < < range < < s . edge < < s . start < < s . end < < payload . toHex ( ) ;
}
else if ( ! strcmp ( value . typeName ( ) , " duplexMode_t " ) )
{
payload . append ( static_cast < uchar > ( value . value < duplexMode_t > ( ) ) ) ;
}
else if ( ! strcmp ( value . typeName ( ) , " spectrumMode_t " ) )
{
payload . append ( static_cast < uchar > ( value . value < spectrumMode_t > ( ) ) ) ;
}
else if ( ! strcmp ( value . typeName ( ) , " centerSpanData " ) )
{
centerSpanData span = value . value < centerSpanData > ( ) ;
double freq = double ( span . freq / 1000000.0 ) ;
payload . append ( makeFreqPayload ( freq ) ) ;
}
else if ( ! strcmp ( value . typeName ( ) , " toneInfo " ) )
{
toneInfo t = value . value < toneInfo > ( ) ;
payload . append ( encodeTone ( t . tone , t . tinv , t . rinv ) ) ;
}
2023-05-26 18:38:40 +01:00
else if ( ! strcmp ( value . typeName ( ) , " bandStackType " ) )
{
bandStackType bsr = value . value < bandStackType > ( ) ;
payload . append ( bsr . band ) ;
payload . append ( bsr . regCode ) ; // [01...03]. 01 = latest, 03 = oldest
2023-09-22 19:06:09 +01:00
qInfo ( logRig ( ) ) < < " Sending BSR, Band Code: " < < bsr . band < < " Register Code: " < < bsr . regCode < < " (Sent: " < < payload . toHex ( ' ' ) < < " ) " ;
2023-05-26 18:38:40 +01:00
}
2023-05-12 00:24:01 +01:00
else
{
qInfo ( logRig ( ) ) < < " Got unknown value type " < < QString ( value . typeName ( ) ) ;
2023-05-24 19:50:01 +01:00
return ;
2023-05-12 00:24:01 +01:00
}
2023-05-24 19:50:01 +01:00
// This was a set command, so queue a get straight after to retrieve the updated value
// will fail on some commands so they would need to be added here:
2023-10-30 21:29:09 +00:00
if ( func ! = funcScopeFixedEdgeFreq & & func ! = funcSpeech & & func ! = funcBandStackReg & & func ! = funcMemoryContents & & func ! = funcSendCW )
2023-09-22 19:06:09 +01:00
{
2024-03-30 20:40:27 +00:00
queue - > addUnique ( priorityImmediate , func , false , receiver ) ;
2023-09-22 19:06:09 +01:00
}
2023-05-12 00:24:01 +01:00
}
prepDataAndSend ( payload ) ;
}
else
{
2023-05-24 19:50:01 +01:00
qDebug ( logRig ( ) ) < < " cachingQueue(): unimplemented command " < < funcString [ func ] ;
2023-05-12 00:24:01 +01:00
}
}
2018-06-19 12:58:52 -07:00