From 7f28201b45a63735b3b710105e1c86dbe1f4e514 Mon Sep 17 00:00:00 2001 From: Johnathan Corgan Date: Thu, 17 Sep 2009 10:37:27 -0700 Subject: Applied 'start streaming at' patch from Douglas Geiger --- usrp2/firmware/apps/app_common_v2.c | 5 +- usrp2/firmware/apps/app_common_v2.h | 2 + usrp2/firmware/apps/factory_test.c | 5 ++ usrp2/firmware/apps/mimo_tx_slave.c | 4 ++ usrp2/firmware/apps/serdes_txrx.c | 4 ++ usrp2/firmware/apps/txrx.c | 54 +++++++++++++++++++ usrp2/host/include/usrp2/usrp2.h | 21 ++++++++ usrp2/host/lib/control.h | 8 +++ usrp2/host/lib/usrp2.cc | 12 +++++ usrp2/host/lib/usrp2_impl.cc | 104 ++++++++++++++++++++++++++++++++++++ usrp2/host/lib/usrp2_impl.h | 2 + 11 files changed, 220 insertions(+), 1 deletion(-) diff --git a/usrp2/firmware/apps/app_common_v2.c b/usrp2/firmware/apps/app_common_v2.c index 67cccd53b..3681046e3 100644 --- a/usrp2/firmware/apps/app_common_v2.c +++ b/usrp2/firmware/apps/app_common_v2.c @@ -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; diff --git a/usrp2/firmware/apps/app_common_v2.h b/usrp2/firmware/apps/app_common_v2.h index 5058661ad..d076ae364 100644 --- a/usrp2/firmware/apps/app_common_v2.h +++ b/usrp2/firmware/apps/app_common_v2.h @@ -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); diff --git a/usrp2/firmware/apps/factory_test.c b/usrp2/firmware/apps/factory_test.c index a4bc06d58..1332f6219 100644 --- a/usrp2/firmware/apps/factory_test.c +++ b/usrp2/firmware/apps/factory_test.c @@ -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) { diff --git a/usrp2/firmware/apps/mimo_tx_slave.c b/usrp2/firmware/apps/mimo_tx_slave.c index e7da984c5..69010c248 100644 --- a/usrp2/firmware/apps/mimo_tx_slave.c +++ b/usrp2/firmware/apps/mimo_tx_slave.c @@ -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) diff --git a/usrp2/firmware/apps/serdes_txrx.c b/usrp2/firmware/apps/serdes_txrx.c index 7816f7a65..6eff8778e 100644 --- a/usrp2/firmware/apps/serdes_txrx.c +++ b/usrp2/firmware/apps/serdes_txrx.c @@ -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) diff --git a/usrp2/firmware/apps/txrx.c b/usrp2/firmware/apps/txrx.c index b2487ed89..59eda45fc 100644 --- a/usrp2/firmware/apps/txrx.c +++ b/usrp2/firmware/apps/txrx.c @@ -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) diff --git a/usrp2/host/include/usrp2/usrp2.h b/usrp2/host/include/usrp2/usrp2.h index 7a612f945..07e5bf1df 100644 --- a/usrp2/host/include/usrp2/usrp2.h +++ b/usrp2/host/include/usrp2/usrp2.h @@ -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. diff --git a/usrp2/host/lib/control.h b/usrp2/host/lib/control.h index 8769e4522..376c281a7 100644 --- a/usrp2/host/lib/control.h +++ b/usrp2/host/lib/control.h @@ -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; diff --git a/usrp2/host/lib/usrp2.cc b/usrp2/host/lib/usrp2.cc index a2a9ecc11..ec3be5541 100644 --- a/usrp2/host/lib/usrp2.cc +++ b/usrp2/host/lib/usrp2.cc @@ -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) { diff --git a/usrp2/host/lib/usrp2_impl.cc b/usrp2/host/lib/usrp2_impl.cc index 3d0304324..ad1ea74b8 100644 --- a/usrp2/host/lib/usrp2_impl.cc +++ b/usrp2/host/lib/usrp2_impl.cc @@ -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) diff --git a/usrp2/host/lib/usrp2_impl.h b/usrp2/host/lib/usrp2_impl.h index ed71a6ba3..aaed66bc7 100644 --- a/usrp2/host/lib/usrp2_impl.h +++ b/usrp2/host/lib/usrp2_impl.h @@ -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); -- cgit