Statistics
| Branch: | Tag: | Revision:

root / usrp / host / apps-inband / test_usrp_inband_tx.cc @ 42d9c6f4

History | View | Annotate | Download (9.5 kB)

1
/* -*- c++ -*- */
2
/*
3
 * Copyright 2007 Free Software Foundation, Inc.
4
 * 
5
 * This file is part of GNU Radio
6
 * 
7
 * GNU Radio is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3, or (at your option)
10
 * any later version.
11
 * 
12
 * GNU Radio is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 * 
17
 * You should have received a copy of the GNU General Public License along
18
 * with this program; if not, write to the Free Software Foundation, Inc.,
19
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
 */
21
22
#ifdef HAVE_CONFIG_H
23
#include <config.h>
24
#endif
25
26
#include <mb_mblock.h>
27
#include <mb_runtime.h>
28
#include <mb_protocol_class.h>
29
#include <mb_exception.h>
30
#include <mb_msg_queue.h>
31
#include <mb_message.h>
32
#include <mb_msg_accepter.h>
33
#include <mb_class_registry.h>
34
#include <pmt.h>
35
#include <stdio.h>
36
#include <string.h>
37
#include <iostream>
38
39
#include <ui_nco.h>
40
#include <symbols_usrp_server_cs.h>
41
#include <symbols_usrp_channel.h>
42
#include <symbols_usrp_low_level_cs.h>
43
#include <symbols_usrp_tx.h>
44
45
static bool verbose = false;
46
47
class test_usrp_tx : public mb_mblock
48
{
49
  mb_port_sptr         d_tx;
50
  mb_port_sptr         d_cs;
51
  pmt_t                d_tx_chan;        // returned tx channel handle
52
53
  enum state_t {
54
    INIT,
55
    OPENING_USRP,
56
    ALLOCATING_CHANNEL,
57
    TRANSMITTING,
58
    CLOSING_CHANNEL,
59
    CLOSING_USRP,
60
  };
61
62
  state_t        d_state;
63
  long                d_nsamples_to_send;
64
  long                d_nsamples_xmitted;
65
  long                d_nframes_xmitted;
66
  long                d_samples_per_frame;
67
  bool                d_done_sending;
68
69
  // for generating sine wave output
70
  ui_nco<float,float>        d_nco;
71
  double                d_amplitude;
72
73
 public:
74
  test_usrp_tx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
75
  ~test_usrp_tx();
76
  void initial_transition();
77
  void handle_message(mb_message_sptr msg);
78
79
 protected:
80
  void open_usrp();
81
  void close_usrp();
82
  void allocate_channel();
83
  void send_packets();
84
  void enter_transmitting();
85
  void build_and_send_next_frame();
86
  void handle_xmit_response(pmt_t invocation_handle);
87
  void enter_closing_channel();
88
};
89
90
test_usrp_tx::test_usrp_tx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
91
  : mb_mblock(runtime, instance_name, user_arg),
92
    d_state(INIT), d_nsamples_to_send((long) 40e6),
93
    d_nsamples_xmitted(0),
94
    d_nframes_xmitted(0),
95
    //d_samples_per_frame((long)(126)),
96
    //d_samples_per_frame((long)(126 * 3.5)),        // non-full packet
97
    d_samples_per_frame((long)(126 * 4)),        // full packet
98
    d_done_sending(false),
99
    d_amplitude(16384)
100
{ 
101
  // std::cout << "[TEST_USRP_TX] Initializing...\n";
102
  
103
  d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
104
  d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
105
  
106
  //bool fake_usrp_p = true;
107
  bool fake_usrp_p = false;
108
109
  // Test the TX side
110
111
  pmt_t usrp_dict = pmt_make_dict();
112
113
  if(fake_usrp_p) {
114
    pmt_dict_set(usrp_dict, 
115
                 pmt_intern("fake-usrp"),
116
                             PMT_T);
117
  }
118
  
119
  // Specify the RBF to use
120
  pmt_dict_set(usrp_dict,
121
               pmt_intern("rbf"),
122
               pmt_intern("cs1.rbf"));
123
124
  // Set TX and RX interpolations
125
  pmt_dict_set(usrp_dict,
126
               pmt_intern("interp-tx"),
127
               pmt_from_long(128));
128
129
  pmt_dict_set(usrp_dict,
130
               pmt_intern("decim-rx"),
131
               pmt_from_long(16));
132
  
133
  pmt_dict_set(usrp_dict,
134
               pmt_intern("rf-freq"),
135
               pmt_from_long(10e6));
136
137
  define_component("server", "usrp_server", usrp_dict);
138
139
  connect("self", "tx0", "server", "tx0");
140
  connect("self", "cs", "server", "cs");
141
142
  // initialize NCO
143
  double freq = 100e3;
144
  int interp = 32;                            // 32 -> 4MS/s
145
  double sample_rate = 128e6 / interp;        
146
  d_nco.set_freq(2*M_PI * freq/sample_rate);
147
148
  // FIXME need to somehow set the interp rate in the USRP.
149
  // for now, we'll have the low-level code hardwire it.
150
}
151
152
test_usrp_tx::~test_usrp_tx()
153
{
154
}
155
156
void
157
test_usrp_tx::initial_transition()
158
{
159
  open_usrp();
160
}
161
162
void
163
test_usrp_tx::handle_message(mb_message_sptr msg)
164
{
165
  pmt_t        event = msg->signal();
166
  pmt_t data = msg->data();
167
168
  pmt_t handle = PMT_F;
169
  pmt_t status = PMT_F;
170
  std::string error_msg;
171
  
172
  //std::cout << msg << std::endl;
173
174
  switch(d_state){
175
  case OPENING_USRP:
176
    if (pmt_eq(event, s_response_open)){
177
      status = pmt_nth(1, data);
178
      if (pmt_eq(status, PMT_T)){
179
        allocate_channel();
180
        return;
181
      }
182
      else {
183
        error_msg = "failed to open usrp:";
184
        goto bail;
185
      }
186
    }
187
    goto unhandled;
188
    
189
  case ALLOCATING_CHANNEL:
190
    if (pmt_eq(event, s_response_allocate_channel)){
191
      status = pmt_nth(1, data);
192
      d_tx_chan = pmt_nth(2, data);
193
194
      if (pmt_eq(status, PMT_T)){
195
        enter_transmitting();
196
        return;
197
      }
198
      else {
199
        error_msg = "failed to allocate channel:";
200
        goto bail;
201
      }
202
    }
203
    goto unhandled;
204
205
  case TRANSMITTING:
206
    if (pmt_eq(event, s_response_xmit_raw_frame)){
207
      handle = pmt_nth(0, data);
208
      status = pmt_nth(1, data);
209
210
      if (pmt_eq(status, PMT_T)){
211
        handle_xmit_response(handle);
212
        return;
213
      }
214
      else {
215
        error_msg = "bad response-xmit-raw-frame:";
216
        goto bail;
217
      }
218
    }
219
    goto unhandled;
220
221
  case CLOSING_CHANNEL:
222
    if (pmt_eq(event, s_response_deallocate_channel)){
223
      status = pmt_nth(1, data);
224
225
      if (pmt_eq(status, PMT_T)){
226
        close_usrp();
227
        return;
228
      }
229
      else {
230
        error_msg = "failed to deallocate channel:";
231
        goto bail;
232
      }
233
    }
234
    goto unhandled;
235
236
  case CLOSING_USRP:
237
    if (pmt_eq(event, s_response_close)){
238
      status = pmt_nth(1, data);
239
240
      if (pmt_eq(status, PMT_T)){
241
        shutdown_all(PMT_T);
242
        return;
243
      }
244
      else {
245
        error_msg = "failed to close USRP:";
246
        goto bail;
247
      }
248
    }
249
    goto unhandled;
250
251
  default:
252
    goto unhandled;
253
  }
254
  return;
255
256
 bail:
257
  std::cerr << error_msg << data
258
            << "status = " << status << std::endl;
259
  shutdown_all(PMT_F);
260
  return;
261
262
 unhandled:
263
  std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
264
            << "in state "<< d_state << std::endl;
265
}
266
267
268
void
269
test_usrp_tx::open_usrp()
270
{
271
  pmt_t which_usrp = pmt_from_long(0);
272
273
  d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, which_usrp));
274
  d_state = OPENING_USRP;
275
}
276
277
void
278
test_usrp_tx::close_usrp()
279
{
280
  d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
281
  d_state = CLOSING_USRP;
282
}
283
284
void
285
test_usrp_tx::allocate_channel()
286
{
287
  long capacity = (long) 16e6;
288
  d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
289
  d_state = ALLOCATING_CHANNEL;
290
}
291
292
void
293
test_usrp_tx::enter_transmitting()
294
{
295
  d_state = TRANSMITTING;
296
  d_nsamples_xmitted = 0;
297
  
298
  // FIXME: carrier sense hack
299
  d_tx->send(s_cmd_to_control_channel,    // C/S packet
300
             pmt_list2(PMT_NIL,           // invoc handle
301
                       pmt_list1(
302
                            pmt_list2(s_op_write_reg, 
303
                                      pmt_list2(
304
                                      pmt_from_long(1), 
305
                                      pmt_from_long(21))))));
306
307
  build_and_send_next_frame();        // fire off 4 to start pipeline
308
  build_and_send_next_frame();
309
  build_and_send_next_frame();
310
  build_and_send_next_frame();
311
}
312
313
void
314
test_usrp_tx::build_and_send_next_frame()
315
{
316
  // allocate the uniform vector for the samples
317
  // FIXME perhaps hold on to this between calls
318
319
#if 1
320
  long nsamples_this_frame =
321
    std::min(d_nsamples_to_send - d_nsamples_xmitted,
322
             d_samples_per_frame);
323
#else
324
  long nsamples_this_frame = d_samples_per_frame;
325
#endif
326
327
  if (nsamples_this_frame == 0){
328
    d_done_sending = true;
329
    return;
330
  }
331
    
332
333
  size_t nshorts = 2 * nsamples_this_frame;        // 16-bit I & Q
334
  pmt_t uvec = pmt_make_s16vector(nshorts, 0);
335
  size_t ignore;
336
  int16_t *samples = pmt_s16vector_writeable_elements(uvec, ignore);
337
338
  // fill in the complex sinusoid
339
340
  for (int i = 0; i < nsamples_this_frame; i++){
341
342
    if (1){
343
      gr_complex s;
344
      d_nco.sincos(&s, 1, d_amplitude);
345
      // write 16-bit i & q
346
      samples[2*i] =   (int16_t) s.real();
347
      samples[2*i+1] = (int16_t) s.imag();
348
    }
349
    else {
350
      gr_complex s(d_amplitude, d_amplitude);
351
352
      // write 16-bit i & q
353
      samples[2*i] =   (int16_t) s.real();
354
      samples[2*i+1] = (int16_t) s.imag();
355
    }
356
  }
357
358
  pmt_t tx_properties = pmt_make_dict();
359
  pmt_dict_set(tx_properties,
360
               pmt_intern("carrier-sense"),
361
               PMT_T);
362
363
  pmt_t timestamp = pmt_from_long(0xffffffff);        // NOW
364
  d_tx->send(s_cmd_xmit_raw_frame,
365
             pmt_list5(pmt_from_long(d_nframes_xmitted),  // invocation-handle
366
                       d_tx_chan,                          // channel
367
                       uvec,                                  // the samples
368
                       timestamp,
369
           tx_properties));
370
371
  d_nsamples_xmitted += nsamples_this_frame;
372
  d_nframes_xmitted++;
373
374
  if(verbose)
375
    std::cout << "[TEST_USRP_INBAND_TX] Transmitted frame\n";
376
}
377
378
379
void
380
test_usrp_tx::handle_xmit_response(pmt_t handle)
381
{
382
  if (d_done_sending &&
383
      pmt_to_long(handle) == (d_nframes_xmitted - 1)){
384
    // We're done sending and have received all responses
385
    enter_closing_channel();
386
  }
387
388
  build_and_send_next_frame();
389
}
390
391
void
392
test_usrp_tx::enter_closing_channel()
393
{
394
  d_state = CLOSING_CHANNEL;
395
  
396
  d_tx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_tx_chan));
397
}
398
399
REGISTER_MBLOCK_CLASS(test_usrp_tx);
400
401
402
// ----------------------------------------------------------------
403
404
int
405
main (int argc, char **argv)
406
{
407
  // handle any command line args here
408
409
  mb_runtime_sptr rt = mb_make_runtime();
410
  pmt_t result = PMT_NIL;
411
412
  rt->run("top", "test_usrp_tx", PMT_F, &result);
413
}