SoDaRadio-5.0.3-master:8901fb5
USRPTX.cxx
Go to the documentation of this file.
1 /*
2  Copyright (c) 2012, 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 "USRPTX.hxx"
30 #include <uhd/utils/safe_main.hpp>
31 #include <uhd/utils/thread_priority.hpp>
32 #include <uhd/usrp/multi_usrp.hpp>
33 #include <unistd.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <fcntl.h>
37 #include <stdio.h>
38 
39 SoDa::USRPTX::USRPTX(Params * params, uhd::usrp::multi_usrp::sptr _usrp,
40  DatMBox * _tx_stream, DatMBox * _cw_env_stream,
41  CmdMBox * _cmd_stream) : SoDa::SoDaThread("USRPTX")
42 {
43  cmd_stream = _cmd_stream;
44  tx_stream = _tx_stream;
45  cw_env_stream = _cw_env_stream;
46  usrp = _usrp;
47 
48  // subscribe to the command stream.
50  // subscribe to the tx data stream
52  // and to the CW envelope stream
54 
55  LO_enabled = false;
56  LO_configured = false;
57  LO_capable = false;
58  beacon_mode = false;
59 
60  // create the tx buffer streamers.
61  stream_args = new uhd::stream_args_t("fc32", "sc16");
62  stream_args->channels.push_back(0);
63  if(0 && (usrp->get_tx_num_channels() > 1)) {
64  // disable this for now... there appears to be a bug in the b210 support in 3.8.1
65  debugMsg("This radio is transverter LO capable");
66  // use the second channel as a transverter LO
67  stream_args->channels.push_back(1);
68  LO_capable = true;
69  }
70  else {
71  debugMsg("This radio is NOT transverter LO capable");
72  }
73 
74  // find out how to configure the transmitter
75  tx_sample_rate = params->getTXRate();
76  tx_buffer_size = params->getRFBufferSize();
77 
78  // 400 Hz is a nice tone
79  // but 400 doesn't really work that well.
80  // 650 is better. but all the RX filters
81  // are centered near 500... let's do that.
82  CW_tone_freq = 500.0;
83  setCWFreq(true, CW_tone_freq);
84 
85  // we aren't waiting for anything.
86  waiting_to_run_dry = false;
87 
88  // build the beacon buffer, and the zero buffer.
89  beacon_env = new float[tx_buffer_size];
90  zero_env = new float[tx_buffer_size];
91  for(unsigned int i = 0; i < tx_buffer_size; i++) {
92  beacon_env[i] = 1.0;
93  zero_env[i] = 0.0;
94  }
95 
96  // build the cwbuffer
97  cw_buf = new std::complex<float>[tx_buffer_size];
98 
99  // set the initial envelope amplitude
100  cw_env_amplitude = 0.7; // more or less sqrt2/2
101 
102  // build the zero buffer and the transverter lo buffer
103  zero_buf = new std::complex<float>[tx_buffer_size];
104  const_buf = new std::complex<float>[tx_buffer_size];
105  for(unsigned int i = 0; i < tx_buffer_size; i++) {
106  zero_buf[i] = std::complex<float>(0.0, 0.0);
107  const_buf[i] = std::complex<float>(1.0, 0.0);
108  }
109 
110  tx_enabled = false;
111 }
112 
114 {
115  uhd::set_thread_priority_safe();
116  // now do the event loop. we watch
117  // for commands and responses on the command stream.
118  // and we watch for data in the input buffer.
119 
120  // get the tx streamer
121  debugMsg("Creating tx streamer.\n");
122  getTXStreamer();
123  debugMsg("Created tx streamer.\n");
124 
125  bool exitflag = false;
126  SoDaBuf * txbuf, * cwenv;
127  Command * cmd;
128  std::vector<std::complex<float> *> buffers(LO_capable ? 2 : 1);
129 
130  while(!exitflag) {
131  bool didwork = false;
132  if(LO_capable && LO_enabled && LO_configured) buffers[1] = const_buf;
133  else if(LO_capable) buffers[1] = zero_buf;
134 
135  if((cmd = cmd_stream->get(cmd_subs)) != NULL) {
136  // process the command.
137  execCommand(cmd);
138  didwork = true;
139  exitflag |= (cmd->target == Command::STOP);
140  cmd_stream->free(cmd);
141  }
142  else if(tx_enabled &&
143  tx_bits &&
146  (txbuf = tx_stream->get(tx_subs)) != NULL) {
147  // get a buffer and
148  buffers[0] = txbuf->getComplexBuf();
149  tx_bits->send(buffers, txbuf->getComplexLen(), md);
150  md.start_of_burst = false;
151  didwork = true;
152 
153  // now free the buffer up.
154  tx_stream->free(txbuf);
155  }
156  else if(tx_enabled &&
157  tx_bits &&
160  cwenv = cw_env_stream->get(cw_subs);
161  if(cwenv != NULL) {
162  // modulate a carrier with a cw message
163  doCW(cw_buf, cwenv->getFloatBuf(), cwenv->getComplexLen());
164  // now send it to the USRP
165  buffers[0] = cw_buf;
166  tx_bits->send(buffers, cwenv->getComplexLen(), md);
167  cw_env_stream->free(cwenv);
168  md.start_of_burst = false;
169  didwork = true;
170  }
171  else {
172  // we have an empty CW buffer -- we've run out of text.
174  buffers[0] = cw_buf;
175  tx_bits->send(buffers, tx_buffer_size, md);
176  // are we supposed to tell anybody about this?
177  if(waiting_to_run_dry) {
179  waiting_to_run_dry = false;
180  }
181  }
182  }
183  else if(tx_enabled &&
184  tx_bits &&
185  beacon_mode) {
186  // modulate a carrier with a constant envelope
188  // now send it to the USRP
189  buffers[0] = cw_buf;
190  tx_bits->send(buffers, tx_buffer_size, md);
191  md.start_of_burst = false;
192  didwork = true;
193  }
194  else if(tx_enabled &&
195  tx_bits) {
196  // all other cases -- we still want to send the LO buffer
197  buffers[0] = zero_buf;
198  tx_bits->send(buffers, tx_buffer_size, md);
199  didwork = true;
200  }
201 
202  if(!didwork) {
203  usleep(100);
204  }
205  }
206 
207  debugMsg("Leaving\n");
208 }
209 
210 
211 void SoDa::USRPTX::doCW(std::complex<float> * out, float * envelope, unsigned int env_len)
212 {
213  unsigned int i;
214  std::complex<float> c;
215 
216  for(i = 0; i < env_len; i++) {
217  c = CW_osc.stepOscCF();
218  out[i] = c * envelope[i] * cw_env_amplitude;
219  }
220 }
221 
222 void SoDa::USRPTX::setCWFreq(bool usb, double freq)
223 {
224  // set to - for USB and + for LSB.
225  CW_osc.setPhaseIncr((usb ? -1.0 : 1.0) * freq * 2.0 * M_PI / tx_sample_rate);
226  // likely to be extremely small...
227 }
228 
230 {
231  if(tx_on) {
232  if(tx_enabled) return;
233  waiting_to_run_dry = false;
234  md.start_of_burst = true;
235  md.end_of_burst = false;
236  md.has_time_spec = false;
237  tx_enabled = true;
238  }
239  else {
240  if(!tx_enabled && !LO_enabled) return;
241  if(!LO_enabled) {
242  // If LO is enabled, we always send SOMETHING....
243  md.end_of_burst = true;
244  tx_bits->send(zero_buf, 10, md);
245  }
246  tx_enabled = false;
247  // flush the input stream for us.
249  }
250 }
251 
253 {
254  tx_bits = usrp->get_tx_stream(*stream_args);
255 }
256 
257 
259 {
260  switch(cmd->target) {
264  setCWFreq(false, CW_tone_freq);
265  }
266  else if(tx_modulation == SoDa::Command::CW_U) {
267  setCWFreq(true, CW_tone_freq);
268  }
269  break;
270  case Command::TX_STATE:
271  // TX_STATE must be 3 to turn the transmitter on.
272  // bit 1 of the command indicates that CTRL has already done the
273  // setup for TX <-> RX mode transitions.
274  if((cmd->iparms[0] & 0x2) != 0) {
275  transmitSwitch(cmd->iparms[0] == 3);
277  }
278  break;
279  case Command::TX_BEACON:
280  beacon_mode = (cmd->iparms[0] != 0);
281  break;
283  waiting_to_run_dry = true;
284  break;
286  debugMsg("Enable Transverter LO");
287  LO_enabled = true;
288  break;
290  debugMsg("Disable Transverter LO");
291  LO_enabled = false;
292  break;
293  default:
294  break;
295  }
296 }
297 
299 {
300  switch(cmd->target) {
301  case Command::TX_STATE:
303  break;
304  default:
305  break;
306  }
307 }
308 
310 {
311  switch(cmd->target) {
313  debugMsg("LO configured");
314  LO_configured = true;
315  break;
316  default:
317  break;
318  }
319 }
320 
uhd::stream_args_t * stream_args
Definition: USRPTX.hxx:150
On receipt of a TVRT_LO_DISABLE command, turn the LO output on TX2 off.
Definition: Command.hxx:391
float * zero_env
envelope for dead silence
Definition: USRPTX.hxx:139
void setPhaseIncr(double _pi)
set the phase increment per step for the oscillator (1/freq)
The Thread baseclass for all SoDa thread objects.
Definition: SoDaBase.hxx:284
void debugMsg(const std::string &msg, unsigned int threshold=1)
Definition: Debug.hxx:64
turn transmitter on and off.
Definition: Command.hxx:197
T * get(unsigned int subscriber_id)
Definition: MultiMBox.hxx:110
USRPTX(Params *params, uhd::usrp::multi_usrp::sptr _usrp, DatMBox *_tx_stream, DatMBox *_cw_env_stream, CmdMBox *_cmd_stream)
Constructor for RF Transmit/modulator process.
Definition: USRPTX.cxx:39
void setCWFreq(bool usb, double freq)
set the CW tone frequency to generate an IQ stream
Definition: USRPTX.cxx:222
bool LO_capable
if true, this hardware model supports LO config
Definition: USRPTX.hxx:157
bool flush(unsigned int subscriber_id)
flush all items from this mailbox for this subscriber
Definition: MultiMBox.hxx:182
SoDa::Command::ModulationType tx_modulation
type of transmit modulation (CW_U,CW_L,USB,LSB...)
Definition: USRPTX.hxx:131
int iparms[4]
integer parameters
Definition: Command.hxx:668
Set the modulation mode for the transmit chain.
Definition: Command.hxx:259
Report when CW TX envelope buffer was empty (cmd enables report)
Definition: Command.hxx:242
This class handles command line parameters and built-ins.
Definition: Params.hxx:42
DatMBox * tx_stream
transmit audio stream
Definition: USRPTX.hxx:126
void doCW(std::complex< float > *out, float *envelope, unsigned int env_len)
given a keying envelope, impose it on the CW tone
Definition: USRPTX.cxx:211
CmdTarget target
the thing we&#39;re touching
Definition: Command.hxx:673
bool beacon_mode
if true, we&#39;re transmitting a steady carrier
Definition: USRPTX.hxx:137
TX Carrier Control – send a dead carrier.
Definition: Command.hxx:208
std::complex< float > stepOscCF()
step the oscillator and produce a complex float result
void execGetCommand(Command *cmd)
execute GET commands from the command channel
Definition: USRPTX.cxx:298
DatMBox * cw_env_stream
envelope stream from text-to-CW converter (CW unit)
Definition: USRPTX.hxx:127
The Buffer Class.
Definition: SoDaBase.hxx:72
std::complex< float > * zero_buf
zero signal envelope to fill in end of transmit stream
Definition: USRPTX.hxx:142
unsigned int tx_buffer_size
size of buffer going to USRP
Definition: USRPTX.hxx:145
void execSetCommand(Command *cmd)
handle SET commands from the command channel
Definition: USRPTX.cxx:258
unsigned int cw_subs
subscription handle for cw envelope stream (from CW unit)
Definition: USRPTX.hxx:124
unsigned int getRFBufferSize() const
Definition: Params.hxx:105
On receipt of a STOP command, all threads should exit their run loop.
Definition: Command.hxx:371
float * getFloatBuf()
Return a pointer to the storage buffer of floats.
Definition: SoDaBase.hxx:137
unsigned int tx_subs
subscription handle for transmit audio stream (from BaseBandTX)
Definition: USRPTX.hxx:122
std::complex< float > * getComplexBuf()
Return a pointer to the storage buffer of complex floats.
Definition: SoDaBase.hxx:133
QuadratureOscillator CW_osc
CW tone IQ oscillator.
Definition: USRPTX.hxx:134
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 transmitSwitch(bool tx_on)
start/stop transmit stream
Definition: USRPTX.cxx:229
float * beacon_env
steady constant amplitude envelope
Definition: USRPTX.hxx:136
void execRepCommand(Command *cmd)
handle Report commands from the command channel
Definition: USRPTX.cxx:309
uhd::usrp::multi_usrp::sptr usrp
the radio.
Definition: USRPTX.hxx:73
ModulationType
modulation selector targets take one of these values
Definition: Command.hxx:478
std::complex< float > * cw_buf
CW modulated envelope to send to USRP.
Definition: USRPTX.hxx:141
void run()
USRPTX run loop: handle commands, and modulate the tx carrier.
Definition: USRPTX.cxx:113
unsigned int cmd_subs
subscription handle for command stream
Definition: USRPTX.hxx:123
double getTXRate() const
TX rate will always be 625K.
Definition: Params.hxx:102
std::complex< float > * const_buf
envelope for dead silence
Definition: USRPTX.hxx:159
float cw_env_amplitude
used to set CW output envelope, constant at 0.7
Definition: USRPTX.hxx:146
double tx_sample_rate
sample rate for buffer going to USRP (UHD)
Definition: USRPTX.hxx:144
void free(T *m)
Definition: MultiMBox.hxx:118
unsigned int getComplexLen()
Return the number of complex float values in this buffer.
Definition: SoDaBase.hxx:101
bool tx_enabled
if true, we&#39;re transmitting.
Definition: USRPTX.hxx:130
bool LO_configured
if true, the LO has had its gain/freq set.
Definition: USRPTX.hxx:156
void getTXStreamer()
setup transmit streamer.
Definition: USRPTX.cxx:252
void put(T *m)
Definition: MultiMBox.hxx:97
On receipt of a TVRT_LO_ENABLE command dump a perpetual constant IF stream of (1.0, 0.0) into the tx2 channel to get a steady output.
Definition: Command.hxx:381
bool waiting_to_run_dry
When set, we should send out a report when we run out of CW buffer.
Definition: USRPTX.hxx:148
double CW_tone_freq
Definition: USRPTX.hxx:133
On receipt of a TVRT_LO_CONFIG command , set the TX2 channel frequency to dparam[0] and the TX2 outpu...
Definition: Command.hxx:404
bool LO_enabled
if true, we&#39;re in local transverter mode
Definition: USRPTX.hxx:155
uhd::tx_metadata_t md
metadata describing USRP transmit buffer
Definition: USRPTX.hxx:152
CmdMBox * cmd_stream
command stream
Definition: USRPTX.hxx:128
void execCommand(Command *cmd)
Execute (dispatch) a message removed from the command stream to one of the basic Command handler func...
Definition: SoDaBase.hxx:335
uhd::tx_streamer::sptr tx_bits
USRP (UHD) transmit stream handle.
Definition: USRPTX.hxx:151