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