Once and for all, here is the properly updated Makefile.am for the apps
[debian/gnuradio] / usrp / limbo / apps-inband / test_usrp_inband_2rx.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2007,2008 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 <mblock/mblock.h>
27 #include <mblock/runtime.h>
28 #include <mb_runtime_nop.h>             // QA only
29 #include <mblock/protocol_class.h>
30 #include <mblock/exception.h>
31 #include <mblock/msg_queue.h>
32 #include <mblock/message.h>
33 #include <mb_mblock_impl.h>
34 #include <mblock/msg_accepter.h>
35 #include <mblock/class_registry.h>
36 #include <pmt.h>
37 #include <stdio.h>
38 #include <string.h>
39 #include <iostream>
40 #include <fstream>
41
42 // Include the symbols needed for communication with USRP server
43 #include <symbols_usrp_server_cs.h>
44 #include <symbols_usrp_channel.h>
45 #include <symbols_usrp_low_level_cs.h>
46 #include <symbols_usrp_rx.h>
47
48 static bool verbose = true;
49
50 class test_usrp_rx : public mb_mblock
51 {
52   mb_port_sptr  d_rx;
53   mb_port_sptr  d_cs;
54   pmt_t         d_rx_chan0, d_rx_chan1;
55
56   enum state_t {
57     INIT,
58     OPENING_USRP,
59     ALLOCATING_CHANNEL,
60     RECEIVING,
61     CLOSING_CHANNEL,
62     CLOSING_USRP,
63   };
64
65   state_t       d_state;
66
67   std::ofstream d_ofile;
68
69   long d_samples_recvd;
70   long d_samples_to_recv;
71
72  public:
73   test_usrp_rx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
74   ~test_usrp_rx();
75   void initial_transition();
76   void handle_message(mb_message_sptr msg);
77
78  protected:
79   void open_usrp();
80   void close_usrp();
81   void allocate_channel();
82   void send_packets();
83   void enter_receiving();
84   void build_and_send_next_frame();
85   void handle_response_recv_raw_samples(pmt_t invocation_handle);
86   void enter_closing_channel();
87 };
88
89 test_usrp_rx::test_usrp_rx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
90   : mb_mblock(runtime, instance_name, user_arg),
91     d_rx_chan0(PMT_NIL), d_rx_chan1(PMT_NIL),
92     d_samples_recvd(0),
93     d_samples_to_recv(20e6)
94
95   d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
96   d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
97   
98   // Pass a dictionary to usrp_server which specifies which interface to use, the stub or USRP
99   pmt_t usrp_dict = pmt_make_dict();
100   
101   // To test the application without a USRP
102   bool fake_usrp_p = false;
103   if(fake_usrp_p) {
104     pmt_dict_set(usrp_dict, 
105                  pmt_intern("fake-usrp"),
106                              PMT_T);
107   }
108
109   // Specify the RBF to use
110   pmt_dict_set(usrp_dict,
111                pmt_intern("rbf"),
112                pmt_intern("inband_2rxhb_2tx.rbf"));
113
114   pmt_dict_set(usrp_dict,
115                pmt_intern("decim-rx"),
116                pmt_from_long(64));
117
118   define_component("server", "usrp_server", usrp_dict);
119
120   connect("self", "rx0", "server", "rx0");
121   connect("self", "cs", "server", "cs");
122
123 }
124
125 test_usrp_rx::~test_usrp_rx()
126 {
127 }
128
129 void
130 test_usrp_rx::initial_transition()
131 {
132   open_usrp();
133 }
134
135 void
136 test_usrp_rx::handle_message(mb_message_sptr msg)
137 {
138   pmt_t event = msg->signal();
139   pmt_t data = msg->data();
140
141   pmt_t handle = PMT_F;
142   pmt_t status = PMT_F;
143   std::string error_msg;
144   
145   switch(d_state){
146     
147     //----------------------------- OPENING_USRP ----------------------------//
148     // We only expect a response from opening the USRP which should be succesful
149     // or failed.
150     case OPENING_USRP:
151       if (pmt_eq(event, s_response_open)){
152         status = pmt_nth(1, data);
153         if (pmt_eq(status, PMT_T)){
154           allocate_channel();
155           return;
156         }
157         else {
158           error_msg = "failed to open usrp:";
159           goto bail;
160         }
161       }
162       goto unhandled;
163       
164     //----------------------- ALLOCATING CHANNELS --------------------//
165     // Allocate an RX channel to perform the overrun test.
166     case ALLOCATING_CHANNEL:
167       if (pmt_eq(event, s_response_allocate_channel)){
168         status = pmt_nth(1, data);
169         if(pmt_eqv(d_rx_chan0, PMT_NIL))
170           d_rx_chan0 = pmt_nth(2, data);
171         else
172           d_rx_chan1 = pmt_nth(2, data);
173
174         if (pmt_eq(status, PMT_T) && !pmt_eqv(d_rx_chan1, PMT_NIL)){
175           enter_receiving();
176           return;
177         }
178         else if(pmt_eq(status, PMT_F)){
179           error_msg = "failed to allocate channel:";
180           goto bail;
181         }
182         return;
183       }
184       goto unhandled;
185
186     //--------------------------- RECEIVING ------------------------------//
187     // In the receiving state, we receive samples until the specified amount
188     // while counting the number of overruns.
189     case RECEIVING:
190       if (pmt_eq(event, s_response_recv_raw_samples)){
191         status = pmt_nth(1, data);
192
193         if (pmt_eq(status, PMT_T)){
194           handle_response_recv_raw_samples(data);
195           return;
196         }
197         else {
198           error_msg = "bad response-xmit-raw-frame:";
199           goto bail;
200         }
201       }
202       goto unhandled;
203     
204     //------------------------- CLOSING CHANNEL ----------------------------//
205     // Check deallocation response for the RX channel 
206     case CLOSING_CHANNEL:
207       if (pmt_eq(event, s_response_deallocate_channel)){
208         status = pmt_nth(1, data);
209
210         if (pmt_eq(status, PMT_T)){
211           close_usrp();
212           return;
213         }
214         else {
215           error_msg = "failed to deallocate channel:";
216           goto bail;
217         }
218       }
219
220       // Alternately, we ignore all response recv samples while waiting for the
221       // channel to actually close
222       if (pmt_eq(event, s_response_recv_raw_samples))
223         return;
224
225       goto unhandled;
226
227     //--------------------------- CLOSING USRP ------------------------------//
228     // Once we have received a successful USRP close response, we shutdown all
229     // mblocks and exit.
230     case CLOSING_USRP:
231       if (pmt_eq(event, s_response_close)){
232         status = pmt_nth(1, data);
233
234         if (pmt_eq(status, PMT_T)){
235           fflush(stdout);
236           shutdown_all(PMT_T);
237           return;
238         }
239         else {
240           error_msg = "failed to close USRP:";
241           goto bail;
242         }
243       }
244       goto unhandled;
245
246     default:
247       goto unhandled;
248   }
249   return;
250
251  // An error occured, print it, and shutdown all m-blocks
252  bail:
253   std::cerr << error_msg << data
254             << "status = " << status << std::endl;
255   shutdown_all(PMT_F);
256   return;
257
258  // Received an unhandled message for a specific state
259  unhandled:
260   if(verbose && !pmt_eq(event, pmt_intern("%shutdown")))
261     std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
262               << "in state "<< d_state << std::endl;
263 }
264
265
266 void
267 test_usrp_rx::open_usrp()
268 {
269   pmt_t which_usrp = pmt_from_long(0);
270
271   d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, which_usrp));
272   d_state = OPENING_USRP;
273   
274   if(verbose)
275     std::cout << "[TEST_USRP_INBAND_RX] Opening the USRP\n";
276 }
277
278 void
279 test_usrp_rx::close_usrp()
280 {
281
282   d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
283   d_state = CLOSING_USRP;
284   
285   if(verbose)
286     std::cout << "[TEST_USRP_INBAND_RX] Closing the USRP\n";
287 }
288
289 void
290 test_usrp_rx::allocate_channel()
291 {
292   long capacity = (long) 16e6;
293   d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
294   d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
295   d_state = ALLOCATING_CHANNEL;
296   
297   if(verbose)
298     std::cout << "[TEST_USRP_INBAND_RX] Requesting RX channel allocation\n";
299 }
300
301 void
302 test_usrp_rx::enter_receiving()
303 {
304   d_state = RECEIVING;
305
306   d_rx->send(s_cmd_start_recv_raw_samples,
307              pmt_list2(PMT_F,
308                        d_rx_chan0));
309   
310   d_rx->send(s_cmd_start_recv_raw_samples,
311              pmt_list2(PMT_F,
312                        d_rx_chan1));
313
314   if(verbose)
315     std::cout << "[TEST_USRP_INBAND_RX] Receiving...\n";
316 }
317
318 void
319 test_usrp_rx::handle_response_recv_raw_samples(pmt_t data)
320 {
321   pmt_t invocation_handle = pmt_nth(0, data);
322   pmt_t status = pmt_nth(1, data);
323   pmt_t v_samples = pmt_nth(2, data);
324   pmt_t timestamp = pmt_nth(3, data);
325   pmt_t channel = pmt_nth(4, data);
326   pmt_t properties = pmt_nth(5, data);
327
328   d_samples_recvd += pmt_length(v_samples) / 4;
329
330   // Check for overrun
331   if(!pmt_is_dict(properties)) {
332     std::cout << "[TEST_USRP_INBAND_RX] Recv samples dictionary is improper\n";
333     return;
334   }
335
336   // Check if the number samples we have received meets the test
337   if(d_samples_recvd >= d_samples_to_recv) {
338     d_rx->send(s_cmd_stop_recv_raw_samples, pmt_list2(PMT_NIL, d_rx_chan0));
339     d_rx->send(s_cmd_stop_recv_raw_samples, pmt_list2(PMT_NIL, d_rx_chan1));
340     enter_closing_channel();
341     return;
342   }
343
344 }
345
346 void
347 test_usrp_rx::enter_closing_channel()
348 {
349   d_state = CLOSING_CHANNEL;
350
351   d_rx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_rx_chan0));
352   d_rx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_rx_chan1));
353   
354   if(verbose)
355     std::cout << "[TEST_USRP_INBAND_RX] Deallocating RX channel\n";
356 }
357
358 REGISTER_MBLOCK_CLASS(test_usrp_rx);
359
360
361 // ----------------------------------------------------------------
362
363 int
364 main (int argc, char **argv)
365 {
366   mb_runtime_sptr rt = mb_make_runtime();
367   pmt_t result = PMT_NIL;
368
369   rt->run("top", "test_usrp_rx", PMT_F, &result);
370
371 }