Merged features/inband-usb -r6431:8293 into trunk.
[debian/gnuradio] / usrp / host / lib / inband / usrp_rx_stub.cc
index 4bdb106b18ac1822b673bee8e8e06e180381f883..1c96b7a7ac44efb0c96a89db420dc0c61af9d40b 100644 (file)
@@ -43,7 +43,7 @@ typedef usrp_inband_usb_packet transport_pkt;
 
 static const bool verbose = false;
 
-bool usrp_rx_stop;
+bool usrp_rx_stop_stub;
 
 // Used for the fake control packet response code to send the responses back up
 // the RX.  The TX stub dumps responses in to this queue.
@@ -52,15 +52,32 @@ std::queue<pmt_t> d_cs_queue;
 usrp_rx_stub::usrp_rx_stub(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg)
   : mb_mblock(rt, instance_name, user_arg),
     d_samples_per_frame((long)(126)),
+    d_decim_rx(128),
     d_amplitude(16384),
     d_disk_write(false)
 {
+
+  // Information about the rates are passed all the way from the app in the form
+  // of a dictionary.  We use this to read the RX decimation rate and compute
+  // the approximate number of MS/s as a form of flow control for the stub.
+  pmt_t usrp_dict = user_arg;
+
+  if (pmt_is_dict(usrp_dict)) {
+    // Read the RX decimation rate
+    if(pmt_t decim_rx = pmt_dict_ref(usrp_dict, 
+                                      pmt_intern("decim-rx"), 
+                                      PMT_NIL)) {
+      if(!pmt_eqv(decim_rx, PMT_NIL)) 
+        d_decim_rx = pmt_to_long(decim_rx);
+    }
+  }
+
   d_cs = define_port("cs", "usrp-rx-cs", true, mb_port::EXTERNAL);
   
   // initialize NCO
   double freq = 100e3;
   int interp = 32;                         // 32 -> 4MS/s
-  double sample_rate = 128e6 / interp; 
+  double sample_rate = 64e6 / interp;  
   d_nco.set_freq(2*M_PI * freq/sample_rate);
 
   //d_disk_write = true;
@@ -68,7 +85,7 @@ usrp_rx_stub::usrp_rx_stub(mb_runtime *rt, const std::string &instance_name, pmt
   if(d_disk_write)
     d_ofile.open("raw_rx.dat",std::ios::binary|std::ios::out);
   
-  usrp_rx_stop = false;
+  usrp_rx_stop_stub = false;
 }
 
 usrp_rx_stub::~usrp_rx_stub() 
@@ -80,7 +97,6 @@ usrp_rx_stub::~usrp_rx_stub()
 void 
 usrp_rx_stub::initial_transition()
 {
-  
 }
 
 void
@@ -90,94 +106,121 @@ usrp_rx_stub::handle_message(mb_message_sptr msg)
   pmt_t port_id = msg->port_id();
   pmt_t data = msg->data(); 
 
+  if (pmt_eq(msg->signal(), s_timeout)
+      && !pmt_eq(msg->data(), s_done)) {
+  
+    if(!usrp_rx_stop_stub) 
+      read_and_respond();
+    else {  // requested to stop
+      cancel_timeout(msg->metadata());
+      usrp_rx_stop_stub=false;
+      if(verbose)
+        std::cout << "[USRP_RX_STUB] Stopping RX stub\n";
+    }
+
+  }
+
   // Theoretically only have 1 message to ever expect, but
   // want to make sure its at least what we want
-  if(pmt_eq(port_id, d_cs->port_symbol())) {
+  if(pmt_eq(port_id, d_cs->port_symbol())
+      && pmt_eqv(event, s_cmd_usrp_rx_start_reading)) {
 
     if(verbose)
-      std::cout << "[USRP_RX_STUB] Starting...\n";
+      std::cout << "[USRP_RX_STUB] Starting with decim @ " 
+                << d_decim_rx << std::endl;
     
-    if(pmt_eqv(event, s_cmd_usrp_rx_start_reading))
-      read_and_respond(data);
+      start_packet_timer();
   }
 }
 
+// Setup a periodic timer which will drive packet generation
 void
-usrp_rx_stub::read_and_respond(pmt_t data)
+usrp_rx_stub::start_packet_timer()
 {
+  d_t0 = mb_time::time();   // current time
+
+  // Calculate the inter-packet arrival time.  
+  double samples_per_sec = (64.0/(double)d_decim_rx)*1000000.0;
+  double frames_per_sec = samples_per_sec / (double)d_samples_per_frame;
+  double frame_rate = 1.0 / frames_per_sec;
+
+  if(verbose) {
+    std::cout << "[USRP_RX_STUB] Scheduling periodic packet generator\n";
+    std::cout << "\tsamples_per_sec: " << samples_per_sec << std::endl;
+    std::cout << "\tframes_per_sec: " << frames_per_sec << std::endl;
+    std::cout << "\tframe_rate: " << frame_rate << std::endl;
+  }
 
-  while(!usrp_rx_stop) {
+  schedule_periodic_timeout(d_t0 + frame_rate, mb_time(frame_rate), PMT_T);
+}
 
-    long nsamples_this_frame = d_samples_per_frame;
+void
+usrp_rx_stub::read_and_respond()
+{
 
-    size_t nshorts = 2 * nsamples_this_frame;  // 16-bit I & Q
-    long channel = 0;
-    long n_bytes = nshorts*2;
-    pmt_t uvec = pmt_make_s16vector(nshorts, 0);
-    size_t ignore;
-    int16_t *samples = pmt_s16vector_writeable_elements(uvec, ignore);
+  long nsamples_this_frame = d_samples_per_frame;
 
-    // fill in the complex sinusoid
+  size_t nshorts = 2 * nsamples_this_frame;    // 16-bit I & Q
+  long channel = 0;
+  long n_bytes = nshorts*2;
+  pmt_t uvec = pmt_make_s16vector(nshorts, 0);
+  size_t ignore;
+  int16_t *samples = pmt_s16vector_writeable_elements(uvec, ignore);
 
-    for (int i = 0; i < nsamples_this_frame; i++){
+  // fill in the complex sinusoid
 
-      if (1){
-        gr_complex s;
-        d_nco.sincos(&s, 1, d_amplitude);
-        // write 16-bit i & q
-        samples[2*i] =   (int16_t) s.real();
-        samples[2*i+1] = (int16_t) s.imag();
-      }
-      else {
-        gr_complex s(d_amplitude, d_amplitude);
+  for (int i = 0; i < nsamples_this_frame; i++){
 
-        // write 16-bit i & q
-        samples[2*i] =   (int16_t) s.real();
-        samples[2*i+1] = (int16_t) s.imag();
-      }
+    if (1){
+      gr_complex s;
+      d_nco.sincos(&s, 1, d_amplitude);
+      // write 16-bit i & q
+      samples[2*i] =   (int16_t) s.real();
+      samples[2*i+1] = (int16_t) s.imag();
     }
-    
-    if(d_disk_write)
-      d_ofile.write((const char *)samples, n_bytes);
-  
-    pmt_t v_pkt = pmt_make_u8vector(sizeof(transport_pkt), 0);
-    transport_pkt *pkt =
-      (transport_pkt *) pmt_u8vector_writeable_elements(v_pkt, ignore);
+    else {
+      gr_complex s(d_amplitude, d_amplitude);
 
-    pkt->set_header(0, channel, 0, n_bytes);
-    pkt->set_timestamp(0xffffffff);
-    memcpy(pkt->payload(), samples, n_bytes);
-    
-    d_cs->send(s_response_usrp_rx_read, pmt_list3(PMT_NIL, PMT_T, v_pkt));
-
-    // Now lets check the shared CS queue between the TX and RX stub.  Each
-    // element in a queue is a list where the first element is an invocation
-    // handle and the second element is a PMT u8 vect representation of the
-    // CS packet response which can just be passed transparently.
-    while(!d_cs_queue.empty()) {
-      
-      pmt_t cs_pkt = d_cs_queue.front();
-      d_cs_queue.pop();
-
-      pmt_t invocation_handle = pmt_nth(0, cs_pkt);
-      pmt_t v_pkt = pmt_nth(1, cs_pkt);
-
-      d_cs->send(s_response_usrp_rx_read,   
-                 pmt_list3(invocation_handle, 
-                           PMT_T, 
-                           v_pkt));  // Take the front CS pkt
-
-      
-      if(verbose)
-        std::cout << "[USRP_RX_STUB] Received CS response from TX stub\n";
+      // write 16-bit i & q
+      samples[2*i] =   (int16_t) s.real();
+      samples[2*i+1] = (int16_t) s.imag();
     }
-
   }
   
-  usrp_rx_stop = false;
+  if(d_disk_write)
+    d_ofile.write((const char *)samples, n_bytes);
+
+  pmt_t v_pkt = pmt_make_u8vector(sizeof(transport_pkt), 0);
+  transport_pkt *pkt =
+    (transport_pkt *) pmt_u8vector_writeable_elements(v_pkt, ignore);
+
+  pkt->set_header(0, channel, 0, n_bytes);
+  pkt->set_timestamp(0xffffffff);
+  memcpy(pkt->payload(), samples, n_bytes);
+  
+  d_cs->send(s_response_usrp_rx_read, pmt_list3(PMT_NIL, PMT_T, v_pkt));
 
-  if(verbose)
-    std::cout << "[USRP_RX_STUB] Got fake RX stop\n";
+  // Now lets check the shared CS queue between the TX and RX stub.  Each
+  // element in a queue is a list where the first element is an invocation
+  // handle and the second element is a PMT u8 vect representation of the
+  // CS packet response which can just be passed transparently.
+  while(!d_cs_queue.empty()) {
+    
+    pmt_t cs_pkt = d_cs_queue.front();
+    d_cs_queue.pop();
+
+    pmt_t invocation_handle = pmt_nth(0, cs_pkt);
+    pmt_t v_pkt = pmt_nth(1, cs_pkt);
+
+    d_cs->send(s_response_usrp_rx_read,   
+               pmt_list3(invocation_handle, 
+                         PMT_T, 
+                         v_pkt));  // Take the front CS pkt
+
+    
+    if(verbose)
+      std::cout << "[USRP_RX_STUB] Received CS response from TX stub\n";
+  }
 
 }