summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usrp2/firmware/apps/app_common_v2.c59
-rw-r--r--usrp2/firmware/apps/app_common_v2.h4
-rw-r--r--usrp2/firmware/apps/factory_test.c25
-rw-r--r--usrp2/firmware/apps/mimo_tx_slave.c10
-rw-r--r--usrp2/firmware/apps/serdes_txrx.c10
-rw-r--r--usrp2/firmware/apps/txrx.c61
-rw-r--r--usrp2/host/include/usrp2/usrp2.h59
-rw-r--r--usrp2/host/lib/control.h26
-rw-r--r--usrp2/host/lib/usrp2.cc52
-rw-r--r--usrp2/host/lib/usrp2_impl.cc296
-rw-r--r--usrp2/host/lib/usrp2_impl.h16
11 files changed, 419 insertions, 199 deletions
diff --git a/usrp2/firmware/apps/app_common_v2.c b/usrp2/firmware/apps/app_common_v2.c
index 67cccd53b..2d131bda7 100644
--- a/usrp2/firmware/apps/app_common_v2.c
+++ b/usrp2/firmware/apps/app_common_v2.c
@@ -152,7 +152,7 @@ config_tx_v2_cmd(const op_config_tx_v2_t *p,
memset(&tune_result, 0, sizeof(tune_result));
bool ok = true;
-
+
if (p->valid & CFGV_GAIN){
ok &= db_set_gain(tx_dboard, p->gain);
}
@@ -161,7 +161,7 @@ config_tx_v2_cmd(const op_config_tx_v2_t *p,
bool was_streaming = is_streaming();
if (was_streaming)
stop_rx_cmd();
-
+
u2_fxpt_freq_t f = u2_fxpt_freq_from_hilo(p->freq_hi, p->freq_lo);
bool tune_ok = db_tune(tx_dboard, f, &tune_result);
ok &= tune_ok;
@@ -185,7 +185,7 @@ config_tx_v2_cmd(const op_config_tx_v2_t *p,
hb1 = 1;
interp = interp >> 1;
}
-
+
if (interp < MIN_CIC_INTERP || interp > MAX_CIC_INTERP)
ok = false;
else {
@@ -215,7 +215,7 @@ config_tx_v2_cmd(const op_config_tx_v2_t *p,
}
static size_t
-config_rx_v2_cmd(const op_config_rx_v2_t *p,
+config_rx_v2_cmd(const op_config_rx_v2_t *p,
void *reply_payload, size_t reply_payload_space)
{
op_config_rx_reply_v2_t *r = (op_config_rx_reply_v2_t *) reply_payload;
@@ -226,7 +226,7 @@ config_rx_v2_cmd(const op_config_rx_v2_t *p,
memset(&tune_result, 0, sizeof(tune_result));
bool ok = true;
-
+
if (p->valid & CFGV_GAIN){
ok &= db_set_gain(rx_dboard, p->gain);
}
@@ -235,7 +235,7 @@ config_rx_v2_cmd(const op_config_rx_v2_t *p,
bool was_streaming = is_streaming();
if (was_streaming)
stop_rx_cmd();
-
+
u2_fxpt_freq_t f = u2_fxpt_freq_from_hilo(p->freq_hi, p->freq_lo);
bool tune_ok = db_tune(rx_dboard, f, &tune_result);
ok &= tune_ok;
@@ -249,17 +249,17 @@ config_rx_v2_cmd(const op_config_rx_v2_t *p,
int decim = p->decim;
int hb1 = 0;
int hb2 = 0;
-
+
if(!(decim & 1)) {
hb2 = 1;
decim = decim >> 1;
}
-
+
if(!(decim & 1)) {
hb1 = 1;
decim = decim >> 1;
}
-
+
if (decim < MIN_CIC_DECIM || decim > MAX_CIC_DECIM)
ok = false;
else {
@@ -294,7 +294,7 @@ read_time_cmd(const op_generic_t *p,
void *reply_payload, size_t reply_payload_space)
{
op_read_time_reply_t *r = (op_read_time_reply_t *) reply_payload;
- if (reply_payload_space < sizeof(*r))
+ if (reply_payload_space < sizeof(*r))
return 0; // no room
r->opcode = OP_READ_TIME_REPLY;
@@ -323,7 +323,7 @@ dboard_info_cmd(const op_generic_t *p,
void *reply_payload, size_t reply_payload_space)
{
op_dboard_info_reply_t *r = (op_dboard_info_reply_t *) reply_payload;
- if (reply_payload_space < sizeof(*r))
+ if (reply_payload_space < sizeof(*r))
return 0; // no room
r->opcode = OP_DBOARD_INFO_REPLY;
@@ -411,14 +411,14 @@ generic_reply(const op_generic_t *p,
bool ok)
{
op_generic_t *r = (op_generic_t *) reply_payload;
- if (reply_payload_space < sizeof(*r))
+ if (reply_payload_space < sizeof(*r))
return 0; // no room
-
+
r->opcode = p->opcode | OP_REPLY_BIT;
r->len = sizeof(*r);
r->rid = p->rid;
r->ok = ok;
-
+
return r->len;
}
@@ -426,14 +426,14 @@ static size_t
add_eop(void *reply_payload, size_t reply_payload_space)
{
op_generic_t *r = (op_generic_t *) reply_payload;
- if (reply_payload_space < sizeof(*r))
+ if (reply_payload_space < sizeof(*r))
return 0; // no room
-
+
r->opcode = OP_EOP;
r->len = sizeof(*r);
r->rid = 0;
r->ok = 0;
-
+
return r->len;
}
@@ -443,15 +443,15 @@ handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len)
unsigned char reply[sizeof(u2_eth_packet_t) + 4 * sizeof(u2_subpkt_t)] _AL4;
unsigned char *reply_payload = &reply[sizeof(u2_eth_packet_t)];
int reply_payload_space = sizeof(reply) - sizeof(u2_eth_packet_t);
-
+
// initialize reply
memset(reply, 0, sizeof(reply));
set_reply_hdr((u2_eth_packet_t *) reply, pkt);
-
+
// point to beginning of payload (subpackets)
unsigned char *payload = ((unsigned char *) pkt) + sizeof(u2_eth_packet_t);
int payload_len = len - sizeof(u2_eth_packet_t);
-
+
size_t subpktlen = 0;
bool ok = false;
@@ -468,7 +468,7 @@ handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len)
case OP_ID:
subpktlen = op_id_cmd(gp, reply_payload, reply_payload_space);
break;
-
+
case OP_CONFIG_TX_V2:
subpktlen = config_tx_v2_cmd((op_config_tx_v2_t *) payload, reply_payload, reply_payload_space);
break;
@@ -478,15 +478,18 @@ 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;
-
+
case OP_STOP_RX:
stop_rx_cmd();
ok = true;
goto generic_reply;
-
+
case OP_BURN_MAC_ADDR:
ok = ethernet_set_mac_addr(&((op_burn_mac_addr_t *)payload)->addr);
goto generic_reply;
@@ -532,8 +535,8 @@ handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len)
case OP_GPIO_SET_DDR:
ok = true;
- hal_gpio_set_ddr(((op_gpio_t *)payload)->bank,
- ((op_gpio_t *)payload)->value,
+ hal_gpio_set_ddr(((op_gpio_t *)payload)->bank,
+ ((op_gpio_t *)payload)->value,
((op_gpio_t *)payload)->mask);
goto generic_reply;
@@ -549,8 +552,8 @@ handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len)
case OP_GPIO_WRITE:
ok = true;
- hal_gpio_write(((op_gpio_t *)payload)->bank,
- ((op_gpio_t *)payload)->value,
+ hal_gpio_write(((op_gpio_t *)payload)->bank,
+ ((op_gpio_t *)payload)->value,
((op_gpio_t *)payload)->mask);
goto generic_reply;
diff --git a/usrp2/firmware/apps/app_common_v2.h b/usrp2/firmware/apps/app_common_v2.h
index 5058661ad..ff1baec06 100644
--- a/usrp2/firmware/apps/app_common_v2.h
+++ b/usrp2/firmware/apps/app_common_v2.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2007,2008 Free Software Foundation, Inc.
+ * Copyright 2007,2008,2009 Free Software Foundation, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -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..e7dde524a 100644
--- a/usrp2/firmware/apps/factory_test.c
+++ b/usrp2/firmware/apps/factory_test.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2007,2008 Free Software Foundation, Inc.
+ * Copyright 2007,2008,2009 Free Software Foundation, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -154,7 +154,7 @@ restart_streaming(void)
dsp_rx_regs->rx_command =
MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame,
streaming_items_per_frame,
- 1, 1);
+ 1, 1);
dsp_rx_regs->rx_time = 0; // enqueue second command
}
@@ -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)
{
@@ -224,7 +229,7 @@ setup_tx()
* that we didn't handle the packet. A bit of a kludge
* but it should work.
*/
-bool
+bool
fw_sets_seqno_inspector(dbsm_t *sm, int buf_this) // returns false
{
uint32_t *p = buffer_ram(buf_this);
@@ -259,22 +264,22 @@ int test_ram()
{
int i,j,k;
output_regs->ram_page = 1<<10;
-
+
extram[0] = 0xDEADBEEF;
extram[1] = 0xF00D1234;
extram[7] = 0x76543210;
-
+
output_regs->ram_page = 2<<10;
extram[7] = 0x55555555;
extram[1] = 0xaaaaaaaa;
extram[0] = 0xeeeeeeee;
-
+
output_regs->ram_page = 1<<10;
-
+
i = extram[0];
k = extram[1];
j = extram[7];
-
+
if((i != 0xDEADBEEF)||(j!=0x76543210)||(k!=0xF00D1234)) {
puts("RAM FAIL1!\n");
puthex32_nl(i);
@@ -282,7 +287,7 @@ int test_ram()
puthex32_nl(k);
return 0;
}
-
+
output_regs->ram_page = 2<<10;
j = extram[7];
@@ -306,7 +311,7 @@ int test_sd()
puts("FAILED INIT of Card\n");
return 0;
}
-
+
unsigned char buf[512];
i = sd_read_block(2048,buf);
if(i == 0) {
diff --git a/usrp2/firmware/apps/mimo_tx_slave.c b/usrp2/firmware/apps/mimo_tx_slave.c
index e7da984c5..4c284b7c9 100644
--- a/usrp2/firmware/apps/mimo_tx_slave.c
+++ b/usrp2/firmware/apps/mimo_tx_slave.c
@@ -160,7 +160,7 @@ restart_streaming(void)
dsp_rx_regs->rx_command =
MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame,
streaming_items_per_frame,
- 1, 1);
+ 1, 1);
dsp_rx_regs->rx_time = 0; // enqueue second command
}
@@ -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)
@@ -230,7 +234,7 @@ setup_tx()
* that we didn't handle the packet. A bit of a kludge
* but it should work.
*/
-bool
+bool
fw_sets_seqno_inspector(dbsm_t *sm, int buf_this) // returns false
{
uint32_t *p = buffer_ram(buf_this);
@@ -310,7 +314,7 @@ main(void)
//output_regs->flush_icache = 1;
-
+
// initialize double buffering state machine for DSP RX -> Ethernet
if (FW_SETS_SEQNO){
diff --git a/usrp2/firmware/apps/serdes_txrx.c b/usrp2/firmware/apps/serdes_txrx.c
index 7816f7a65..aa4a3f33c 100644
--- a/usrp2/firmware/apps/serdes_txrx.c
+++ b/usrp2/firmware/apps/serdes_txrx.c
@@ -152,7 +152,7 @@ restart_streaming(void)
dsp_rx_regs->rx_command =
MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame,
streaming_items_per_frame,
- 1, 1);
+ 1, 1);
dsp_rx_regs->rx_time = 0; // enqueue second command
}
@@ -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)
@@ -222,7 +226,7 @@ setup_tx()
* that we didn't handle the packet. A bit of a kludge
* but it should work.
*/
-bool
+bool
fw_sets_seqno_inspector(dbsm_t *sm, int buf_this) // returns false
{
uint32_t *p = buffer_ram(buf_this);
@@ -302,7 +306,7 @@ main(void)
//output_regs->flush_icache = 1;
-
+
// initialize double buffering state machine for DSP RX -> Ethernet
if (FW_SETS_SEQNO){
diff --git a/usrp2/firmware/apps/txrx.c b/usrp2/firmware/apps/txrx.c
index b2487ed89..975f314bd 100644
--- a/usrp2/firmware/apps/txrx.c
+++ b/usrp2/firmware/apps/txrx.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2007,2008 Free Software Foundation, Inc.
+ * Copyright 2007,2008,2009 Free Software Foundation, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -152,7 +152,35 @@ restart_streaming(void)
dsp_rx_regs->rx_command =
MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame,
streaming_items_per_frame,
- 1, 1);
+ 1, 1);
+
+ 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
}
@@ -184,6 +212,33 @@ 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.src = *ethernet_mac_addr();
+ 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)
@@ -222,7 +277,7 @@ setup_tx()
* that we didn't handle the packet. A bit of a kludge
* but it should work.
*/
-bool
+bool
fw_sets_seqno_inspector(dbsm_t *sm, int buf_this) // returns false
{
uint32_t *p = buffer_ram(buf_this);
diff --git a/usrp2/host/include/usrp2/usrp2.h b/usrp2/host/include/usrp2/usrp2.h
index 7a612f945..2d9e2a4b0 100644
--- a/usrp2/host/include/usrp2/usrp2.h
+++ b/usrp2/host/include/usrp2/usrp2.h
@@ -60,7 +60,7 @@ namespace usrp2 {
*
* \returns a vector of properties, 1 entry for each matching USRP2 found.
*/
- props_vector_t find(const std::string &ifc, const std::string &mac_addr="");
+ props_vector_t find(const std::string &ifc, const std::string &mac_addr="");
class tune_result;
@@ -79,10 +79,10 @@ namespace usrp2 {
/*!
* Shared pointer to this class
- */
+ */
typedef boost::shared_ptr<usrp2> sptr;
-
- /*!
+
+ /*!
* Static function to return an instance of usrp2 as a shared pointer
*
* \param ifc Network interface name, e.g., "eth0"
@@ -96,7 +96,7 @@ namespace usrp2 {
/*!
* Class destructor
*/
- ~usrp2();
+ ~usrp2();
/*!
* Returns the MAC address associated with this USRP
@@ -120,10 +120,10 @@ namespace usrp2 {
*/
bool set_rx_gain(double gain);
- //! return minimum Rx gain
+ //! return minimum Rx gain
double rx_gain_min();
- //! return maximum Rx gain
+ //! return maximum Rx gain
double rx_gain_max();
//! return Rx gain db_per_step
@@ -160,7 +160,7 @@ namespace usrp2 {
/*!
* Set received sample format
- *
+ *
* domain: complex or real
* type: floating, fixed point, or raw
* depth: bits per sample
@@ -172,12 +172,33 @@ namespace usrp2 {
/*!
* Start streaming receive mode. 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.
*/
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.
*/
@@ -193,7 +214,7 @@ namespace usrp2 {
* Returns number of times receive overruns have occurred
*/
unsigned int rx_overruns();
-
+
/*!
* Returns total number of missing frames from overruns.
*/
@@ -210,10 +231,10 @@ namespace usrp2 {
*/
bool set_tx_gain(double gain);
- //! return minimum Tx gain
+ //! return minimum Tx gain
double tx_gain_min();
- //! return maximum Tx gain
+ //! return maximum Tx gain
double tx_gain_max();
//! return Tx gain db_per_step
@@ -255,7 +276,7 @@ namespace usrp2 {
/*!
* Set transmit sample format
- *
+ *
* domain: complex or real
* type: floating, fixed point, or raw
* depth: bits per sample
@@ -272,7 +293,7 @@ namespace usrp2 {
* \param nsamples is the number of samples to transmit
* \param metadata provides the timestamp and flags
*
- * The complex<float> samples are converted to the appropriate
+ * The complex<float> samples are converted to the appropriate
* "on the wire" representation, depending on the current USRP2
* configuration. Typically, this is big-endian 16-bit I & Q.
*/
@@ -400,12 +421,12 @@ namespace usrp2 {
*
* \param addr 32-bit aligned address. Only the lower 16-bits are significant.
* \param words Number of 32-bit words
- *
+ *
* \returns Vector of 32-bit read values
*
* WARNING: Attempts to read memory from addresses that do not correspond to RAM or
* memory-mapped peripherals may cause the USRP2 to hang, requiring a power cycle.
- *
+ *
*/
std::vector<uint32_t> peek32(uint32_t addr, uint32_t words);
@@ -419,7 +440,7 @@ namespace usrp2 {
*
* WARNING: Attempts to read memory from addresses that do not correspond to RAM or
* memory-mapped peripherals may cause the USRP2 to hang, requiring a power cycle.
- *
+ *
*/
bool poke32(uint32_t addr, const std::vector<uint32_t> &data);
@@ -587,7 +608,7 @@ namespace usrp2 {
// Only class members can instantiate this class
usrp2(const std::string &ifc, props *p, size_t rx_bufsize);
-
+
// All private state is held in opaque pointer
std::auto_ptr<impl> d_impl;
};
diff --git a/usrp2/host/lib/control.h b/usrp2/host/lib/control.h
index 8769e4522..46ce791ea 100644
--- a/usrp2/host/lib/control.h
+++ b/usrp2/host/lib/control.h
@@ -33,27 +33,35 @@ namespace usrp2 {
/*!
* OP_CONFIG_RX_V2 command packet
*/
- struct op_config_rx_v2_cmd
+ struct op_config_rx_v2_cmd
{
u2_eth_packet_t h;
op_config_rx_v2_t op;
op_generic_t eop;
};
- struct op_start_rx_streaming_cmd
+ struct op_start_rx_streaming_cmd
{
u2_eth_packet_t h;
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;
op_generic_t op;
op_generic_t eop;
};
- struct op_config_tx_v2_cmd
+ struct op_config_tx_v2_cmd
{
u2_eth_packet_t h;
op_config_tx_v2_t op;
@@ -67,7 +75,7 @@ namespace usrp2 {
op_generic_t eop;
};
- struct op_burn_mac_addr_cmd
+ struct op_burn_mac_addr_cmd
{
u2_eth_packet_t h;
op_burn_mac_addr_t op;
@@ -113,20 +121,20 @@ namespace usrp2 {
/*!
* Control mechanism to allow API calls to block waiting for reply packets
- */
+ */
class pending_reply
{
private:
unsigned int d_rid;
void *d_buffer;
size_t d_len;
-
+
// d_mutex is used with d_cond and also protects d_complete
omni_mutex d_mutex;
omni_condition d_cond;
bool d_complete;
- public:
+ public:
/*!
* Construct a pending reply from the reply ID, response packet
* buffer, and buffer length.
@@ -165,7 +173,7 @@ namespace usrp2 {
*/
size_t len() const { return d_len; }
};
-
+
} // namespace usrp2
#endif /* INCLUDED_CONTROL_H */
diff --git a/usrp2/host/lib/usrp2.cc b/usrp2/host/lib/usrp2.cc
index a2a9ecc11..801a436a3 100644
--- a/usrp2/host/lib/usrp2.cc
+++ b/usrp2/host/lib/usrp2.cc
@@ -62,7 +62,7 @@ namespace usrp2 {
else {
if (key == p->key) // found it
return usrp2::sptr(p->value);
- else
+ else
++p; // keep looking
}
}
@@ -90,15 +90,15 @@ namespace usrp2 {
p.addr[3] = 0x85;
p.addr[4] = 0x30;
p.addr[5] = 0x00;
-
+
int len = s.size();
switch (len) {
-
+
case 5:
if (sscanf(s.c_str(), "%hhx:%hhx", &p.addr[4], &p.addr[5]) != 2)
return false;
break;
-
+
case 17:
if (sscanf(s.c_str(), "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
&p.addr[0], &p.addr[1], &p.addr[2],
@@ -109,7 +109,7 @@ namespace usrp2 {
default:
return false;
}
-
+
char buf[128];
snprintf(buf, sizeof(buf),
"%02x:%02x:%02x:%02x:%02x:%02x",
@@ -148,13 +148,13 @@ namespace usrp2 {
{
// NOP
}
-
+
// Public class destructor. d_impl will auto-delete.
usrp2::~usrp2()
{
// NOP
}
-
+
std::string
usrp2::mac_addr()
{
@@ -169,12 +169,12 @@ namespace usrp2 {
// Receive
- bool
+ bool
usrp2::set_rx_gain(double gain)
{
return d_impl->set_rx_gain(gain);
}
-
+
double
usrp2::rx_gain_min()
{
@@ -204,7 +204,7 @@ namespace usrp2 {
{
return d_impl->set_rx_center_freq(frequency, result);
}
-
+
double
usrp2::rx_freq_min()
{
@@ -222,7 +222,7 @@ namespace usrp2 {
{
return d_impl->set_rx_decim(decimation_factor);
}
-
+
int
usrp2::rx_decim()
{
@@ -234,13 +234,25 @@ namespace usrp2 {
{
return d_impl->set_rx_scale_iq(scale_i, scale_q);
}
-
+
bool
usrp2::start_rx_streaming(unsigned int channel, unsigned int items_per_frame)
{
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)
{
@@ -258,7 +270,7 @@ namespace usrp2 {
{
return d_impl->rx_overruns();
}
-
+
unsigned int
usrp2::rx_missing()
{
@@ -267,12 +279,12 @@ namespace usrp2 {
// Transmit
- bool
+ bool
usrp2::set_tx_gain(double gain)
{
return d_impl->set_tx_gain(gain);
}
-
+
double
usrp2::tx_gain_min()
{
@@ -302,7 +314,7 @@ namespace usrp2 {
{
return d_impl->set_tx_center_freq(frequency, result);
}
-
+
double
usrp2::tx_freq_min()
{
@@ -321,7 +333,7 @@ namespace usrp2 {
{
return d_impl->set_tx_interp(interpolation_factor);
}
-
+
int
usrp2::tx_interp()
{
@@ -339,7 +351,7 @@ namespace usrp2 {
{
return d_impl->set_tx_scale_iq(scale_i, scale_q);
}
-
+
bool
usrp2::tx_32fc(unsigned int channel,
const std::complex<float> *samples,
@@ -404,7 +416,7 @@ namespace usrp2 {
{
return d_impl->rx_daughterboard_id(dbid);
}
-
+
// low level methods
diff --git a/usrp2/host/lib/usrp2_impl.cc b/usrp2/host/lib/usrp2_impl.cc
index 3d0304324..a74707634 100644
--- a/usrp2/host/lib/usrp2_impl.cc
+++ b/usrp2/host/lib/usrp2_impl.cc
@@ -106,7 +106,7 @@ namespace usrp2 {
//assert((((uintptr_t) p) % 4) == 0); // must be 4-byte aligned
u2_fixed_hdr_t *fh = static_cast<u2_fixed_hdr_t *>(p);
-
+
// FIXME unaligned loads!
md->word0 = u2p_word0(fh);
md->timestamp = u2p_timestamp(fh);
@@ -131,13 +131,13 @@ namespace usrp2 {
usrp2::impl::impl(const std::string &ifc, props *p, size_t rx_bufsize)
: d_eth_buf(new eth_buffer(rx_bufsize)), d_interface_name(ifc), d_pf(0), d_bg_thread(0),
d_bg_running(false), d_rx_seqno(-1), d_tx_seqno(0), d_next_rid(0),
- d_num_rx_frames(0), d_num_rx_missing(0), d_num_rx_overruns(0), d_num_rx_bytes(0),
+ d_num_rx_frames(0), d_num_rx_missing(0), d_num_rx_overruns(0), d_num_rx_bytes(0),
d_num_enqueued(0), d_enqueued_mutex(), d_bg_pending_cond(&d_enqueued_mutex),
d_channel_rings(NCHANS), d_tx_interp(0), d_rx_decim(0), d_dont_enqueue(true)
{
if (!d_eth_buf->open(ifc, htons(U2_ETHERTYPE)))
throw std::runtime_error("Unable to register USRP2 protocol");
-
+
d_addr = p->addr;
// Create a packet filter for U2_ETHERTYPE packets sourced from target USRP2
@@ -146,7 +146,7 @@ namespace usrp2 {
d_pf = pktfilter::make_ethertype_inbound_target(U2_ETHERTYPE, (const unsigned char*)&(usrp_mac.addr));
if (!d_pf || !d_eth_buf->attach_pktfilter(d_pf))
throw std::runtime_error("Unable to attach packet filter.");
-
+
if (USRP2_IMPL_DEBUG)
std::cerr << "usrp2 constructor: using USRP2 at " << d_addr << std::endl;
@@ -199,12 +199,12 @@ namespace usrp2 {
if (!set_rx_decim(12))
std::cerr << "usrp2::ctor set_rx_decim failed\n";
-
+
// set workable defaults for scaling
if (!set_rx_scale_iq(DEFAULT_RX_SCALE, DEFAULT_RX_SCALE))
std::cerr << "usrp2::ctor set_rx_scale_iq failed\n";
}
-
+
usrp2::impl::~impl()
{
stop_bg();
@@ -212,17 +212,17 @@ namespace usrp2 {
delete d_pf;
d_eth_buf->close();
delete d_eth_buf;
-
+
if (USRP2_IMPL_DEBUG) {
std::cerr << std::endl
- << "usrp2 destructor: received " << d_num_rx_frames
+ << "usrp2 destructor: received " << d_num_rx_frames
<< " frames, with " << d_num_rx_missing << " lost ("
<< (d_num_rx_frames == 0 ? 0 : (int)(100.0*d_num_rx_missing/d_num_rx_frames))
<< "%), totaling " << d_num_rx_bytes
<< " bytes" << std::endl;
}
}
-
+
bool
usrp2::impl::parse_mac_addr(const std::string &s, u2_mac_addr_t *p)
{
@@ -232,14 +232,14 @@ namespace usrp2 {
p->addr[3] = 0x85;
p->addr[4] = 0x30;
p->addr[5] = 0x00;
-
+
int len = s.size();
-
+
switch (len){
-
+
case 5:
return sscanf(s.c_str(), "%hhx:%hhx", &p->addr[4], &p->addr[5]) == 2;
-
+
case 17:
return sscanf(s.c_str(), "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
&p->addr[0], &p->addr[1], &p->addr[2],
@@ -248,36 +248,36 @@ namespace usrp2 {
return false;
}
}
-
+
void
usrp2::impl::init_et_hdrs(u2_eth_packet_t *p, const std::string &dst)
{
p->ehdr.ethertype = htons(U2_ETHERTYPE);
- parse_mac_addr(dst, &p->ehdr.dst);
+ parse_mac_addr(dst, &p->ehdr.dst);
memcpy(&p->ehdr.src, d_eth_buf->mac(), 6);
p->thdr.flags = 0; // FIXME transport header values?
p->thdr.seqno = d_tx_seqno++;
p->thdr.ack = 0;
}
-
- void
+
+ void
usrp2::impl::init_etf_hdrs(u2_eth_packet_t *p, const std::string &dst,
int word0_flags, int chan, uint32_t timestamp)
{
init_et_hdrs(p, dst);
u2p_set_word0(&p->fixed, word0_flags, chan);
u2p_set_timestamp(&p->fixed, timestamp);
-
+
if (chan == CONTROL_CHAN) { // no sequence numbers, back it out
p->thdr.seqno = 0;
d_tx_seqno--;
}
}
-
+
void
usrp2::impl::init_config_rx_v2_cmd(op_config_rx_v2_cmd *cmd)
{
- memset(cmd, 0, sizeof(*cmd));
+ memset(cmd, 0, sizeof(*cmd));
init_etf_hdrs(&cmd->h, d_addr, 0, CONTROL_CHAN, -1);
cmd->op.opcode = OP_CONFIG_RX_V2;
cmd->op.len = sizeof(cmd->op);
@@ -289,7 +289,7 @@ namespace usrp2 {
void
usrp2::impl::init_config_tx_v2_cmd(op_config_tx_v2_cmd *cmd)
{
- memset(cmd, 0, sizeof(*cmd));
+ memset(cmd, 0, sizeof(*cmd));
init_etf_hdrs(&cmd->h, d_addr, 0, CONTROL_CHAN, -1);
cmd->op.opcode = OP_CONFIG_TX_V2;
cmd->op.len = sizeof(cmd->op);
@@ -320,7 +320,7 @@ namespace usrp2 {
usrp2::impl::transmit_cmd_and_wait(void *cmd, size_t len, pending_reply *p, double secs)
{
d_pending_replies[p->rid()] = p;
-
+
if (!transmit_cmd(cmd, len)){
d_pending_replies[p->rid()] = 0;
return false;
@@ -340,11 +340,11 @@ namespace usrp2 {
{
d_bg_running = false;
d_bg_pending_cond.signal();
-
+
void *dummy_status;
- d_bg_thread->join(&dummy_status);
+ d_bg_thread->join(&dummy_status);
}
-
+
void
usrp2::impl::bg_loop()
{
@@ -356,10 +356,10 @@ namespace usrp2 {
// rings, and signal blocked API threads
int res = d_eth_buf->rx_frames(this, 100); // FIXME magic timeout
if (res == eth_buffer::EB_ERROR)
- break;
+ break;
// Wait for user API thread(s) to process all enqueued packets.
- // The channel ring thread that decrements d_num_enqueued to zero
+ // The channel ring thread that decrements d_num_enqueued to zero
// will signal this thread to continue.
{
omni_mutex_lock l(d_enqueued_mutex);
@@ -369,7 +369,7 @@ namespace usrp2 {
}
d_bg_running = false;
}
-
+
//
// passed to eth_buffer::rx_frames
//
@@ -401,11 +401,11 @@ namespace usrp2 {
{
// point to beginning of payload (subpackets)
unsigned char *p = (unsigned char *)base + sizeof(u2_eth_packet_t);
-
+
// FIXME (p % 4) == 2. Not good. Must watch for unaligned loads.
// FIXME iterate over payload, handling more than a single subpacket.
-
+
int opcode = p[0];
unsigned int oplen = p[1];
unsigned int rid = p[2];
@@ -417,8 +417,8 @@ namespace usrp2 {
std::cerr << "usrp2: mismatched command reply length (expected: "
<< buflen << " got: " << oplen << "). "
<< "op = " << opcode_to_string(opcode) << std::endl;
- }
-
+ }
+
// Copy reply into caller's buffer
memcpy(rp->buffer(), p, std::min(oplen, buflen));
rp->notify_completion();
@@ -430,26 +430,26 @@ namespace usrp2 {
DEBUG_LOG("l");
return data_handler::RELEASE;
}
-
+
data_handler::result
usrp2::impl::handle_data_packet(const void *base, size_t len)
{
u2_eth_samples_t *pkt = (u2_eth_samples_t *)base;
d_num_rx_frames++;
d_num_rx_bytes += len;
-
+
/* --- FIXME start of fake transport layer handler --- */
if (d_rx_seqno != -1) {
int expected_seqno = (d_rx_seqno + 1) & 0xFF;
- int seqno = pkt->hdrs.thdr.seqno;
-
+ int seqno = pkt->hdrs.thdr.seqno;
+
if (seqno != expected_seqno) {
::write(2, "S", 1); // missing sequence number
int missing = seqno - expected_seqno;
if (missing < 0)
missing += 256;
-
+
d_num_rx_overruns++;
d_num_rx_missing += missing;
}
@@ -469,9 +469,9 @@ namespace usrp2 {
DEBUG_LOG("!");
return data_handler::RELEASE; // discard packet, no channel handler
}
-
+
// Strip off ethernet header and transport header and enqueue the rest
-
+
size_t offset = offsetof(u2_eth_samples_t, hdrs.fixed);
if (d_channel_rings[chan]->enqueue(&pkt->hdrs.fixed, len-offset)) {
inc_enqueued();
@@ -481,7 +481,7 @@ namespace usrp2 {
else {
DEBUG_LOG("!");
return data_handler::RELEASE; // discard, no room in channel ring
- }
+ }
return data_handler::RELEASE;
}
}
@@ -491,7 +491,7 @@ namespace usrp2 {
// Receive
// ----------------------------------------------------------------
- bool
+ bool
usrp2::impl::set_rx_gain(double gain)
{
op_config_rx_v2_cmd cmd;
@@ -500,7 +500,7 @@ namespace usrp2 {
init_config_rx_v2_cmd(&cmd);
cmd.op.valid = htons(CFGV_GAIN);
cmd.op.gain = htons(u2_double_to_fxpt_gain(gain));
-
+
pending_reply p(cmd.op.rid, &reply, sizeof(reply));
if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
return false;
@@ -508,7 +508,7 @@ namespace usrp2 {
bool success = (ntohx(reply.ok) == 1);
return success;
}
-
+
bool
usrp2::impl::set_rx_lo_offset(double frequency)
{
@@ -527,7 +527,7 @@ namespace usrp2 {
cmd.eop.opcode = OP_EOP;
cmd.eop.len = sizeof(cmd.eop);
-
+
pending_reply p(cmd.op.rid, &reply, sizeof(reply));
if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
return false;
@@ -547,7 +547,7 @@ namespace usrp2 {
u2_fxpt_freq_t fxpt = u2_double_to_fxpt_freq(frequency);
cmd.op.freq_hi = htonl(u2_fxpt_freq_hi(fxpt));
cmd.op.freq_lo = htonl(u2_fxpt_freq_lo(fxpt));
-
+
pending_reply p(cmd.op.rid, &reply, sizeof(reply));
if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
return false;
@@ -555,18 +555,18 @@ namespace usrp2 {
bool success = (ntohx(reply.ok) == 1);
if (result && success) {
result->baseband_freq =
- u2_fxpt_freq_to_double(
- u2_fxpt_freq_from_hilo(ntohl(reply.baseband_freq_hi),
+ u2_fxpt_freq_to_double(
+ u2_fxpt_freq_from_hilo(ntohl(reply.baseband_freq_hi),
ntohl(reply.baseband_freq_lo)));
result->dxc_freq =
- u2_fxpt_freq_to_double(
- u2_fxpt_freq_from_hilo(ntohl(reply.ddc_freq_hi),
+ u2_fxpt_freq_to_double(
+ u2_fxpt_freq_from_hilo(ntohl(reply.ddc_freq_hi),
ntohl(reply.ddc_freq_lo)));
result->residual_freq =
- u2_fxpt_freq_to_double(
- u2_fxpt_freq_from_hilo(ntohl(reply.residual_freq_hi),
+ u2_fxpt_freq_to_double(
+ u2_fxpt_freq_from_hilo(ntohl(reply.residual_freq_hi),
ntohl(reply.residual_freq_lo)));
result->spectrum_inverted = (bool)(ntohx(reply.inverted) == 1);
@@ -574,7 +574,7 @@ namespace usrp2 {
return success;
}
-
+
bool
usrp2::impl::set_rx_decim(int decimation_factor)
{
@@ -584,7 +584,7 @@ namespace usrp2 {
init_config_rx_v2_cmd(&cmd);
cmd.op.valid = htons(CFGV_INTERP_DECIM);
cmd.op.decim = htonl(decimation_factor);
-
+
pending_reply p(cmd.op.rid, &reply, sizeof(reply));
if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
return false;
@@ -594,7 +594,7 @@ namespace usrp2 {
d_rx_decim = decimation_factor;
return success;
}
-
+
bool
usrp2::impl::set_rx_scale_iq(int scale_i, int scale_q)
{
@@ -604,7 +604,7 @@ namespace usrp2 {
init_config_rx_v2_cmd(&cmd);
cmd.op.valid = htons(CFGV_SCALE_IQ);
cmd.op.scale_iq = htonl(((scale_i & 0xffff) << 16) | (scale_q & 0xffff));
-
+
pending_reply p(cmd.op.rid, &reply, sizeof(reply));
if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
return false;
@@ -612,7 +612,7 @@ namespace usrp2 {
bool success = (ntohx(reply.ok) == 1);
return success;
}
-
+
bool
usrp2::impl::start_rx_streaming(unsigned int channel, unsigned int items_per_frame)
{
@@ -635,10 +635,10 @@ namespace usrp2 {
<< " 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;
@@ -650,13 +650,13 @@ namespace usrp2 {
cmd.op.items_per_frame = htonl(items_per_frame);
cmd.eop.opcode = OP_EOP;
cmd.eop.len = sizeof(cmd.eop);
-
+
d_dont_enqueue = false;
bool success = false;
pending_reply p(cmd.op.rid, &reply, sizeof(reply));
success = transmit_cmd_and_wait(&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()));
else
@@ -666,7 +666,111 @@ 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_and_wait(&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_and_wait(&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)
{
@@ -698,7 +802,7 @@ namespace usrp2 {
cmd.op.rid = d_next_rid++;
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_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT);
@@ -717,25 +821,25 @@ namespace usrp2 {
<< " )" << std::endl;
return false;
}
-
+
if (channel > 0) {
std::cerr << "usrp2: channel " << channel
<< " not implemented" << std::endl;
return false;
}
-
+
ring_sptr rp = d_channel_rings[channel];
if (!rp){
std::cerr << "usrp2: channel " << channel
<< " not receiving" << std::endl;
return false;
}
-
+
// Wait for frames available in channel ring
DEBUG_LOG("W");
rp->wait_for_not_empty();
DEBUG_LOG("s");
-
+
// Iterate through frames and present to user
void *p;
size_t frame_len_in_bytes;
@@ -791,7 +895,7 @@ namespace usrp2 {
// Transmit
// ----------------------------------------------------------------
- bool
+ bool
usrp2::impl::set_tx_gain(double gain)
{
op_config_tx_v2_cmd cmd;
@@ -800,7 +904,7 @@ namespace usrp2 {
init_config_tx_v2_cmd(&cmd);
cmd.op.valid = htons(CFGV_GAIN);
cmd.op.gain = htons(u2_double_to_fxpt_gain(gain));
-
+
pending_reply p(cmd.op.rid, &reply, sizeof(reply));
if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
return false;
@@ -808,7 +912,7 @@ namespace usrp2 {
bool success = (ntohx(reply.ok) == 1);
return success;
}
-
+
bool
usrp2::impl::set_tx_lo_offset(double frequency)
{
@@ -827,7 +931,7 @@ namespace usrp2 {
cmd.eop.opcode = OP_EOP;
cmd.eop.len = sizeof(cmd.eop);
-
+
pending_reply p(cmd.op.rid, &reply, sizeof(reply));
if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
return false;
@@ -847,7 +951,7 @@ namespace usrp2 {
u2_fxpt_freq_t fxpt = u2_double_to_fxpt_freq(frequency);
cmd.op.freq_hi = htonl(u2_fxpt_freq_hi(fxpt));
cmd.op.freq_lo = htonl(u2_fxpt_freq_lo(fxpt));
-
+
pending_reply p(cmd.op.rid, &reply, sizeof(reply));
if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
return false;
@@ -855,18 +959,18 @@ namespace usrp2 {
bool success = (ntohx(reply.ok) == 1);
if (result && success) {
result->baseband_freq =
- u2_fxpt_freq_to_double(
- u2_fxpt_freq_from_hilo(ntohl(reply.baseband_freq_hi),
+ u2_fxpt_freq_to_double(
+ u2_fxpt_freq_from_hilo(ntohl(reply.baseband_freq_hi),
ntohl(reply.baseband_freq_lo)));
result->dxc_freq =
- u2_fxpt_freq_to_double(
- u2_fxpt_freq_from_hilo(ntohl(reply.duc_freq_hi),
+ u2_fxpt_freq_to_double(
+ u2_fxpt_freq_from_hilo(ntohl(reply.duc_freq_hi),
ntohl(reply.duc_freq_lo)));
result->residual_freq =
- u2_fxpt_freq_to_double(
- u2_fxpt_freq_from_hilo(ntohl(reply.residual_freq_hi),
+ u2_fxpt_freq_to_double(
+ u2_fxpt_freq_from_hilo(ntohl(reply.residual_freq_hi),
ntohl(reply.residual_freq_lo)));
result->spectrum_inverted = (bool)(ntohx(reply.inverted) == 1);
@@ -874,7 +978,7 @@ namespace usrp2 {
return success;
}
-
+
bool
usrp2::impl::set_tx_interp(int interpolation_factor)
{
@@ -884,7 +988,7 @@ namespace usrp2 {
init_config_tx_v2_cmd(&cmd);
cmd.op.valid = htons(CFGV_INTERP_DECIM);
cmd.op.interp = htonl(interpolation_factor);
-
+
pending_reply p(cmd.op.rid, &reply, sizeof(reply));
if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
return false;
@@ -901,7 +1005,7 @@ namespace usrp2 {
return success;
}
-
+
void
usrp2::impl::default_tx_scale_iq(int interpolation_factor, int *scale_i, int *scale_q)
{
@@ -914,7 +1018,7 @@ namespace usrp2 {
// Calculate dsp_core_tx gain absent scale multipliers
float gain = (1.65*i*i*i)/(4096*pow(2, ceil(log2(i*i*i))));
-
+
// Calculate closest multiplier constant to reverse gain
int scale = (int)rint(1.0/gain);
// fprintf(stderr, "if=%i i=%i gain=%f scale=%i\n", interpolation_factor, i, gain, scale);
@@ -935,7 +1039,7 @@ namespace usrp2 {
init_config_tx_v2_cmd(&cmd);
cmd.op.valid = htons(CFGV_SCALE_IQ);
cmd.op.scale_iq = htonl(((scale_i & 0xffff) << 16) | (scale_q & 0xffff));
-
+
pending_reply p(cmd.op.rid, &reply, sizeof(reply));
if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
return false;
@@ -1063,7 +1167,7 @@ namespace usrp2 {
cmd.op.flags = flags;
cmd.eop.opcode = OP_EOP;
cmd.eop.len = sizeof(cmd.eop);
-
+
pending_reply p(cmd.op.rid, &reply, sizeof(reply));
if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
return false;
@@ -1137,10 +1241,10 @@ namespace usrp2 {
dst->dbid = ntohl(src->dbid);
dst->freq_min =
- u2_fxpt_freq_to_double(u2_fxpt_freq_from_hilo(ntohl(src->freq_min_hi),
+ u2_fxpt_freq_to_double(u2_fxpt_freq_from_hilo(ntohl(src->freq_min_hi),
ntohl(src->freq_min_lo)));
dst->freq_max =
- u2_fxpt_freq_to_double(u2_fxpt_freq_from_hilo(ntohl(src->freq_max_hi),
+ u2_fxpt_freq_to_double(u2_fxpt_freq_from_hilo(ntohl(src->freq_max_hi),
ntohl(src->freq_max_lo)));
dst->gain_min = u2_fxpt_gain_to_double(ntohs(src->gain_min));
@@ -1161,7 +1265,7 @@ namespace usrp2 {
cmd.op.rid = d_next_rid++;
cmd.eop.opcode = OP_EOP;
cmd.eop.len = sizeof(cmd.eop);
-
+
pending_reply p(cmd.op.rid, &reply, sizeof(reply));
if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
return false;
@@ -1188,7 +1292,7 @@ namespace usrp2 {
cmd.op.rid = d_next_rid++;
cmd.eop.opcode = OP_EOP;
cmd.eop.len = sizeof(cmd.eop);
-
+
pending_reply p(cmd.op.rid, &reply, sizeof(reply));
if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
return false;
@@ -1210,7 +1314,7 @@ namespace usrp2 {
cmd.op.ok = enable ? 1 : 0;
cmd.eop.opcode = OP_EOP;
cmd.eop.len = sizeof(cmd.eop);
-
+
pending_reply p(cmd.op.rid, &reply, sizeof(reply));
if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
return false;
@@ -1225,7 +1329,7 @@ namespace usrp2 {
// fprintf(stderr, "usrp2::peek: addr=%08X words=%u\n", addr, words);
if (addr % 4 != 0) {
- fprintf(stderr, "usrp2::peek: addr (=%08X) must be 32-bit word aligned\n", addr);
+ fprintf(stderr, "usrp2::peek: addr (=%08X) must be 32-bit word aligned\n", addr);
return result;
}
@@ -1267,7 +1371,7 @@ namespace usrp2 {
usrp2::impl::poke32(uint32_t addr, const std::vector<uint32_t> &data)
{
if (addr % 4 != 0) {
- fprintf(stderr, "usrp2::poke32: addr (=%08X) must be 32-bit word aligned\n", addr);
+ fprintf(stderr, "usrp2::poke32: addr (=%08X) must be 32-bit word aligned\n", addr);
return false;
}
@@ -1339,7 +1443,7 @@ namespace usrp2 {
cmd.op.rid = d_next_rid++;
cmd.eop.opcode = OP_EOP;
cmd.eop.len = sizeof(cmd.eop);
-
+
pending_reply p(cmd.op.rid, &reply, sizeof(reply));
if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
return false;
@@ -1368,7 +1472,7 @@ namespace usrp2 {
cmd.op.mask = htons(mask);
cmd.eop.opcode = OP_EOP;
cmd.eop.len = sizeof(cmd.eop);
-
+
pending_reply p(cmd.op.rid, &reply, sizeof(reply));
if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
return false;
@@ -1401,7 +1505,7 @@ namespace usrp2 {
memcpy(&cmd.op.sels, sels.c_str(), 16);
cmd.eop.opcode = OP_EOP;
cmd.eop.len = sizeof(cmd.eop);
-
+
pending_reply p(cmd.op.rid, &reply, sizeof(reply));
if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
return false;
@@ -1430,7 +1534,7 @@ namespace usrp2 {
cmd.op.mask = htons(mask);
cmd.eop.opcode = OP_EOP;
cmd.eop.len = sizeof(cmd.eop);
-
+
pending_reply p(cmd.op.rid, &reply, sizeof(reply));
if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
return false;
@@ -1459,7 +1563,7 @@ namespace usrp2 {
cmd.op.mask = 0; // not used
cmd.eop.opcode = OP_EOP;
cmd.eop.len = sizeof(cmd.eop);
-
+
pending_reply p(cmd.op.rid, &reply, sizeof(reply));
if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
return false;
@@ -1496,7 +1600,7 @@ namespace usrp2 {
cmd.op.mask = 0; // not used
cmd.eop.opcode = OP_EOP;
cmd.eop.len = sizeof(cmd.eop);
-
+
pending_reply p(cmd.op.rid, &reply, sizeof(reply));
if (!transmit_cmd_and_wait(&cmd, sizeof(cmd), &p, DEF_CMD_TIMEOUT))
return false;
diff --git a/usrp2/host/lib/usrp2_impl.h b/usrp2/host/lib/usrp2_impl.h
index ed71a6ba3..d78a00db4 100644
--- a/usrp2/host/lib/usrp2_impl.h
+++ b/usrp2/host/lib/usrp2_impl.h
@@ -30,7 +30,7 @@
#define MAX_SUBPKT_LEN 252
namespace usrp2 {
-
+
class eth_buffer;
class pktfilter;
class usrp2_thread;
@@ -62,7 +62,7 @@ namespace usrp2 {
std::string d_addr; // FIXME: use u2_mac_addr_t instead
usrp2_thread *d_bg_thread;
volatile bool d_bg_running; // TODO: multistate if needed
-
+
int d_rx_seqno;
int d_tx_seqno;
int d_next_rid;
@@ -84,7 +84,7 @@ namespace usrp2 {
db_info d_tx_db_info;
db_info d_rx_db_info;
- int d_tx_interp; // shadow tx interp
+ int d_tx_interp; // shadow tx interp
int d_rx_decim; // shadow rx decim
bool d_dont_enqueue;
@@ -93,13 +93,13 @@ namespace usrp2 {
omni_mutex_lock l(d_enqueued_mutex);
d_num_enqueued++;
}
-
+
void dec_enqueued() {
omni_mutex_lock l(d_enqueued_mutex);
if (--d_num_enqueued == 0)
d_bg_pending_cond.signal();
}
-
+
static bool parse_mac_addr(const std::string &s, u2_mac_addr_t *p);
void init_et_hdrs(u2_eth_packet_t *p, const std::string &dst);
void init_etf_hdrs(u2_eth_packet_t *p, const std::string &dst,
@@ -118,7 +118,7 @@ namespace usrp2 {
public:
impl(const std::string &ifc, props *p, size_t rx_bufsize);
~impl();
-
+
void bg_loop();
std::string mac_addr() const { return d_addr; } // FIXME: convert from u2_mac_addr_t
@@ -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);
@@ -196,7 +198,7 @@ namespace usrp2 {
std::vector<uint32_t> peek32(uint32_t addr, uint32_t words);
bool poke32(uint32_t addr, const std::vector<uint32_t> &data);
};
-
+
} // namespace usrp2
#endif /* INCLUDED_USRP2_IMPL_H */