Applied 'start streaming at' patch from Douglas Geiger
authorJohnathan Corgan <jcorgan@corganenterprises.com>
Thu, 17 Sep 2009 17:37:27 +0000 (10:37 -0700)
committerJohnathan Corgan <jcorgan@corganenterprises.com>
Thu, 3 Dec 2009 23:49:12 +0000 (15:49 -0800)
usrp2/firmware/apps/app_common_v2.c
usrp2/firmware/apps/app_common_v2.h
usrp2/firmware/apps/factory_test.c
usrp2/firmware/apps/mimo_tx_slave.c
usrp2/firmware/apps/serdes_txrx.c
usrp2/firmware/apps/txrx.c
usrp2/host/include/usrp2/usrp2.h
usrp2/host/lib/control.h
usrp2/host/lib/usrp2.cc
usrp2/host/lib/usrp2_impl.cc
usrp2/host/lib/usrp2_impl.h

index 67cccd53b43131bc0ef6acad563963634231cef9..3681046e309fdc515feb48ceed9469cb2df19d1d 100644 (file)
@@ -478,7 +478,10 @@ handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len)
       break;
 
     case OP_START_RX_STREAMING:
-      start_rx_streaming_cmd(&pkt->ehdr.src, (op_start_rx_streaming_t *) payload);
+      if (pkt->fixed.timestamp == -1) // Start now (default)
+        start_rx_streaming_cmd(&pkt->ehdr.src, (op_start_rx_streaming_t *) payload);
+      else
+        start_rx_streaming_at_cmd(&pkt->ehdr.src, (op_start_rx_streaming_t *)payload, pkt->fixed.timestamp);
       ok = true;
       goto generic_reply;
     
index 5058661ad05c437b02386f531fe7324433b6084f..d076ae36462ca0e71d233ecf802ca29292fa88a0 100644 (file)
@@ -55,8 +55,10 @@ print_tune_result(char *msg, bool tune_ok,
 
 
 void start_rx_streaming_cmd(const u2_mac_addr_t *host, op_start_rx_streaming_t *p);
+void start_rx_streaming_at_cmd(const u2_mac_addr_t *host, op_start_rx_streaming_t *p, uint32_t time);
 void stop_rx_cmd(void);
 void restart_streaming(void);
+void restart_streaming_at(uint32_t time);
 bool is_streaming(void);
 
 void handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len);
index a4bc06d58cf5cc523e4c3b171ca314dc5f635998..1332f62198d42c2f929e35e22dd7071176998570 100644 (file)
@@ -187,6 +187,11 @@ start_rx_streaming_cmd(const u2_mac_addr_t *host, op_start_rx_streaming_t *p)
 }
 
 
+void start_rx_streaming_at_cmd(const u2_mac_addr_t *host, op_start_rx_streaming_t *p, uint32_t time)
+{}
+void restart_streaming_at(uint32_t time)
+{}
+
 void
 stop_rx_cmd(void)
 {
index e7da984c5e2d1218a1c7ed319faa15b212a986af..69010c248198b451331069239e65a7f26c852c0b 100644 (file)
@@ -192,6 +192,10 @@ start_rx_streaming_cmd(const u2_mac_addr_t *host, op_start_rx_streaming_t *p)
   restart_streaming();
 }
 
+void start_rx_streaming_at_cmd(const u2_mac_addr_t *host, op_start_rx_streaming_t *p, uint32_t time)
+{}
+void restart_streaming_at(uint32_t time)
+{}
 
 void
 stop_rx_cmd(void)
index 7816f7a653e5fc28a071a8e128d0ba527748a214..6eff8778ee67d6beae4c0df869beb3d64156c951 100644 (file)
@@ -184,6 +184,10 @@ start_rx_streaming_cmd(const u2_mac_addr_t *host, op_start_rx_streaming_t *p)
   restart_streaming();
 }
 
+void start_rx_streaming_at_cmd(const u2_mac_addr_t *host, op_start_rx_streaming_t *p, uint32_t time)
+{}
+void restart_streaming_at(uint32_t time)
+{}
 
 void
 stop_rx_cmd(void)
index b2487ed89d38f7f5c8b8a9266ffea44861f389e7..59eda45fc4be21ceeb65c343009d83910f425b91 100644 (file)
@@ -157,6 +157,34 @@ restart_streaming(void)
   dsp_rx_regs->rx_time = 0;            // enqueue second command
 }
 
+void
+restart_streaming_at(uint32_t time)
+{
+  // setup RX DSP regs
+  dsp_rx_regs->clear_state = 1;                        // reset
+
+  streaming_p = true;
+  streaming_frame_count = FRAMES_PER_CMD;
+
+  dsp_rx_regs->rx_command =
+    MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame,
+             streaming_items_per_frame,
+             0, 1);                    // set "chain" bit
+
+  // kick off the state machine
+  dbsm_start(&dsp_rx_sm);
+
+  dsp_rx_regs->rx_time = time;         // enqueue first of two commands
+
+  // make sure this one and the rest have the "now" and "chain" bits set.
+  dsp_rx_regs->rx_command =
+    MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame,
+             streaming_items_per_frame,
+             1, 1);                            
+
+  dsp_rx_regs->rx_time = 0;            // enqueue second command
+}
+
 void
 start_rx_streaming_cmd(const u2_mac_addr_t *host, op_start_rx_streaming_t *p)
 {
@@ -184,6 +212,32 @@ start_rx_streaming_cmd(const u2_mac_addr_t *host, op_start_rx_streaming_t *p)
   restart_streaming();
 }
 
+void
+start_rx_streaming_at_cmd(const u2_mac_addr_t *host, op_start_rx_streaming_t *p, uint32_t time)
+{
+  host_mac_addr = *host;       // remember who we're sending to
+
+  /*
+   * Construct  ethernet header and word0 and preload into two buffers
+   */
+  u2_eth_packet_t      pkt;
+  memset(&pkt, 0, sizeof(pkt));
+  pkt.ehdr.dst = *host;
+  pkt.ehdr.ethertype = U2_ETHERTYPE;
+  u2p_set_word0(&pkt.fixed, 0, 0);
+  // DSP RX will fill in timestamp
+
+  memcpy_wa(buffer_ram(DSP_RX_BUF_0), &pkt, sizeof(pkt));
+  memcpy_wa(buffer_ram(DSP_RX_BUF_1), &pkt, sizeof(pkt));
+
+
+  if (FW_SETS_SEQNO)
+    fw_seqno = 0;
+
+  streaming_items_per_frame = p->items_per_frame;
+  restart_streaming_at(time);
+}
+
 
 void
 stop_rx_cmd(void)
index 7a612f945bba06380af6cccb9df9c8a7997dff4d..07e5bf1df12b694875648c3b0becf52778f146fb 100644 (file)
@@ -177,6 +177,27 @@ namespace usrp2 {
      * \param items_per_frame  Number of 32-bit items per frame.
      */
     bool start_rx_streaming(unsigned int channel=0, unsigned int items_per_frame=0);
+    
+    /*!
+     * Start streaming receive mode at specified timestamp. USRP2 will send a
+     * continuous stream of DSP pipeline samples to host. Call rx_samples(...)
+     * to access.
+     *
+     * \param channel          Stream channel number (0-30)
+     * \param items_per_frame  Number of 32-bit items per frame.
+     * \param time             Timestamp to start streaming at
+     */
+    bool start_rx_streaming_at(unsigned int channel=0, unsigned int items_per_frame=0, unsigned int time=0);
+    
+    /*!
+     * Sync to PPS and start streaming receive mode at specified timestamp.
+     * Just like calling sync_to_pps() and start_rx_streaming_at().
+     *
+     * \param channel          Stream channel number (0-30)
+     * \param items_per_frame  Number of 32-bit items per frame.
+     * \param time             Timestamp to start streaming at
+     */
+    bool sync_and_start_rx_streaming_at(unsigned int channel=0, unsigned int items_per_frame=0, uint32_t time=0);
   
     /*!
      * Stop streaming receive mode.
index 8769e4522f2e7dcfe38cba6170eef5065c0b1c36..376c281a700910ad1485ea4fd7671c1c77cd76c4 100644 (file)
@@ -46,6 +46,14 @@ namespace usrp2 {
     op_start_rx_streaming_t op;
     op_generic_t           eop;
   };
+  
+  struct op_sync_and_start_rx_streaming_cmd 
+  {
+    u2_eth_packet_t        h;
+    op_generic_t            sync_op;
+    op_start_rx_streaming_t rx_op;
+    op_generic_t           eop;
+  };
     
   struct op_stop_rx_cmd {
     u2_eth_packet_t h;
index a2a9ecc1158a5b5a2483bca6ae111c38109506b4..ec3be55410f95a2b4baef6ec7ca1c9d47b655ec8 100644 (file)
@@ -241,6 +241,18 @@ namespace usrp2 {
     return d_impl->start_rx_streaming(channel, items_per_frame);
   }
   
+  bool
+  usrp2::start_rx_streaming_at(unsigned int channel, unsigned int items_per_frame, unsigned int time)
+  {
+    return d_impl->start_rx_streaming_at(channel, items_per_frame,time);
+  }
+  
+  bool
+  usrp2::sync_and_start_rx_streaming_at(unsigned int channel, unsigned int items_per_frame, unsigned int time)
+  {
+    return d_impl->sync_and_start_rx_streaming_at(channel, items_per_frame, time);
+  }
+  
   bool
   usrp2::rx_samples(unsigned int channel, rx_sample_handler *handler)
   {
index 3d030432429c42d270743697840161552f4db43f..ad1ea74b8b903a91e3ca63c3403aefaffbea49f3 100644 (file)
@@ -666,6 +666,110 @@ namespace usrp2 {
       return success;
     }
   }
+
+  bool
+  usrp2::impl::start_rx_streaming_at(unsigned int channel, unsigned int items_per_frame, unsigned int time)
+  {
+    if (channel > MAX_CHAN) {
+      std::cerr << "usrp2: invalid channel number (" << channel
+               << ")" << std::endl;
+      return false;
+    }
+
+    if (channel > 0) { // until firmware supports multiple streams
+      std::cerr << "usrp2: channel " << channel
+               << " not implemented" << std::endl;
+      return false;
+    }
+
+    {
+      omni_mutex_lock l(d_channel_rings_mutex);
+      if (d_channel_rings[channel]) {
+       std::cerr << "usrp2: channel " << channel
+                 << " already streaming" << std::endl;
+       return false;
+      }
+      
+      if (items_per_frame == 0)
+       items_per_frame = U2_MAX_SAMPLES;               // minimize overhead
+      
+      op_start_rx_streaming_cmd cmd;
+      op_generic_t reply;
+
+      memset(&cmd, 0, sizeof(cmd));
+      init_etf_hdrs(&cmd.h, d_addr, 0, CONTROL_CHAN, time);
+      cmd.op.opcode = OP_START_RX_STREAMING;
+      cmd.op.len = sizeof(cmd.op);
+      cmd.op.rid = d_next_rid++;
+      cmd.op.items_per_frame = htonl(items_per_frame);
+      cmd.eop.opcode = OP_EOP;
+      cmd.eop.len = sizeof(cmd.eop);
+    
+      bool success = false;
+      pending_reply p(cmd.op.rid, &reply, sizeof(reply));
+      success = transmit_cmd(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT);
+      success = success && (ntohx(reply.ok) == 1);
+      
+      if (success)
+       d_channel_rings[channel] = ring_sptr(new ring(d_eth_buf->max_frames()));
+
+      return success;
+    }
+  }
+  
+  bool
+  usrp2::impl::sync_and_start_rx_streaming_at(unsigned int channel, unsigned int items_per_frame, unsigned int time)
+  {
+  
+    if (channel > MAX_CHAN) {
+      std::cerr << "usrp2: invalid channel number (" << channel
+               << ")" << std::endl;
+      return false;
+    }
+
+    if (channel > 0) { // until firmware supports multiple streams
+      std::cerr << "usrp2: channel " << channel
+               << " not implemented" << std::endl;
+      return false;
+    }
+
+    {
+      omni_mutex_lock l(d_channel_rings_mutex);
+      if (d_channel_rings[channel]) {
+       std::cerr << "usrp2: channel " << channel
+                 << " already streaming" << std::endl;
+       return false;
+      }
+      
+      if (items_per_frame == 0)
+       items_per_frame = U2_MAX_SAMPLES;               // minimize overhead
+      
+      op_sync_and_start_rx_streaming_cmd cmd;
+      op_generic_t reply;
+
+      memset(&cmd, 0, sizeof(cmd));
+      init_etf_hdrs(&cmd.h, d_addr, 0, CONTROL_CHAN, time);
+      cmd.sync_op.opcode = OP_SYNC_TO_PPS;
+      cmd.sync_op.len = sizeof(cmd.sync_op);
+      cmd.sync_op.rid = d_next_rid++;
+      cmd.rx_op.opcode = OP_START_RX_STREAMING;
+      cmd.rx_op.len = sizeof(cmd.rx_op);
+      cmd.rx_op.rid = d_next_rid++;
+      cmd.rx_op.items_per_frame = htonl(items_per_frame);
+      cmd.eop.opcode = OP_EOP;
+      cmd.eop.len = sizeof(cmd.eop);
+    
+      bool success = false;
+      pending_reply p(cmd.sync_op.rid, &reply, sizeof(reply));
+      success = transmit_cmd(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT);
+      success = success && (ntohx(reply.ok) == 1);
+      
+      if (success)
+       d_channel_rings[channel] = ring_sptr(new ring(d_eth_buf->max_frames()));
+
+      return success;
+    }
+  }
   
   bool
   usrp2::impl::stop_rx_streaming(unsigned int channel)
index ed71a6ba33903c09589b342ea75cdccb8c1fcf34..aaed66bc7995e3e717ece4884b3b4079f7d0d66f 100644 (file)
@@ -143,6 +143,8 @@ namespace usrp2 {
     bool write_gpio(int bank, uint16_t value, uint16_t mask);
     bool read_gpio(int bank, uint16_t *value);
     bool start_rx_streaming(unsigned int channel, unsigned int items_per_frame);
+    bool start_rx_streaming_at(unsigned int channel, unsigned int items_per_frame, unsigned int time);
+    bool sync_and_start_rx_streaming_at(unsigned int channel, unsigned int items_per_frame, unsigned int time);
     bool rx_samples(unsigned int channel, rx_sample_handler *handler);
     bool flush_rx_samples(unsigned int channel);
     bool stop_rx_streaming(unsigned int channel);