SoDaRadio-5.0.3-master:8901fb5
soda_listener.cpp
Go to the documentation of this file.
1 /*
2 Copyright (c) 2017 Matthew H. Reilly (kb1vc)
3 All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8 
9  Redistributions of source code must retain the above copyright
10  notice, this list of conditions and the following disclaimer.
11  Redistributions in binary form must reproduce the above copyright
12  notice, this list of conditions and the following disclaimer in
13  the documentation and/or other materials provided with the
14  distribution.
15 
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28 
29 #include "soda_listener.hpp"
30 
31 GUISoDa::Listener::Listener(QObject * parent, const QString & _socket_basename) : QObject(parent) {
32  quit = false;
33  socket_basename = _socket_basename;
34 }
35 
37 {
38  cmd_socket = new QLocalSocket(this);
39  // first wait for the file to be created
40  QString cmd_socket_name = socket_basename + "_cmd";
41  int wcount = 0;
42  while(!QFile::exists(cmd_socket_name)) {
43  QThread::sleep(5);
44  wcount++;
45  if(wcount > 30) {
46  qDebug() << QString("Waited %1 seconds for socket file [%2] to be created. Is the radio process dead?").arg(wcount * 5).arg(cmd_socket_name);
47  emit(fatalError(QString("No socket file [%1] found after timeout of %2 seconds").arg(cmd_socket_name).arg(wcount * 5)));
48  return false;
49  }
50  }
51 
52  cmd_socket->connectToServer(cmd_socket_name);
53  while(!cmd_socket->waitForConnected(1000)) {
54  qDebug() << QString("Waited connection on local socket [%1_cmd]. Is something wrong?").arg(socket_basename);
55  qDebug() << cmd_socket->errorString();
56  QThread::sleep(5); // sleep for 5 seconds...
57  }
58 
59  connect(cmd_socket, SIGNAL(readyRead()),
60  this, SLOT(processCmd()));
61  connect(cmd_socket, SIGNAL(error(QLocalSocket::LocalSocketError)),
62  this, SLOT(cmdErrorHandler(QLocalSocket::LocalSocketError)));
63 
64 
65  spect_socket = new QLocalSocket(this);
66  spect_socket->connectToServer(socket_basename + "_wfall");
67  while(!spect_socket->waitForConnected(30000)) {
68  qDebug() << QString("Waited 30 seconds for connection on local socket [%1_wfall]. Is something wrong?").arg(socket_basename);
69  qDebug() << cmd_socket->errorString();
70  QThread::sleep(5); // sleep for 5 seconds...
71  }
72 
73  connect(spect_socket, SIGNAL(readyRead()),
74  this, SLOT(processSpectrum()));
75  connect(spect_socket, SIGNAL(error(QLocalSocket::LocalSocketError)),
76  this, SLOT(cmdErrorHandler(QLocalSocket::LocalSocketError)));
77 
78  spect_buffer_len = 0;
79 
80  return true;
81 }
82 
84 {
86  return;
87 }
88 
89 int GUISoDa::Listener::put(const char * buf, int len)
90 {
91  cmd_socket->write((char*) &len, sizeof(int));
92 
93  unsigned int to_go = len;
94 
95  const char * cp = buf;
96  while(to_go > 0) {
97  int l = cmd_socket->write(cp, to_go);
98  if(l < 0) return l;
99  else {
100  to_go -= l;
101  cp += l;
102  }
103  }
104 
105  cmd_socket->flush();
106  return len;
107 }
108 
109 int GUISoDa::Listener::get(char * buf, int maxlen)
110 {
111  int len;
112  int stat = cmd_socket->read((char*) & len, sizeof(int));
113 
114  if(stat < 0) return stat;
115 
116  if(len > maxlen) len = maxlen;
117 
118  unsigned int to_go = len;
119 
120  char * cp = buf;
121  while(to_go > 0) {
122  int l = cmd_socket->read(cp, to_go);
123  if(l < 0) return l;
124  else {
125  to_go -= l;
126  cp += l;
127  }
128  }
129 
130  return len;
131 }
132 
134 {
135  int len = get((char*) &cmd, sizeof(SoDa::Command));
136  return len > 0;
137 }
138 
139 void GUISoDa::Listener::setupSpectrumBuffer(double cfreq, double span, long buflen)
140 {
141  spect_center_freq = cfreq;
142 
143  if(spect_buffer_len < buflen) {
144  if(spect_buffer_len > 0) delete[] spect_buffer;
145 
146  spect_buffer_len = buflen;
147  spect_buffer = new float[buflen];
148  }
149  else {
150  spect_buffer_len = buflen;
151  }
152 }
153 
155  int rlen = spect_buffer_len * sizeof(float);
156  while(spect_socket->bytesAvailable() > (sizeof(int) + rlen)) {
157  int len;
158  int stat = spect_socket->read((char*) & len, sizeof(int));
159 
160  if(rlen != len) {
161  char * nbuf = new char[len];
162  // throw it away.
163  spect_socket->read(nbuf, len);
164  delete[] nbuf;
165  }
166  else {
167  stat = spect_socket->read((char*) spect_buffer, rlen);
168  emit(updateData(spect_center_freq, spect_buffer));
169  }
170  }
171 }
172 
174  SoDa::Command incmd;
175 
176  while(cmd_socket->bytesAvailable() > sizeof(SoDa::Command)) {
177  int len = get(incmd);
178 
179  if(incmd.cmd == SoDa::Command::REP) handleREP(incmd);
180  else if(incmd.cmd == SoDa::Command::GET) handleGET(incmd);
181  else if(incmd.cmd == SoDa::Command::SET) handleSET(incmd);
182  }
183 }
184 
185 
187 {
188  int len = put((char*) &cmd, sizeof(SoDa::Command));
189  return len > 0;
190 }
191 
192 void GUISoDa::Listener::setRXFreq(double freq) {
194  perror("What happened here?");
195  }
196  current_rx_freq = freq;
197 }
198 
199 void GUISoDa::Listener::setTXFreq(double freq) {
201  perror("What happened here?");
202  }
203  current_tx_freq = freq;
204 }
205 
207  double dgain = gain;
209  perror("What happened here?");
210  }
211 }
212 
214  double dgain = gain;
216  perror("What happened here?");
217  }
218 }
219 
221  double dgain = gain;
222  // this is a little complex...
223  dgain = 50.0 * (log10(dgain) / log10(100.0));
225  perror("What happened here?");
226  }
227 }
228 
230  double dgain = gain;
232  perror("What happened here?");
233  }
234 }
235 
236 
238 {
239 
241  perror("What happened here?");
242  }
244  perror("What happened here?");
245  }
246 }
247 
249 {
251  perror("What happened here?");
252  }
253 }
254 
256 {
257  switch(cmd.target) {
259  emit(addModulation(QString(cmd.sparm), cmd.tag));
260  break;
262  emit(addFilterName(QString(cmd.sparm), cmd.tag));
263  break;
265  emit(addRXAntName(QString(cmd.sparm)));
266  break;
268  emit(addTXAntName(QString(cmd.sparm)));
269  break;
271  emit(configureSpectrum(cmd.dparms[0], cmd.dparms[1], ((long) cmd.dparms[2])));
272  setupSpectrumBuffer(cmd.dparms[0], cmd.dparms[1], (long) cmd.dparms[2]);
273  break;
275  emit(repHWMBVersion(QString(cmd.sparm)));
276  break;
278  emit(repSDRVersion(QString(cmd.sparm)));
279  break;
281  emit(repMarkerOffset(cmd.dparms[0], cmd.dparms[1]));
282  break;
284  emit(initSetupComplete());
285  break;
287  emit(repPTT(cmd.iparms[0] == 1));
288  break;
290  emit(repGPSTime(cmd.iparms[0], cmd.iparms[1], cmd.iparms[2]));
291  break;
293  emit(repGPSLatLon(cmd.dparms[0], cmd.dparms[1]));
294  break;
295  default:
296  break;
297  }
298  return true;
299 }
300 
301 void GUISoDa::Listener::setRXAnt(const QString & antname)
302 {
303  if(!put(SoDa::Command(SoDa::Command::SET, SoDa::Command::RX_ANT, antname.toStdString()))) {
304  perror("What happened here?");
305  }
306 }
307 
308 void GUISoDa::Listener::setTXAnt(const QString & antname)
309 {
310  if(!put(SoDa::Command(SoDa::Command::SET, SoDa::Command::TX_ANT, antname.toStdString()))) {
311  perror("What happened here?");
312  }
313 }
314 
316 {
318  perror("What happened here?");
319  }
320 }
321 
323 {
325  perror("What happened here?");
326  }
327 }
328 
330 {
332  perror("What happened here?");
333  }
334 }
335 
337 {
339  perror("What happened here?");
340  }
341 }
342 
344 {
346  perror("What happened here?");
347  }
348 }
349 
351 {
353  perror("What happened here?");
354  }
355 }
356 
358 {
359  int tx_state = on ? 1 : 0;
361  perror("What happened here?");
362  }
363 }
364 
366 {
368  perror("What happened here?");
369  }
370 }
371 
372 void GUISoDa::Listener::sendCW(const QString & txt)
373 {
374  char cwbuf[SoDa::Command::getMaxStringLen()];
375  unsigned int i, j;
376  for(i = 0, j = 0; i <= txt.size(); i++) {
377  if(i == txt.size()) {
378  cwbuf[j] = '\000';
379  }
380  else {
381  char c = txt.at(i).toLatin1();
382  if(isprint(c)) {
383  cwbuf[j] = c;
384  }
385  else {
386  cwbuf[j] = ' ';
387  }
388  }
389 
390  j++;
391 
392  if((j >= SoDa::Command::getMaxStringLen()) || (i == txt.size())) {
394  perror("What happened here?");
395  }
396  j = 0;
397  }
398  }
399 }
400 
402 {
403  switch(cmd.target) {
404  default:
405  break;
406  }
407 
408  return true;
409 }
410 
412 {
413  switch(cmd.target) {
414  default:
415  break;
416  }
417  return true;
418 }
419 
421 {
423  perror("What happened here -- listener closeRadio?");
424  }
425 }
426 
Not many choices for TX ant, just TX.
Definition: Command.hxx:154
void repMarkerOffset(double lo, double hi)
void addFilterName(QString filter_name, int filt_id)
turn transmitter on and off.
Definition: Command.hxx:197
RX audio gain setting.
Definition: Command.hxx:175
Set the TX final amplifier.
Definition: Command.hxx:167
Set the RX front end attenuator/amp.
Definition: Command.hxx:161
Set the modulation mode for the receive chain.
Definition: Command.hxx:251
void sendCW(const QString &txt)
void repPTT(bool on)
void addTXAntName(const QString &ant_name)
int iparms[4]
integer parameters
Definition: Command.hxx:668
int put(const char *buf, int len)
void setTXAnt(const QString &antname)
void setSidetoneVolume(int vol)
void updateData(double cfreq, float *y)
Set the modulation mode for the transmit chain.
Definition: Command.hxx:259
void setModulation(int mod_id)
Report the motherboard name (the model name of the USRP)
Definition: Command.hxx:362
all spec info in one call, cf, span, and buflen
Definition: Command.hxx:279
void initSetupComplete()
void setRXFreq(double freq)
CmdTarget target
the thing we&#39;re touching
Definition: Command.hxx:673
Report UTC (time) from GPS receiver.
Definition: Command.hxx:326
void setSpectrumAvgWindow(int window)
unsigned int tag
used to pair an int with a string or other param.
Definition: Command.hxx:666
Report a string/name pair for modulation mode.
Definition: Command.hxx:450
void setCWSpeed(int speed)
indicate to GUI that we&#39;ve sent all the initial configuration information
Definition: Command.hxx:460
void repSDRVersion(const QString &version)
static int getMaxStringLen()
how long can a string parameter to a command be?
Definition: Command.hxx:664
void setPTT(bool on)
Flush outstanding CW text strings from pending buffer.
Definition: Command.hxx:228
void setAFSidetoneGain(int gain)
void setSpectrumUpdateRate(int rate)
On receipt of a STOP command, all threads should exit their run loop.
Definition: Command.hxx:371
This is a list of all the commands that can "do something" to one or more components in the SoDa radi...
Definition: Command.hxx:47
void setAFFilter(int id)
void repGPSTime(int hh, int mm, int ss)
how many FFT samples contribute to a spectrum report
Definition: Command.hxx:281
void setTXPower(int vol)
void addModulation(QString modtype, int mod_id)
char sparm[64]
a buffer holding the string
Definition: Command.hxx:670
QLocalSocket * spect_socket
Report LAT and LON from GPS receiver.
Definition: Command.hxx:318
the center frequency (command from GUI)
Definition: Command.hxx:273
bool init()
connect to radio server sockets and initialize listener state
Report TX antenna choice (asciiz string, uint tag)
Definition: Command.hxx:444
TX CW text control – a buffer of up to 8 characters.
Definition: Command.hxx:215
RX ant choices are TX/RX, and RX2.
Definition: Command.hxx:148
CmdType cmd
the command type (SET, GET, REP)
Definition: Command.hxx:672
void setRXGain(int gain)
double dparms[4]
double float parameters
Definition: Command.hxx:669
bool handleREP(const SoDa::Command &cmd)
void repHWMBVersion(const QString &version)
void setSpectrumCenter(double freq)
how many FFT samples between spectrum reports
Definition: Command.hxx:282
Tune the 3rd LO, if the current FE frequency is such that the desired frequency is between RX_FE_FREQ...
Definition: Command.hxx:89
Set speed of CW generator.
Definition: Command.hxx:221
Report the SDR (SoDa server program) version info.
Definition: Command.hxx:344
bool handleSET(const SoDa::Command &cmd)
int get(char *buf, int maxlen)
void cmdErrorHandler(QLocalSocket::LocalSocketError err)
void setupSpectrumBuffer(double cfreq, double span, long buflen)
void start()
initiate transfers on the socket.
void configureSpectrum(double cfreq, double span, long buckets)
RX audio gain for sidetone (CW) monitor.
Definition: Command.hxx:182
Listener(QObject *parent=0, const QString &socket_basename="tmp")
void setTXFreq(double freq)
Report a string/name pair for AF filter bandwidth.
Definition: Command.hxx:455
void setRXAnt(const QString &antname)
Report RX antenna choice (asciiz string, uint tag)
Definition: Command.hxx:439
QLocalSocket * cmd_socket
bool handleGET(const SoDa::Command &cmd)
void addRXAntName(const QString &ant_name)
void setTXGain(int gain)
Same effect as TX_TUNE_FREQ.
Definition: Command.hxx:122
void setAFGain(int gain)
void fatalError(const QString &error_string)
void repGPSLatLon(double lat, double lon)