kopia lustrzana https://gitlab.com/eliggett/wfview
Initial commit.
commit
4d86ab11cc
|
@ -0,0 +1,103 @@
|
|||
#include "commhandler.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
commHandler::commHandler()
|
||||
{
|
||||
//constructor
|
||||
// grab baud rate and other comm port details
|
||||
// if they need to be changed later, please
|
||||
// destroy this and create a new one.
|
||||
|
||||
port = new QSerialPort();
|
||||
|
||||
// The following should become arguments and/or functions
|
||||
baudrate = 115200;
|
||||
stopbits = 1;
|
||||
portName = "/dev/ttyUSB0";
|
||||
|
||||
setupComm(); // basic parameters
|
||||
openPort();
|
||||
|
||||
connect(port, SIGNAL(readyRead()), this, SLOT(receiveDataIn()));
|
||||
|
||||
}
|
||||
|
||||
commHandler::~commHandler()
|
||||
{
|
||||
this->closePort();
|
||||
}
|
||||
|
||||
|
||||
void commHandler::setupComm()
|
||||
{
|
||||
port->setPortName(portName);
|
||||
port->setBaudRate(baudrate);
|
||||
port->setStopBits(QSerialPort::OneStop);// OneStop is other option
|
||||
}
|
||||
|
||||
void commHandler::receiveDataFromUserToRig(const QByteArray &data)
|
||||
{
|
||||
sendDataOut(data);
|
||||
}
|
||||
|
||||
void commHandler::sendDataOut(const QByteArray &writeData)
|
||||
{
|
||||
|
||||
mutex.lock();
|
||||
quint64 bytesWritten;
|
||||
|
||||
// sned out data
|
||||
//port.send() or whatever
|
||||
bytesWritten = port->write(writeData);
|
||||
|
||||
//qDebug() << "bytesWritten: " << bytesWritten << " length of byte array: " << writeData.length() << " size of byte array: " << writeData.size();
|
||||
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
void commHandler::receiveDataIn()
|
||||
{
|
||||
// connected to comm port data signal
|
||||
// inPortData.append(port->readAll());
|
||||
|
||||
inPortData = port->readAll();
|
||||
|
||||
// qDebug() << "Data: " << inPortData;
|
||||
emit haveDataFromPort(inPortData);
|
||||
}
|
||||
|
||||
void commHandler::openPort()
|
||||
{
|
||||
bool success;
|
||||
// port->open();
|
||||
success = port->open(QIODevice::ReadWrite);
|
||||
if(success)
|
||||
{
|
||||
isConnected = true;
|
||||
qDebug() << "Opened port!";
|
||||
return;
|
||||
} else {
|
||||
// debug?
|
||||
qDebug() << "Could not open serial port.";
|
||||
isConnected = false;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void commHandler::closePort()
|
||||
{
|
||||
port->close();
|
||||
isConnected = false;
|
||||
}
|
||||
|
||||
void commHandler::debugThis()
|
||||
{
|
||||
qDebug() << "comm debug called.";
|
||||
|
||||
inPortData = port->readAll();
|
||||
emit haveDataFromPort(inPortData);
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
#ifndef COMMHANDLER_H
|
||||
#define COMMHANDLER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <QMutex>
|
||||
#include <QDataStream>
|
||||
#include <QtSerialPort/QSerialPort>
|
||||
|
||||
// This class abstracts the comm port in a useful way and connects to
|
||||
// the command creator and command parser.
|
||||
|
||||
class commHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
commHandler();
|
||||
~commHandler();
|
||||
|
||||
private slots:
|
||||
void receiveDataIn();
|
||||
void receiveDataFromUserToRig(const QByteArray &data);
|
||||
void debugThis();
|
||||
|
||||
signals:
|
||||
void haveTextMessage(QString message); // status, debug
|
||||
void sendDataOutToPort(const QByteArray &writeData);
|
||||
void haveDataFromPort(QByteArray data); // emit this when we have data, connect to rigcommander
|
||||
|
||||
private:
|
||||
void setupComm();
|
||||
void openPort();
|
||||
void closePort();
|
||||
|
||||
void sendDataOut(const QByteArray &writeData);
|
||||
void debugMe();
|
||||
void hexPrint();
|
||||
|
||||
//QDataStream stream;
|
||||
QByteArray outPortData;
|
||||
QByteArray inPortData;
|
||||
|
||||
//QDataStream outStream;
|
||||
//QDataStream inStream;
|
||||
|
||||
unsigned char buffer[256];
|
||||
|
||||
QString portName;
|
||||
QSerialPort *port;
|
||||
qint32 baudrate;
|
||||
unsigned char stopbits;
|
||||
|
||||
|
||||
bool isConnected; // port opened
|
||||
mutable QMutex mutex;
|
||||
};
|
||||
|
||||
#endif // COMMHANDLER_H
|
|
@ -0,0 +1,14 @@
|
|||
#include "wfmain.h"
|
||||
#include <QApplication>
|
||||
|
||||
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
wfmain w;
|
||||
w.show();
|
||||
|
||||
return a.exec();
|
||||
}
|
|
@ -0,0 +1,625 @@
|
|||
#include "rigcommander.h"
|
||||
#include <QDebug>
|
||||
|
||||
|
||||
//
|
||||
// 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:
|
||||
// echo "w \0xFE\0xFE\0x094\0xE0\0x27\0x11\0x00\0xFD" | rigctl -m 373 -r /dev/ttyUSB0 -s 115200 -vvvvv
|
||||
|
||||
// Note: When sending \x00, must use QByteArray.setRawData()
|
||||
|
||||
|
||||
rigCommander::rigCommander()
|
||||
{
|
||||
// construct
|
||||
civAddr = 0x94; // address of the radio. Decimal is 148.
|
||||
setCIVAddr(civAddr);
|
||||
//payloadPrefix = QByteArray("\xFE\xFE\x94\xE0");
|
||||
payloadPrefix = QByteArray("\xFE\xFE");
|
||||
payloadPrefix.append(civAddr);
|
||||
payloadPrefix.append("\xE0");
|
||||
|
||||
payloadSuffix = QByteArray("\xFD");
|
||||
comm = new commHandler();
|
||||
|
||||
// data from the comm port to the program:
|
||||
connect(comm, SIGNAL(haveDataFromPort(QByteArray)), this, SLOT(handleNewData(QByteArray)));
|
||||
|
||||
// data from the program to the comm port:
|
||||
connect(this, SIGNAL(dataForComm(QByteArray)), comm, SLOT(receiveDataFromUserToRig(QByteArray)));
|
||||
|
||||
connect(this, SIGNAL(getMoreDebug()), comm, SLOT(debugThis()));
|
||||
}
|
||||
|
||||
rigCommander::~rigCommander()
|
||||
{
|
||||
delete comm;
|
||||
}
|
||||
|
||||
void rigCommander::process()
|
||||
{
|
||||
// new thread enters here. Do nothing.
|
||||
}
|
||||
|
||||
void rigCommander::prepDataAndSend(QByteArray data)
|
||||
{
|
||||
data.prepend(payloadPrefix);
|
||||
//printHex(data, false, true);
|
||||
data.append(payloadSuffix);
|
||||
//qDebug() << "Final payload in rig commander to be sent to rig: ";
|
||||
//printHex(data, false, true);
|
||||
emit dataForComm(data);
|
||||
}
|
||||
|
||||
void rigCommander::enableSpectOutput()
|
||||
{
|
||||
QByteArray payload("\x27\x11\x01");
|
||||
prepDataAndSend(payload);
|
||||
}
|
||||
|
||||
void rigCommander::disableSpectOutput()
|
||||
{
|
||||
QByteArray payload;
|
||||
payload.setRawData("\x27\x11\x00", 3);
|
||||
prepDataAndSend(payload);
|
||||
}
|
||||
|
||||
void rigCommander::enableSpectrumDisplay()
|
||||
{
|
||||
// 27 10 01
|
||||
QByteArray payload("\x27\x10\x01");
|
||||
prepDataAndSend(payload);
|
||||
}
|
||||
|
||||
void rigCommander::disableSpectrumDisplay()
|
||||
{
|
||||
// 27 10 00
|
||||
QByteArray payload;
|
||||
payload.setRawData("\x27\x10\x00", 3);
|
||||
prepDataAndSend(payload);
|
||||
}
|
||||
|
||||
void rigCommander::setSpectrumBounds()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void rigCommander::setScopeEdge(char edge)
|
||||
{
|
||||
// 1 2 or 3
|
||||
// 27 16 00 0X
|
||||
if((edge <1) || (edge >3))
|
||||
return;
|
||||
QByteArray payload;
|
||||
payload.setRawData("\x27\x16\x00", 3);
|
||||
payload.append(edge);
|
||||
prepDataAndSend(payload);
|
||||
}
|
||||
|
||||
void rigCommander::setScopeSpan(char span)
|
||||
{
|
||||
// See ICD, page 165, "19-12".
|
||||
// 2.5k = 0
|
||||
// 5k = 2, etc.
|
||||
if((span <1 ) || (span >7))
|
||||
return;
|
||||
|
||||
QByteArray payload;
|
||||
double freq; // MHz
|
||||
payload.setRawData("\x27\x15\x00", 3);
|
||||
// next 6 bytes are the frequency
|
||||
switch(span)
|
||||
{
|
||||
case 0:
|
||||
// 2.5k
|
||||
freq = 2.5E-3;
|
||||
break;
|
||||
case 1:
|
||||
// 5k
|
||||
freq = 5.0E-3;
|
||||
break;
|
||||
case 2:
|
||||
freq = 10.0E-3;
|
||||
break;
|
||||
case 3:
|
||||
freq = 25.0E-3;
|
||||
break;
|
||||
case 4:
|
||||
freq = 50.0E-3;
|
||||
break;
|
||||
case 5:
|
||||
freq = 100.0E-3;
|
||||
break;
|
||||
case 6:
|
||||
freq = 250.0E-3;
|
||||
break;
|
||||
case 7:
|
||||
freq = 500.0E-3;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
payload.append( makeFreqPayload(freq));
|
||||
payload.append("\x00");
|
||||
printHex(payload, false, true);
|
||||
prepDataAndSend(payload);
|
||||
}
|
||||
|
||||
void rigCommander::setSpectrumCenteredMode(bool centerEnable)
|
||||
{
|
||||
QByteArray specModePayload;
|
||||
if(centerEnable)
|
||||
{
|
||||
specModePayload.setRawData("\x27\x14\x00\x00", 4);
|
||||
} else {
|
||||
specModePayload.setRawData("\x27\x14\x00\x01", 4);
|
||||
}
|
||||
prepDataAndSend(specModePayload);
|
||||
}
|
||||
|
||||
void rigCommander::setFrequency(double freq)
|
||||
{
|
||||
QByteArray freqPayload = makeFreqPayload(freq);
|
||||
QByteArray cmdPayload;
|
||||
|
||||
cmdPayload.append(freqPayload);
|
||||
cmdPayload.prepend('\x00');
|
||||
|
||||
printHex(cmdPayload, false, true);
|
||||
prepDataAndSend(cmdPayload);
|
||||
}
|
||||
|
||||
QByteArray rigCommander::makeFreqPayload(double freq)
|
||||
{
|
||||
quint64 freqInt = (quint64) (freq * 1E6);
|
||||
|
||||
QByteArray result;
|
||||
unsigned char a;
|
||||
int numchars = 5;
|
||||
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);
|
||||
}
|
||||
//qDebug() << "encoded frequency for " << freq << " as int " << freqInt;
|
||||
//printHex(result, false, true);
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
void rigCommander::setMode(char mode)
|
||||
{
|
||||
QByteArray payload;
|
||||
if((mode >=0) && (mode < 10))
|
||||
{
|
||||
// valid
|
||||
payload.setRawData("\x06", 1); // cmd 06 will apply the default filter, no need to specify.
|
||||
payload.append(mode);
|
||||
prepDataAndSend(payload);
|
||||
}
|
||||
}
|
||||
|
||||
void rigCommander::getFrequency()
|
||||
{
|
||||
// figure out frequency and then respond with haveFrequency();
|
||||
// send request to radio
|
||||
// 1. make the data
|
||||
QByteArray payload("\x03");
|
||||
prepDataAndSend(payload);
|
||||
}
|
||||
|
||||
void rigCommander::getMode()
|
||||
{
|
||||
QByteArray payload("\x04");
|
||||
prepDataAndSend(payload);
|
||||
}
|
||||
|
||||
void rigCommander::getDataMode()
|
||||
{
|
||||
QByteArray payload("\x1A\x06");
|
||||
prepDataAndSend(payload);
|
||||
}
|
||||
|
||||
void rigCommander::setCIVAddr(unsigned char civAddr)
|
||||
{
|
||||
this->civAddr = civAddr;
|
||||
}
|
||||
|
||||
void rigCommander::handleNewData(const QByteArray &data)
|
||||
{
|
||||
parseData(data);
|
||||
}
|
||||
|
||||
void rigCommander::parseData(QByteArray data)
|
||||
{
|
||||
|
||||
// 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)
|
||||
|
||||
//qDebug() << "Data received: ";
|
||||
//printHex(data, false, true);
|
||||
if(data.length() < 4)
|
||||
{
|
||||
if(data.length())
|
||||
{
|
||||
qDebug() << "Data length too short: " << data.length() << " bytes. Data:";
|
||||
printHex(data, false, true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(!data.startsWith("\xFE\xFE"))
|
||||
{
|
||||
qDebug() << "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'))
|
||||
{
|
||||
data.prepend('\xFE');
|
||||
qDebug() << "Warning: Working with prepended data stream.";
|
||||
parseData(payloadIn);
|
||||
return;
|
||||
} else {
|
||||
qDebug() << "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;
|
||||
}
|
||||
}
|
||||
|
||||
if((unsigned char)data[02] == civAddr)
|
||||
{
|
||||
// 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);
|
||||
//qDebug() << "Trimmed off echo:";
|
||||
//printHex(payloadIn, false, true);
|
||||
parseData(payloadIn);
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
// //qDebug() << "Trimmed off echo:";
|
||||
// //printHex(payloadIn, false, true);
|
||||
// parseData(payloadIn);
|
||||
// break;
|
||||
case '\xE0':
|
||||
// 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);
|
||||
parseCommand();
|
||||
break;
|
||||
case '\x00':
|
||||
// data send initiated by the rig due to user control
|
||||
// extract the payload out and parse.
|
||||
payloadIn = data.right(data.length() - 4);
|
||||
parseCommand();
|
||||
break;
|
||||
default:
|
||||
// could be for other equipment on the CIV network.
|
||||
// just drop for now.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void rigCommander::parseCommand()
|
||||
{
|
||||
// note: data already is trimmed of the beginning FE FE E0 94 stuff.
|
||||
|
||||
// printHex(data, false, true);
|
||||
//payloadIn = data;
|
||||
switch(payloadIn[00])
|
||||
{
|
||||
|
||||
case 00:
|
||||
// frequency data
|
||||
parseFrequency();
|
||||
break;
|
||||
case 03:
|
||||
parseFrequency();
|
||||
break;
|
||||
case '\x01':
|
||||
//qDebug() << "Have mode data";
|
||||
this->parseMode();
|
||||
break;
|
||||
case '\x04':
|
||||
//qDebug() << "Have mode data";
|
||||
this->parseMode();
|
||||
break;
|
||||
case '\x27':
|
||||
// scope data
|
||||
//qDebug() << "Have scope data";
|
||||
//printHex(payloadIn, false, true);
|
||||
parseSpectrum();
|
||||
break;
|
||||
case '\xFB':
|
||||
// Fine Business, ACK from rig.
|
||||
break;
|
||||
case '\xFA':
|
||||
// error
|
||||
qDebug() << "Error (FA) received from rig.";
|
||||
printHex(payloadIn, false ,true);
|
||||
break;
|
||||
default:
|
||||
qDebug() << "Have other data with cmd: " << std::hex << payloadIn[00];
|
||||
printHex(payloadIn, false, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void rigCommander::parseSpectrum()
|
||||
{
|
||||
// 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
|
||||
|
||||
unsigned char sequence = bcdHexToDecimal(payloadIn[03]);
|
||||
//unsigned char sequenceMax = bcdHexToDecimal(payloadIn[04]);
|
||||
unsigned char scopeMode = bcdHexToDecimal(payloadIn[05]);
|
||||
// unsigned char waveInfo = payloadIn[06]; // really just one byte?
|
||||
//qDebug() << "Spectrum Data received: " << sequence << "/" << sequenceMax << " mode: " << scopeMode << " waveInfo: " << waveInfo << " length: " << payloadIn.length();
|
||||
|
||||
// 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)
|
||||
{
|
||||
// wave information
|
||||
spectrumLine.clear();
|
||||
// parseFrequency(endPosition); // overload does not emit! Return? Where? how...
|
||||
spectrumStartFreq = parseFrequency(payloadIn, 9);
|
||||
spectrumEndFreq = parseFrequency(payloadIn, 14);
|
||||
if(scopeMode == 0)
|
||||
{
|
||||
// "center" mode, start is actuall center, end is bandwidth.
|
||||
spectrumStartFreq -= spectrumEndFreq;
|
||||
spectrumEndFreq = spectrumStartFreq + 2*(spectrumEndFreq);
|
||||
}
|
||||
} else if ((sequence > 1) && (sequence < 11))
|
||||
{
|
||||
// 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.
|
||||
payloadIn.chop(1);
|
||||
spectrumLine.insert(spectrumLine.length(), payloadIn.right(payloadIn.length() - 5)); // write over the FD, last one doesn't, oh well.
|
||||
//qDebug() << "sequence: " << sequence << "spec index: " << (sequence-2)*55 << " payloadPosition: " << payloadIn.length() - 5 << " payload length: " << payloadIn.length();
|
||||
} else if (sequence == 11)
|
||||
{
|
||||
// last spectrum, a little bit different (last 25 pixels). Total at end is 475 pixels.
|
||||
payloadIn.chop(1);
|
||||
spectrumLine.insert(spectrumLine.length(), payloadIn.right(payloadIn.length() - 5));
|
||||
//qDebug() << "sequence: " << sequence << " spec index: " << (sequence-2)*55 << " payloadPosition: " << payloadIn.length() - 5 << " payload length: " << payloadIn.length();
|
||||
emit haveSpectrumData(spectrumLine, spectrumStartFreq, spectrumEndFreq);
|
||||
}
|
||||
|
||||
/*
|
||||
if(spectrumLine.length() != 475)
|
||||
{
|
||||
qDebug() << "Unusual length spectrum: " << spectrumLine.length();
|
||||
printHex(spectrumLine, false, true);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
unsigned char rigCommander::bcdHexToDecimal(unsigned char in)
|
||||
{
|
||||
unsigned char out = 0;
|
||||
out = in & 0x0f;
|
||||
out += ((in & 0xf0) >> 4)*10;
|
||||
return out;
|
||||
}
|
||||
|
||||
void rigCommander::parseFrequency()
|
||||
{
|
||||
// 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 = payloadIn[04] & 0x0f;
|
||||
frequencyMhz += 10*((payloadIn[04] & 0xf0) >> 4);
|
||||
|
||||
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;
|
||||
|
||||
emit haveFrequency(frequencyMhz);
|
||||
}
|
||||
|
||||
float rigCommander::parseFrequency(QByteArray data, unsigned char lastPosition)
|
||||
{
|
||||
// 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);
|
||||
|
||||
float freq = 0.0;
|
||||
|
||||
freq = data[lastPosition] & 0x0f;
|
||||
freq += 10*((data[lastPosition] & 0xf0) >> 4);
|
||||
|
||||
freq += ((data[lastPosition-1] & 0xf0) >>4)/10.0 ;
|
||||
freq += (data[lastPosition-1] & 0x0f) / 100.0;
|
||||
|
||||
freq += ((data[lastPosition-2] & 0xf0) >> 4) / 1000.0;
|
||||
freq += (data[lastPosition-2] & 0x0f) / 10000.0;
|
||||
|
||||
freq += ((data[lastPosition-3] & 0xf0) >> 4) / 100000.0;
|
||||
freq += (data[lastPosition-3] & 0x0f) / 1000000.0;
|
||||
|
||||
return freq;
|
||||
}
|
||||
|
||||
|
||||
void rigCommander::parseMode()
|
||||
{
|
||||
QString mode;
|
||||
// LSB:
|
||||
//"INDEX: 00 01 02 03 "
|
||||
//"DATA: 01 00 02 fd "
|
||||
|
||||
// USB:
|
||||
//"INDEX: 00 01 02 03 "
|
||||
//"DATA: 01 01 02 fd "
|
||||
switch(payloadIn[01])
|
||||
{
|
||||
case '\x00':
|
||||
mode = "LSB";
|
||||
break;
|
||||
case '\x01':
|
||||
mode = "USB";
|
||||
break;
|
||||
case '\x02':
|
||||
mode = "AM";
|
||||
break;
|
||||
case '\x03':
|
||||
mode = "CW";
|
||||
break;
|
||||
case '\x04':
|
||||
mode = "RTTY";
|
||||
break;
|
||||
case '\x05':
|
||||
mode = "FM";
|
||||
break;
|
||||
case '\x07':
|
||||
mode = "CW-R";
|
||||
break;
|
||||
case '\x08':
|
||||
mode = "RTTY-R";
|
||||
break;
|
||||
default:
|
||||
qDebug() << "Mode: Unknown: " << payloadIn[01];
|
||||
mode = QString("Unk: %1").arg(payloadIn[01]);
|
||||
}
|
||||
|
||||
emit haveMode(mode);
|
||||
}
|
||||
|
||||
|
||||
QByteArray rigCommander::stripData(const QByteArray &data, unsigned char cutPosition)
|
||||
{
|
||||
QByteArray rtndata;
|
||||
if(data.length() < cutPosition)
|
||||
{
|
||||
return rtndata;
|
||||
}
|
||||
|
||||
rtndata = data.right(cutPosition);
|
||||
return rtndata;
|
||||
}
|
||||
|
||||
void rigCommander::getDebug()
|
||||
{
|
||||
// generic debug function for development.
|
||||
emit getMoreDebug();
|
||||
}
|
||||
|
||||
void rigCommander::printHex(const QByteArray &pdata, bool printVert, bool printHoriz)
|
||||
{
|
||||
qDebug() << "---- Begin hex dump -----:";
|
||||
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));
|
||||
qDebug() << strings.at(i);
|
||||
}
|
||||
}
|
||||
|
||||
if(printHoriz)
|
||||
{
|
||||
qDebug() << index;
|
||||
qDebug() << sdata;
|
||||
}
|
||||
qDebug() << "----- End hex dump -----";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
#ifndef RIGCOMMANDER_H
|
||||
#define RIGCOMMANDER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "commhandler.h"
|
||||
|
||||
// This file figures out what to send to the comm and also
|
||||
// parses returns into useful things.
|
||||
|
||||
class rigCommander : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
rigCommander();
|
||||
~rigCommander();
|
||||
|
||||
public slots:
|
||||
void process();
|
||||
|
||||
void enableSpectOutput();
|
||||
void disableSpectOutput();
|
||||
void enableSpectrumDisplay();
|
||||
void disableSpectrumDisplay();
|
||||
void setSpectrumBounds();
|
||||
void setSpectrumCenteredMode(bool centerEnable); // centered or band-wise
|
||||
void setScopeSpan(char span);
|
||||
void setScopeEdge(char edge);
|
||||
void setFrequency(double freq);
|
||||
void setMode(char mode);
|
||||
void getFrequency();
|
||||
void getMode();
|
||||
void getDataMode();
|
||||
void setCIVAddr(unsigned char civAddr);
|
||||
void handleNewData(const QByteArray &data);
|
||||
void getDebug();
|
||||
|
||||
signals:
|
||||
void haveSpectrumData(QByteArray spectrum, double startFreq, double endFreq); // pass along data to UI
|
||||
void haveFrequency(double frequencyMhz);
|
||||
void haveMode(QString mode);
|
||||
void haveSpectrumBounds();
|
||||
void dataForComm(const QByteArray &outData);
|
||||
void getMoreDebug();
|
||||
void finished();
|
||||
|
||||
|
||||
private:
|
||||
QByteArray stripData(const QByteArray &data, unsigned char cutPosition);
|
||||
void parseData(QByteArray data); // new data come here
|
||||
void parseCommand();
|
||||
unsigned char bcdHexToDecimal(unsigned char in);
|
||||
void parseFrequency();
|
||||
float parseFrequency(QByteArray data, unsigned char lastPosition); // supply index where Mhz is found
|
||||
QByteArray makeFreqPayload(double frequency);
|
||||
void parseMode();
|
||||
void parseSpectrum();
|
||||
void sendDataOut();
|
||||
void prepDataAndSend(QByteArray data);
|
||||
void debugMe();
|
||||
void printHex(const QByteArray &pdata, bool printVert, bool printHoriz);
|
||||
commHandler * comm;
|
||||
QByteArray payloadIn;
|
||||
QByteArray echoPerfix;
|
||||
QByteArray replyPrefix;
|
||||
QByteArray genericReplyPrefix;
|
||||
|
||||
QByteArray payloadPrefix;
|
||||
QByteArray payloadSuffix;
|
||||
|
||||
QByteArray rigData;
|
||||
|
||||
QByteArray spectrumLine;
|
||||
double spectrumStartFreq;
|
||||
double spectrumEndFreq;
|
||||
|
||||
|
||||
double frequencyMhz;
|
||||
unsigned char civAddr; // 0x94 is default = 148decimal
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // RIGCOMMANDER_H
|
|
@ -0,0 +1,487 @@
|
|||
#include "wfmain.h"
|
||||
#include "ui_wfmain.h"
|
||||
|
||||
#include "commhandler.h"
|
||||
|
||||
wfmain::wfmain(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::wfmain)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
plot = ui->plot; // rename it waterfall.
|
||||
wf = ui->waterfall;
|
||||
|
||||
spectWidth = 475; // fixed for now
|
||||
wfLength = 160; // fixed for now
|
||||
|
||||
// Initialize before use!
|
||||
|
||||
QByteArray empty((int)spectWidth, '\x01');
|
||||
spectrumPeaks = QByteArray( (int)spectWidth, '\x01' );
|
||||
for(quint16 i=0; i<wfLength; i++)
|
||||
{
|
||||
wfimage.append(empty);
|
||||
}
|
||||
|
||||
|
||||
// 0 1 2 3 4
|
||||
modes << "LSB" << "USB" << "AM" << "CW" << "RTTY";
|
||||
// 5 6 7 8 9
|
||||
modes << "CW-R" << "RTTY-R" << "LSB-D" << "USB-D";
|
||||
ui->modeSelectCombo->insertItems(0, modes);
|
||||
|
||||
spans << "2.5k" << "5.0k" << "10k" << "25k";
|
||||
spans << "50k" << "100k" << "250k" << "500k";
|
||||
ui->scopeBWCombo->insertItems(0, spans);
|
||||
|
||||
edges << "1" << "2" << "3"; // yep
|
||||
ui->scopeEdgeCombo->insertItems(0,edges);
|
||||
|
||||
// comm = new commHandler();
|
||||
rig = new rigCommander();
|
||||
rigThread = new QThread(this);
|
||||
|
||||
rig->moveToThread(rigThread);
|
||||
connect(rigThread, SIGNAL(started()), rig, SLOT(process()));
|
||||
connect(rig, SIGNAL(finished()), rigThread, SLOT(quit()));
|
||||
rigThread->start();
|
||||
|
||||
|
||||
connect(rig, SIGNAL(haveFrequency(double)), this, SLOT(receiveFreq(double)));
|
||||
connect(this, SIGNAL(getFrequency()), rig, SLOT(getFrequency()));
|
||||
connect(this, SIGNAL(getMode()), rig, SLOT(getMode()));
|
||||
connect(this, SIGNAL(getDebug()), rig, SLOT(getDebug()));
|
||||
connect(this, SIGNAL(spectOutputDisable()), rig, SLOT(disableSpectOutput()));
|
||||
connect(this, SIGNAL(spectOutputEnable()), rig, SLOT(enableSpectOutput()));
|
||||
connect(this, SIGNAL(scopeDisplayDisable()), rig, SLOT(disableSpectrumDisplay()));
|
||||
connect(this, SIGNAL(scopeDisplayEnable()), rig, SLOT(enableSpectrumDisplay()));
|
||||
connect(rig, SIGNAL(haveMode(QString)), this, SLOT(receiveMode(QString)));
|
||||
connect(rig, SIGNAL(haveSpectrumData(QByteArray, double, double)), this, SLOT(receiveSpectrumData(QByteArray, double, double)));
|
||||
connect(this, SIGNAL(setFrequency(double)), rig, SLOT(setFrequency(double)));
|
||||
connect(this, SIGNAL(setScopeCenterMode(bool)), rig, SLOT(setSpectrumCenteredMode(bool)));
|
||||
connect(this, SIGNAL(setScopeEdge(char)), rig, SLOT(setScopeEdge(char)));
|
||||
connect(this, SIGNAL(setScopeSpan(char)), rig, SLOT(setScopeSpan(char)));
|
||||
connect(this, SIGNAL(setMode(char)), rig, SLOT(setMode(char)));
|
||||
|
||||
|
||||
// Plot user interaction
|
||||
connect(plot, SIGNAL(mouseDoubleClick(QMouseEvent*)), this, SLOT(handlePlotDoubleClick(QMouseEvent*)));
|
||||
connect(wf, SIGNAL(mouseDoubleClick(QMouseEvent*)), this, SLOT(handleWFDoubleClick(QMouseEvent*)));
|
||||
|
||||
|
||||
ui->plot->addGraph(); // primary
|
||||
ui->plot->addGraph(0, 0); // secondary, peaks, same axis as first?
|
||||
ui->waterfall->addGraph();
|
||||
|
||||
|
||||
|
||||
colorMap = new QCPColorMap(wf->xAxis, wf->yAxis);
|
||||
colorMapData = NULL;
|
||||
wf->addPlottable(colorMap);
|
||||
colorScale = new QCPColorScale(wf);
|
||||
colorMap->data()->setValueRange(QCPRange(0, wfLength-1));
|
||||
colorMap->data()->setKeyRange(QCPRange(0, spectWidth-1));
|
||||
colorMap->setDataRange(QCPRange(0, 160));
|
||||
colorMap->setGradient(QCPColorGradient::gpJet);
|
||||
colorMapData = new QCPColorMapData(spectWidth, wfLength, QCPRange(0, spectWidth-1), QCPRange(0, wfLength-1));
|
||||
colorMap->setData(colorMapData);
|
||||
spectRowCurrent = 0;
|
||||
wf->yAxis->setRangeReversed(true);
|
||||
|
||||
ui->tabWidget->setCurrentIndex(0);
|
||||
|
||||
QColor color(20+200/4.0*1,70*(1.6-1/4.0), 150, 150);
|
||||
plot->graph(1)->setLineStyle(QCPGraph::lsLine);
|
||||
plot->graph(1)->setPen(QPen(color.lighter(200)));
|
||||
plot->graph(1)->setBrush(QBrush(color));
|
||||
|
||||
drawPeaks = false;
|
||||
ui->drawPeakChk->setChecked(false);
|
||||
|
||||
ui->freqMhzLineEdit->setValidator( new QDoubleValidator(0, 100, 6, this));
|
||||
|
||||
delayedCommand = new QTimer(this);
|
||||
delayedCommand->setInterval(250);
|
||||
delayedCommand->setSingleShot(true);
|
||||
connect(delayedCommand, SIGNAL(timeout()), this, SLOT(runDelayedCommand()));
|
||||
|
||||
}
|
||||
|
||||
wfmain::~wfmain()
|
||||
{
|
||||
// rigThread->quit();
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void wfmain::runDelayedCommand()
|
||||
{
|
||||
// switch case on enum
|
||||
switch (cmdOut)
|
||||
{
|
||||
case cmdGetFreq:
|
||||
emit getFrequency();
|
||||
break;
|
||||
case cmdGetMode:
|
||||
emit getMode();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void wfmain::receiveFreq(double freqMhz)
|
||||
{
|
||||
//qDebug() << "Frequency: " << freqMhz;
|
||||
ui->freqLabel->setText(QString("%1").arg(freqMhz, 0, 'f'));
|
||||
}
|
||||
|
||||
void wfmain::receiveSpectrumData(QByteArray spectrum, double startFreq, double endFreq)
|
||||
{
|
||||
if((startFreq != oldLowerFreq) || (endFreq != oldUpperFreq))
|
||||
{
|
||||
if(drawPeaks)
|
||||
on_clearPeakBtn_clicked();
|
||||
}
|
||||
|
||||
oldLowerFreq = startFreq;
|
||||
oldUpperFreq = endFreq;
|
||||
|
||||
//qDebug() << "start: " << startFreq << " end: " << endFreq;
|
||||
quint16 specLen = spectrum.length();
|
||||
//qDebug() << "Spectrum data received at UI! Length: " << specLen;
|
||||
if(specLen != 475)
|
||||
{
|
||||
//qDebug () << "Unusual spectrum: length: " << specLen;
|
||||
if(specLen > 475)
|
||||
{
|
||||
specLen = 475;
|
||||
} else {
|
||||
// as-is
|
||||
}
|
||||
return; // safe. Using these unusual length things is a problem.
|
||||
}
|
||||
|
||||
QVector <double> x(spectWidth), y(spectWidth), y2(spectWidth);
|
||||
|
||||
for(int i=0; i < spectWidth; i++)
|
||||
{
|
||||
x[i] = (i * (endFreq-startFreq)/spectWidth) + startFreq;
|
||||
|
||||
}
|
||||
|
||||
for(int i=0; i<specLen; i++)
|
||||
{
|
||||
//x[i] = (i * (endFreq-startFreq)/specLen) + startFreq;
|
||||
y[i] = spectrum.at(i);
|
||||
if(drawPeaks)
|
||||
{
|
||||
if(spectrum.at(i) > spectrumPeaks.at(i))
|
||||
{
|
||||
spectrumPeaks[i] = spectrum.at(i);
|
||||
}
|
||||
y2[i] = spectrumPeaks.at(i);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//ui->qcp->addGraph();
|
||||
plot->graph(0)->setData(x,y);
|
||||
if(drawPeaks)
|
||||
{
|
||||
plot->graph(1)->setData(x,y2); // peaks
|
||||
}
|
||||
plot->yAxis->setRange(0, 160);
|
||||
plot->xAxis->setRange(startFreq, endFreq);
|
||||
plot->replot();
|
||||
|
||||
if(specLen == spectWidth)
|
||||
{
|
||||
wfimage.prepend(spectrum);
|
||||
if(wfimage.length() > wfLength)
|
||||
{
|
||||
wfimage.remove(wfLength);
|
||||
}
|
||||
|
||||
// Waterfall:
|
||||
for(int row = 0; row < wfLength; row++)
|
||||
{
|
||||
for(int col = 0; col < spectWidth; col++)
|
||||
{
|
||||
//colorMap->data()->cellToCoord(xIndex, yIndex, &x, &y)
|
||||
// Very fast but doesn't roll downward:
|
||||
//colorMap->data()->setCell( col, spectRowCurrent, spectrum.at(col) );
|
||||
// Slow but rolls:
|
||||
colorMap->data()->setCell( col, row, wfimage.at(row).at(col));
|
||||
}
|
||||
}
|
||||
|
||||
//colorMap->data()->setRange(QCPRange(startFreq, endFreq), QCPRange(0,wfLength-1));
|
||||
wf->yAxis->setRange(0,wfLength - 1);
|
||||
wf->xAxis->setRange(0, spectWidth-1);
|
||||
wf->replot();
|
||||
spectRowCurrent = (spectRowCurrent + 1) % wfLength;
|
||||
//qDebug() << "updating spectrum, new row is: " << spectRowCurrent;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void wfmain::handlePlotDoubleClick(QMouseEvent *me)
|
||||
{
|
||||
double x;
|
||||
double y;
|
||||
//double px;
|
||||
x = plot->xAxis->pixelToCoord(me->pos().x());
|
||||
y = plot->yAxis->pixelToCoord(me->pos().y());
|
||||
emit setFrequency(x);
|
||||
cmdOut = cmdGetFreq;
|
||||
delayedCommand->start();
|
||||
|
||||
qDebug() << "PLOT double click: " << x << ", " << y;
|
||||
}
|
||||
|
||||
void wfmain::handleWFDoubleClick(QMouseEvent *me)
|
||||
{
|
||||
double x;
|
||||
//double y;
|
||||
//x = wf->xAxis->pixelToCoord(me->pos().x());
|
||||
//y = wf->yAxis->pixelToCoord(me->pos().y());
|
||||
// cheap trick until I figure out how the axis works on the WF:
|
||||
x = plot->xAxis->pixelToCoord(me->pos().x());
|
||||
emit setFrequency(x);
|
||||
cmdOut = cmdGetFreq;
|
||||
delayedCommand->start();
|
||||
|
||||
//qDebug() << "WF double click: " << x << ", " << y;
|
||||
|
||||
}
|
||||
|
||||
void wfmain::handlePlotClick(QMouseEvent *me)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void wfmain::handleWFClick(QMouseEvent *me)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void wfmain::on_startBtn_clicked()
|
||||
{
|
||||
//emit scopeDisplayEnable(); // TODO: need a little delay between these two
|
||||
emit spectOutputEnable();
|
||||
}
|
||||
|
||||
void wfmain::on_getFreqBtn_clicked()
|
||||
{
|
||||
emit getFrequency();
|
||||
}
|
||||
|
||||
void wfmain::on_getModeBtn_clicked()
|
||||
{
|
||||
emit getMode();
|
||||
}
|
||||
|
||||
void wfmain::on_debugBtn_clicked()
|
||||
{
|
||||
emit getDebug();
|
||||
}
|
||||
|
||||
void wfmain::on_stopBtn_clicked()
|
||||
{
|
||||
emit spectOutputDisable();
|
||||
//emit scopeDisplayDisable();
|
||||
}
|
||||
|
||||
void wfmain::receiveMode(QString mode)
|
||||
{
|
||||
ui->modeLabel->setText(mode);
|
||||
int index;
|
||||
//bool ok;
|
||||
index = modes.indexOf(QRegExp(mode));
|
||||
if( currentModeIndex == index)
|
||||
{
|
||||
// do nothing, no need to change the selected mode and fire more events off.
|
||||
return;
|
||||
}
|
||||
if((index >= 0) && (index < 9))
|
||||
{
|
||||
ui->modeSelectCombo->setCurrentIndex(index);
|
||||
currentModeIndex = index;
|
||||
}
|
||||
// Note: we need to know if the DATA mode is active to reach mode-D
|
||||
// some kind of queued query:
|
||||
cmdOut = cmdGetDataMode;
|
||||
//delayedCommand->start();
|
||||
}
|
||||
|
||||
void wfmain::on_clearPeakBtn_clicked()
|
||||
{
|
||||
spectrumPeaks = QByteArray( (int)spectWidth, '\x01' );
|
||||
}
|
||||
|
||||
void wfmain::on_drawPeakChk_clicked(bool checked)
|
||||
{
|
||||
if(checked)
|
||||
{
|
||||
on_clearPeakBtn_clicked(); // clear
|
||||
drawPeaks = true;
|
||||
|
||||
} else {
|
||||
drawPeaks = false;
|
||||
plot->graph(1)->clearData();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void wfmain::on_fullScreenChk_clicked(bool checked)
|
||||
{
|
||||
if(checked)
|
||||
this->showFullScreen();
|
||||
else
|
||||
this->showNormal();
|
||||
|
||||
|
||||
}
|
||||
|
||||
void wfmain::on_goFreqBtn_clicked()
|
||||
{
|
||||
bool ok = false;
|
||||
double freq = ui->freqMhzLineEdit->text().toDouble(&ok);
|
||||
if(ok)
|
||||
{
|
||||
emit setFrequency(freq);
|
||||
cmdOut = cmdGetFreq;
|
||||
delayedCommand->start();
|
||||
}
|
||||
ui->freqMhzLineEdit->selectAll();
|
||||
freqTextSelected = true;
|
||||
|
||||
}
|
||||
|
||||
void wfmain::checkFreqSel()
|
||||
{
|
||||
if(freqTextSelected)
|
||||
{
|
||||
freqTextSelected = false;
|
||||
ui->freqMhzLineEdit->clear();
|
||||
}
|
||||
}
|
||||
|
||||
void wfmain::on_f0btn_clicked()
|
||||
{
|
||||
checkFreqSel();
|
||||
ui->freqMhzLineEdit->setText(ui->freqMhzLineEdit->text().append("0"));
|
||||
}
|
||||
void wfmain::on_f1btn_clicked()
|
||||
{
|
||||
checkFreqSel();
|
||||
ui->freqMhzLineEdit->setText(ui->freqMhzLineEdit->text().append("1"));
|
||||
}
|
||||
|
||||
void wfmain::on_f2btn_clicked()
|
||||
{
|
||||
checkFreqSel();
|
||||
ui->freqMhzLineEdit->setText(ui->freqMhzLineEdit->text().append("2"));
|
||||
|
||||
}
|
||||
void wfmain::on_f3btn_clicked()
|
||||
{
|
||||
ui->freqMhzLineEdit->setText(ui->freqMhzLineEdit->text().append("3"));
|
||||
|
||||
}
|
||||
void wfmain::on_f4btn_clicked()
|
||||
{
|
||||
checkFreqSel();
|
||||
ui->freqMhzLineEdit->setText(ui->freqMhzLineEdit->text().append("4"));
|
||||
|
||||
}
|
||||
void wfmain::on_f5btn_clicked()
|
||||
{
|
||||
checkFreqSel();
|
||||
ui->freqMhzLineEdit->setText(ui->freqMhzLineEdit->text().append("5"));
|
||||
|
||||
}
|
||||
void wfmain::on_f6btn_clicked()
|
||||
{
|
||||
checkFreqSel();
|
||||
ui->freqMhzLineEdit->setText(ui->freqMhzLineEdit->text().append("6"));
|
||||
|
||||
}
|
||||
void wfmain::on_f7btn_clicked()
|
||||
{
|
||||
checkFreqSel();
|
||||
ui->freqMhzLineEdit->setText(ui->freqMhzLineEdit->text().append("7"));
|
||||
|
||||
}
|
||||
void wfmain::on_f8btn_clicked()
|
||||
{
|
||||
checkFreqSel();
|
||||
ui->freqMhzLineEdit->setText(ui->freqMhzLineEdit->text().append("8"));
|
||||
|
||||
}
|
||||
void wfmain::on_f9btn_clicked()
|
||||
{
|
||||
checkFreqSel();
|
||||
ui->freqMhzLineEdit->setText(ui->freqMhzLineEdit->text().append("9"));
|
||||
|
||||
}
|
||||
void wfmain::on_fDotbtn_clicked()
|
||||
{
|
||||
checkFreqSel();
|
||||
ui->freqMhzLineEdit->setText(ui->freqMhzLineEdit->text().append("."));
|
||||
|
||||
}
|
||||
|
||||
|
||||
void wfmain::on_fBackbtn_clicked()
|
||||
{
|
||||
QString currentFreq = ui->freqMhzLineEdit->text();
|
||||
currentFreq.chop(1);
|
||||
ui->freqMhzLineEdit->setText(currentFreq);
|
||||
}
|
||||
|
||||
void wfmain::on_fCEbtn_clicked()
|
||||
{
|
||||
ui->freqMhzLineEdit->clear();
|
||||
freqTextSelected = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void wfmain::on_scopeCenterModeChk_clicked(bool checked)
|
||||
{
|
||||
emit setScopeCenterMode(checked);
|
||||
}
|
||||
|
||||
void wfmain::on_fEnterBtn_clicked()
|
||||
{
|
||||
on_goFreqBtn_clicked();
|
||||
}
|
||||
|
||||
void wfmain::on_scopeBWCombo_currentIndexChanged(int index)
|
||||
{
|
||||
emit setScopeSpan((char)index);
|
||||
}
|
||||
|
||||
void wfmain::on_scopeEdgeCombo_currentIndexChanged(int index)
|
||||
{
|
||||
emit setScopeEdge((char)index+1);
|
||||
}
|
||||
|
||||
void wfmain::on_modeSelectCombo_currentIndexChanged(int index)
|
||||
{
|
||||
if(index < 10)
|
||||
{
|
||||
qDebug() << "Mode selection changed. index: " << index;
|
||||
emit setMode(index);
|
||||
|
||||
if(index > 7)
|
||||
{
|
||||
// set data mode on
|
||||
} else {
|
||||
// set data mode off
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
#ifndef WFMAIN_H
|
||||
#define WFMAIN_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QThread>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
#include <QTimer>
|
||||
|
||||
|
||||
#include "commhandler.h"
|
||||
#include "rigcommander.h"
|
||||
#include <qcustomplot.h>
|
||||
|
||||
namespace Ui {
|
||||
class wfmain;
|
||||
}
|
||||
|
||||
class wfmain : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit wfmain(QWidget *parent = 0);
|
||||
~wfmain();
|
||||
|
||||
signals:
|
||||
void getFrequency();
|
||||
void setFrequency(double freq);
|
||||
void getMode();
|
||||
void setMode(char modeIndex);
|
||||
void getDebug();
|
||||
void spectOutputEnable();
|
||||
void spectOutputDisable();
|
||||
void scopeDisplayEnable();
|
||||
void scopeDisplayDisable();
|
||||
void setScopeCenterMode(bool centerEnable);
|
||||
void setScopeSpan(char span);
|
||||
void setScopeEdge(char edge);
|
||||
|
||||
private slots:
|
||||
void on_startBtn_clicked();
|
||||
void receiveFreq(double);
|
||||
void receiveMode(QString);
|
||||
void receiveSpectrumData(QByteArray spectrum, double startFreq, double endFreq);
|
||||
void handlePlotClick(QMouseEvent *);
|
||||
void handlePlotDoubleClick(QMouseEvent *);
|
||||
void handleWFClick(QMouseEvent *);
|
||||
void handleWFDoubleClick(QMouseEvent *);
|
||||
void runDelayedCommand();
|
||||
|
||||
void on_getFreqBtn_clicked();
|
||||
|
||||
void on_getModeBtn_clicked();
|
||||
|
||||
void on_debugBtn_clicked();
|
||||
|
||||
void on_stopBtn_clicked();
|
||||
|
||||
void on_clearPeakBtn_clicked();
|
||||
|
||||
void on_drawPeakChk_clicked(bool checked);
|
||||
|
||||
void on_fullScreenChk_clicked(bool checked);
|
||||
|
||||
void on_goFreqBtn_clicked();
|
||||
|
||||
void on_f0btn_clicked();
|
||||
void on_f1btn_clicked();
|
||||
void on_f2btn_clicked();
|
||||
void on_f3btn_clicked();
|
||||
void on_f4btn_clicked();
|
||||
void on_f5btn_clicked();
|
||||
void on_f6btn_clicked();
|
||||
void on_f7btn_clicked();
|
||||
void on_f8btn_clicked();
|
||||
void on_f9btn_clicked();
|
||||
void on_fDotbtn_clicked();
|
||||
|
||||
|
||||
|
||||
void on_fBackbtn_clicked();
|
||||
|
||||
void on_fCEbtn_clicked();
|
||||
|
||||
|
||||
void on_scopeCenterModeChk_clicked(bool checked);
|
||||
|
||||
void on_fEnterBtn_clicked();
|
||||
|
||||
void on_scopeBWCombo_currentIndexChanged(int index);
|
||||
|
||||
void on_scopeEdgeCombo_currentIndexChanged(int index);
|
||||
|
||||
void on_modeSelectCombo_currentIndexChanged(int index);
|
||||
|
||||
private:
|
||||
Ui::wfmain *ui;
|
||||
QCustomPlot *plot; // line plot
|
||||
QCustomPlot *wf; // waterfall image
|
||||
//commHandler *comm;
|
||||
rigCommander * rig;
|
||||
QThread * rigThread;
|
||||
QCPColorMap * colorMap;
|
||||
QCPColorMapData * colorMapData;
|
||||
QCPColorScale * colorScale;
|
||||
QTimer * delayedCommand;
|
||||
|
||||
QStringList modes;
|
||||
int currentModeIndex;
|
||||
QStringList spans;
|
||||
QStringList edges;
|
||||
QStringList commPorts;
|
||||
|
||||
quint16 spectWidth;
|
||||
quint16 wfLength;
|
||||
|
||||
quint16 spectRowCurrent;
|
||||
|
||||
QByteArray spectrumPeaks;
|
||||
|
||||
QVector <QByteArray> wfimage;
|
||||
|
||||
bool drawPeaks;
|
||||
bool freqTextSelected;
|
||||
void checkFreqSel();
|
||||
|
||||
double oldLowerFreq;
|
||||
double oldUpperFreq;
|
||||
enum cmds {cmdGetFreq, cmdGetMode, cmdGetDataMode};
|
||||
cmds cmdOut;
|
||||
|
||||
};
|
||||
|
||||
#endif // WFMAIN_H
|
Plik diff jest za duży
Load Diff
|
@ -0,0 +1,46 @@
|
|||
#-------------------------------------------------
|
||||
#
|
||||
# Project created by QtCreator 2018-05-26T16:57:32
|
||||
#
|
||||
#-------------------------------------------------
|
||||
|
||||
QT += core gui serialport
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport
|
||||
|
||||
TARGET = wfview
|
||||
TEMPLATE = app
|
||||
|
||||
QMAKE_CXXFLAGS += -march=native
|
||||
|
||||
# The following define makes your compiler emit warnings if you use
|
||||
# any feature of Qt which as been marked as deprecated (the exact warnings
|
||||
# depend on your compiler). Please consult the documentation of the
|
||||
# deprecated API in order to know how to port your code away from it.
|
||||
DEFINES += QT_DEPRECATED_WARNINGS
|
||||
DEFINES += QCUSTOMPLOT_COMPILE_LIBRARY
|
||||
|
||||
#CONFIG(debug, release|debug) {
|
||||
# win32:QCPLIB = qcustomplotd1
|
||||
# else: QCPLIB = qcustomplotd
|
||||
#} else {
|
||||
# win32:QCPLIB = qcustomplot1
|
||||
# else: QCPLIB = qcustomplot
|
||||
#}
|
||||
|
||||
QCPLIB = qcustomplot
|
||||
|
||||
LIBS += -L./ -l$$QCPLIB
|
||||
|
||||
|
||||
SOURCES += main.cpp\
|
||||
wfmain.cpp \
|
||||
commhandler.cpp \
|
||||
rigcommander.cpp
|
||||
|
||||
HEADERS += wfmain.h \
|
||||
../../../../../usr/include/qcustomplot.h \
|
||||
commhandler.h \
|
||||
rigcommander.h
|
||||
|
||||
FORMS += wfmain.ui
|
Ładowanie…
Reference in New Issue