summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mblock/src/lib/mb_message.cc9
-rw-r--r--pmt/src/lib/pmt.cc6
-rw-r--r--pmt/src/lib/pmt.h5
-rw-r--r--pmt/src/lib/pmt_pool.cc17
-rw-r--r--pmt/src/lib/pmt_pool.h8
-rw-r--r--pmt/src/lib/qa_pmt_prims.cc14
-rw-r--r--pmt/src/lib/qa_pmt_prims.h2
-rw-r--r--usrp/fpga/Makefile.extra3
-rwxr-xr-xusrp/fpga/inband_lib/chan_fifo_reader.v262
-rw-r--r--usrp/fpga/inband_lib/channel_demux.v38
-rwxr-xr-xusrp/fpga/inband_lib/channel_ram.v175
-rwxr-xr-xusrp/fpga/inband_lib/cmd_reader.v565
-rwxr-xr-xusrp/fpga/inband_lib/data_packet_fifo.v118
-rwxr-xr-xusrp/fpga/inband_lib/packet_builder.v84
-rwxr-xr-xusrp/fpga/inband_lib/register_io.v94
-rwxr-xr-xusrp/fpga/inband_lib/rx_buffer_inband.v388
-rwxr-xr-xusrp/fpga/inband_lib/tx_buffer_inband.v305
-rwxr-xr-xusrp/fpga/inband_lib/usb_fifo_reader.v25
-rwxr-xr-xusrp/fpga/inband_lib/usb_fifo_writer.v183
-rwxr-xr-xusrp/fpga/megacells/fifo_1kx16.bsf2
-rwxr-xr-xusrp/fpga/megacells/fifo_1kx16.v6
-rwxr-xr-xusrp/fpga/megacells/fifo_1kx16_bb.v4
-rw-r--r--usrp/fpga/rbf/Makefile.am4
-rwxr-xr-xusrp/fpga/rbf/rev2/inband_1rxhb_1tx.rbfbin0 -> 161180 bytes
-rwxr-xr-xusrp/fpga/rbf/rev2/inband_2rxhb_2tx.rbfbin0 -> 191849 bytes
-rwxr-xr-xusrp/fpga/rbf/rev4/inband_1rxhb_1tx.rbfbin0 -> 161180 bytes
-rwxr-xr-xusrp/fpga/rbf/rev4/inband_2rxhb_2tx.rbfbin0 -> 191849 bytes
-rw-r--r--usrp/fpga/toplevel/usrp_inband_usb/config.vh2
-rw-r--r--usrp/fpga/toplevel/usrp_inband_usb/usrp_inband_usb.qsf7
-rw-r--r--usrp/fpga/toplevel/usrp_inband_usb/usrp_inband_usb.v81
-rw-r--r--usrp/host/apps-inband/Makefile.am31
-rw-r--r--usrp/host/apps-inband/gmac.cc690
-rw-r--r--usrp/host/apps-inband/gmac.h91
-rw-r--r--usrp/host/apps-inband/gmac.mbh146
-rw-r--r--usrp/host/apps-inband/gmac_symbols.h47
-rw-r--r--usrp/host/apps-inband/test_gmac_tx.cc330
-rw-r--r--usrp/host/apps-inband/test_usrp_inband_2rx.cc371
-rw-r--r--usrp/host/apps-inband/test_usrp_inband_2tx.cc (renamed from usrp/host/apps-inband/test_usrp_inband_cs.cc)212
-rw-r--r--usrp/host/apps-inband/test_usrp_inband_overrun.cc5
-rw-r--r--usrp/host/apps-inband/test_usrp_inband_registers.cc2
-rw-r--r--usrp/host/apps-inband/test_usrp_inband_rx.cc26
-rw-r--r--usrp/host/apps-inband/test_usrp_inband_timestamps.cc2
-rw-r--r--usrp/host/apps-inband/test_usrp_inband_tx.cc83
-rw-r--r--usrp/host/apps-inband/test_usrp_inband_underrun.cc8
-rw-r--r--usrp/host/lib/inband/Makefile.am7
-rw-r--r--usrp/host/lib/inband/fake_usrp.cc135
-rw-r--r--usrp/host/lib/inband/fake_usrp.h43
-rw-r--r--usrp/host/lib/inband/qa_inband_usrp_server.cc239
-rw-r--r--usrp/host/lib/inband/qa_inband_usrp_server.h2
-rw-r--r--usrp/host/lib/inband/test_usrp_inband.cc298
-rw-r--r--usrp/host/lib/inband/usrp_inband_usb_packet.cc235
-rw-r--r--usrp/host/lib/inband/usrp_inband_usb_packet.h5
-rw-r--r--usrp/host/lib/inband/usrp_rx.cc63
-rw-r--r--usrp/host/lib/inband/usrp_rx.h6
-rw-r--r--usrp/host/lib/inband/usrp_rx_stub.cc181
-rw-r--r--usrp/host/lib/inband/usrp_rx_stub.h12
-rw-r--r--usrp/host/lib/inband/usrp_server.cc512
-rw-r--r--usrp/host/lib/inband/usrp_server.h12
-rw-r--r--usrp/host/lib/inband/usrp_server.mbh2
-rw-r--r--usrp/host/lib/inband/usrp_tx.cc14
-rw-r--r--usrp/host/lib/inband/usrp_tx_stub.cc6
-rw-r--r--usrp/host/lib/inband/usrp_usb_interface.cc114
-rw-r--r--usrp/host/lib/inband/usrp_usb_interface.h4
-rw-r--r--usrp/host/lib/legacy/fusb_linux.cc26
64 files changed, 2755 insertions, 3612 deletions
diff --git a/mblock/src/lib/mb_message.cc b/mblock/src/lib/mb_message.cc
index 0bce455ce..ce98a931e 100644
--- a/mblock/src/lib/mb_message.cc
+++ b/mblock/src/lib/mb_message.cc
@@ -26,12 +26,13 @@
#include <stdio.h>
#include <pmt_pool.h>
-static const int CACHE_LINE_SIZE = 64; // good guess
-
-
+static const int CACHE_LINE_SIZE = 64; // good guess
+static const int MAX_MESSAGES = 1024; // KLUDGE max number of messages in sys
+ // 0 -> no limit
#if MB_MESSAGE_LOCAL_ALLOCATOR
-static pmt_pool global_msg_pool(sizeof(mb_message), CACHE_LINE_SIZE);
+static pmt_pool
+global_msg_pool(sizeof(mb_message), CACHE_LINE_SIZE, 16*1024, MAX_MESSAGES);
void *
mb_message::operator new(size_t size)
diff --git a/pmt/src/lib/pmt.cc b/pmt/src/lib/pmt.cc
index a141224b3..537b7a05a 100644
--- a/pmt/src/lib/pmt.cc
+++ b/pmt/src/lib/pmt.cc
@@ -963,6 +963,12 @@ pmt_list6(pmt_t x1, pmt_t x2, pmt_t x3, pmt_t x4, pmt_t x5, pmt_t x6)
}
pmt_t
+pmt_list_add(pmt_t list, pmt_t item)
+{
+ return pmt_reverse(pmt_cons(item, pmt_reverse(list)));
+}
+
+pmt_t
pmt_caar(pmt_t pair)
{
return (pmt_car(pmt_car(pair)));
diff --git a/pmt/src/lib/pmt.h b/pmt/src/lib/pmt.h
index fa368a6a1..970dd6c7d 100644
--- a/pmt/src/lib/pmt.h
+++ b/pmt/src/lib/pmt.h
@@ -609,6 +609,11 @@ pmt_t pmt_list5(pmt_t x1, pmt_t x2, pmt_t x3, pmt_t x4, pmt_t x5);
*/
pmt_t pmt_list6(pmt_t x1, pmt_t x2, pmt_t x3, pmt_t x4, pmt_t x5, pmt_t x6);
+/*!
+ * \brief Return \p list with \p item added to it.
+ */
+pmt_t pmt_list_add(pmt_t list, pmt_t item);
+
/*
* ------------------------------------------------------------------------
diff --git a/pmt/src/lib/pmt_pool.cc b/pmt/src/lib/pmt_pool.cc
index 8f1329a7e..05d9c005b 100644
--- a/pmt/src/lib/pmt_pool.cc
+++ b/pmt/src/lib/pmt_pool.cc
@@ -32,10 +32,13 @@ ROUNDUP(size_t x, size_t stride)
return ((((x) + (stride) - 1)/(stride)) * (stride));
}
-pmt_pool::pmt_pool(size_t itemsize, size_t alignment, size_t allocation_size)
- : d_itemsize(ROUNDUP(itemsize, alignment)),
+pmt_pool::pmt_pool(size_t itemsize, size_t alignment,
+ size_t allocation_size, size_t max_items)
+ : d_cond(&d_mutex),
+ d_itemsize(ROUNDUP(itemsize, alignment)),
d_alignment(alignment),
d_allocation_size(std::max(allocation_size, 16 * itemsize)),
+ d_max_items(max_items), d_n_items(0),
d_freelist(0)
{
}
@@ -53,9 +56,15 @@ pmt_pool::malloc()
omni_mutex_lock l(d_mutex);
item *p;
+ if (d_max_items != 0){
+ while (d_n_items >= d_max_items)
+ d_cond.wait();
+ }
+
if (d_freelist){ // got something?
p = d_freelist;
d_freelist = p->d_next;
+ d_n_items++;
return p;
}
@@ -79,6 +88,7 @@ pmt_pool::malloc()
// now return the first one
p = d_freelist;
d_freelist = p->d_next;
+ d_n_items++;
return p;
}
@@ -93,4 +103,7 @@ pmt_pool::free(void *foo)
item *p = (item *) foo;
p->d_next = d_freelist;
d_freelist = p;
+ d_n_items--;
+ if (d_max_items != 0)
+ d_cond.signal();
}
diff --git a/pmt/src/lib/pmt_pool.h b/pmt/src/lib/pmt_pool.h
index ac0c07bb6..42276a14f 100644
--- a/pmt/src/lib/pmt_pool.h
+++ b/pmt/src/lib/pmt_pool.h
@@ -38,10 +38,13 @@ class pmt_pool {
};
omni_mutex d_mutex;
+ omni_condition d_cond;
size_t d_itemsize;
size_t d_alignment;
size_t d_allocation_size;
+ size_t d_max_items;
+ size_t d_n_items;
item *d_freelist;
std::vector<char *> d_allocations;
@@ -50,8 +53,11 @@ public:
* \param itemsize size in bytes of the items to be allocated.
* \param alignment alignment in bytes of all objects to be allocated (must be power-of-2).
* \param allocation_size number of bytes to allocate at a time from the underlying allocator.
+ * \param max_items is the maximum number of items to allocate. If this number is exceeded,
+ * the allocate blocks. 0 implies no limit.
*/
- pmt_pool(size_t itemsize, size_t alignment = 16, size_t allocation_size = 4096);
+ pmt_pool(size_t itemsize, size_t alignment = 16,
+ size_t allocation_size = 4096, size_t max_items = 0);
~pmt_pool();
void *malloc();
diff --git a/pmt/src/lib/qa_pmt_prims.cc b/pmt/src/lib/qa_pmt_prims.cc
index 26b3e26d3..57db4a1a9 100644
--- a/pmt/src/lib/qa_pmt_prims.cc
+++ b/pmt/src/lib/qa_pmt_prims.cc
@@ -301,6 +301,20 @@ qa_pmt_prims::test_io()
CPPUNIT_ASSERT_EQUAL(std::string("k0"), pmt_write_string(k0));
}
+void
+qa_pmt_prims::test_lists()
+{
+ pmt_t s0 = pmt_intern("s0");
+ pmt_t s1 = pmt_intern("s1");
+ pmt_t s2 = pmt_intern("s2");
+ pmt_t s3 = pmt_intern("s3");
+
+ pmt_t l1 = pmt_list4(s0, s1, s2, s3);
+ pmt_t l2 = pmt_list3(s0, s1, s2);
+ pmt_t l3 = pmt_list_add(l2, s3);
+ CPPUNIT_ASSERT(pmt_equal(l1, l3));
+}
+
// ------------------------------------------------------------------------
// class foo is used in test_any below.
diff --git a/pmt/src/lib/qa_pmt_prims.h b/pmt/src/lib/qa_pmt_prims.h
index be49a30e4..919fc2dca 100644
--- a/pmt/src/lib/qa_pmt_prims.h
+++ b/pmt/src/lib/qa_pmt_prims.h
@@ -40,6 +40,7 @@ class qa_pmt_prims : public CppUnit::TestCase {
CPPUNIT_TEST(test_dict);
CPPUNIT_TEST(test_any);
CPPUNIT_TEST(test_io);
+ CPPUNIT_TEST(test_lists);
CPPUNIT_TEST(test_serialize);
CPPUNIT_TEST_SUITE_END();
@@ -56,6 +57,7 @@ class qa_pmt_prims : public CppUnit::TestCase {
void test_dict();
void test_any();
void test_io();
+ void test_lists();
void test_serialize();
};
diff --git a/usrp/fpga/Makefile.extra b/usrp/fpga/Makefile.extra
index 8154e2eb0..56df23c98 100644
--- a/usrp/fpga/Makefile.extra
+++ b/usrp/fpga/Makefile.extra
@@ -4,14 +4,11 @@ EXTRA_DIST = \
inband_lib/channel_demux.v \
inband_lib/channel_ram.v \
inband_lib/cmd_reader.v \
- inband_lib/data_packet_fifo.v \
inband_lib/packet_builder.v \
inband_lib/register_io.v \
inband_lib/rx_buffer_inband.v \
inband_lib/tx_buffer_inband.v \
inband_lib/tx_packer.v \
- inband_lib/usb_fifo_reader.v \
- inband_lib/usb_fifo_writer.v \
inband_lib/usb_packet_fifo.v \
megacells/accum32.bsf \
megacells/accum32.cmp \
diff --git a/usrp/fpga/inband_lib/chan_fifo_reader.v b/usrp/fpga/inband_lib/chan_fifo_reader.v
index a6edf2c60..69da9ec5a 100755
--- a/usrp/fpga/inband_lib/chan_fifo_reader.v
+++ b/usrp/fpga/inband_lib/chan_fifo_reader.v
@@ -1,106 +1,102 @@
module chan_fifo_reader
- ( reset, tx_clock, tx_strobe, adc_time, samples_format,
+ (reset, tx_clock, tx_strobe, timestamp_clock, samples_format,
fifodata, pkt_waiting, rdreq, skip, tx_q, tx_i,
underrun, tx_empty, debug, rssi, threshhold, rssi_wait) ;
- input wire reset ;
- input wire tx_clock ;
- input wire tx_strobe ; //signal to output tx_i and tx_q
- input wire [31:0] adc_time ; //current time
- input wire [3:0] samples_format ;// not useful at this point
- input wire [31:0] fifodata ; //the data input
- input wire pkt_waiting ; //signal the next packet is ready
- output reg rdreq ; //actually an ack to the current fifodata
- output reg skip ; //finish reading current packet
- output reg [15:0] tx_q ; //top 16 bit output of fifodata
- output reg [15:0] tx_i ; //bottom 16 bit output of fifodata
- output reg underrun ;
- output reg tx_empty ; //cause 0 to be the output
- input wire [31:0] rssi;
- input wire [31:0] threshhold;
- input wire [31:0] rssi_wait;
+ input wire reset ;
+ input wire tx_clock ;
+ input wire tx_strobe ; //signal to output tx_i and tx_q
+ input wire [31:0] timestamp_clock ; //current time
+ input wire [3:0] samples_format ;// not useful at this point
+ input wire [31:0] fifodata ; //the data input
+ input wire pkt_waiting ; //signal the next packet is ready
+ output reg rdreq ; //actually an ack to the current fifodata
+ output reg skip ; //finish reading current packet
+ output reg [15:0] tx_q ; //top 16 bit output of fifodata
+ output reg [15:0] tx_i ; //bottom 16 bit output of fifodata
+ output reg underrun ;
+ output reg tx_empty ; //cause 0 to be the output
+ input wire [31:0] rssi;
+ input wire [31:0] threshhold;
+ input wire [31:0] rssi_wait;
- output wire [14:0] debug;
- assign debug = {reader_state, trash, skip, timestamp[4:0], adc_time[4:0]};
- // Should not be needed if adc clock rate < tx clock rate
- // Used only to debug
- `define JITTER 5
-
- //Samples format
- // 16 bits interleaved complex samples
- `define QI16 4'b0
+ output wire [14:0] debug;
+ assign debug = {7'd0, rdreq, skip, reader_state, pkt_waiting, tx_strobe, tx_clock};
+
+ //Samples format
+ // 16 bits interleaved complex samples
+ `define QI16 4'b0
- // States
- parameter IDLE = 3'd0;
- parameter HEADER = 3'd1;
- parameter TIMESTAMP = 3'd2;
- parameter WAIT = 3'd3;
- parameter WAITSTROBE = 3'd4;
- parameter SEND = 3'd5;
+ // States
+ parameter IDLE = 3'd0;
+ parameter HEADER = 3'd1;
+ parameter TIMESTAMP = 3'd2;
+ parameter WAIT = 3'd3;
+ parameter WAITSTROBE = 3'd4;
+ parameter SEND = 3'd5;
- // Header format
- `define PAYLOAD 8:2
- `define ENDOFBURST 27
- `define STARTOFBURST 28
- `define RSSI_FLAG 26
+ // Header format
+ `define PAYLOAD 8:2
+ `define ENDOFBURST 27
+ `define STARTOFBURST 28
+ `define RSSI_FLAG 26
- /* State registers */
- reg [2:0] reader_state;
- /* Local registers */
- reg [6:0] payload_len;
- reg [6:0] read_len;
- reg [31:0] timestamp;
- reg burst;
- reg trash;
- reg rssi_flag;
- reg [31:0] time_wait;
+ /* State registers */
+ reg [2:0] reader_state;
+ /* Local registers */
+ reg [6:0] payload_len;
+ reg [6:0] read_len;
+ reg [31:0] timestamp;
+ reg burst;
+ reg trash;
+ reg rssi_flag;
+ reg [31:0] time_wait;
- always @(posedge tx_clock)
- begin
- if (reset)
- begin
- reader_state <= IDLE;
- rdreq <= 0;
- skip <= 0;
- underrun <= 0;
- burst <= 0;
- tx_empty <= 1;
- tx_q <= 0;
- tx_i <= 0;
- trash <= 0;
- rssi_flag <= 0;
- time_wait <= 0;
+ always @(posedge tx_clock)
+ begin
+ if (reset)
+ begin
+ reader_state <= IDLE;
+ rdreq <= 0;
+ skip <= 0;
+ underrun <= 0;
+ burst <= 0;
+ tx_empty <= 1;
+ tx_q <= 0;
+ tx_i <= 0;
+ trash <= 0;
+ rssi_flag <= 0;
+ time_wait <= 0;
end
else
- begin
+ begin
case (reader_state)
- IDLE:
+ IDLE:
begin
- /*
- * reset all the variables and wait for a tx_strobe
- * it is assumed that the ram connected to this fifo_reader
- * is a short hand fifo meaning that the header to the next packet
- * is already available to this fifo_reader when pkt_waiting is on
- */
- skip <=0;
- time_wait <= 0;
- if (pkt_waiting == 1)
- begin
- reader_state <= HEADER;
- rdreq <= 1;
- underrun <= 0;
- end
- if (burst == 1 && pkt_waiting == 0)
- underrun <= 1;
-
- if (tx_strobe == 1)
- tx_empty <= 1 ;
+ /*
+ * reset all the variables and wait for a tx_strobe
+ * it is assumed that the ram connected to this fifo_reader
+ * is a short hand fifo meaning that the header to the next packet
+ * is already available to this fifo_reader when pkt_waiting is on
+ */
+ skip <=0;
+ time_wait <= 0;
+ if (pkt_waiting == 1)
+ begin
+ reader_state <= HEADER;
+ rdreq <= 1;
+ underrun <= 0;
+ end
+ if (burst == 1 && pkt_waiting == 0)
+ underrun <= 1;
+ if (tx_strobe == 1)
+ tx_empty <= 1 ;
end
- /* Process header */
+ /* Process header */
HEADER:
- begin
+ begin
if (tx_strobe == 1)
tx_empty <= 1 ;
@@ -114,68 +110,64 @@ module chan_fifo_reader
else if (fifodata[`ENDOFBURST] == 1)
burst <= 0;
- if (trash == 1 && fifodata[`STARTOFBURST] == 0)
- begin
- skip <= 1;
- reader_state <= IDLE;
- rdreq <= 0;
- end
- else
- begin
- payload_len <= fifodata[`PAYLOAD] ;
- read_len <= 0;
- rdreq <= 1;
- reader_state <= TIMESTAMP;
- end
- end
+ if (trash == 1 && fifodata[`STARTOFBURST] == 0)
+ begin
+ skip <= 1;
+ reader_state <= IDLE;
+ rdreq <= 0;
+ end
+ else
+ begin
+ payload_len <= fifodata[`PAYLOAD] ;
+ read_len <= 0;
+ rdreq <= 1;
+ reader_state <= TIMESTAMP;
+ end
+ end
TIMESTAMP:
- begin
+ begin
timestamp <= fifodata;
reader_state <= WAIT;
if (tx_strobe == 1)
tx_empty <= 1 ;
rdreq <= 0;
- end
+ end
- // Decide if we wait, send or discard samples
+ // Decide if we wait, send or discard samples
WAIT:
- begin
+ begin
if (tx_strobe == 1)
tx_empty <= 1 ;
time_wait <= time_wait + 32'd1;
- // Outdated
- if ((timestamp < adc_time) ||
- (time_wait >= rssi_wait && rssi_wait != 0 && rssi_flag))
+ // Outdated
+ if ((timestamp < timestamp_clock) ||
+ (time_wait >= rssi_wait && rssi_wait != 0 && rssi_flag))
begin
- trash <= 1;
- reader_state <= IDLE;
- skip <= 1;
+ trash <= 1;
+ reader_state <= IDLE;
+ skip <= 1;
end
// Let's send it
- else if ((timestamp <= adc_time + `JITTER
- && timestamp > adc_time)
+ else if (timestamp == timestamp_clock
|| timestamp == 32'hFFFFFFFF)
- begin
- if (rssi <= threshhold || rssi_flag == 0)
- begin
- trash <= 0;
- reader_state <= WAITSTROBE;
- end
- else
- reader_state <= WAIT;
- end
- else
- reader_state <= WAIT;
- // Wait a little bit more
- //else if (timestamp > adc_time + `JITTER)
- // reader_state <= WAIT;
- end
+ begin
+ if (rssi <= threshhold || rssi_flag == 0)
+ begin
+ trash <= 0;
+ reader_state <= WAITSTROBE;
+ end
+ else
+ reader_state <= WAIT;
+ end
+ else
+ reader_state <= WAIT;
+ end
// Wait for the transmit chain to be ready
WAITSTROBE:
- begin
+ begin
// If end of payload...
if (read_len == payload_len)
begin
@@ -189,11 +181,11 @@ module chan_fifo_reader
reader_state <= SEND;
rdreq <= 1;
end
- end
+ end
- // Send the samples to the tx_chain
+ // Send the samples to the tx_chain
SEND:
- begin
+ begin
reader_state <= WAITSTROBE;
read_len <= read_len + 7'd1;
tx_empty <= 0;
@@ -213,13 +205,13 @@ module chan_fifo_reader
tx_q <= fifodata[31:16];
end
endcase
- end
+ end
default:
- begin
- //error handling
+ begin
+ //error handling
reader_state <= IDLE;
- end
+ end
endcase
end
end
diff --git a/usrp/fpga/inband_lib/channel_demux.v b/usrp/fpga/inband_lib/channel_demux.v
index d46be9397..cca5cdb65 100644
--- a/usrp/fpga/inband_lib/channel_demux.v
+++ b/usrp/fpga/inband_lib/channel_demux.v
@@ -1,24 +1,24 @@
module channel_demux
- #(parameter NUM_CHAN = 2, parameter CHAN_WIDTH = 2) ( //usb Side
- input [31:0]usbdata_final,
- input WR_final,
-
- // TX Side
- input reset,
- input txclk,
- output reg [CHAN_WIDTH:0] WR_channel,
- output reg [31:0] ram_data,
- output reg [CHAN_WIDTH:0] WR_done_channel );
-/* Parse header and forward to ram */
- reg [2:0]reader_state;
- reg [4:0]channel ;
- reg [6:0]read_length ;
+ #(parameter NUM_CHAN = 2) ( //usb Side
+ input [31:0]usbdata_final,
+ input WR_final,
+ // TX Side
+ input reset,
+ input txclk,
+ output reg [NUM_CHAN:0] WR_channel,
+ output reg [31:0] ram_data,
+ output reg [NUM_CHAN:0] WR_done_channel );
+ /* Parse header and forward to ram */
+
+ reg [2:0]reader_state;
+ reg [4:0]channel ;
+ reg [6:0]read_length ;
// States
- parameter IDLE = 3'd0;
- parameter HEADER = 3'd1;
- parameter WAIT = 3'd2;
- parameter FORWARD = 3'd3;
+ parameter IDLE = 3'd0;
+ parameter HEADER = 3'd1;
+ parameter WAIT = 3'd2;
+ parameter FORWARD = 3'd3;
`define CHANNEL 20:16
`define PKT_SIZE 127
@@ -27,7 +27,7 @@ module channel_demux
NUM_CHAN : (usbdata_final[`CHANNEL]);
always @(posedge txclk)
- begin
+ begin
if (reset)
begin
reader_state <= IDLE;
diff --git a/usrp/fpga/inband_lib/channel_ram.v b/usrp/fpga/inband_lib/channel_ram.v
index 60450f02d..9621246c5 100755
--- a/usrp/fpga/inband_lib/channel_ram.v
+++ b/usrp/fpga/inband_lib/channel_ram.v
@@ -1,114 +1,107 @@
module channel_ram
- ( // System
- input txclk,
- input reset,
+ ( // System
+ input txclk, input reset,
+ // USB side
+ input [31:0] datain, input WR, input WR_done, output have_space,
+ // Reader side
+ output [31:0] dataout, input RD, input RD_done, output packet_waiting);
- // USB side
- input [31:0] datain,
- input WR,
- input WR_done,
- output have_space,
-
- // Reader side
- output [31:0] dataout,
- input RD,
- input RD_done,
- output packet_waiting);
-
- reg [6:0] wr_addr, rd_addr;
- reg [1:0] which_ram_wr, which_ram_rd;
- reg [2:0] nb_packets;
+ reg [6:0] wr_addr, rd_addr;
+ reg [1:0] which_ram_wr, which_ram_rd;
+ reg [2:0] nb_packets;
- reg [31:0] ram0 [0:127];
- reg [31:0] ram1 [0:127];
- reg [31:0] ram2 [0:127];
- reg [31:0] ram3 [0:127];
+ reg [31:0] ram0 [0:127];
+ reg [31:0] ram1 [0:127];
+ reg [31:0] ram2 [0:127];
+ reg [31:0] ram3 [0:127];
- reg [31:0] dataout0;
- reg [31:0] dataout1;
- reg [31:0] dataout2;
- reg [31:0] dataout3;
+ reg [31:0] dataout0;
+ reg [31:0] dataout1;
+ reg [31:0] dataout2;
+ reg [31:0] dataout3;
- wire wr_done_int;
- wire rd_done_int;
- wire [6:0] rd_addr_final;
- wire [1:0] which_ram_rd_final;
+ wire wr_done_int;
+ wire rd_done_int;
+ wire [6:0] rd_addr_final;
+ wire [1:0] which_ram_rd_final;
- // USB side
- always @(posedge txclk)
- if(WR & (which_ram_wr == 2'd0)) ram0[wr_addr] <= datain;
+ // USB side
+ always @(posedge txclk)
+ if(WR & (which_ram_wr == 2'd0)) ram0[wr_addr] <= datain;
- always @(posedge txclk)
- if(WR & (which_ram_wr == 2'd1)) ram1[wr_addr] <= datain;
+ always @(posedge txclk)
+ if(WR & (which_ram_wr == 2'd1)) ram1[wr_addr] <= datain;
- always @(posedge txclk)
- if(WR & (which_ram_wr == 2'd2)) ram2[wr_addr] <= datain;
+ always @(posedge txclk)
+ if(WR & (which_ram_wr == 2'd2)) ram2[wr_addr] <= datain;
- always @(posedge txclk)
- if(WR & (which_ram_wr == 2'd3)) ram3[wr_addr] <= datain;
+ always @(posedge txclk)
+ if(WR & (which_ram_wr == 2'd3)) ram3[wr_addr] <= datain;
assign wr_done_int = ((WR && (wr_addr == 7'd127)) || WR_done);
- always @(posedge txclk)
- if(reset)
- wr_addr <= 0;
- else if (WR_done)
- wr_addr <= 0;
- else if (WR)
- wr_addr <= wr_addr + 7'd1;
+ always @(posedge txclk)
+ if(reset)
+ wr_addr <= 0;
+ else if (WR_done)
+ wr_addr <= 0;
+ else if (WR)
+ wr_addr <= wr_addr + 7'd1;
- always @(posedge txclk)
- if(reset)
- which_ram_wr <= 0;
- else if (wr_done_int)
- which_ram_wr <= which_ram_wr + 2'd1;
+ always @(posedge txclk)
+ if(reset)
+ which_ram_wr <= 0;
+ else if (wr_done_int)
+ which_ram_wr <= which_ram_wr + 2'd1;
- assign have_space = (nb_packets < 3'd3);
+ assign have_space = (nb_packets < 3'd3);
- // Reader side
- // short hand fifo
- // rd_addr_final is what rd_addr is going to be next clock cycle
- // which_ram_rd_final is what which_ram_rd is going to be next clock cycle
- always @(posedge txclk) dataout0 <= ram0[rd_addr_final];
- always @(posedge txclk) dataout1 <= ram1[rd_addr_final];
- always @(posedge txclk) dataout2 <= ram2[rd_addr_final];
- always @(posedge txclk) dataout3 <= ram3[rd_addr_final];
+ // Reader side
+ // short hand fifo
+ // rd_addr_final is what rd_addr is going to be next clock cycle
+ // which_ram_rd_final is what which_ram_rd is going to be next clock cycle
+ always @(posedge txclk) dataout0 <= ram0[rd_addr_final];
+ always @(posedge txclk) dataout1 <= ram1[rd_addr_final];
+ always @(posedge txclk) dataout2 <= ram2[rd_addr_final];
+ always @(posedge txclk) dataout3 <= ram3[rd_addr_final];
- assign dataout = (which_ram_rd_final[1]) ?
- (which_ram_rd_final[0] ? dataout3 : dataout2) :
- (which_ram_rd_final[0] ? dataout1 : dataout0);
+ assign dataout = (which_ram_rd_final[1]) ?
+ (which_ram_rd_final[0] ? dataout3 : dataout2) :
+ (which_ram_rd_final[0] ? dataout1 : dataout0);
- //RD_done is the only way to signal the end of one packet
- assign rd_done_int = RD_done;
+ //RD_done is the only way to signal the end of one packet
+ assign rd_done_int = RD_done;
- always @(posedge txclk)
- if (reset)
- rd_addr <= 0;
- else if (RD_done)
- rd_addr <= 0;
- else if (RD) rd_addr <= rd_addr + 7'd1;
+ always @(posedge txclk)
+ if (reset)
+ rd_addr <= 0;
+ else if (RD_done)
+ rd_addr <= 0;
+ else if (RD)
+ rd_addr <= rd_addr + 7'd1;
- assign rd_addr_final = (reset|RD_done) ? (6'd0) :
- ((RD)?(rd_addr+7'd1):rd_addr);
- always @(posedge txclk)
- if (reset)
- which_ram_rd <= 0;
- else if (rd_done_int)
- which_ram_rd <= which_ram_rd + 2'd1;
+ assign rd_addr_final = (reset|RD_done) ? (6'd0) :
+ ((RD)?(rd_addr+7'd1):rd_addr);
+
+ always @(posedge txclk)
+ if (reset)
+ which_ram_rd <= 0;
+ else if (rd_done_int)
+ which_ram_rd <= which_ram_rd + 2'd1;
- assign which_ram_rd_final = (reset) ? (2'd0):
+ assign which_ram_rd_final = (reset) ? (2'd0):
((rd_done_int) ? (which_ram_rd + 2'd1) : which_ram_rd);
- //packet_waiting is set to zero if rd_done_int is high
- //because there is no guarantee that nb_packets will be pos.
- //assign packet_waiting = (nb_packets != 0) & (~rd_done_int);
- assign packet_waiting = (nb_packets > 1) | ((nb_packets == 1)&(~rd_done_int));
- always @(posedge txclk)
- if (reset)
- nb_packets <= 0;
- else if (wr_done_int & ~rd_done_int)
- nb_packets <= nb_packets + 3'd1;
- else if (rd_done_int & ~wr_done_int)
- nb_packets <= nb_packets - 3'd1;
+ //packet_waiting is set to zero if rd_done_int is high
+ //because there is no guarantee that nb_packets will be pos.
+
+ assign packet_waiting = (nb_packets > 1) | ((nb_packets == 1)&(~rd_done_int));
+ always @(posedge txclk)
+ if (reset)
+ nb_packets <= 0;
+ else if (wr_done_int & ~rd_done_int)
+ nb_packets <= nb_packets + 3'd1;
+ else if (rd_done_int & ~wr_done_int)
+ nb_packets <= nb_packets - 3'd1;
-endmodule \ No newline at end of file
+endmodule
diff --git a/usrp/fpga/inband_lib/cmd_reader.v b/usrp/fpga/inband_lib/cmd_reader.v
index 7604321e4..b69ea02b7 100755
--- a/usrp/fpga/inband_lib/cmd_reader.v
+++ b/usrp/fpga/inband_lib/cmd_reader.v
@@ -1,292 +1,305 @@
-module cmd_reader(
- //System
- input reset,
- input txclk,
- input [31:0] adc_time,
- //FX2 Side
- output reg skip,
- output reg rdreq,
- input [31:0] fifodata,
- input pkt_waiting,
- //Rx side
- input rx_WR_enabled,
- output reg [15:0] rx_databus,
- output reg rx_WR,
- output reg rx_WR_done,
- //register io
- input wire [31:0] reg_data_out,
- output reg [31:0] reg_data_in,
- output reg [6:0] reg_addr,
- output reg [1:0] reg_io_enable,
- output wire [14:0] debug
- );
+module cmd_reader
+ (//System
+ input reset, input txclk, input [31:0] timestamp_clock,
+ //FX2 Side
+ output reg skip, output reg rdreq,
+ input [31:0] fifodata, input pkt_waiting,
+ //Rx side
+ input rx_WR_enabled, output reg [15:0] rx_databus,
+ output reg rx_WR, output reg rx_WR_done,
+ //register io
+ input wire [31:0] reg_data_out, output reg [31:0] reg_data_in,
+ output reg [6:0] reg_addr, output reg [1:0] reg_io_enable,
+ output wire [14:0] debug, output reg stop, output reg [15:0] stop_time);
- // States
- parameter IDLE = 4'd0;
- parameter HEADER = 4'd1;
- parameter TIMESTAMP = 4'd2;
- parameter WAIT = 4'd3;
- parameter TEST = 4'd4;
- parameter SEND = 4'd5;
- parameter PING = 4'd6;
- parameter WRITE_REG = 4'd7;
- parameter WRITE_REG_MASKED = 4'd8;
- parameter READ_REG = 4'd9;
- parameter DELAY = 4'd14;
+ // States
+ parameter IDLE = 4'd0;
+ parameter HEADER = 4'd1;
+ parameter TIMESTAMP = 4'd2;
+ parameter WAIT = 4'd3;
+ parameter TEST = 4'd4;
+ parameter SEND = 4'd5;
+ parameter PING = 4'd6;
+ parameter WRITE_REG = 4'd7;
+ parameter WRITE_REG_MASKED = 4'd8;
+ parameter READ_REG = 4'd9;
+ parameter DELAY = 4'd14;
- `define OP_PING_FIXED 8'd0
- `define OP_PING_FIXED_REPLY 8'd1
- `define OP_WRITE_REG 8'd2
- `define OP_WRITE_REG_MASKED 8'd3
- `define OP_READ_REG 8'd4
- `define OP_READ_REG_REPLY 8'd5
- `define OP_DELAY 8'd12
+ `define OP_PING_FIXED 8'd0
+ `define OP_PING_FIXED_REPLY 8'd1
+ `define OP_WRITE_REG 8'd2
+ `define OP_WRITE_REG_MASKED 8'd3
+ `define OP_READ_REG 8'd4
+ `define OP_READ_REG_REPLY 8'd5
+ `define OP_DELAY 8'd12
- reg [6:0] payload;
- reg [6:0] payload_read;
- reg [3:0] state;
- reg [15:0] high;
- reg [15:0] low;
- reg pending;
- reg [31:0] value0;
- reg [31:0] value1;
- reg [31:0] value2;
- reg [1:0] lines_in;
- reg [1:0] lines_out;
- reg [1:0] lines_out_total;
+ reg [6:0] payload;
+ reg [6:0] payload_read;
+ reg [3:0] state;
+ reg [15:0] high;
+ reg [15:0] low;
+ reg pending;
+ reg [31:0] value0;
+ reg [31:0] value1;
+ reg [31:0] value2;
+ reg [1:0] lines_in;
+ reg [1:0] lines_out;
+ reg [1:0] lines_out_total;
- `define JITTER 5
- `define OP_CODE 31:24
- `define PAYLOAD 8:2
+ `define JITTER 5
+ `define OP_CODE 31:24
+ `define PAYLOAD 8:2
- wire [7:0] ops;
- assign ops = value0[`OP_CODE];
- assign debug = {state[3:0], lines_out[1:0], pending, rx_WR, rx_WR_enabled, value0[2:0], ops[2:0]};
+ wire [7:0] ops;
+ assign ops = value0[`OP_CODE];
+ assign debug = {state[3:0], lines_out[1:0], pending, rx_WR, rx_WR_enabled, value0[2:0], ops[2:0]};
- always @(posedge txclk)
- if (reset)
- begin
- pending <= 0;
- state <= IDLE;
- skip <= 0;
- rdreq <= 0;
- rx_WR <= 0;
- reg_io_enable <= 0;
- reg_data_in <= 0;
- reg_addr <= 0;
- end
- else case (state)
- IDLE : begin
- payload_read <= 0;
- skip <= 0;
- lines_in <= 0;
- if (pkt_waiting)
- begin
- state <= HEADER;
- rdreq <= 1;
- end
- end
+ always @(posedge txclk)
+ if (reset)
+ begin
+ pending <= 0;
+ state <= IDLE;
+ skip <= 0;
+ rdreq <= 0;
+ rx_WR <= 0;
+ reg_io_enable <= 0;
+ reg_data_in <= 0;
+ reg_addr <= 0;
+ stop <= 0;
+ end
+ else case (state)
+ IDLE :
+ begin
+ payload_read <= 0;
+ skip <= 0;
+ lines_in <= 0;
+ if(pkt_waiting)
+ begin
+ state <= HEADER;
+ rdreq <= 1;
+ end
+ end
+
+ HEADER :
+ begin
+ payload <= fifodata[`PAYLOAD];
+ state <= TIMESTAMP;
+ end
+
+ TIMESTAMP :
+ begin
+ value0 <= fifodata;
+ state <= WAIT;
+ rdreq <= 0;
+ end
- HEADER : begin
- payload <= fifodata[`PAYLOAD];
- state <= TIMESTAMP;
- end
+ WAIT :
+ begin
+ // Let's send it
+ if ((value0 <= timestamp_clock + `JITTER
+ && value0 > timestamp_clock)
+ || value0 == 32'hFFFFFFFF)
+ state <= TEST;
+ // Wait a little bit more
+ else if (value0 > timestamp_clock + `JITTER)
+ state <= WAIT;
+ // Outdated
+ else if (value0 < timestamp_clock)
+ begin
+ state <= IDLE;
+ skip <= 1;
+ end
+ end
- TIMESTAMP : begin
- value0 <= fifodata;
- state <= WAIT;
- rdreq <= 0;
- end
-
- WAIT : begin
- // Let's send it
- if ((value0 <= adc_time + `JITTER
- && value0 > adc_time)
- || value0 == 32'hFFFFFFFF)
- state <= TEST;
- // Wait a little bit more
- else if (value0 > adc_time + `JITTER)
- state <= WAIT;
- // Outdated
- else if (value0 < adc_time)
- begin
- state <= IDLE;
+ TEST :
+ begin
+ reg_io_enable <= 0;
+ rx_WR <= 0;
+ rx_WR_done <= 1;
+ stop <= 0;
+ if (payload_read == payload)
+ begin
+ skip <= 1;
+ state <= IDLE;
+ rdreq <= 0;
+ end
+ else
+ begin
+ value0 <= fifodata;
+ lines_in <= 2'd1;
+ rdreq <= 1;
+ payload_read <= payload_read + 7'd1;
+ lines_out <= 0;
+ case (fifodata[`OP_CODE])
+ `OP_PING_FIXED:
+ begin
+ state <= PING;
+ end
+ `OP_WRITE_REG:
+ begin
+ state <= WRITE_REG;
+ pending <= 1;
+ end
+ `OP_WRITE_REG_MASKED:
+ begin
+ state <= WRITE_REG_MASKED;
+ pending <= 1;
+ end
+ `OP_READ_REG:
+ begin
+ state <= READ_REG;
+ end
+ `OP_DELAY:
+ begin
+ state <= DELAY;
+ end
+ default:
+ begin
+ //error, skip this packet
skip <= 1;
- end
- end
-
- TEST : begin
- reg_io_enable <= 0;
- rx_WR <= 0;
- rx_WR_done <= 1;
- if (payload_read == payload)
- begin
- skip <= 1;
- state <= IDLE;
- rdreq <= 0;
- end
- else
- begin
- value0 <= fifodata;
- lines_in <= 2'd1;
- rdreq <= 1;
- payload_read <= payload_read + 7'd1;
- lines_out <= 0;
- case (fifodata[`OP_CODE])
- `OP_PING_FIXED: begin
- state <= PING;
- end
- `OP_WRITE_REG: begin
- state <= WRITE_REG;
- pending <= 1;
- end
- `OP_WRITE_REG_MASKED: begin
- state <= WRITE_REG_MASKED;
- pending <= 1;
- end
- `OP_READ_REG: begin
- state <= READ_REG;
- end
- `OP_DELAY: begin
- state <= DELAY;
- end
- default: begin
- //error, skip this packet
- skip <= 1;
- state <= IDLE;
- end
- endcase
- end
- end
+ state <= IDLE;
+ end
+ endcase
+ end
+ end
- SEND: begin
- rdreq <= 0;
- rx_WR_done <= 0;
- if (pending)
- begin
- rx_WR <= 1;
- rx_databus <= high;
- pending <= 0;
- if (lines_out == lines_out_total)
- state <= TEST;
- else case (ops)
- `OP_READ_REG: begin
- state <= READ_REG;
- end
- default: begin
- state <= TEST;
- end
- endcase
- end
- else
- begin
- if (rx_WR_enabled)
- begin
- rx_WR <= 1;
- rx_databus <= low;
- pending <= 1;
- lines_out <= lines_out + 2'd1;
- end
- else
- rx_WR <= 0;
- end
- end
+ SEND:
+ begin
+ rdreq <= 0;
+ rx_WR_done <= 0;
+ if (pending)
+ begin
+ rx_WR <= 1;
+ rx_databus <= high;
+ pending <= 0;
+ if (lines_out == lines_out_total)
+ state <= TEST;
+ else case (ops)
+ `OP_READ_REG:
+ begin
+ state <= READ_REG;
+ end
+ default:
+ begin
+ state <= TEST;
+ end
+ endcase
+ end
+ else
+ begin
+ if (rx_WR_enabled)
+ begin
+ rx_WR <= 1;
+ rx_databus <= low;
+ pending <= 1;
+ lines_out <= lines_out + 2'd1;
+ end
+ else
+ rx_WR <= 0;
+ end
+ end
- PING: begin
- rx_WR <= 0;
- rdreq <= 0;
- rx_WR_done <= 0;
- lines_out_total <= 2'd1;
- pending <= 0;
- state <= SEND;
- high <= {`OP_PING_FIXED_REPLY, 8'd2};
- low <= value0[15:0];
- end
+ PING:
+ begin
+ rx_WR <= 0;
+ rdreq <= 0;
+ rx_WR_done <= 0;
+ lines_out_total <= 2'd1;
+ pending <= 0;
+ state <= SEND;
+ high <= {`OP_PING_FIXED_REPLY, 8'd2};
+ low <= value0[15:0];
+ end
- READ_REG: begin
- rx_WR <= 0;
- rx_WR_done <= 0;
- rdreq <= 0;
- lines_out_total <= 2'd2;
- pending <= 0;
- state <= SEND;
- if (lines_out == 0)
- begin
- high <= {`OP_READ_REG_REPLY, 8'd6};
- low <= value0[15:0];
- reg_io_enable <= 2'd3;
- reg_addr <= value0[6:0];
- end
- else
- begin
- high <= reg_data_out[31:16];
- low <= reg_data_out[15:0];
- end
- end
+ READ_REG:
+ begin
+ rx_WR <= 0;
+ rx_WR_done <= 0;
+ rdreq <= 0;
+ lines_out_total <= 2'd2;
+ pending <= 0;
+ state <= SEND;
+ if (lines_out == 0)
+ begin
+ high <= {`OP_READ_REG_REPLY, 8'd6};
+ low <= value0[15:0];
+ reg_io_enable <= 2'd3;
+ reg_addr <= value0[6:0];
+ end
+ else
+ begin
+ high <= reg_data_out[31:16];
+ low <= reg_data_out[15:0];
+ end
+ end
- WRITE_REG: begin
- rx_WR <= 0;
- if (pending)
- pending <= 0;
- else
- begin
- if (lines_in == 2'd1)
- begin
- payload_read <= payload_read + 7'd1;
- lines_in <= lines_in + 2'd1;
- value1 <= fifodata;
- rdreq <= 0;
- end
- else
- begin
- reg_io_enable <= 2'd2;
- reg_data_in <= value1;
- reg_addr <= value0[6:0];
- state <= TEST;
- end
- end
- end
+ WRITE_REG:
+ begin
+ rx_WR <= 0;
+ if (pending)
+ pending <= 0;
+ else
+ begin
+ if (lines_in == 2'd1)
+ begin
+ payload_read <= payload_read + 7'd1;
+ lines_in <= lines_in + 2'd1;
+ value1 <= fifodata;
+ rdreq <= 0;
+ end
+ else
+ begin
+ reg_io_enable <= 2'd2;
+ reg_data_in <= value1;
+ reg_addr <= value0[6:0];
+ state <= TEST;
+ end
+ end
+ end
- WRITE_REG_MASKED: begin
- rx_WR <= 0;
- if (pending)
- pending <= 0;
- else
- begin
- if (lines_in == 2'd1)
- begin
- rdreq <= 1;
- payload_read <= payload_read + 7'd1;
- lines_in <= lines_in + 2'd1;
- value1 <= fifodata;
- end
- else if (lines_in == 2'd2)
- begin
- rdreq <= 0;
- payload_read <= payload_read + 7'd1;
- lines_in <= lines_in + 2'd1;
- value2 <= fifodata;
- end
- else
- begin
- reg_io_enable <= 2'd2;
- reg_data_in <= (value1 & value2);
- reg_addr <= value0[6:0];
- state <= TEST;
- end
- end
- end
+ WRITE_REG_MASKED:
+ begin
+ rx_WR <= 0;
+ if (pending)
+ pending <= 0;
+ else
+ begin
+ if (lines_in == 2'd1)
+ begin
+ rdreq <= 1;
+ payload_read <= payload_read + 7'd1;
+ lines_in <= lines_in + 2'd1;
+ value1 <= fifodata;
+ end
+ else if (lines_in == 2'd2)
+ begin
+ rdreq <= 0;
+ payload_read <= payload_read + 7'd1;
+ lines_in <= lines_in + 2'd1;
+ value2 <= fifodata;
+ end
+ else
+ begin
+ reg_io_enable <= 2'd2;
+ reg_data_in <= (value1 & value2);
+ reg_addr <= value0[6:0];
+ state <= TEST;
+ end
+ end
+ end
- DELAY : begin
- rdreq <= 0;
- value1 <= value1 + 32'd1;
- if (value0[15:0] == value1[15:0])
- state <= TEST;
- end
+ DELAY :
+ begin
+ rdreq <= 0;
+ stop <= 1;
+ stop_time <= value0[15:0];
+ state <= TEST;
+ end
- default : begin
- //error state handling
- state <= IDLE;
- end
- endcase
-endmodule \ No newline at end of file
+ default :
+ begin
+ //error state handling
+ state <= IDLE;
+ end
+ endcase
+endmodule
diff --git a/usrp/fpga/inband_lib/data_packet_fifo.v b/usrp/fpga/inband_lib/data_packet_fifo.v
deleted file mode 100755
index a9bcbdae7..000000000
--- a/usrp/fpga/inband_lib/data_packet_fifo.v
+++ /dev/null
@@ -1,118 +0,0 @@
-module data_packet_fifo
- ( input reset,
- input clock,
- input [31:0]ram_data_in,
- input write_enable,
- output reg have_space,
- output reg [31:0]ram_data_out,
- output reg pkt_waiting,
- output reg isfull,
- output reg [1:0]usb_ram_packet_out,
- output reg [1:0]usb_ram_packet_in,
- input read_enable,
- input pkt_complete,
- input skip_packet) ;
-
- /* Some parameters for usage later on */
- parameter DATA_WIDTH = 32 ;
- parameter PKT_DEPTH = 128 ;
- parameter NUM_PACKETS = 4 ;
-
- /* Create the RAM here */
- reg [DATA_WIDTH-1:0] usb_ram [PKT_DEPTH*NUM_PACKETS-1:0] ;
-
- /* Create the address signals */
- reg [6:0] usb_ram_offset_out ;
- //reg [1:0] usb_ram_packet_out ;
- reg [6:0] usb_ram_offset_in ;
- //reg [1:0] usb_ram_packet_in ;
-
- wire [6-2+NUM_PACKETS:0] usb_ram_aout ;
- wire [6-2+NUM_PACKETS:0] usb_ram_ain ;
- //reg isfull;
-
- assign usb_ram_aout = {usb_ram_packet_out, usb_ram_offset_out} ;
- assign usb_ram_ain = {usb_ram_packet_in, usb_ram_offset_in} ;
-
- // Check if there is one full packet to process
- always @(usb_ram_ain, usb_ram_aout, isfull)
- begin
- if (usb_ram_ain == usb_ram_aout)
- pkt_waiting <= isfull ;
- else if (usb_ram_ain > usb_ram_aout)
- pkt_waiting <= (usb_ram_ain - usb_ram_aout) >= PKT_DEPTH;
- else
- pkt_waiting <= (usb_ram_ain + 10'b1000000000 - usb_ram_aout) >= PKT_DEPTH;
- end
-
- // Check if there is room
- always @(usb_ram_ain, usb_ram_aout, isfull)
- begin
- if (usb_ram_ain == usb_ram_aout)
- have_space <= ~isfull;
- else if (usb_ram_ain > usb_ram_aout)
- have_space <= ((usb_ram_ain - usb_ram_aout) <= PKT_DEPTH * (NUM_PACKETS - 1))? 1'b1 : 1'b0;
- else
- have_space <= (usb_ram_aout - usb_ram_ain) >= PKT_DEPTH;
- end
-
-
-
- /* RAM Writing/Reading process */
- always @(posedge clock)
- begin
- if( write_enable )
- begin
- usb_ram[usb_ram_ain] <= ram_data_in ;
- end
- ram_data_out <= usb_ram[usb_ram_aout] ;
- end
-
- /* RAM Write/Read Address process */
- always @(posedge clock)
- begin
- if( reset )
- begin
- usb_ram_packet_out <= 0 ;
- usb_ram_offset_out <= 0 ;
- usb_ram_offset_in <= 0 ;
- usb_ram_packet_in <= 0 ;
- isfull <= 0;
- end
- else
- begin
- if( skip_packet )
- begin
- usb_ram_packet_out <= usb_ram_packet_out + 1 ;
- usb_ram_offset_out <= 0 ;
- isfull <= 0;
- end
- else if(read_enable)
- begin
- if( usb_ram_offset_out == 7'b1111111 )
- begin
- isfull <= 0 ;
- usb_ram_offset_out <= 0 ;
- usb_ram_packet_out <= usb_ram_packet_out + 1 ;
- end
- else
- usb_ram_offset_out <= usb_ram_offset_out + 1 ;
- end
- if( pkt_complete )
- begin
- usb_ram_packet_in <= usb_ram_packet_in + 1 ;
- usb_ram_offset_in <= 0 ;
- if ((usb_ram_packet_in + 2'b1) == usb_ram_packet_out)
- isfull <= 1 ;
- end
- else if( write_enable )
- begin
- if (usb_ram_offset_in == 7'b1111111)
- usb_ram_offset_in <= 7'b1111111 ;
- else
- usb_ram_offset_in <= usb_ram_offset_in + 1 ;
- end
- end
- end
-
-endmodule
diff --git a/usrp/fpga/inband_lib/packet_builder.v b/usrp/fpga/inband_lib/packet_builder.v
index fbf0a656e..2c9122394 100755
--- a/usrp/fpga/inband_lib/packet_builder.v
+++ b/usrp/fpga/inband_lib/packet_builder.v
@@ -1,8 +1,8 @@
-module packet_builder #(parameter NUM_CHAN = 1)(
+module packet_builder #(parameter NUM_CHAN = 2)(
// System
input rxclk,
input reset,
- input [31:0] adctime,
+ input [31:0] timestamp_clock,
input [3:0] channels,
// ADC side
input [15:0]chan_fifodata,
@@ -14,17 +14,17 @@ module packet_builder #(parameter NUM_CHAN = 1)(
output reg WR,
output reg [15:0]fifodata,
input have_space,
- input wire [31:0]rssi_0, input wire [31:0]rssi_1, input wire [31:0]rssi_2,
- input wire [31:0]rssi_3, output wire [7:0] debugbus,
- input [NUM_CHAN:0] overrun, input [NUM_CHAN:0] underrun);
+ input wire [31:0]rssi_0, input wire [31:0]rssi_1, input wire [31:0]rssi_2,
+ input wire [31:0]rssi_3, output wire [7:0] debugbus,
+ input [NUM_CHAN:0] underrun);
// States
`define IDLE 3'd0
`define HEADER1 3'd1
- `define HEADER2 3'd2
+ `define HEADER2 3'd2
`define TIMESTAMP 3'd3
- `define FORWARD 3'd4
+ `define FORWARD 3'd4
`define MAXPAYLOAD 504
@@ -39,51 +39,67 @@ module packet_builder #(parameter NUM_CHAN = 1)(
`define UNDERRUN 14
`define OVERRUN 15
+ reg [NUM_CHAN:0] overrun;
reg [2:0] state;
reg [8:0] read_length;
reg [8:0] payload_len;
- reg tstamp_complete;
+ reg timestamp_complete;
reg [3:0] check_next;
- wire [8:0] chan_used;
+
wire [31:0] true_rssi;
- wire [4:0] true_channel;
+ wire [4:0] true_channel;
+ wire ready_to_send;
+
+ assign debugbus = {chan_empty[0], rd_select[0], have_space,
+ (chan_usedw >= 10'd504), (chan_usedw ==0),
+ ready_to_send, state[1:0]};
- assign debugbus = {state, chan_empty[0], underrun[0], check_next[0],
- have_space, rd_select[0]};
- assign chan_used = chan_usedw[8:0];
- assign true_rssi = (rd_select[1]) ? ((rd_select[0]) ? rssi_3:rssi_2) :
+ assign true_rssi = (rd_select[1]) ? ((rd_select[0]) ? rssi_3:rssi_2) :
((rd_select[0]) ? rssi_1:rssi_0);
- assign true_channel = (check_next == 4'd0 ? 5'h1f : {1'd0, check_next - 4'd1});
+ assign true_channel = (check_next == 4'd0 ? 5'h1f : {1'd0, check_next - 4'd1});
+ assign ready_to_send = (chan_usedw >= 10'd504) || (chan_usedw == 0) ||
+ ((rd_select == NUM_CHAN)&&(chan_usedw > 0));
+
always @(posedge rxclk)
begin
if (reset)
begin
+ overrun <= 0;
WR <= 0;
rd_select <= 0;
chan_rdreq <= 0;
- tstamp_complete <= 0;
+ timestamp_complete <= 0;
check_next <= 0;
state <= `IDLE;
end
else case (state)
`IDLE: begin
- chan_rdreq <= #1 0;
- if (have_space)
- begin
- if(~chan_empty[check_next])
- begin
- state <= #1 `HEADER1;
- rd_select <= #1 check_next;
- end
- check_next <= #1 (check_next == channels ? 4'd0 : check_next + 4'd1);
- end
+ chan_rdreq <= #1 0;
+ //check if the channel is full
+ if(~chan_empty[check_next])
+ begin
+ if (have_space)
+ begin
+ //transmit if the usb buffer have space
+ //check if we should send
+ if (ready_to_send)
+ state <= #1 `HEADER1;
+
+ overrun[check_next] <= 0;
+ end
+ else
+ begin
+ state <= #1 `IDLE;
+ overrun[check_next] <= 1;
+ end
+ rd_select <= #1 check_next;
+ end
+ check_next <= #1 (check_next == channels ? 4'd0 : check_next + 4'd1);
end
`HEADER1: begin
- fifodata[`PAYLOAD_LEN] <= #1 (chan_used > 9'd252
- ? 9'd252 : chan_used << 1);
- payload_len <= #1 (chan_used > 9'd252
- ? 9'd252 : chan_used << 1);
+ fifodata[`PAYLOAD_LEN] <= #1 9'd504;
+ payload_len <= #1 9'd504;
fifodata[`TAG] <= #1 0;
fifodata[`MBZ] <= #1 0;
WR <= #1 1;
@@ -103,13 +119,13 @@ module packet_builder #(parameter NUM_CHAN = 1)(
end
`TIMESTAMP: begin
- fifodata <= #1 (tstamp_complete ? adctime[31:16] : adctime[15:0]);
- tstamp_complete <= #1 ~tstamp_complete;
+ fifodata <= #1 (timestamp_complete ? timestamp_clock[31:16] : timestamp_clock[15:0]);
+ timestamp_complete <= #1 ~timestamp_complete;
- if (~tstamp_complete)
+ if (~timestamp_complete)
chan_rdreq <= #1 1;
- state <= #1 (tstamp_complete ? `FORWARD : `TIMESTAMP);
+ state <= #1 (timestamp_complete ? `FORWARD : `TIMESTAMP);
end
`FORWARD: begin
diff --git a/usrp/fpga/inband_lib/register_io.v b/usrp/fpga/inband_lib/register_io.v
index b116b3ace..2b0cd1732 100755
--- a/usrp/fpga/inband_lib/register_io.v
+++ b/usrp/fpga/inband_lib/register_io.v
@@ -1,15 +1,38 @@
module register_io
- (input clk, input reset, input wire [1:0] enable, input wire [6:0] addr,
- input wire [31:0] datain, output reg [31:0] dataout, output wire [15:0] debugbus,
- input wire [31:0] rssi_0, input wire [31:0] rssi_1,
- input wire [31:0] rssi_2, input wire [31:0] rssi_3,
- output wire [31:0] threshhold, output wire [31:0] rssi_wait);
-
+ (clk, reset, enable, addr, datain, dataout, debugbus, addr_wr, data_wr, strobe_wr,
+ rssi_0, rssi_1, rssi_2, rssi_3, threshhold, rssi_wait, reg_0, reg_1, reg_2, reg_3,
+ debug_en, misc, txmux);
+
+ input clk;
+ input reset;
+ input wire [1:0] enable;
+ input wire [6:0] addr;
+ input wire [31:0] datain;
+ output reg [31:0] dataout;
+ output wire [15:0] debugbus;
+ output reg [6:0] addr_wr;
+ output reg [31:0] data_wr;
+ output wire strobe_wr;
+ input wire [31:0] rssi_0;
+ input wire [31:0] rssi_1;
+ input wire [31:0] rssi_2;
+ input wire [31:0] rssi_3;
+ output wire [31:0] threshhold;
+ output wire [31:0] rssi_wait;
+ input wire [15:0] reg_0;
+ input wire [15:0] reg_1;
+ input wire [15:0] reg_2;
+ input wire [15:0] reg_3;
+ input wire [3:0] debug_en;
+ input wire [7:0] misc;
+ input wire [31:0] txmux;
+
reg strobe;
- wire [31:0] out[7:0];
+ wire [31:0] out[2:1];
assign debugbus = {clk, enable, addr[2:0], datain[4:0], dataout[4:0]};
assign threshhold = out[1];
assign rssi_wait = out[2];
+ assign strobe_wr = strobe;
always @(*)
if (reset | ~enable[1])
@@ -22,41 +45,38 @@ module register_io
if (enable[0])
begin
//read
- if (addr == 7'd9)
- dataout <= rssi_0;
- else if (addr == 7'd10)
- dataout <= rssi_1;
- else if (addr == 7'd11)
- dataout <= rssi_2;
- else if (addr == 7'd12)
- dataout <= rssi_3;
- else
- dataout <= out[addr[2:0]];
- strobe <= 0;
- end
+ if (addr <= 7'd52 && addr > 7'd50)
+ dataout <= out[addr-7'd50];
+ else
+ dataout <= 32'hFFFFFFFF;
+ strobe <= 0;
+ end
else
begin
//write
dataout <= dataout;
strobe <= 1;
+ data_wr <= datain;
+ addr_wr <= addr;
end
end
- //register declarations
- setting_reg #(0) setting_reg0(.clock(clk),.reset(reset),
- .strobe(strobe),.addr(addr),.in(datain),.out(out[0]));
- setting_reg #(1) setting_reg1(.clock(clk),.reset(reset),
- .strobe(strobe),.addr(addr),.in(datain),.out(out[1]));
- setting_reg #(2) setting_reg2(.clock(clk),.reset(reset),
- .strobe(strobe),.addr(addr),.in(datain),.out(out[2]));
- setting_reg #(3) setting_reg3(.clock(clk),.reset(reset),
- .strobe(strobe),.addr(addr),.in(datain),.out(out[3]));
- setting_reg #(4) setting_reg4(.clock(clk),.reset(reset),
- .strobe(strobe),.addr(addr),.in(datain),.out(out[4]));
- setting_reg #(5) setting_reg5(.clock(clk),.reset(reset),
- .strobe(strobe),.addr(addr),.in(datain),.out(out[5]));
- setting_reg #(6) setting_reg6(.clock(clk),.reset(reset),
- .strobe(strobe),.addr(addr),.in(datain),.out(out[6]));
- setting_reg #(7) setting_reg7(.clock(clk),.reset(reset),
- .strobe(strobe),.addr(addr),.in(datain),.out(out[7]));
-endmodule \ No newline at end of file
+//register declarations
+ /*setting_reg #(50) setting_reg0(.clock(clk),.reset(reset),
+ .strobe(strobe_wr),.addr(addr_wr),.in(data_wr),.out(out[0]));*/
+ setting_reg #(51) setting_reg1(.clock(clk),.reset(reset),
+ .strobe(strobe_wr),.addr(addr_wr),.in(data_wr),.out(out[1]));
+ setting_reg #(52) setting_reg2(.clock(clk),.reset(reset),
+ .strobe(strobe_wr),.addr(addr_wr),.in(data_wr),.out(out[2]));
+ /*setting_reg #(53) setting_reg3(.clock(clk),.reset(reset),
+ .strobe(strobe_wr),.addr(addr_wr),.in(data_wr),.out(out[3]));
+ setting_reg #(54) setting_reg4(.clock(clk),.reset(reset),
+ .strobe(strobe_wr),.addr(addr_wr),.in(data_wr),.out(out[4]));
+ setting_reg #(55) setting_reg5(.clock(clk),.reset(reset),
+ .strobe(strobe_wr),.addr(addr_wr),.in(data_wr),.out(out[5]));
+ setting_reg #(56) setting_reg6(.clock(clk),.reset(reset),
+ .strobe(strobe_wr),.addr(addr_wr),.in(data_wr),.out(out[6]));
+ setting_reg #(57) setting_reg7(.clock(clk),.reset(reset),
+ .strobe(strobe_wr),.addr(addr_wr),.in(data_wr),.out(out[7]));*/
+
+endmodule
diff --git a/usrp/fpga/inband_lib/rx_buffer_inband.v b/usrp/fpga/inband_lib/rx_buffer_inband.v
index 1eaecabed..cbd2d8958 100755
--- a/usrp/fpga/inband_lib/rx_buffer_inband.v
+++ b/usrp/fpga/inband_lib/rx_buffer_inband.v
@@ -1,179 +1,209 @@
-//`include "../../firmware/include/fpga_regs_common.v"
-//`include "../../firmware/include/fpga_regs_standard.v"
-module rx_buffer_inband
- ( input usbclk,
- input bus_reset,
- input reset, // DSP side reset (used here), do not reset registers
- input reset_regs, //Only reset registers
- output [15:0] usbdata,
- input RD,
- output wire have_pkt_rdy,
- output reg rx_overrun,
- input wire [3:0] channels,
- input wire [15:0] ch_0,
- input wire [15:0] ch_1,
- input wire [15:0] ch_2,
- input wire [15:0] ch_3,
- input wire [15:0] ch_4,
- input wire [15:0] ch_5,
- input wire [15:0] ch_6,
- input wire [15:0] ch_7,
- input rxclk,
- input rxstrobe,
- input clear_status,
- input [6:0] serial_addr,
- input [31:0] serial_data,
- input serial_strobe,
- output wire [15:0] debugbus,
-
- //Connection with tx_inband
- input rx_WR,
- input [15:0] rx_databus,
- input rx_WR_done,
- output reg rx_WR_enabled,
- //signal strength
- input wire [31:0] rssi_0, input wire [31:0] rssi_1,
- input wire [31:0] rssi_2, input wire [31:0] rssi_3,
- input wire [1:0] tx_overrun, input wire [1:0] tx_underrun
- );
-
- parameter NUM_CHAN = 1;
- genvar i ;
-
- // FX2 Bug Fix
- reg [8:0] read_count;
- always @(negedge usbclk)
- if(bus_reset)
- read_count <= #1 9'd0;
- else if(RD & ~read_count[8])
- read_count <= #1 read_count + 9'd1;
- else
- read_count <= #1 RD ? read_count : 9'b0;
-
- // Time counter
- reg [31:0] adctime;
- always @(posedge rxclk)
- if (reset)
- adctime <= 0;
- else if (rxstrobe)
- adctime <= adctime + 1;
-
- // USB side fifo
- wire [11:0] rdusedw;
- wire [11:0] wrusedw;
- wire [15:0] fifodata;
- wire WR;
- wire have_space;
-
- fifo_4kx16_dc rx_usb_fifo (
- .aclr ( reset ),
- .data ( fifodata ),
- .rdclk ( ~usbclk ),
- .rdreq ( RD & ~read_count[8] ),
- .wrclk ( rxclk ),
- .wrreq ( WR ),
- .q ( usbdata ),
- .rdempty ( ),
- .rdusedw ( rdusedw ),
- .wrfull ( ),
- .wrusedw ( wrusedw ) );
-
- assign have_pkt_rdy = (rdusedw >= 12'd256);
- assign have_space = (wrusedw < 12'd760);
-
- // Rx side fifos
- wire chan_rdreq;
- wire [15:0] chan_fifodata;
- wire [9:0] chan_usedw;
- wire [NUM_CHAN:0] chan_empty;
- wire [3:0] rd_select;
- wire [NUM_CHAN:0] rx_full;
-
- packet_builder #(NUM_CHAN) rx_pkt_builer (
- .rxclk ( rxclk ),
- .reset ( reset ),
- .adctime ( adctime ),
- .channels ( 4'd1 ),
- .chan_rdreq ( chan_rdreq ),
- .chan_fifodata ( chan_fifodata ),
- .chan_empty ( chan_empty ),
- .rd_select ( rd_select ),
- .chan_usedw ( chan_usedw ),
- .WR ( WR ),
- .fifodata ( fifodata ),
- .have_space ( have_space ),
- .rssi_0(rssi_0), .rssi_1(rssi_1),
- .rssi_2(rssi_2),.rssi_3(rssi_3), .debugbus(debug),
- .overrun(tx_overrun), .underrun(tx_underrun));
-
- // Detect overrun
- always @(posedge rxclk)
- if(reset)
- rx_overrun <= 1'b0;
- else if(rx_full[0])
- rx_overrun <= 1'b1;
- else if(clear_status)
- rx_overrun <= 1'b0;
-
- reg [6:0] test;
- always @(posedge rxclk)
- if (reset)
- test <= 0;
- else
- test <= test + 7'd1;
-
- // TODO write this genericly
- wire [15:0]ch[NUM_CHAN:0];
- assign ch[0] = ch_0;
-
- wire cmd_empty;
- always @(posedge rxclk)
- if(reset)
- rx_WR_enabled <= 1;
- else if(cmd_empty)
- rx_WR_enabled <= 1;
- else if(rx_WR_done)
- rx_WR_enabled <= 0;
-
- wire [15:0] dataout [0:NUM_CHAN];
- wire [9:0] usedw [0:NUM_CHAN];
- wire empty[0:NUM_CHAN];
-
- generate for (i = 0 ; i < NUM_CHAN; i = i + 1)
- begin : generate_channel_fifos
- wire rdreq;
-
- assign rdreq = (rd_select == i) & chan_rdreq;
- //assign chan_empty[i] = usedw[i] < 10'd126;
- fifo_1kx16 rx_chan_fifo (
- .aclr ( reset ),
- .clock ( rxclk ),
- .data ( ch[i] ),
- .rdreq ( rdreq ),
- .wrreq ( ~rx_full[i] & rxstrobe),
- .empty (empty[i]),
- .full (rx_full[i]),
- .q ( dataout[i]),
- .usedw ( usedw[i]),
- .almost_empty(chan_empty[i])
- );
- end
- endgenerate
- wire [7:0] debug;
- fifo_1kx16 rx_cmd_fifo (
- .aclr ( reset ),
- .clock ( rxclk ),
- .data ( rx_databus ),
- .rdreq ( (rd_select == NUM_CHAN) & chan_rdreq ),
- .wrreq ( rx_WR & rx_WR_enabled),
- .empty ( cmd_empty),
- .full ( rx_full[NUM_CHAN] ),
- .q ( dataout[NUM_CHAN]),
- .usedw ( usedw[NUM_CHAN] )
- );
- assign chan_empty[NUM_CHAN] = cmd_empty | rx_WR_enabled;
- assign chan_fifodata = dataout[rd_select];
- assign chan_usedw = usedw[rd_select];
- assign debugbus = {rxstrobe, chan_rdreq, debug,
- rx_full[0], chan_empty[0], empty[0], have_space, RD, rxclk};
-endmodule
+//`include "../../firmware/include/fpga_regs_common.v"
+//`include "../../firmware/include/fpga_regs_standard.v"
+module rx_buffer_inband
+ ( input usbclk,
+ input bus_reset,
+ input reset, // DSP side reset (used here), do not reset registers
+ input reset_regs, //Only reset registers
+ output [15:0] usbdata,
+ input RD,
+ output wire have_pkt_rdy,
+ output reg rx_overrun,
+ input wire [3:0] channels,
+ input wire [15:0] ch_0,
+ input wire [15:0] ch_1,
+ input wire [15:0] ch_2,
+ input wire [15:0] ch_3,
+ input wire [15:0] ch_4,
+ input wire [15:0] ch_5,
+ input wire [15:0] ch_6,
+ input wire [15:0] ch_7,
+ input rxclk,
+ input rxstrobe,
+ input clear_status,
+ input [6:0] serial_addr,
+ input [31:0] serial_data,
+ input serial_strobe,
+ output wire [15:0] debugbus,
+
+ //Connection with tx_inband
+ input rx_WR,
+ input [15:0] rx_databus,
+ input rx_WR_done,
+ output reg rx_WR_enabled,
+ //signal strength
+ input wire [31:0] rssi_0, input wire [31:0] rssi_1,
+ input wire [31:0] rssi_2, input wire [31:0] rssi_3,
+ input wire [1:0] tx_underrun
+ );
+
+ parameter NUM_CHAN = 1;
+ genvar i ;
+
+ // FX2 Bug Fix
+ reg [8:0] read_count;
+ always @(negedge usbclk)
+ if(bus_reset)
+ read_count <= #1 9'd0;
+ else if(RD & ~read_count[8])
+ read_count <= #1 read_count + 9'd1;
+ else
+ read_count <= #1 RD ? read_count : 9'b0;
+
+ // Time counter
+ reg [31:0] timestamp_clock;
+ always @(posedge rxclk)
+ if (reset)
+ timestamp_clock <= 0;
+ else
+ timestamp_clock <= timestamp_clock + 1;
+
+ // USB side fifo
+ wire [11:0] rdusedw;
+ wire [11:0] wrusedw;
+ wire [15:0] fifodata;
+ wire [15:0] fifodata_il[0:NUM_CHAN];
+ wire WR;
+ wire have_space;
+ reg sel;
+ reg wr;
+
+ always@(posedge rxclk)
+ begin
+ if(reset)
+ begin
+ sel<=1;
+ wr<=0;
+ end
+ else if(rxstrobe)
+ begin
+ sel<=0;
+ wr<=1;
+ end
+ else if(wr&~sel)
+ sel<=1;
+ else if(wr&sel)
+ wr<=0;
+ else
+ wr<=0;
+ end
+
+ assign fifodata_il[0] = (sel)?ch_1:ch_0;
+ assign fifodata_il[1] = (sel)?ch_3:ch_2;
+
+ fifo_4kx16_dc rx_usb_fifo (
+ .aclr ( reset ),
+ .data ( fifodata ),
+ .rdclk ( ~usbclk ),
+ .rdreq ( RD & ~read_count[8] ),
+ .wrclk ( rxclk ),
+ .wrreq ( WR ),
+ .q ( usbdata ),
+ .rdempty ( ),
+ .rdusedw ( rdusedw ),
+ .wrfull ( ),
+ .wrusedw ( wrusedw ) );
+
+ assign have_pkt_rdy = (rdusedw >= 12'd256);
+ assign have_space = (wrusedw < 12'd760);
+
+ // Rx side fifos
+ // These are of size [NUM_CHAN:0] because the extra channel is used for the
+ // RX command channel. If there were no command channel, they would be
+ // NUM_CHAN-1.
+ wire chan_rdreq;
+ wire [15:0] chan_fifodata;
+ wire [9:0] chan_usedw;
+ wire [NUM_CHAN:0] chan_empty;
+ wire [3:0] rd_select;
+ wire [NUM_CHAN:0] rx_full;
+
+ packet_builder #(NUM_CHAN) rx_pkt_builer (
+ .rxclk ( rxclk ),
+ .reset ( reset ),
+ .timestamp_clock ( timestamp_clock ),
+ .channels ( NUM_CHAN ),
+ .chan_rdreq ( chan_rdreq ),
+ .chan_fifodata ( chan_fifodata ),
+ .chan_empty ( chan_empty ),
+ .rd_select ( rd_select ),
+ .chan_usedw ( chan_usedw ),
+ .WR ( WR ),
+ .fifodata ( fifodata ),
+ .have_space ( have_space ),
+ .rssi_0(rssi_0), .rssi_1(rssi_1),
+ .rssi_2(rssi_2),.rssi_3(rssi_3), .debugbus(debug),
+ .underrun(tx_underrun));
+
+ // Detect overrun
+ always @(posedge rxclk)
+ if(reset)
+ rx_overrun <= 1'b0;
+ else if(rx_full[0])
+ rx_overrun <= 1'b1;
+ else if(clear_status)
+ rx_overrun <= 1'b0;
+
+
+ // FIXME: what is the purpose of these two lines?
+ wire [15:0]ch[NUM_CHAN:0];
+ assign ch[0] = ch_0;
+
+ wire cmd_empty;
+
+ always @(posedge rxclk)
+ if(reset)
+ rx_WR_enabled <= 1;
+ else if(cmd_empty)
+ rx_WR_enabled <= 1;
+ else if(rx_WR_done)
+ rx_WR_enabled <= 0;
+
+
+ // Of Size 0:NUM_CHAN due to extra command channel.
+ wire [15:0] dataout [0:NUM_CHAN];
+ wire [9:0] usedw [0:NUM_CHAN];
+ wire empty[0:NUM_CHAN];
+
+ generate for (i = 0 ; i < NUM_CHAN; i = i + 1)
+ begin : generate_channel_fifos
+
+ wire rdreq;
+
+ assign rdreq = (rd_select == i) & chan_rdreq;
+
+ fifo_1kx16 rx_chan_fifo (
+ .aclr ( reset ),
+ .clock ( rxclk ),
+ .data ( fifodata_il[i] ),
+ .rdreq ( rdreq ),
+ .wrreq ( ~rx_full[i] & wr),
+ .empty (empty[i]),
+ .full (rx_full[i]),
+ .q ( dataout[i]),
+ .usedw ( usedw[i]),
+ .almost_empty(chan_empty[i])
+ );
+ end
+ endgenerate
+
+ wire [7:0] debug;
+
+ fifo_1kx16 rx_cmd_fifo (
+ .aclr ( reset ),
+ .clock ( rxclk ),
+ .data ( rx_databus ),
+ .rdreq ( (rd_select == NUM_CHAN) & chan_rdreq ),
+ .wrreq ( rx_WR & rx_WR_enabled),
+ .empty ( cmd_empty),
+ .full ( rx_full[NUM_CHAN] ),
+ .q ( dataout[NUM_CHAN]),
+ .usedw ( usedw[NUM_CHAN] )
+ );
+
+ assign chan_empty[NUM_CHAN] = cmd_empty | rx_WR_enabled;
+ assign chan_fifodata = dataout[rd_select];
+ assign chan_usedw = usedw[rd_select];
+ assign debugbus = {4'd0, rxclk, rxstrobe, rx_full[0], rx_full[1], sel, wr};
+
+endmodule
diff --git a/usrp/fpga/inband_lib/tx_buffer_inband.v b/usrp/fpga/inband_lib/tx_buffer_inband.v
index fec9dbe31..2dd75f42f 100755
--- a/usrp/fpga/inband_lib/tx_buffer_inband.v
+++ b/usrp/fpga/inband_lib/tx_buffer_inband.v
@@ -1,224 +1,143 @@
module tx_buffer_inband
- ( usbclk, bus_reset, reset, usbdata, WR, have_space,
- channels, tx_i_0, tx_q_0, tx_i_1, tx_q_1,
- tx_i_2, tx_q_2, tx_i_3, tx_q_3, txclk, txstrobe,
- clear_status, tx_empty, debugbus,
- rx_databus, rx_WR, rx_WR_done, rx_WR_enabled, reg_io_enable,
- reg_data_in, reg_data_out, reg_addr, rssi_0, rssi_1, rssi_2,
- rssi_3, rssi_wait, threshhold, tx_underrun
- );
+ ( //System
+ input wire usbclk, input wire bus_reset, input wire reset,
+ input wire [15:0] usbdata, output wire have_space, input wire [3:0] channels,
+ //output transmit signals
+ output wire [15:0] tx_i_0, output wire [15:0] tx_q_0,
+ output wire [15:0] tx_i_1, output wire [15:0] tx_q_1,
+ output wire [15:0] tx_i_2, output wire [15:0] tx_q_2,
+ output wire [15:0] tx_i_3, output wire [15:0] tx_q_3,
+ input wire txclk, input wire txstrobe, input wire WR,
+ input wire clear_status, output wire tx_empty, output wire [15:0] debugbus,
+ //command reader io
+ output wire [15:0] rx_databus, output wire rx_WR, output wire rx_WR_done,
+ input wire rx_WR_enabled,
+ //register io
+ output wire [1:0] reg_io_enable, output wire [31:0] reg_data_in, output wire [6:0] reg_addr,
+ input wire [31:0] reg_data_out,
+ //input characteristic signals
+ input wire [31:0] rssi_0, input wire [31:0] rssi_1, input wire [31:0] rssi_2,
+ input wire [31:0] rssi_3, input wire [31:0] rssi_wait, input wire [31:0] threshhold,
+ output wire [1:0] tx_underrun,
+ //system stop
+ output wire stop, output wire [15:0] stop_time);
- parameter NUM_CHAN = 2 ;
- /* Debug paramters */
- parameter STROBE_RATE_0 = 8'd1 ;
- parameter STROBE_RATE_1 = 8'd2 ;
+ parameter NUM_CHAN = 1 ;
- input wire usbclk ;
- input wire bus_reset ; // Used here for the 257-Hack to fix the FX2 bug
- input wire reset ; // standard DSP-side reset
- input wire [15:0] usbdata ;
- input wire WR ;
- input wire txclk ;
- input wire txstrobe ;
- input wire rx_WR_enabled;
- /* Not used yet */
- input wire [3:0] channels ;
- input wire clear_status ;
- /*register io*/
- input wire [31:0]reg_data_out;
- // rssi
- input wire [31:0]rssi_0;
- input wire [31:0]rssi_1;
- input wire [31:0]rssi_2;
- input wire [31:0]rssi_3;
- input wire [31:0]threshhold;
- input wire [31:0]rssi_wait;
-
- output wire have_space ;
- output wire tx_empty ;
- output wire [15:0] tx_i_0 ;
- output wire [15:0] tx_q_0 ;
- output wire [15:0] tx_i_1 ;
- output wire [15:0] tx_q_1 ;
- output wire [15:0] debugbus ;
- /* Not used yet */
- output wire [15:0] tx_i_2 ;
- output wire [15:0] tx_q_2 ;
- output wire [15:0] tx_i_3 ;
- output wire [15:0] tx_q_3 ;
-
- output wire [15:0] rx_databus ;
- output wire rx_WR;
- output wire rx_WR_done;
- /* reg_io */
- output wire [31:0] reg_data_in;
- output wire [6:0] reg_addr;
- output wire [1:0] reg_io_enable;
- output wire [NUM_CHAN-1:0] tx_underrun;
-
- /* To generate channel readers */
- genvar i ;
+ /* To generate channel readers */
+ genvar i ;
- /* These will eventually be external register */
- reg [31:0] adc_time ;
- wire [7:0] txstrobe_rate [NUM_CHAN-1:0] ;
- wire [31:0] rssi [3:0];
- assign rssi[0] = rssi_0;
- assign rssi[1] = rssi_1;
- assign rssi[2] = rssi_2;
- assign rssi[3] = rssi_3;
+ /* These will eventually be external register */
+ reg [31:0] timestamp_clock ;
+ wire [7:0] txstrobe_rate [NUM_CHAN-1:0] ;
+ wire [31:0] rssi [3:0];
+ assign rssi[0] = rssi_0;
+ assign rssi[1] = rssi_1;
+ assign rssi[2] = rssi_2;
+ assign rssi[3] = rssi_3;
- always @(posedge txclk)
- if (reset)
- adc_time <= 0;
- else if (txstrobe)
- adc_time <= adc_time + 1;
+ always @(posedge txclk)
+ if (reset)
+ timestamp_clock <= 0;
+ else
+ timestamp_clock <= timestamp_clock + 1;
/* Connections between tx_usb_fifo_reader and
cnannel/command processing blocks */
- wire [31:0] tx_data_bus ;
- wire [NUM_CHAN:0] chan_WR ;
- wire [NUM_CHAN:0] chan_done ;
+ wire [31:0] tx_data_bus ;
+ wire [NUM_CHAN:0] chan_WR ;
+ wire [NUM_CHAN:0] chan_done ;
/* Connections between data block and the
FX2/TX chains */
- wire [NUM_CHAN:0] chan_underrun ;
- wire [NUM_CHAN:0] chan_txempty ;
+ wire [NUM_CHAN:0] chan_underrun;
+ wire [NUM_CHAN:0] chan_txempty;
- /* Conections between tx_data_packet_fifo and
+ /* Conections between tx_data_packet_fifo and
its reader + strobe generator */
- wire [31:0] chan_fifodata [NUM_CHAN:0] ;
- wire chan_pkt_waiting [NUM_CHAN:0] ;
- wire chan_rdreq [NUM_CHAN:0] ;
- wire chan_skip [NUM_CHAN:0] ;
- wire [NUM_CHAN:0] chan_have_space ;
- wire chan_txstrobe [NUM_CHAN-1:0] ;
+ wire [31:0] chan_fifodata [NUM_CHAN:0] ;
+ wire chan_pkt_waiting [NUM_CHAN:0] ;
+ wire chan_rdreq [NUM_CHAN:0] ;
+ wire chan_skip [NUM_CHAN:0] ;
+ wire chan_have_space [NUM_CHAN:0] ;
- wire [14:0] debug;
+ wire [14:0] debug [NUM_CHAN:0];
- /* Outputs to transmit chains */
- wire [15:0] tx_i [NUM_CHAN-1:0] ;
- wire [15:0] tx_q [NUM_CHAN-1:0] ;
+ /* Outputs to transmit chains */
+ wire [15:0] tx_i [NUM_CHAN:0] ;
+ wire [15:0] tx_q [NUM_CHAN:0] ;
+
+ assign tx_i[NUM_CHAN] = 0;
+ assign tx_q[NUM_CHAN] = 0;
- /* TODO: Figure out how to write this genericly */
- assign have_space = chan_have_space[0] & chan_have_space[1];
- assign tx_empty = chan_txempty[0] & chan_txempty[1] ;
- assign tx_i_0 = chan_txempty[0] ? 16'b0 : tx_i[0] ;
- assign tx_q_0 = chan_txempty[0] ? 16'b0 : tx_q[0] ;
- assign tx_i_1 = chan_txempty[1] ? 16'b0 : tx_i[1] ;
- assign tx_q_1 = chan_txempty[1] ? 16'b0 : tx_q[1] ;
+ assign have_space = chan_have_space[0] & chan_have_space[1];
+ assign tx_empty = chan_txempty[0] & chan_txempty[1] ;
+
+ assign tx_i_0 = chan_txempty[0] ? 16'b0 : tx_i[0] ;
+ assign tx_q_0 = chan_txempty[0] ? 16'b0 : tx_q[0] ;
+ assign tx_i_1 = chan_txempty[1] ? 16'b0 : tx_i[1] ;
+ assign tx_q_1 = chan_txempty[1] ? 16'b0 : tx_q[1] ;
- /* Debug statement */
- assign txstrobe_rate[0] = STROBE_RATE_0 ;
- assign txstrobe_rate[1] = STROBE_RATE_1 ;
- assign tx_q_2 = 16'b0 ;
- assign tx_i_2 = 16'b0 ;
- assign tx_q_3 = 16'b0 ;
- assign tx_i_3 = 16'b0 ;
- assign tx_i_3 = 16'b0 ;
+ assign tx_q_2 = 16'b0 ;
+ assign tx_i_2 = 16'b0 ;
+ assign tx_q_3 = 16'b0 ;
+ assign tx_i_3 = 16'b0 ;
+ assign tx_i_3 = 16'b0 ;
- assign debugbus = {debug, txclk};
+ assign debugbus = {have_space, txclk, WR, WR_final, chan_WR, chan_done,
+ chan_pkt_waiting[0], chan_pkt_waiting[1],
+ chan_rdreq[0], chan_rdreq[1], chan_txempty[0], chan_txempty[1]};
- wire [31:0] usbdata_final;
- wire WR_final;
+ wire [31:0] usbdata_final;
+ wire WR_final;
- tx_packer tx_usb_packer
- (
- .bus_reset (bus_reset),
- .usbclk (usbclk),
- .WR_fx2 (WR),
- .usbdata (usbdata),
- .reset (reset),
- .txclk (txclk),
- .usbdata_final (usbdata_final),
- .WR_final (WR_final)
- );
+ tx_packer tx_usb_packer
+ (.bus_reset(bus_reset), .usbclk(usbclk), .WR_fx2(WR),
+ .usbdata(usbdata), .reset(reset), .txclk(txclk),
+ .usbdata_final(usbdata_final), .WR_final(WR_final));
- channel_demux channel_demuxer
- (
- .usbdata_final (usbdata_final),
- .WR_final (WR_final),
- .reset (reset),
- .txclk (txclk),
- .WR_channel (chan_WR),
- .WR_done_channel (chan_done),
- .ram_data (tx_data_bus)
- );
+ channel_demux #(NUM_CHAN) channel_demuxer
+ (.usbdata_final(usbdata_final), .WR_final(WR_final),
+ .reset(reset), .txclk(txclk), .WR_channel(chan_WR),
+ .WR_done_channel(chan_done), .ram_data(tx_data_bus));
- generate for (i = 0 ; i < NUM_CHAN; i = i + 1)
- begin : generate_channel_readers
- assign tx_underrun[i] = chan_underrun[i];
- channel_ram tx_data_packet_fifo
- ( .reset (reset),
- .txclk (txclk),
- .datain (tx_data_bus),
- .WR (chan_WR[i]),
- .WR_done (chan_done[i]),
- .have_space (chan_have_space[i]),
- .dataout (chan_fifodata[i]),
- .packet_waiting (chan_pkt_waiting[i]),
- .RD (chan_rdreq[i]),
- .RD_done (chan_skip[i])
- );
+ generate for (i = 0 ; i < NUM_CHAN; i = i + 1)
+ begin : generate_channel_readers
+ assign tx_underrun[i] = chan_underrun[i];
- chan_fifo_reader tx_chan_reader
- ( .reset (reset),
- .tx_clock (txclk),
- .tx_strobe (txstrobe),
- .adc_time (adc_time),
- .samples_format (4'b0),
- .tx_q (tx_q[i]),
- .tx_i (tx_i[i]),
- .underrun (chan_underrun[i]),
- .skip (chan_skip[i]),
- .rdreq (chan_rdreq[i]),
- .fifodata (chan_fifodata[i]),
- .pkt_waiting (chan_pkt_waiting[i]),
- .tx_empty (chan_txempty[i]),
- .rssi (rssi[i]),
- .threshhold (threshhold),
- .rssi_wait (rssi_wait)
- );
-
+ channel_ram tx_data_packet_fifo
+ (.reset(reset), .txclk(txclk), .datain(tx_data_bus),
+ .WR(chan_WR[i]), .WR_done(chan_done[i]),
+ .have_space(chan_have_space[i]), .dataout(chan_fifodata[i]),
+ .packet_waiting(chan_pkt_waiting[i]), .RD(chan_rdreq[i]),
+ .RD_done(chan_skip[i]));
+
+ chan_fifo_reader tx_chan_reader
+ (.reset(reset), .tx_clock(txclk), .tx_strobe(txstrobe),
+ .timestamp_clock(timestamp_clock), .samples_format(4'b0),
+ .tx_q(tx_q[i]), .tx_i(tx_i[i]), .underrun(chan_underrun[i]),
+ .skip(chan_skip[i]), .rdreq(chan_rdreq[i]),
+ .fifodata(chan_fifodata[i]), .pkt_waiting(chan_pkt_waiting[i]),
+ .tx_empty(chan_txempty[i]), .rssi(rssi[i]), .debug(debug[i]),
+ .threshhold(threshhold), .rssi_wait(rssi_wait));
end
endgenerate
- channel_ram tx_cmd_packet_fifo
- ( .reset (reset),
- .txclk (txclk),
- .datain (tx_data_bus),
- .WR (chan_WR[NUM_CHAN]),
- .WR_done (chan_done[NUM_CHAN]),
- .have_space (chan_have_space[NUM_CHAN]),
- .dataout (chan_fifodata[NUM_CHAN]),
- .packet_waiting (chan_pkt_waiting[NUM_CHAN]),
- .RD (chan_rdreq[NUM_CHAN]),
- .RD_done (chan_skip[NUM_CHAN])
- );
+ channel_ram tx_cmd_packet_fifo
+ (.reset(reset), .txclk(txclk), .datain(tx_data_bus), .WR(chan_WR[NUM_CHAN]),
+ .WR_done(chan_done[NUM_CHAN]), .have_space(chan_have_space[NUM_CHAN]),
+ .dataout(chan_fifodata[NUM_CHAN]), .packet_waiting(chan_pkt_waiting[NUM_CHAN]),
+ .RD(chan_rdreq[NUM_CHAN]), .RD_done(chan_skip[NUM_CHAN]));
-
- cmd_reader tx_cmd_reader
- ( .reset (reset),
- .txclk (txclk),
- .adc_time (adc_time),
- .skip (chan_skip[NUM_CHAN]),
- .rdreq (chan_rdreq[NUM_CHAN]),
- .fifodata (chan_fifodata[NUM_CHAN]),
- .pkt_waiting (chan_pkt_waiting[NUM_CHAN]),
- .rx_databus (rx_databus),
- .rx_WR (rx_WR),
- .rx_WR_done (rx_WR_done),
- .rx_WR_enabled (rx_WR_enabled),
- .reg_data_in (reg_data_in),
- .reg_data_out (reg_data_out),
- .reg_addr (reg_addr),
- .reg_io_enable (reg_io_enable),
- .debug (debug)
- );
-
-
-
+ cmd_reader tx_cmd_reader
+ (.reset(reset), .txclk(txclk), .timestamp_clock(timestamp_clock), .skip(chan_skip[NUM_CHAN]),
+ .rdreq(chan_rdreq[NUM_CHAN]), .fifodata(chan_fifodata[NUM_CHAN]),
+ .pkt_waiting(chan_pkt_waiting[NUM_CHAN]), .rx_databus(rx_databus),
+ .rx_WR(rx_WR), .rx_WR_done(rx_WR_done), .rx_WR_enabled(rx_WR_enabled),
+ .reg_data_in(reg_data_in), .reg_data_out(reg_data_out), .reg_addr(reg_addr),
+ .reg_io_enable(reg_io_enable), .debug(debug[NUM_CHAN]), .stop(stop), .stop_time(stop_time));
+
endmodule // tx_buffer
diff --git a/usrp/fpga/inband_lib/usb_fifo_reader.v b/usrp/fpga/inband_lib/usb_fifo_reader.v
deleted file mode 100755
index d002d90ff..000000000
--- a/usrp/fpga/inband_lib/usb_fifo_reader.v
+++ /dev/null
@@ -1,25 +0,0 @@
-module usb_fifo_reader (
- input usbclk,
- input bus_reset,
- input RD,
- output rdreq,
- );
-
- // FX2 Bug Fix
- reg [8:0] read_count;
- always @(negedge usbclk)
- if(bus_reset)
- read_count <= #1 9'd0;
- else if(RD & ~read_count[8])
- read_count <= #1 read_count + 9'd1;
- else
- read_count <= #1 RD ? read_count : 9'b0;
-
- assign rdreq = RD & ~read_count[8];
-
-
-
-endmodule
-
-
- \ No newline at end of file
diff --git a/usrp/fpga/inband_lib/usb_fifo_writer.v b/usrp/fpga/inband_lib/usb_fifo_writer.v
deleted file mode 100755
index abe1dd567..000000000
--- a/usrp/fpga/inband_lib/usb_fifo_writer.v
+++ /dev/null
@@ -1,183 +0,0 @@
-
-module usb_fifo_writer
- #(parameter BUS_WIDTH = 16,
- parameter NUM_CHAN = 2,
- parameter FIFO_WIDTH = 32)
- ( //FX2 Side
- input bus_reset,
- input usbclk,
- input WR_fx2,
- input [15:0]usbdata,
-
- // TX Side
- input reset,
- input txclk,
- output reg [NUM_CHAN:0] WR_channel,
- output reg [FIFO_WIDTH-1:0] ram_data,
- output reg [NUM_CHAN:0] WR_done_channel );
-
-
- reg [8:0] write_count;
-
- /* Fix FX2 bug */
- always @(posedge usbclk)
- if(bus_reset) // Use bus reset because this is on usbclk
- write_count <= #1 0;
- else if(WR_fx2 & ~write_count[8])
- write_count <= #1 write_count + 9'd1;
- else
- write_count <= #1 WR_fx2 ? write_count : 9'b0;
-
- reg WR_fx2_fixed;
- reg [15:0]usbdata_fixed;
-
- always @(posedge usbclk)
- begin
- WR_fx2_fixed <= WR_fx2 & ~write_count[8];
- usbdata_fixed <= usbdata;
- end
-
- /* Used to convert 16 bits bus_data to the 32 bits wide fifo */
- reg word_complete ;
- reg [BUS_WIDTH-1:0] usbdata_delayed ;
- reg writing ;
- wire [FIFO_WIDTH-1:0] usbdata_packed ;
- wire WR_packed ;
-
- always @(posedge usbclk)
- begin
- if (bus_reset)
- begin
- word_complete <= 0 ;
- writing <= 0 ;
- end
- else if (WR_fx2_fixed)
- begin
- writing <= 1 ;
- if (word_complete)
- word_complete <= 0 ;
- else
- begin
- usbdata_delayed <= usbdata_fixed ;
- word_complete <= 1 ;
- end
- end
- else
- writing <= 0 ;
- end
-
- assign usbdata_packed = {usbdata_fixed, usbdata_delayed} ;
- assign WR_packed = word_complete & writing ;
-
- /* Make sure data are sync with usbclk */
- reg [31:0]usbdata_usbclk;
- reg WR_usbclk;
-
- always @(posedge usbclk)
- begin
- if (WR_packed)
- usbdata_usbclk <= usbdata_packed;
- WR_usbclk <= WR_packed;
- end
-
- /* Cross clock boundaries */
- reg [FIFO_WIDTH-1:0] usbdata_tx ;
- reg WR_tx;
- reg WR_1;
- reg WR_2;
- reg [31:0] usbdata_final;
- reg WR_final;
-
- always @(posedge txclk) usbdata_tx <= usbdata_usbclk;
-
- always @(posedge txclk)
- if (reset)
- WR_1 <= 0;
- else
- WR_1 <= WR_usbclk;
-
- always @(posedge txclk)
- if (reset)
- WR_2 <= 0;
- else
- WR_2 <= WR_1;
-
- always @(posedge txclk)
- begin
- if (reset)
- WR_tx <= 0;
- else
- WR_tx <= WR_1 & ~WR_2;
- end
-
- always @(posedge txclk)
- begin
- if (reset)
- WR_final <= 0;
- else
- begin
- WR_final <= WR_tx;
- if (WR_tx)
- usbdata_final <= usbdata_tx;
- end
- end
-
- /* Parse header and forward to ram */
- reg [3:0]reader_state;
- reg [4:0]channel ;
- reg [9:0]read_length ;
-
- parameter IDLE = 4'd0;
- parameter HEADER = 4'd1;
- parameter WAIT = 4'd2;
- parameter FORWARD = 4'd3;
-
- `define CHANNEL 20:16
- `define PKT_SIZE 512
-
- always @(posedge txclk)
- begin
- if (reset)
- begin
- reader_state <= 0;
- WR_channel <= 0;
- WR_done_channel <= 0;
- end
- else
- case (reader_state)
- IDLE: begin
- if (WR_final)
- reader_state <= HEADER;
- end
-
- // Store channel and forware header
- HEADER: begin
- channel <= (usbdata_final[`CHANNEL] == 5'h1f ? NUM_CHAN : usbdata_final[`CHANNEL]) ;
- WR_channel[(usbdata_final[`CHANNEL] == 5'h1f ? NUM_CHAN : usbdata_final[`CHANNEL])] <= 1;
- //channel <= usbdata_final[`CHANNEL] ;
- //WR_channel[usbdata_final[`CHANNEL]] <= 1;
- ram_data <= usbdata_final;
- read_length <= 10'd4 ;
-
- reader_state <= WAIT;
- end
-
- WAIT: begin
- WR_channel[channel] <= 0;
-
- if (read_length == `PKT_SIZE)
- reader_state <= IDLE;
- else if (WR_final)
- reader_state <= FORWARD;
- end
-
- FORWARD: begin
- WR_channel[channel] <= 1;
- ram_data <= usbdata_final;
- read_length <= read_length + 10'd4;
-
- reader_state <= WAIT;
- end
- endcase
- end
-endmodule \ No newline at end of file
diff --git a/usrp/fpga/megacells/fifo_1kx16.bsf b/usrp/fpga/megacells/fifo_1kx16.bsf
index 329be2d44..2de80816f 100755
--- a/usrp/fpga/megacells/fifo_1kx16.bsf
+++ b/usrp/fpga/megacells/fifo_1kx16.bsf
@@ -95,7 +95,7 @@ applicable agreement for further details.
)
(drawing
(text "16 bits x 1024 words" (rect 58 132 144 144)(font "Arial" ))
- (text "almost_empty < 126" (rect 58 122 144 134)(font "Arial" ))
+ (text "almost_empty < 504" (rect 58 122 144 134)(font "Arial" ))
(line (pt 16 16)(pt 144 16)(line_width 1))
(line (pt 144 16)(pt 144 144)(line_width 1))
(line (pt 144 144)(pt 16 144)(line_width 1))
diff --git a/usrp/fpga/megacells/fifo_1kx16.v b/usrp/fpga/megacells/fifo_1kx16.v
index e22b416e5..4f7e94ef5 100755
--- a/usrp/fpga/megacells/fifo_1kx16.v
+++ b/usrp/fpga/megacells/fifo_1kx16.v
@@ -86,7 +86,7 @@ module fifo_1kx16 (
);
defparam
scfifo_component.add_ram_output_register = "OFF",
- scfifo_component.almost_empty_value = 126,
+ scfifo_component.almost_empty_value = 504,
scfifo_component.intended_device_family = "Cyclone",
scfifo_component.lpm_hint = "RAM_BLOCK_TYPE=M4K",
scfifo_component.lpm_numwords = 1024,
@@ -105,7 +105,7 @@ endmodule
// CNX file retrieval info
// ============================================================
// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "1"
-// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "126"
+// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "504"
// Retrieval info: PRIVATE: AlmostFull NUMERIC "0"
// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1"
// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0"
@@ -133,7 +133,7 @@ endmodule
// Retrieval info: PRIVATE: wsFull NUMERIC "1"
// Retrieval info: PRIVATE: wsUsedW NUMERIC "0"
// Retrieval info: CONSTANT: ADD_RAM_OUTPUT_REGISTER STRING "OFF"
-// Retrieval info: CONSTANT: ALMOST_EMPTY_VALUE NUMERIC "126"
+// Retrieval info: CONSTANT: ALMOST_EMPTY_VALUE NUMERIC "504"
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone"
// Retrieval info: CONSTANT: LPM_HINT STRING "RAM_BLOCK_TYPE=M4K"
// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "1024"
diff --git a/usrp/fpga/megacells/fifo_1kx16_bb.v b/usrp/fpga/megacells/fifo_1kx16_bb.v
index 283aada81..9d9912bc2 100755
--- a/usrp/fpga/megacells/fifo_1kx16_bb.v
+++ b/usrp/fpga/megacells/fifo_1kx16_bb.v
@@ -57,7 +57,7 @@ endmodule
// CNX file retrieval info
// ============================================================
// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "1"
-// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "126"
+// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "504"
// Retrieval info: PRIVATE: AlmostFull NUMERIC "0"
// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1"
// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0"
@@ -85,7 +85,7 @@ endmodule
// Retrieval info: PRIVATE: wsFull NUMERIC "1"
// Retrieval info: PRIVATE: wsUsedW NUMERIC "0"
// Retrieval info: CONSTANT: ADD_RAM_OUTPUT_REGISTER STRING "OFF"
-// Retrieval info: CONSTANT: ALMOST_EMPTY_VALUE NUMERIC "126"
+// Retrieval info: CONSTANT: ALMOST_EMPTY_VALUE NUMERIC "504"
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone"
// Retrieval info: CONSTANT: LPM_HINT STRING "RAM_BLOCK_TYPE=M4K"
// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "1024"
diff --git a/usrp/fpga/rbf/Makefile.am b/usrp/fpga/rbf/Makefile.am
index 49d2f2592..c7c9ce670 100644
--- a/usrp/fpga/rbf/Makefile.am
+++ b/usrp/fpga/rbf/Makefile.am
@@ -26,8 +26,12 @@ datadir = $(prefix)/share/usrp
rbfs = \
rev2/std_2rxhb_2tx.rbf \
rev2/std_4rx_0tx.rbf \
+ rev2/inband_1rxhb_1tx.rbf \
+ rev2/inband_2rxhb_2tx.rbf \
rev4/std_2rxhb_2tx.rbf \
rev4/std_4rx_0tx.rbf \
+ rev4/inband_1rxhb_1tx.rbf \
+ rev4/inband_2rxhb_2tx.rbf \
rev2/multi_2rxhb_2tx.rbf \
rev4/multi_2rxhb_2tx.rbf
diff --git a/usrp/fpga/rbf/rev2/inband_1rxhb_1tx.rbf b/usrp/fpga/rbf/rev2/inband_1rxhb_1tx.rbf
new file mode 100755
index 000000000..c1c9af2ce
--- /dev/null
+++ b/usrp/fpga/rbf/rev2/inband_1rxhb_1tx.rbf
Binary files differ
diff --git a/usrp/fpga/rbf/rev2/inband_2rxhb_2tx.rbf b/usrp/fpga/rbf/rev2/inband_2rxhb_2tx.rbf
new file mode 100755
index 000000000..ca1a0f92b
--- /dev/null
+++ b/usrp/fpga/rbf/rev2/inband_2rxhb_2tx.rbf
Binary files differ
diff --git a/usrp/fpga/rbf/rev4/inband_1rxhb_1tx.rbf b/usrp/fpga/rbf/rev4/inband_1rxhb_1tx.rbf
new file mode 100755
index 000000000..c1c9af2ce
--- /dev/null
+++ b/usrp/fpga/rbf/rev4/inband_1rxhb_1tx.rbf
Binary files differ
diff --git a/usrp/fpga/rbf/rev4/inband_2rxhb_2tx.rbf b/usrp/fpga/rbf/rev4/inband_2rxhb_2tx.rbf
new file mode 100755
index 000000000..ca1a0f92b
--- /dev/null
+++ b/usrp/fpga/rbf/rev4/inband_2rxhb_2tx.rbf
Binary files differ
diff --git a/usrp/fpga/toplevel/usrp_inband_usb/config.vh b/usrp/fpga/toplevel/usrp_inband_usb/config.vh
index 3291dc10b..007a529e3 100644
--- a/usrp/fpga/toplevel/usrp_inband_usb/config.vh
+++ b/usrp/fpga/toplevel/usrp_inband_usb/config.vh
@@ -34,7 +34,7 @@
`include "../include/common_config_1rxhb_1tx.vh"
// Uncomment this for 2 rx channels (w/ halfband) & 2 transmit channels
-//`include "../include/common_config_2rxhb_2tx.vh"
+// `include "../include/common_config_2rxhb_2tx.vh"
// Uncomment this for 4 rx channels (w/o halfband) & 0 transmit channels
//`include "../include/common_config_4rx_0tx.vh"
diff --git a/usrp/fpga/toplevel/usrp_inband_usb/usrp_inband_usb.qsf b/usrp/fpga/toplevel/usrp_inband_usb/usrp_inband_usb.qsf
index c9eebc1ad..ae0807f6f 100644
--- a/usrp/fpga/toplevel/usrp_inband_usb/usrp_inband_usb.qsf
+++ b/usrp/fpga/toplevel/usrp_inband_usb/usrp_inband_usb.qsf
@@ -27,7 +27,7 @@
# ========================
set_global_assignment -name ORIGINAL_QUARTUS_VERSION 3.0
set_global_assignment -name PROJECT_CREATION_TIME_DATE "00:14:04 JULY 13, 2003"
-set_global_assignment -name LAST_QUARTUS_VERSION "5.1 SP1"
+set_global_assignment -name LAST_QUARTUS_VERSION "7.2 SP2"
# Pin & Location Assignments
# ==========================
@@ -392,7 +392,6 @@ set_global_assignment -name VERILOG_FILE ../../sdr_lib/hb/ram16_2sum.v
set_global_assignment -name VERILOG_FILE ../../sdr_lib/hb/coeff_rom.v
set_global_assignment -name VERILOG_FILE ../../sdr_lib/hb/halfband_decim.v
set_global_assignment -name VERILOG_FILE ../../sdr_lib/hb/mac.v
-set_global_assignment -name VERILOG_FILE ../../sdr_lib/hb/coeff_ram.v
set_global_assignment -name VERILOG_FILE ../../sdr_lib/tx_chain.v
set_global_assignment -name VERILOG_FILE ../../sdr_lib/rx_dcoffset.v
set_global_assignment -name VERILOG_FILE ../../sdr_lib/adc_interface.v
@@ -419,4 +418,6 @@ set_global_assignment -name VERILOG_FILE ../../sdr_lib/serial_io.v
set_global_assignment -name VERILOG_FILE ../../sdr_lib/strobe_gen.v
set_global_assignment -name VERILOG_FILE ../../sdr_lib/sign_extend.v
set_global_assignment -name VERILOG_FILE ../../inband_lib/channel_ram.v
-set_global_assignment -name VERILOG_FILE ../../inband_lib/register_io.v \ No newline at end of file
+set_global_assignment -name VERILOG_FILE ../../inband_lib/register_io.v
+set_global_assignment -name LL_ROOT_REGION ON -section_id "Root Region"
+set_global_assignment -name LL_MEMBER_STATE LOCKED -section_id "Root Region" \ No newline at end of file
diff --git a/usrp/fpga/toplevel/usrp_inband_usb/usrp_inband_usb.v b/usrp/fpga/toplevel/usrp_inband_usb/usrp_inband_usb.v
index cc625b0e7..79f0dfa4a 100644
--- a/usrp/fpga/toplevel/usrp_inband_usb/usrp_inband_usb.v
+++ b/usrp/fpga/toplevel/usrp_inband_usb/usrp_inband_usb.v
@@ -97,8 +97,6 @@ module usrp_inband_usb
// Tri-state bus macro
bustri bustri( .data(usbdata_out),.enabledt(OE),.tridata(usbdata) );
- assign clk64 = master_clk;
-
wire [15:0] ch0tx,ch1tx,ch2tx,ch3tx; //,ch4tx,ch5tx,ch6tx,ch7tx;
wire [15:0] ch0rx,ch1rx,ch2rx,ch3rx,ch4rx,ch5rx,ch6rx,ch7rx;
@@ -129,19 +127,7 @@ module usrp_inband_usb
assign bb_tx_q0 = ch1tx;
assign bb_tx_i1 = ch2tx;
assign bb_tx_q1 = ch3tx;
-
-wire [6:0] reg_addr;
-wire [31:0] reg_data_out;
-wire [31:0] reg_data_in;
-wire [1:0] reg_io_enable;
-wire [31:0] rssi_threshhold;
-wire [31:0] rssi_wait;
-
-register_io register_control
-(.clk(clk64),.reset(1'b0),.enable(reg_io_enable),.addr(reg_addr),.datain(reg_data_in),
- .dataout(reg_data_out),.rssi_0(rssi_0), .rssi_1(rssi_1), .rssi_2(rssi_2),
- .rssi_3(rssi_3), .threshhold(rssi_threshhold), .rssi_wait(rssi_wait));
-wire [1:0] tx_overrun;
+
wire [1:0] tx_underrun;
`ifdef TX_IN_BAND
@@ -164,9 +150,15 @@ wire [1:0] tx_underrun;
.reg_data_out(reg_data_out),
.reg_data_in(reg_data_in),
.reg_io_enable(reg_io_enable),
- .debugbus(),
+ .debugbus(rx_debugbus),
.rssi_0(rssi_0), .rssi_1(rssi_1), .rssi_2(rssi_2),
- .rssi_3(rssi_3), .threshhold(rssi_threshhold), .rssi_wait(rssi_wait));
+ .rssi_3(rssi_3), .threshhold(rssi_threshhold), .rssi_wait(rssi_wait),
+ .stop(stop), .stop_time(stop_time));
+
+ `ifdef TX_DUAL
+ defparam tx_buffer.NUM_CHAN=2;
+ `endif
+
`else
tx_buffer tx_buffer
( .usbclk(usbclk),.bus_reset(tx_bus_reset),.reset(tx_dsp_reset),
@@ -276,14 +268,18 @@ wire [1:0] tx_underrun;
.ch_6(ch6rx),.ch_7(ch7rx),
.rxclk(clk64),.rxstrobe(hb_strobe),
.clear_status(clear_status),
- .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe),
.rx_WR(rx_WR),
.rx_databus(rx_databus),
.rx_WR_done(rx_WR_done),
.rx_WR_enabled(rx_WR_enabled),
.debugbus(tx_debugbus),
.rssi_0(rssi_0), .rssi_1(rssi_1), .rssi_2(rssi_2), .rssi_3(rssi_3),
- .tx_overrun(tx_overrun), .tx_underrun(tx_underrun));
+ .tx_underrun(tx_underrun));
+
+ `ifdef RX_DUAL
+ defparam rx_buffer.NUM_CHAN=2;
+ `endif
+
`else
rx_buffer rx_buffer
( .usbclk(usbclk),.bus_reset(rx_bus_reset),.reset(rx_dsp_reset),
@@ -357,11 +353,52 @@ wire [1:0] tx_underrun;
serial_io serial_io
( .master_clk(clk64),.serial_clock(SCLK),.serial_data_in(SDI),
.enable(SEN_FPGA),.reset(1'b0),.serial_data_out(SDO),
- .serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe),
+ .serial_addr(addr_db),.serial_data(data_db),.serial_strobe(strobe_db),
.readback_0({io_rx_a,io_tx_a}),.readback_1({io_rx_b,io_tx_b}),.readback_2(capabilities),.readback_3(32'hf0f0931a),
.readback_4(rssi_0),.readback_5(rssi_1),.readback_6(rssi_2),.readback_7(rssi_3)
);
+ wire [6:0] reg_addr;
+ wire [31:0] reg_data_out;
+ wire [31:0] reg_data_in;
+ wire [1:0] reg_io_enable;
+ wire [31:0] rssi_threshhold;
+ wire [31:0] rssi_wait;
+ wire [6:0] addr_wr;
+ wire [31:0] data_wr;
+ wire strobe_wr;
+ wire [6:0] addr_db;
+ wire [31:0] data_db;
+ wire strobe_db;
+ assign serial_strobe = strobe_db | strobe_wr;
+ assign serial_addr = (strobe_db)? (addr_db) : (addr_wr);
+ assign serial_data = (strobe_db)? (data_db) : (data_wr);
+ //assign serial_strobe = strobe_wr;
+ //assign serial_data = data_wr;
+ //assign serial_addr = addr_wr;
+
+ register_io register_control
+ (.clk(clk64),.reset(1'b0),.enable(reg_io_enable),.addr(reg_addr),.datain(reg_data_in),
+ .dataout(reg_data_out), .addr_wr(addr_wr), .data_wr(data_wr), .strobe_wr(strobe_wr),
+ .rssi_0(rssi_0), .rssi_1(rssi_1), .rssi_2(rssi_2),
+ .rssi_3(rssi_3), .threshhold(rssi_threshhold), .rssi_wait(rssi_wait),
+ .reg_0(reg_0),.reg_1(reg_1),.reg_2(reg_2),.reg_3(reg_3),
+ .debug_en(debug_en), .misc(settings),
+ .txmux({dac3mux,dac2mux,dac1mux,dac0mux,tx_realsignals,tx_numchan}));
+
+
+ //implementing freeze mode
+ reg [15:0] timestop;
+ wire stop;
+ wire [15:0] stop_time;
+ assign clk64 = (timestop == 0) ? master_clk : 0;
+ always @(posedge master_clk)
+ if (timestop[15:0] != 0)
+ timestop <= timestop - 16'd1;
+ else if (stop)
+ timestop <= stop_time;
+
+
wire [15:0] reg_0,reg_1,reg_2,reg_3;
master_control master_control
( .master_clk(clk64),.usbclk(usbclk),
@@ -374,8 +411,8 @@ wire [1:0] tx_underrun;
.rx_sample_strobe(rx_sample_strobe),.strobe_decim(strobe_decim),
.tx_empty(tx_empty),
//.debug_0(rx_a_a),.debug_1(ddc0_in_i),
- .debug_0(tx_debugbus),.debug_1(tx_debugbus),
- .debug_2({rx_sample_strobe,strobe_decim,serial_strobe,serial_addr}),.debug_3({rx_dsp_reset,tx_dsp_reset,rx_bus_reset,tx_bus_reset,enable_rx,(tx_underrun == 0),rx_overrun,decim_rate}),
+ .debug_0(rx_debugbus),.debug_1(ddc0_in_i),
+ .debug_2({rx_sample_strobe,strobe_decim,serial_strobe,serial_addr}),.debug_3({rx_dsp_reset,tx_dsp_reset,rx_bus_reset,tx_bus_reset,enable_rx,tx_underrun,rx_overrun,decim_rate}),
.reg_0(reg_0),.reg_1(reg_1),.reg_2(reg_2),.reg_3(reg_3) );
io_pins io_pins
diff --git a/usrp/host/apps-inband/Makefile.am b/usrp/host/apps-inband/Makefile.am
index 86bb40618..f231b57f7 100644
--- a/usrp/host/apps-inband/Makefile.am
+++ b/usrp/host/apps-inband/Makefile.am
@@ -30,46 +30,31 @@ AM_CPPFLAGS = \
bin_PROGRAMS =
noinst_PROGRAMS = \
- test_usrp_inband_cs \
test_usrp_inband_ping \
test_usrp_inband_registers \
test_usrp_inband_rx \
+ test_usrp_inband_2rx \
test_usrp_inband_tx \
+ test_usrp_inband_2tx \
test_usrp_inband_timestamps \
test_usrp_inband_overrun \
test_usrp_inband_underrun \
- test_gmac_tx \
read_packets
noinst_HEADERS = \
ui_nco.h \
- ui_sincos.h \
- gmac.h \
- gmac_symbols.h
+ ui_sincos.h
-EXTRA_DIST = \
- gmac.mbh
-
-#------------------------------------------------------------------
-# Build gmac sources
-
-BUILT_SOURCES = \
- gmac_mbh.cc
-
-gmac_mbh.cc : gmac.mbh
- $(COMPILE_MBH) $(srcdir)/gmac.mbh gmac_mbh.cc
-
-
-test_usrp_inband_cs_SOURCES = test_usrp_inband_cs.cc ui_sincos.c
-test_usrp_inband_cs_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
-
test_usrp_inband_ping_SOURCES = test_usrp_inband_ping.cc
test_usrp_inband_ping_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
test_usrp_inband_tx_SOURCES = test_usrp_inband_tx.cc ui_sincos.c
test_usrp_inband_tx_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
+test_usrp_inband_2tx_SOURCES = test_usrp_inband_2tx.cc ui_sincos.c
+test_usrp_inband_2tx_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
+
test_usrp_inband_timestamps_SOURCES = test_usrp_inband_timestamps.cc ui_sincos.c
test_usrp_inband_timestamps_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
@@ -85,8 +70,8 @@ test_usrp_inband_underrun_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
test_usrp_inband_rx_SOURCES = test_usrp_inband_rx.cc ui_sincos.c
test_usrp_inband_rx_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
-test_gmac_tx_SOURCES = test_gmac_tx.cc gmac.cc gmac_mbh.cc ui_sincos.c
-test_gmac_tx_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
+test_usrp_inband_2rx_SOURCES = test_usrp_inband_2rx.cc ui_sincos.c
+test_usrp_inband_2rx_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
read_packets_SOURCES = read_packets.cc
read_packets_LDADD = $(USRP_LA) $(USRP_INBAND_LA)
diff --git a/usrp/host/apps-inband/gmac.cc b/usrp/host/apps-inband/gmac.cc
deleted file mode 100644
index 107582e12..000000000
--- a/usrp/host/apps-inband/gmac.cc
+++ /dev/null
@@ -1,690 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2007 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <gmac.h>
-
-#include <mb_mblock.h>
-#include <mb_runtime.h>
-#include <mb_protocol_class.h>
-#include <mb_exception.h>
-#include <mb_msg_queue.h>
-#include <mb_message.h>
-#include <mb_msg_accepter.h>
-#include <mb_class_registry.h>
-#include <pmt.h>
-#include <stdio.h>
-#include <string.h>
-#include <iostream>
-#include <ui_nco.h>
-
-#include <symbols_usrp_server_cs.h>
-#include <symbols_usrp_channel.h>
-#include <symbols_usrp_low_level_cs.h>
-#include <symbols_usrp_tx.h>
-#include <symbols_usrp_rx.h>
-
-#include <gmac_symbols.h>
-
-static bool verbose = true;
-
-gmac::gmac(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg)
- : mb_mblock(rt, instance_name, user_arg),
- d_us_rx_chan(PMT_NIL), d_us_tx_chan(PMT_NIL)
-{
-
- // When the MAC layer is initialized, we must connect to the USRP and setup
- // channels. We begin by defining ports to connect to the 'usrp_server' block
- // and then initialize the USRP by opening it through the 'usrp_server.'
-
- // Initialize the ports
- define_ports();
-
- // Initialize the connection to the USRP
- initialize_usrp();
-
-}
-
-gmac::~gmac()
-{
-}
-
-// The full functionality of GMAC is based on messages passed back and forth
-// between the application and a physical layer and/or usrp_server. Each
-// message triggers additional events, states, and messages to be sent.
-void gmac::handle_message(mb_message_sptr msg)
-{
-
- // The MAC functionality is dispatched based on the event, which is the
- // driving force of the MAC. The event can be anything from incoming samples
- // to a message to change the carrier sense threshold.
- pmt_t event = msg->signal();
- pmt_t data = msg->data();
- pmt_t port_id = msg->port_id();
-
- pmt_t handle = PMT_F;
- pmt_t status = PMT_F;
- pmt_t dict = PMT_NIL;
- std::string error_msg;
-
- switch(d_state) {
-
- //---------------------------- INIT ------------------------------------//
- // In the INIT state, there should be no messages across the ports.
- case INIT:
- error_msg = "no messages should be passed during the INIT state:";
- goto unhandled;
-
- //-------------------------- OPENING USRP -------------------------------//
- // In this state we expect a response from usrp_server over the CS channel
- // as to whether or not the opening of the USRP was successful. If so, we
- // switch states to allocating the channels for use.
- case OPENING_USRP:
-
- if(pmt_eq(event, s_response_open)
- && pmt_eq(d_us_cs->port_symbol(), port_id)) {
-
- status = pmt_nth(1, data); // PMT_T or PMT_F
-
- if(pmt_eq(status, PMT_T)) { // on success, allocate channels!
- allocate_channels();
- return;
- }
- else {
- error_msg = "failed to open usrp:";
- goto bail;
- }
-
- }
-
- goto unhandled; // all other messages not handled in this state
-
- //------------------------ ALLOCATING CHANNELS --------------------------//
- // When allocating channels, we need to wait for 2 responses from USRP
- // server: one for TX and one for RX. Both are initialized to NIL so we
- // know to continue to the next state once both are set.
- case ALLOCATING_CHANNELS:
-
- // ************* TX ALLOCATION RESPONSE ***************** //
- if(pmt_eq(event, s_response_allocate_channel)
- && pmt_eq(d_us_tx->port_symbol(), port_id))
- {
- status = pmt_nth(1, data);
-
- if(pmt_eq(status, PMT_T)) { // extract channel on success
- d_us_tx_chan = pmt_nth(2, data);
-
- if(verbose)
- std::cout << "[GMAC] Received TX allocation"
- << " on channel " << d_us_tx_chan << std::endl;
-
- // If the RX has also been allocated already, we can continue
- if(!pmt_eqv(d_us_rx_chan, PMT_NIL)) {
- //enter_receiving();
- initialize_gmac();
- }
-
- return;
- }
- else { // TX allocation failed
- error_msg = "failed to allocate TX channel:";
- goto bail;
- }
- }
-
- // ************* RX ALLOCATION RESPONSE ****************//
- if(pmt_eq(event, s_response_allocate_channel)
- && pmt_eq(d_us_rx->port_symbol(), port_id))
- {
- status = pmt_nth(1, data);
-
- if(pmt_eq(status, PMT_T)) {
-
- d_us_rx_chan = pmt_nth(2, data);
-
- if(verbose)
- std::cout << "[GMAC] Received RX allocation"
- << " on channel " << d_us_rx_chan << std::endl;
-
- // If the TX has also been allocated already, we can continue
- if(!pmt_eqv(d_us_tx_chan, PMT_NIL)) {
- //enter_receiving();
- initialize_gmac();
- }
-
- return;
- }
- else { // RX allocation failed
- error_msg = "failed to allocate RX channel:";
- goto bail;
- }
- }
-
- goto unhandled;
-
- //----------------------------- INIT GMAC --------------------------------//
- // In the INIT_GMAC state, now that the USRP is initialized we can do things
- // like right the carrier sense threshold to the FPGA register.
- case INIT_GMAC:
- goto unhandled;
-
-
- //----------------------------- IDLE ------------------------------------//
- // In the idle state the MAC is not quite 'idle', it is just not doing
- // anything specific. It is still being passive with data between the
- // application and the lower layer.
- case IDLE:
-
- //-------- TX PORT ----------------------------------------------------//
- if(pmt_eq(d_tx->port_symbol(), port_id)) {
-
- //-------- INCOMING PACKET ------------------------------------------//
- if(pmt_eq(event, s_cmd_tx_pkt)) {
- handle_cmd_tx_pkt(data);
- return;
- }
-
- }
-
- //--------- USRP TX PORT ----------------------------------------------//
- if(pmt_eq(d_us_tx->port_symbol(), port_id)) {
-
- //-------- INCOMING PACKET RESPONSE ---------------------------------//
- if(pmt_eq(event, s_response_xmit_raw_frame)) {
- handle_response_xmit_raw_frame(data);
- return;
- }
-
- }
-
- //--------- CS PORT ---------------------------------------------------//
- if(pmt_eq(d_cs->port_symbol(), port_id)) {
-
- //------- ENABLE CARRIER SENSE --------------------------------------//
- if(pmt_eq(event, s_cmd_carrier_sense_enable)) {
- handle_cmd_carrier_sense_enable(data);
- return;
- }
-
- //------- CARRIER SENSE THRESHOLD -----------------------------------//
- if(pmt_eq(event, s_cmd_carrier_sense_threshold)) {
- handle_cmd_carrier_sense_threshold(data);
- return;
- }
-
- //------- CARRIER SENSE DEADLINE ------------------------------------//
- if(pmt_eq(event, s_cmd_carrier_sense_deadline)) {
- handle_cmd_carrier_sense_deadline(data);
- return;
- }
-
- //------- DISABLE CARRIER SENSE -------------------------------------//
- if(pmt_eq(event, s_cmd_carrier_sense_disable)) {
- handle_cmd_carrier_sense_disable(data);
- return;
- }
-
- }
-
- goto unhandled;
-
- //------------------------ CLOSING CHANNELS -----------------------------//
- case CLOSING_CHANNELS:
-
- if (pmt_eq(event, s_response_deallocate_channel)
- && pmt_eq(d_us_tx->port_symbol(), port_id))
- {
- status = pmt_nth(1, data);
-
- if(pmt_eq(status, PMT_T)) {
- d_us_tx_chan = PMT_NIL;
-
- if(verbose)
- std::cout << "[GMAC] Received TX deallocation\n";
-
- // If the RX is also deallocated, we can close the USRP
- if(pmt_eq(d_us_rx_chan, PMT_NIL))
- close_usrp();
-
- return;
-
- } else {
-
- error_msg = "failed to deallocate TX channel:";
- goto bail;
-
- }
- }
-
- if (pmt_eq(event, s_response_deallocate_channel)
- && pmt_eq(d_us_rx->port_symbol(), port_id))
- {
- status = pmt_nth(1, data);
-
- // If successful, set the port to NIL
- if(pmt_eq(status, PMT_T)) {
- d_us_rx_chan = PMT_NIL;
-
- if(verbose)
- std::cout << "[GMAC] Received RX deallocation\n";
-
- // If the TX is also deallocated, we can close the USRP
- if(pmt_eq(d_us_tx_chan, PMT_NIL))
- close_usrp();
-
- return;
-
- } else {
-
- error_msg = "failed to deallocate RX channel:";
- goto bail;
-
- }
- }
-
- goto unhandled;
-
- //-------------------------- CLOSING USRP -------------------------------//
- case CLOSING_USRP:
- goto unhandled;
-
- }
-
- // An error occured, print it, and shutdown all m-blocks
- bail:
- std::cerr << error_msg << data
- << "status = " << status << std::endl;
- shutdown_all(PMT_F);
- return;
-
- // Received an unhandled message for a specific state
- unhandled:
- if(0 && verbose && !pmt_eq(event, pmt_intern("%shutdown")))
- std::cout << "[GMAC] unhandled msg: " << msg
- << "in state "<< d_state << std::endl;
-}
-
-// The MAC layer connects to 'usrp_server' which has a control/status channel,
-// a TX, and an RX port. The MAC layer can then relay TX/RX data back and
-// forth to the application, or a physical layer once available.
-void gmac::define_ports()
-{
- // Ports we use to connect to usrp_server
- d_us_tx = define_port("us-tx0", "usrp-tx", false, mb_port::INTERNAL);
- d_us_rx = define_port("us-rx0", "usrp-rx", false, mb_port::INTERNAL);
- d_us_cs = define_port("us-cs", "usrp-server-cs", false, mb_port::INTERNAL);
-
- // Ports applications used to connect to us
- d_tx = define_port("tx0", "gmac-tx", true, mb_port::EXTERNAL);
- d_rx = define_port("rx0", "gmac-rx", true, mb_port::EXTERNAL);
- d_cs = define_port("cs", "gmac-cs", true, mb_port::EXTERNAL);
-}
-
-// To initialize the USRP we must pass several parameters to 'usrp_server' such
-// as the RBF to use, and the interpolation/decimation rate. The MAC layer will
-// then pass these parameters to the block with a message to establish the
-// connection to the USRP.
-void gmac::initialize_usrp()
-{
-
- if(verbose)
- std::cout << "[GMAC] Initializing USRP\n";
-
- // The initialization parameters are passed to usrp_server via a PMT
- // dictionary.
- pmt_t usrp_dict = pmt_make_dict();
-
- // Specify the RBF to use
- pmt_dict_set(usrp_dict,
- pmt_intern("rbf"),
- pmt_intern("test2.rbf"));
-
- pmt_dict_set(usrp_dict,
- pmt_intern("interp-tx"),
- pmt_from_long(128));
-
- pmt_dict_set(usrp_dict,
- pmt_intern("decim-rx"),
- pmt_from_long(16));
-
- // Center frequency
- pmt_dict_set(usrp_dict,
- pmt_intern("rf-freq"),
- pmt_from_long((long)10e6));
-
- // Default is to use USRP considered '0' (incase of multiple)
- d_which_usrp = pmt_from_long(0);
-
- define_component("USRP-SERVER", "usrp_server", usrp_dict);
-
- connect("self", "us-tx0", "USRP-SERVER", "tx0");
- connect("self", "us-rx0", "USRP-SERVER", "rx0");
- connect("self", "us-cs", "USRP-SERVER", "cs");
-
- // Finally, enter the OPENING_USRP state by sending a request to open the
- // USRP.
- open_usrp();
-
-}
-
-// In the initialization state of the MAC layer we set default values for
-// several functionalities.
-void gmac::initialize_gmac()
-{
-
- // The initial state is the INIT state.
- d_state = INIT_GMAC;
-
- // Set carrier sense to enabled by default with the specified threshold and
- // the deadline to 0 -- which is wait forever.
- set_carrier_sense(true, 25, 0, PMT_NIL);
-
- // Can now notify the application that we are initialized
- d_cs->send(s_response_gmac_initialized,
- pmt_list2(PMT_NIL, PMT_T));
-
- // The MAC enters an IDLE state where it waits for messages and dispatches
- // based on them
- enter_idle();
-}
-
-// Method for setting the carrier sense and an associated threshold which is
-// written to a register on the FPGA, which it will read if the CS flag is set
-// and perform carrier sense based on.
-//
-// We currently do not wait for the successful response for the write to
-// register command, we assume it will succeed else the MAC must
-void gmac::set_carrier_sense(bool toggle, long threshold, long deadline, pmt_t invocation)
-{
- d_carrier_sense = toggle;
-
- // Only waste the bandwidth and processing of a C/S packet if needed
- if(threshold != d_cs_thresh) {
- d_us_tx->send(s_cmd_to_control_channel, // C/S packet
- pmt_list2(invocation, // invoc handle
- pmt_list1(
- pmt_list2(s_op_write_reg,
- pmt_list2(
- pmt_from_long(REG_CS_THRESH),
- pmt_from_long(threshold))))));
- d_cs_thresh = threshold;
-
- if(verbose)
- std::cout << "[GMAC] Changing CS threshold: " << d_cs_thresh << std::endl;
- }
-
- if(deadline != d_cs_deadline) {
- d_us_tx->send(s_cmd_to_control_channel, // C/S packet
- pmt_list2(invocation, // invoc handle
- pmt_list1(
- pmt_list2(s_op_write_reg,
- pmt_list2(
- pmt_from_long(REG_CS_DEADLINE),
- pmt_from_long(deadline))))));
- d_cs_deadline = deadline;
-
- if(verbose)
- std::cout << "[GMAC] Changing CS deadline: " << d_cs_deadline << std::endl;
- }
-
- if(verbose)
- std::cout << "[GMAC] Setting carrier sense to " << toggle << std::endl;
-}
-
-// The following sends a command to open the USRP, which will upload the
-// specified RBF when creating the instance of the USRP server and set all other
-// relevant parameters.
-void gmac::open_usrp()
-{
- d_state = OPENING_USRP;
-
- d_us_cs->send(s_cmd_open, pmt_list2(PMT_NIL, d_which_usrp));
-
- if(verbose)
- std::cout << "[GMAC] Opening USRP "
- << d_which_usrp << std::endl;
-}
-
-// Before sending the close to the USRP we wait a couple seconds to let any data
-// through the USB exit, else a bug in the driver will kick an error and cause
-// an abnormal termination.
-void gmac::close_usrp()
-{
- d_state = CLOSING_USRP;
-
- sleep(2);
-
- d_us_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
-}
-
-// RX and TX channels must be allocated so that the USRP server can
-// properly share bandwidth across multiple USRPs. No commands will be
-// successful to the USRP through the USRP server on the TX or RX channels until
-// a bandwidth allocation has been received.
-void gmac::allocate_channels()
-{
- d_state = ALLOCATING_CHANNELS;
-
- if(verbose)
- std::cout << "[GMAC] Sending channel allocation requests\n";
-
- long capacity = (long) 16e6;
- d_us_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
- d_us_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
-
-}
-
-// Before closing the USRP connection, we deallocate our channels so that the
-// capacity can be reused.
-void gmac::close_channels()
-{
- d_state = CLOSING_CHANNELS;
-
- d_us_tx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_us_tx_chan));
- d_us_rx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_us_rx_chan));
-
- if(verbose)
- std::cout << "[GMAC] Closing channels...\n";
-}
-
-// Used to enter the receiving state
-void gmac::enter_receiving()
-{
- d_us_rx->send(s_cmd_start_recv_raw_samples,
- pmt_list2(PMT_F,
- d_us_rx_chan));
-
- if(verbose)
- std::cout << "[GMAC] Started RX sample stream\n";
-}
-
-// A simple idle state, nothing more to it.
-void gmac::enter_idle()
-{
- d_state = IDLE;
-}
-
-// Handles the transmission of a pkt from the application. The invocation
-// handle is passed on but a response is not given back to the application until
-// the response is passed from usrp_server. This ensures that the MAC passes
-// back the success or failure. Furthermore, the MAC could decide to retransmit
-// on a failure based on the result of the packet transmission.
-//
-// This should eventually be connected to a physically layer rather than
-// directly to usrp_server. (d_us_tx should be replaced with a different
-// connection)
-void gmac::handle_cmd_tx_pkt(pmt_t data)
-{
- pmt_t invocation_handle = pmt_nth(0, data);
- pmt_t dst = pmt_nth(1, data);
- pmt_t samples = pmt_nth(2, data);
- pmt_t pkt_properties = pmt_nth(3, data);
-
- pmt_t us_tx_properties = pmt_make_dict();
-
- // Set the packet to be carrier sensed?
- if(carrier_sense_pkt(pkt_properties))
- pmt_dict_set(us_tx_properties,
- pmt_intern("carrier-sense"),
- PMT_T);
-
- pmt_t timestamp = pmt_from_long(0xffffffff); // NOW
-
- // Construct the proper message for USRP server
- d_us_tx->send(s_cmd_xmit_raw_frame,
- pmt_list5(invocation_handle,
- d_us_tx_chan,
- samples,
- timestamp,
- us_tx_properties));
-
- if(verbose && 0)
- std::cout << "[GMAC] Transmitted packet\n";
-}
-
-// Handles a response from the USRP server about the transmission of a frame,
-// whether it was successful or failed. This should eventually be replaced with
-// a response from the PHY layer. This is where a retransmit could be
-// implemented.
-void gmac::handle_response_xmit_raw_frame(pmt_t data)
-{
- pmt_t invocation_handle = pmt_nth(0, data);
- pmt_t status = pmt_nth(1, data);
-
- d_tx->send(s_response_tx_pkt,
- pmt_list2(invocation_handle,
- status));
-}
-
-// This method determines whether carrier sense should be enabled based on two
-// properties. The first is the MAC setting, which the user can set to carrier
-// sense packets by default or not. The second is a per packet setting, which
-// can be used to override the MAC setting for the given packet only.
-bool gmac::carrier_sense_pkt(pmt_t pkt_properties)
-{
- // First we extract the per packet properties to check the per packet setting
- // if it exists
- if(pmt_is_dict(pkt_properties)) {
-
- if(pmt_t pkt_cs = pmt_dict_ref(pkt_properties,
- pmt_intern("carrier-sense"),
- PMT_NIL)) {
- // If the per packet property says true, enable carrier sense regardless
- // of the MAC setting
- if(pmt_eqv(pkt_cs, PMT_T))
- return true;
- // If the per packet setting says false, disable carrier sense regardless
- // of the MAC setting
- else if(pmt_eqv(pkt_cs, PMT_F))
- return false;
- }
- }
-
- // If we've hit this point, the packet properties did not state whether
- // carrier sense should be used or not, so we use the MAC setting
- if(d_carrier_sense)
- return true;
- else
- return false;
-
-}
-
-// This method is envoked by an incoming cmd-enable-carrier-sense signal on the
-// C/S port. It can be used to re-adjust the threshold or simply enabled
-// carrier sense. When a threshold is not provided, the MAC will use an
-// averaging algorithm to determine the threshold (in the future).
-void gmac::handle_cmd_carrier_sense_enable(pmt_t data)
-{
- pmt_t invocation_handle = pmt_nth(0, data);
- pmt_t threshold = pmt_nth(1, data);
- pmt_t deadline = pmt_nth(2, data);
- long l_threshold, l_deadline;
-
- // FIXME: for now, if threshold is NIL, we do not change the threshold.
- // This should be replaced with an averaging algorithm
- if(pmt_eqv(threshold, PMT_NIL))
- l_threshold = d_cs_thresh;
- else
- l_threshold = pmt_to_long(threshold);
-
- // If the deadline is NIL, we do not change the value
- if(pmt_eqv(threshold, PMT_NIL))
- l_deadline = d_cs_deadline;
- else
- l_deadline = pmt_to_long(deadline);
-
- set_carrier_sense(true, l_threshold, l_deadline, invocation_handle);
-}
-
-// This method is called when an incoming disable carrier sense command is sent
-// over the control status channel. It so far does not ellicit a response, this
-// needs to be added correctly. It needs to wait for the response for the C/S
-// packet from usrp_server.
-void gmac::handle_cmd_carrier_sense_disable(pmt_t data)
-{
- pmt_t invocation_handle = pmt_nth(0, data);
-
- // We don't change the threshold, we leave it as is because the application
- // did not request that it changes, only to disable carrier sense.
- set_carrier_sense(false, d_cs_thresh, d_cs_deadline, invocation_handle);
-}
-
-// When the app requests that the threshold changes, the state of the carrier
-// sense should not change. If it was enabled, it should remain enabled.
-// Likewise if it was disabled. The deadline value should also remain
-// unchanged.
-void gmac::handle_cmd_carrier_sense_threshold(pmt_t data)
-{
- pmt_t invocation_handle = pmt_nth(0, data);
- pmt_t threshold = pmt_nth(1, data);
- long l_threshold;
-
- // FIXME: for now, if threshold is NIL, we do not change the threshold.
- // This should be replaced with an averaging algorithm
- if(pmt_eqv(threshold, PMT_NIL))
- l_threshold = d_cs_thresh;
- else
- l_threshold = pmt_to_long(threshold);
-
- set_carrier_sense(d_carrier_sense, l_threshold, d_cs_deadline, invocation_handle);
-}
-
-// Ability to change the deadline using a C/S packet. The state of all other
-// carrier sense parameters should not change.
-void gmac::handle_cmd_carrier_sense_deadline(pmt_t data)
-{
- pmt_t invocation_handle = pmt_nth(0, data);
- pmt_t deadline = pmt_nth(1, data);
- long l_deadline;
-
- // If the deadline passed is NIL, do *not* change the value.
- if(pmt_eqv(deadline, PMT_NIL))
- l_deadline = d_cs_deadline;
- else
- l_deadline = pmt_to_long(deadline);
-
- set_carrier_sense(d_carrier_sense, d_cs_thresh, l_deadline, invocation_handle);
-}
-
-REGISTER_MBLOCK_CLASS(gmac);
diff --git a/usrp/host/apps-inband/gmac.h b/usrp/host/apps-inband/gmac.h
deleted file mode 100644
index a6d0bcb12..000000000
--- a/usrp/host/apps-inband/gmac.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2007 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef INCLUDED_GMAC_H
-#define INCLUDED_GMAC_H
-
-#include <mb_mblock.h>
-
-class gmac;
-
-class gmac : public mb_mblock
-{
-
- // The state is used to determine how to handle incoming messages and of
- // course, the state of the MAC protocol.
- enum state_t {
- INIT,
- OPENING_USRP,
- ALLOCATING_CHANNELS,
- INIT_GMAC,
- IDLE,
- CLOSING_CHANNELS,
- CLOSING_USRP,
- };
- state_t d_state;
-
- // Ports used for applications to connect to this block
- mb_port_sptr d_tx, d_rx, d_cs;
-
- // Ports to connect to usrp_server (us)
- mb_port_sptr d_us_tx, d_us_rx, d_us_cs;
-
- // The channel numbers assigned for use
- pmt_t d_us_rx_chan, d_us_tx_chan;
-
- pmt_t d_which_usrp;
-
- bool d_carrier_sense;
- long d_cs_thresh;
- long d_cs_deadline;
-
- enum FPGA_REGISTERS {
- REG_CS_THRESH = 1,
- REG_CS_DEADLINE = 2
- };
-
- public:
- gmac(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg);
- ~gmac();
- void handle_message(mb_message_sptr msg);
-
- private:
- void define_ports();
- void initialize_usrp();
- void initialize_gmac();
- void set_carrier_sense(bool toggle, long threshold, long deadline, pmt_t invocation);
- void allocate_channels();
- void enter_receiving();
- void enter_idle();
- void close_channels();
- void open_usrp();
- void close_usrp();
- void handle_cmd_tx_pkt(pmt_t data);
- void handle_response_xmit_raw_frame(pmt_t data);
- bool carrier_sense_pkt(pmt_t pkt_properties);
- void handle_cmd_carrier_sense_enable(pmt_t data);
- void handle_cmd_carrier_sense_threshold(pmt_t data);
- void handle_cmd_carrier_sense_disable(pmt_t data);
- void handle_cmd_carrier_sense_deadline(pmt_t data);
-
-};
-
-#endif // INCLUDED_GMAC_H
diff --git a/usrp/host/apps-inband/gmac.mbh b/usrp/host/apps-inband/gmac.mbh
deleted file mode 100644
index 4fa9a062f..000000000
--- a/usrp/host/apps-inband/gmac.mbh
+++ /dev/null
@@ -1,146 +0,0 @@
-;; -*- scheme -*- ; not really, but tells emacs how to format this
-;;
-;; Copyright 2007 Free Software Foundation, Inc.
-;;
-;; This file is part of GNU Radio
-;;
-;; GNU Radio is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-;;
-;; GNU Radio is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-;;
-;; You should have received a copy of the GNU General Public License along
-;; with this program; if not, write to the Free Software Foundation, Inc.,
-;; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-;;
-
-;; ----------------------------------------------------------------
-;; This is an mblock header file
-;;
-;; The format is very much a work-in-progress.
-;; It'll be compiled to C++.
-;; ----------------------------------------------------------------
-
-;; In the outgoing messages described below, invocation-handle is an
-;; identifier provided by the client to tag the method invocation.
-;; The identifier will be returned with the response, to provide the
-;; client with a mechanism to match asynchronous responses with the
-;; commands that generate them. The value of the invocation-handle is
-;; opaque the the server, and is not required by the server to be
-;; unique.
-;;
-;; In the incoming messages described below, invocation-handle is the
-;; identifier provided by the client in the prompting invocation. The
-;; identifier is returned with the response, so that the client has a
-;; mechanism to match asynchronous responses with the commands that
-;; generated them.
-;;
-;; status is either #t, indicating success, or a symbol indicating an error.
-;; All symbol's names shall begin with %error-
-
-
-;; ----------------------------------------------------------------
-;; gmac-tx
-;;
-;; The protocol class is defined from the client's point-of-view.
-;; (The client port is unconjugated, the server port is conjugated.)
-
-(define-protocol-class gmac-tx
-
- (:outgoing
-
- ;; Transmitting packets can carry an invocation handle so the application
- ;; can get TX results on specific packets, such as whether a packet tagged
- ;; as #1 was successfully transmitted or not. This would allow the
- ;; application to implement something sliding window like.
- ;;
- ;; 'dst' is the destination MAC address (given a MAC addressing scheme)
- ;;
- ;; 'data' will be treated transparently and passed on as samples.
- ;;
- ;; 'properties' can be used in the future to set per-packet options such as
- ;; carrier sense overriding functionality.
- (cmd-tx-pkt invocation-handle dst data properties)
-
- )
-
- (:incoming
-
- ;; The response will carry the same invocation-handle passed with cmd-tx-pkt
- (response-tx-pkt invocation-handle status)
-
- )
- )
-
-;; ----------------------------------------------------------------
-;; gmac-rx
-;;
-;; The protocol class is defined from the client's point-of-view.
-;; (The client port is unconjugated, the server port is conjugated.)
-
-(define-protocol-class gmac-rx
-
- (:outgoing
-
- ;; There are currently no outgoing commands, I believe that the RX
- ;; should always be enabled, there is no point in having an enable/disable
- ;; that I can see.
-
- )
-
- (:incoming
-
- ;; Contains packets decoded by the MAC destined for this machine, sent by
- ;; the specified address.
- (response-rx-pkt invocation-handle src data)
-
- )
- )
-
-
-;; ----------------------------------------------------------------
-;; gmac-cs
-;;
-;; The protocol class is defined from the client's point-of-view.
-;; (The client port is unconjugated, the server port is conjugated.)
-;;
-;; This defines a control/status interface to the MAC layer, for control over
-;; functionality such as carrier sense and future functionality such as channel
-;; hopping.
-
-
-(define-protocol-class gmac-cs
-
- (:outgoing
-
- ;; Threshold represents the carrier sense threshold based on the digital
- ;; reading out of the DAC. If the threshold is set to PMT_NIL then the
- ;; MAC will use averaging to determine an appropriate threshold.
- (cmd-carrier-sense-enable invocation-handle threshold deadline)
- (cmd-carrier-sense-threshold invocation-handle threshold)
- (cmd-carrier-sense-disable invocation-handle)
-
- ;; Setting the number of fast transmission retries on a failure before
- ;; reporting a loss back to the application.
- (cmd-set-tx-retries invocation-handle retries)
-
- )
-
- (:incoming
-
- (response-gmac-initialized invocation-handle status)
-
- (response-carrier-sense-enable invocation-handle status)
- (response-carrier-sense-threshold invocation-handle status)
- (response-carrier-sense-deadline invocation-handle status)
- (response-carrier-sense-disable invocation-handle status)
-
- (response-set-tx-retries invocation-handle status)
-
- )
- )
diff --git a/usrp/host/apps-inband/gmac_symbols.h b/usrp/host/apps-inband/gmac_symbols.h
deleted file mode 100644
index 0d7804be1..000000000
--- a/usrp/host/apps-inband/gmac_symbols.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2007 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef INCLUDED_GMAC_SYMBOLS_H
-#define INCLUDED_GMAC_SYMBOLS_H
-
-#include <pmt.h>
-
-// TX
-static pmt_t s_cmd_tx_pkt = pmt_intern("cmd-tx-pkt");
-static pmt_t s_response_tx_pkt = pmt_intern("response-tx-pkt");
-
-// RX
-static pmt_t s_response_rx_pkt = pmt_intern("response-rx-pkt");
-
-// CS
-static pmt_t s_cmd_carrier_sense_enable = pmt_intern("cmd-carrier-sense-enable");
-static pmt_t s_cmd_carrier_sense_threshold = pmt_intern("cmd-carrier-sense-threshold");
-static pmt_t s_cmd_carrier_sense_deadline = pmt_intern("cmd-carrier-sense-deadline");
-static pmt_t s_cmd_carrier_sense_disable = pmt_intern("cmd-carrier-sense-disable");
-static pmt_t s_cmd_set_tx_retries = pmt_intern("cmd-set-tx-retries");
-static pmt_t s_response_gmac_initialized = pmt_intern("response-gmac-initialized");
-static pmt_t s_response_carrier_sense_enable = pmt_intern("response-carrier-sense-enable");
-static pmt_t s_response_carrier_sense_treshold = pmt_intern("response-carrier-sense-threshold");
-static pmt_t s_response_carrier_sense_deadline = pmt_intern("response-carrier-sense-deadline");
-static pmt_t s_response_carrier_sense_disable = pmt_intern("response-carrier-sense-disable");
-static pmt_t s_response_set_tx_retries = pmt_intern("response-set-tx-retries");
-
-#endif // INCLUDED_GMAC_SYMBOLS_H
diff --git a/usrp/host/apps-inband/test_gmac_tx.cc b/usrp/host/apps-inband/test_gmac_tx.cc
deleted file mode 100644
index 74f16c669..000000000
--- a/usrp/host/apps-inband/test_gmac_tx.cc
+++ /dev/null
@@ -1,330 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2007 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <mb_mblock.h>
-#include <mb_runtime.h>
-#include <mb_protocol_class.h>
-#include <mb_exception.h>
-#include <mb_msg_queue.h>
-#include <mb_message.h>
-#include <mb_msg_accepter.h>
-#include <mb_class_registry.h>
-#include <pmt.h>
-#include <stdio.h>
-#include <string.h>
-#include <iostream>
-
-#include <ui_nco.h>
-#include <gmac.h>
-#include <gmac_symbols.h>
-
-static bool verbose = true;
-
-class test_gmac_tx : public mb_mblock
-{
- mb_port_sptr d_tx;
- mb_port_sptr d_cs;
- pmt_t d_tx_chan; // returned tx channel handle
-
- enum state_t {
- INIT,
- TRANSMITTING,
- };
-
- state_t d_state;
- long d_nsamples_to_send;
- long d_nsamples_xmitted;
- long d_nframes_xmitted;
- long d_samples_per_frame;
- bool d_done_sending;
-
- // for generating sine wave output
- ui_nco<float,float> d_nco;
- double d_amplitude;
-
- public:
- test_gmac_tx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
- ~test_gmac_tx();
- void handle_message(mb_message_sptr msg);
-
- protected:
- void open_usrp();
- void close_usrp();
- void allocate_channel();
- void send_packets();
- void enter_transmitting();
- void build_and_send_next_frame();
- void handle_xmit_response(pmt_t invocation_handle);
- void enter_closing_channel();
-};
-
-test_gmac_tx::test_gmac_tx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
- : mb_mblock(runtime, instance_name, user_arg),
- d_state(INIT), d_nsamples_to_send((long) 40e6),
- d_nsamples_xmitted(0),
- d_nframes_xmitted(0),
- d_samples_per_frame((long)(126 * 4)), // full packet
- d_done_sending(false),
- d_amplitude(16384)
-{
-
- define_component("GMAC", "gmac", PMT_NIL);
- d_tx = define_port("tx0", "gmac-tx", false, mb_port::INTERNAL);
- d_cs = define_port("cs", "gmac-cs", false, mb_port::INTERNAL);
-
- connect("self", "tx0", "GMAC", "tx0");
- connect("self", "cs", "GMAC", "cs");
-
- // initialize NCO
- double freq = 100e3;
- int interp = 32; // 32 -> 4MS/s
- double sample_rate = 128e6 / interp;
- d_nco.set_freq(2*M_PI * freq/sample_rate);
-
-}
-
-test_gmac_tx::~test_gmac_tx()
-{
-}
-
-void
-test_gmac_tx::handle_message(mb_message_sptr msg)
-{
- pmt_t event = msg->signal();
- pmt_t data = msg->data();
- pmt_t port_id = msg->port_id();
-
- pmt_t handle = PMT_F;
- pmt_t status = PMT_F;
- pmt_t dict = PMT_NIL;
- std::string error_msg;
-
- // Dispatch based on state
- switch(d_state) {
-
- //------------------------------ INIT ---------------------------------//
- // When GMAC is done initializing, it will send a response
- case INIT:
-
- if(pmt_eq(event, s_response_gmac_initialized)) {
- handle = pmt_nth(0, data);
- status = pmt_nth(1, data);
-
- if(pmt_eq(status, PMT_T)) {
- enter_transmitting();
- return;
- }
- else {
- error_msg = "error initializing gmac:";
- goto bail;
- }
- }
- goto unhandled;
-
- //-------------------------- TRANSMITTING ----------------------------//
- // In the transmit state we count the number of underruns received and
- // ballpark the number with an expected count (something >1 for starters)
- case TRANSMITTING:
-
- // Check that the transmits are OK
- if (pmt_eq(event, s_response_tx_pkt)){
- handle = pmt_nth(0, data);
- status = pmt_nth(1, data);
-
- if (pmt_eq(status, PMT_T)){
- handle_xmit_response(handle);
- return;
- }
- else {
- error_msg = "bad response-tx-pkt:";
- goto bail;
- }
- }
-
- goto unhandled;
-
- }
-
- // An error occured, print it, and shutdown all m-blocks
- bail:
- std::cerr << error_msg << data
- << "status = " << status << std::endl;
- shutdown_all(PMT_F);
- return;
-
- // Received an unhandled message for a specific state
- unhandled:
- if(verbose && !pmt_eq(event, pmt_intern("%shutdown")))
- std::cout << "[TEST_GMAC_TX] unhandled msg: " << msg
- << "in state "<< d_state << std::endl;
-}
-
-void
-test_gmac_tx::enter_transmitting()
-{
- d_state = TRANSMITTING;
- d_nsamples_xmitted = 0;
-
- d_cs->send(s_cmd_carrier_sense_deadline,
- pmt_list2(PMT_NIL,
- pmt_from_long(50000000)));
-
- build_and_send_next_frame(); // fire off 4 to start pipeline
- build_and_send_next_frame();
- build_and_send_next_frame();
- build_and_send_next_frame();
-}
-
-void
-test_gmac_tx::build_and_send_next_frame()
-{
- // allocate the uniform vector for the samples
- // FIXME perhaps hold on to this between calls
-
-#if 0
- long nsamples_this_frame =
- std::min(d_nsamples_to_send - d_nsamples_xmitted,
- d_samples_per_frame);
-#else
- long nsamples_this_frame = d_samples_per_frame;
-#endif
-
- if (nsamples_this_frame == 0){
- d_done_sending = true;
- return;
- }
-
-
- size_t nshorts = 2 * nsamples_this_frame; // 16-bit I & Q
- pmt_t uvec = pmt_make_s16vector(nshorts, 0);
- size_t ignore;
- int16_t *samples = pmt_s16vector_writeable_elements(uvec, ignore);
-
- // fill in the complex sinusoid
- for (int i = 0; i < nsamples_this_frame; i++){
-
- 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);
-
- // write 16-bit i & q
- samples[2*i] = (int16_t) s.real();
- samples[2*i+1] = (int16_t) s.imag();
- }
- }
-
- // Per packet properties
- pmt_t tx_properties = pmt_make_dict();
-
- if(d_nframes_xmitted > 25000) {
- pmt_dict_set(tx_properties,
- pmt_intern("carrier-sense"),
- PMT_F);
- }
-
- if(d_nframes_xmitted > 35000) {
- pmt_dict_set(tx_properties,
- pmt_intern("carrier-sense"),
- PMT_NIL);
- }
-
- if(d_nframes_xmitted == 45000) {
- d_cs->send(s_cmd_carrier_sense_threshold,
- pmt_list2(PMT_NIL,
- pmt_from_long(100)));
- }
-
- if(d_nframes_xmitted == 60000) {
- d_cs->send(s_cmd_carrier_sense_threshold,
- pmt_list2(PMT_NIL,
- pmt_from_long(25)));
- }
-
- if(d_nframes_xmitted == 75000) {
- d_cs->send(s_cmd_carrier_sense_disable,
- pmt_list1(PMT_NIL));
- }
-
- if(d_nframes_xmitted > 90000 && d_nframes_xmitted < 110000) {
- pmt_dict_set(tx_properties,
- pmt_intern("carrier-sense"),
- PMT_T);
- }
-
- if(d_nframes_xmitted > 110000) {
-
- if(d_nframes_xmitted % 100 == 0)
- pmt_dict_set(tx_properties,
- pmt_intern("carrier-sense"),
- PMT_T);
-}
-
- pmt_t timestamp = pmt_from_long(0xffffffff); // NOW
- d_tx->send(s_cmd_tx_pkt,
- pmt_list4(PMT_NIL, // invocation-handle
- PMT_NIL, // destination
- uvec, // the samples
- tx_properties)); // per pkt properties
-
- d_nsamples_xmitted += nsamples_this_frame;
- d_nframes_xmitted++;
-
- if(verbose && 0)
- std::cout << "[TEST_GMAC_TX] Transmitted frame\n";
-}
-
-
-void
-test_gmac_tx::handle_xmit_response(pmt_t handle)
-{
- if (d_done_sending &&
- pmt_to_long(handle) == (d_nframes_xmitted - 1)){
- // We're done sending and have received all responses
- }
-
- build_and_send_next_frame();
-}
-
-REGISTER_MBLOCK_CLASS(test_gmac_tx);
-
-
-// ----------------------------------------------------------------
-
-int
-main (int argc, char **argv)
-{
- // handle any command line args here
-
- mb_runtime_sptr rt = mb_make_runtime();
- pmt_t result = PMT_NIL;
-
- rt->run("test_gmac_tx", "test_gmac_tx", PMT_F, &result);
-}
diff --git a/usrp/host/apps-inband/test_usrp_inband_2rx.cc b/usrp/host/apps-inband/test_usrp_inband_2rx.cc
new file mode 100644
index 000000000..da8d7271c
--- /dev/null
+++ b/usrp/host/apps-inband/test_usrp_inband_2rx.cc
@@ -0,0 +1,371 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <mb_mblock.h>
+#include <mb_runtime.h>
+#include <mb_runtime_nop.h> // QA only
+#include <mb_protocol_class.h>
+#include <mb_exception.h>
+#include <mb_msg_queue.h>
+#include <mb_message.h>
+#include <mb_mblock_impl.h>
+#include <mb_msg_accepter.h>
+#include <mb_class_registry.h>
+#include <pmt.h>
+#include <stdio.h>
+#include <string.h>
+#include <iostream>
+#include <fstream>
+
+// Include the symbols needed for communication with USRP server
+#include <symbols_usrp_server_cs.h>
+#include <symbols_usrp_channel.h>
+#include <symbols_usrp_low_level_cs.h>
+#include <symbols_usrp_rx.h>
+
+static bool verbose = true;
+
+class test_usrp_rx : public mb_mblock
+{
+ mb_port_sptr d_rx;
+ mb_port_sptr d_cs;
+ pmt_t d_rx_chan0, d_rx_chan1;
+
+ enum state_t {
+ INIT,
+ OPENING_USRP,
+ ALLOCATING_CHANNEL,
+ RECEIVING,
+ CLOSING_CHANNEL,
+ CLOSING_USRP,
+ };
+
+ state_t d_state;
+
+ std::ofstream d_ofile;
+
+ long d_samples_recvd;
+ long d_samples_to_recv;
+
+ public:
+ test_usrp_rx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+ ~test_usrp_rx();
+ void initial_transition();
+ void handle_message(mb_message_sptr msg);
+
+ protected:
+ void open_usrp();
+ void close_usrp();
+ void allocate_channel();
+ void send_packets();
+ void enter_receiving();
+ void build_and_send_next_frame();
+ void handle_response_recv_raw_samples(pmt_t invocation_handle);
+ void enter_closing_channel();
+};
+
+test_usrp_rx::test_usrp_rx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+ : mb_mblock(runtime, instance_name, user_arg),
+ d_rx_chan0(PMT_NIL), d_rx_chan1(PMT_NIL),
+ d_samples_recvd(0),
+ d_samples_to_recv(20e6)
+{
+ d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
+ d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
+
+ // Pass a dictionary to usrp_server which specifies which interface to use, the stub or USRP
+ pmt_t usrp_dict = pmt_make_dict();
+
+ // To test the application without a USRP
+ bool fake_usrp_p = false;
+ if(fake_usrp_p) {
+ pmt_dict_set(usrp_dict,
+ pmt_intern("fake-usrp"),
+ PMT_T);
+ }
+
+ // Specify the RBF to use
+ pmt_dict_set(usrp_dict,
+ pmt_intern("rbf"),
+ pmt_intern("inband_2rxhb_2tx.rbf"));
+
+ pmt_dict_set(usrp_dict,
+ pmt_intern("decim-rx"),
+ pmt_from_long(64));
+
+ define_component("server", "usrp_server", usrp_dict);
+
+ connect("self", "rx0", "server", "rx0");
+ connect("self", "cs", "server", "cs");
+
+}
+
+test_usrp_rx::~test_usrp_rx()
+{
+}
+
+void
+test_usrp_rx::initial_transition()
+{
+ open_usrp();
+}
+
+void
+test_usrp_rx::handle_message(mb_message_sptr msg)
+{
+ pmt_t event = msg->signal();
+ pmt_t data = msg->data();
+
+ pmt_t handle = PMT_F;
+ pmt_t status = PMT_F;
+ std::string error_msg;
+
+ switch(d_state){
+
+ //----------------------------- OPENING_USRP ----------------------------//
+ // We only expect a response from opening the USRP which should be succesful
+ // or failed.
+ case OPENING_USRP:
+ if (pmt_eq(event, s_response_open)){
+ status = pmt_nth(1, data);
+ if (pmt_eq(status, PMT_T)){
+ allocate_channel();
+ return;
+ }
+ else {
+ error_msg = "failed to open usrp:";
+ goto bail;
+ }
+ }
+ goto unhandled;
+
+ //----------------------- ALLOCATING CHANNELS --------------------//
+ // Allocate an RX channel to perform the overrun test.
+ case ALLOCATING_CHANNEL:
+ if (pmt_eq(event, s_response_allocate_channel)){
+ status = pmt_nth(1, data);
+ if(pmt_eqv(d_rx_chan0, PMT_NIL))
+ d_rx_chan0 = pmt_nth(2, data);
+ else
+ d_rx_chan1 = pmt_nth(2, data);
+
+ if (pmt_eq(status, PMT_T) && !pmt_eqv(d_rx_chan1, PMT_NIL)){
+ enter_receiving();
+ return;
+ }
+ else if(pmt_eq(status, PMT_F)){
+ error_msg = "failed to allocate channel:";
+ goto bail;
+ }
+ return;
+ }
+ goto unhandled;
+
+ //--------------------------- RECEIVING ------------------------------//
+ // In the receiving state, we receive samples until the specified amount
+ // while counting the number of overruns.
+ case RECEIVING:
+ if (pmt_eq(event, s_response_recv_raw_samples)){
+ status = pmt_nth(1, data);
+
+ if (pmt_eq(status, PMT_T)){
+ handle_response_recv_raw_samples(data);
+ return;
+ }
+ else {
+ error_msg = "bad response-xmit-raw-frame:";
+ goto bail;
+ }
+ }
+ goto unhandled;
+
+ //------------------------- CLOSING CHANNEL ----------------------------//
+ // Check deallocation response for the RX channel
+ case CLOSING_CHANNEL:
+ if (pmt_eq(event, s_response_deallocate_channel)){
+ status = pmt_nth(1, data);
+
+ if (pmt_eq(status, PMT_T)){
+ close_usrp();
+ return;
+ }
+ else {
+ error_msg = "failed to deallocate channel:";
+ goto bail;
+ }
+ }
+
+ // Alternately, we ignore all response recv samples while waiting for the
+ // channel to actually close
+ if (pmt_eq(event, s_response_recv_raw_samples))
+ return;
+
+ goto unhandled;
+
+ //--------------------------- CLOSING USRP ------------------------------//
+ // Once we have received a successful USRP close response, we shutdown all
+ // mblocks and exit.
+ case CLOSING_USRP:
+ if (pmt_eq(event, s_response_close)){
+ status = pmt_nth(1, data);
+
+ if (pmt_eq(status, PMT_T)){
+ fflush(stdout);
+ shutdown_all(PMT_T);
+ return;
+ }
+ else {
+ error_msg = "failed to close USRP:";
+ goto bail;
+ }
+ }
+ goto unhandled;
+
+ default:
+ goto unhandled;
+ }
+ return;
+
+ // An error occured, print it, and shutdown all m-blocks
+ bail:
+ std::cerr << error_msg << data
+ << "status = " << status << std::endl;
+ shutdown_all(PMT_F);
+ return;
+
+ // Received an unhandled message for a specific state
+ unhandled:
+ if(verbose && !pmt_eq(event, pmt_intern("%shutdown")))
+ std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
+ << "in state "<< d_state << std::endl;
+}
+
+
+void
+test_usrp_rx::open_usrp()
+{
+ pmt_t which_usrp = pmt_from_long(0);
+
+ d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, which_usrp));
+ d_state = OPENING_USRP;
+
+ if(verbose)
+ std::cout << "[TEST_USRP_INBAND_RX] Opening the USRP\n";
+}
+
+void
+test_usrp_rx::close_usrp()
+{
+
+ d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
+ d_state = CLOSING_USRP;
+
+ if(verbose)
+ std::cout << "[TEST_USRP_INBAND_RX] Closing the USRP\n";
+}
+
+void
+test_usrp_rx::allocate_channel()
+{
+ long capacity = (long) 16e6;
+ d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
+ d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
+ d_state = ALLOCATING_CHANNEL;
+
+ if(verbose)
+ std::cout << "[TEST_USRP_INBAND_RX] Requesting RX channel allocation\n";
+}
+
+void
+test_usrp_rx::enter_receiving()
+{
+ d_state = RECEIVING;
+
+ d_rx->send(s_cmd_start_recv_raw_samples,
+ pmt_list2(PMT_F,
+ d_rx_chan0));
+
+ d_rx->send(s_cmd_start_recv_raw_samples,
+ pmt_list2(PMT_F,
+ d_rx_chan1));
+
+ if(verbose)
+ std::cout << "[TEST_USRP_INBAND_RX] Receiving...\n";
+}
+
+void
+test_usrp_rx::handle_response_recv_raw_samples(pmt_t data)
+{
+ pmt_t invocation_handle = pmt_nth(0, data);
+ pmt_t status = pmt_nth(1, data);
+ pmt_t v_samples = pmt_nth(2, data);
+ pmt_t timestamp = pmt_nth(3, data);
+ pmt_t channel = pmt_nth(4, data);
+ pmt_t properties = pmt_nth(5, data);
+
+ d_samples_recvd += pmt_length(v_samples) / 4;
+
+ // Check for overrun
+ if(!pmt_is_dict(properties)) {
+ std::cout << "[TEST_USRP_INBAND_RX] Recv samples dictionary is improper\n";
+ return;
+ }
+
+ // Check if the number samples we have received meets the test
+ if(d_samples_recvd >= d_samples_to_recv) {
+ d_rx->send(s_cmd_stop_recv_raw_samples, pmt_list2(PMT_NIL, d_rx_chan0));
+ d_rx->send(s_cmd_stop_recv_raw_samples, pmt_list2(PMT_NIL, d_rx_chan1));
+ enter_closing_channel();
+ return;
+ }
+
+}
+
+void
+test_usrp_rx::enter_closing_channel()
+{
+ d_state = CLOSING_CHANNEL;
+
+ d_rx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_rx_chan0));
+ d_rx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_rx_chan1));
+
+ if(verbose)
+ std::cout << "[TEST_USRP_INBAND_RX] Deallocating RX channel\n";
+}
+
+REGISTER_MBLOCK_CLASS(test_usrp_rx);
+
+
+// ----------------------------------------------------------------
+
+int
+main (int argc, char **argv)
+{
+ mb_runtime_sptr rt = mb_make_runtime();
+ pmt_t result = PMT_NIL;
+
+ rt->run("top", "test_usrp_rx", PMT_F, &result);
+
+}
diff --git a/usrp/host/apps-inband/test_usrp_inband_cs.cc b/usrp/host/apps-inband/test_usrp_inband_2tx.cc
index 2497f8d5c..5ab9be06a 100644
--- a/usrp/host/apps-inband/test_usrp_inband_cs.cc
+++ b/usrp/host/apps-inband/test_usrp_inband_2tx.cc
@@ -25,16 +25,17 @@
#include <mb_mblock.h>
#include <mb_runtime.h>
+#include <mb_runtime_nop.h> // QA only
#include <mb_protocol_class.h>
#include <mb_exception.h>
#include <mb_msg_queue.h>
#include <mb_message.h>
+#include <mb_mblock_impl.h>
#include <mb_msg_accepter.h>
#include <mb_class_registry.h>
#include <pmt.h>
#include <stdio.h>
#include <string.h>
-#include <sys/time.h>
#include <iostream>
#include <ui_nco.h>
@@ -42,21 +43,14 @@
#include <symbols_usrp_channel.h>
#include <symbols_usrp_low_level_cs.h>
#include <symbols_usrp_tx.h>
-#include <symbols_usrp_rx.h>
-#define NBPING 10
+static bool verbose = true;
-static bool verbose = false;
-
-class test_usrp_cs : public mb_mblock
+class test_usrp_tx : public mb_mblock
{
mb_port_sptr d_tx;
- mb_port_sptr d_rx;
mb_port_sptr d_cs;
- pmt_t d_tx_chan; // returned tx channel handle
- pmt_t d_rx_chan; // returned tx channel handle
-
- struct timeval times[NBPING];
+ pmt_t d_tx_chan0, d_tx_chan1;
enum state_t {
INIT,
@@ -79,8 +73,8 @@ class test_usrp_cs : public mb_mblock
double d_amplitude;
public:
- test_usrp_cs(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
- ~test_usrp_cs();
+ test_usrp_tx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+ ~test_usrp_tx();
void initial_transition();
void handle_message(mb_message_sptr msg);
@@ -89,32 +83,25 @@ class test_usrp_cs : public mb_mblock
void close_usrp();
void allocate_channel();
void send_packets();
- void enter_receiving();
void enter_transmitting();
- void build_and_send_ping();
void build_and_send_next_frame();
void handle_xmit_response(pmt_t invocation_handle);
void enter_closing_channel();
};
-test_usrp_cs::test_usrp_cs(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+test_usrp_tx::test_usrp_tx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
: mb_mblock(runtime, instance_name, user_arg),
- d_tx_chan(PMT_NIL),
- d_rx_chan(PMT_NIL),
- d_state(INIT), d_nsamples_to_send((long) 40e6),
+ d_tx_chan0(PMT_NIL), d_tx_chan1(PMT_NIL),
+ d_state(INIT), d_nsamples_to_send((long) 80e6),
d_nsamples_xmitted(0),
d_nframes_xmitted(0),
- //d_samples_per_frame((long)(126)),
- //d_samples_per_frame((long)(126 * 3.5)), // non-full packet
d_samples_per_frame((long)(126 * 4)), // full packet
d_done_sending(false),
d_amplitude(16384)
{
- if(verbose)
- std::cout << "[TEST_USRP_INBAND_CS] Initializing...\n";
+ // std::cout << "[TEST_USRP_TX] Initializing...\n";
d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
- d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
//bool fake_usrp_p = true;
@@ -129,6 +116,11 @@ test_usrp_cs::test_usrp_cs(mb_runtime *runtime, const std::string &instance_name
pmt_intern("fake-usrp"),
PMT_T);
}
+
+ // Specify the RBF to use
+ pmt_dict_set(usrp_dict,
+ pmt_intern("rbf"),
+ pmt_intern("inband_2rxhb_2tx.rbf"));
// Set TX and RX interpolations
pmt_dict_set(usrp_dict,
@@ -136,18 +128,12 @@ test_usrp_cs::test_usrp_cs(mb_runtime *runtime, const std::string &instance_name
pmt_from_long(128));
pmt_dict_set(usrp_dict,
- pmt_intern("decim-rx"),
- pmt_from_long(16));
-
- // Specify the RBF to use
- pmt_dict_set(usrp_dict,
- pmt_intern("rbf"),
- pmt_intern("boe.rbf"));
+ pmt_intern("rf-freq"),
+ pmt_from_long(10e6));
define_component("server", "usrp_server", usrp_dict);
connect("self", "tx0", "server", "tx0");
- connect("self", "rx0", "server", "rx0");
connect("self", "cs", "server", "cs");
// initialize NCO
@@ -160,22 +146,21 @@ test_usrp_cs::test_usrp_cs(mb_runtime *runtime, const std::string &instance_name
// for now, we'll have the low-level code hardwire it.
}
-test_usrp_cs::~test_usrp_cs()
+test_usrp_tx::~test_usrp_tx()
{
}
void
-test_usrp_cs::initial_transition()
+test_usrp_tx::initial_transition()
{
open_usrp();
}
void
-test_usrp_cs::handle_message(mb_message_sptr msg)
+test_usrp_tx::handle_message(mb_message_sptr msg)
{
pmt_t event = msg->signal();
pmt_t data = msg->data();
- pmt_t port_id = msg->port_id();
pmt_t handle = PMT_F;
pmt_t status = PMT_F;
@@ -200,48 +185,21 @@ test_usrp_cs::handle_message(mb_message_sptr msg)
case ALLOCATING_CHANNEL:
if (pmt_eq(event, s_response_allocate_channel)){
+ status = pmt_nth(1, data);
+ if(pmt_eqv(d_tx_chan0, PMT_NIL))
+ d_tx_chan0 = pmt_nth(2, data);
+ else
+ d_tx_chan1 = pmt_nth(2, data);
- if(pmt_eq(d_tx->port_symbol(), port_id)) {
- status = pmt_nth(1, data);
- d_tx_chan = pmt_nth(2, data);
-
- if (pmt_eq(status, PMT_T)){
-
- if(verbose)
- std::cout << "[TEST_USRP_INBAND_CS] Received allocation for TX\n";
-
- if(!pmt_eqv(d_rx_chan, PMT_NIL)) {
- enter_receiving();
- enter_transmitting();
- }
- return;
- }
- else {
- error_msg = "failed to allocate channel:";
- goto bail;
- }
+ if (pmt_eq(status, PMT_T) && !pmt_eqv(d_tx_chan1, PMT_NIL)){
+ enter_transmitting();
+ return;
}
-
- if(pmt_eq(d_rx->port_symbol(), port_id)) {
- status = pmt_nth(1, data);
- d_rx_chan = pmt_nth(2, data);
-
- if (pmt_eq(status, PMT_T)){
-
- if(verbose)
- std::cout << "[TEST_USRP_INBAND_CS] Received allocation for TX\n";
-
- if(!pmt_eqv(d_tx_chan, PMT_NIL)) {
- enter_receiving();
- enter_transmitting();
- }
- return;
- }
- else {
- error_msg = "failed to allocate channel:";
- goto bail;
- }
+ else if(pmt_eq(status, PMT_F)){
+ error_msg = "failed to allocate channel:";
+ goto bail;
}
+ return;
}
goto unhandled;
@@ -303,81 +261,64 @@ test_usrp_cs::handle_message(mb_message_sptr msg)
return;
unhandled:
- if(verbose)
- std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
- << "in state "<< d_state << std::endl;
+ std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
+ << "in state "<< d_state << std::endl;
}
void
-test_usrp_cs::open_usrp()
+test_usrp_tx::open_usrp()
{
pmt_t which_usrp = pmt_from_long(0);
d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, which_usrp));
d_state = OPENING_USRP;
+
+ if(verbose)
+ std::cout << "[TEST_USRP_INBAND_TX] Opening the USRP\n";
}
void
-test_usrp_cs::close_usrp()
+test_usrp_tx::close_usrp()
{
d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
d_state = CLOSING_USRP;
-
+
if(verbose)
- std::cout << "[TEST_USRP_INBAND_CS] Closing USRP\n";
+ std::cout << "[TEST_USRP_INBAND_TX] Closing the USRP\n";
}
void
-test_usrp_cs::allocate_channel()
+test_usrp_tx::allocate_channel()
{
long capacity = (long) 16e6;
+
+ // Send two capacity requests, which will allocate us two channels
+ d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
- d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
d_state = ALLOCATING_CHANNEL;
+
+ if(verbose)
+ std::cout << "[TEST_USRP_INBAND_TX] Requesting TX channel allocation\n";
}
void
-test_usrp_cs::enter_receiving()
-{
- d_rx->send(s_cmd_start_recv_raw_samples,
- pmt_list2(PMT_F,
- d_rx_chan));
-}
-
-void
-test_usrp_cs::enter_transmitting()
+test_usrp_tx::enter_transmitting()
{
d_state = TRANSMITTING;
d_nsamples_xmitted = 0;
-
- if(verbose)
- std::cout << "[TEST_USRP_INBAND_CS] Beginning transmission\n";
-
- sleep(1);
-
-// build_and_send_next_frame(); // fire off 4 to start pipeline
-
- build_and_send_ping();
- build_and_send_ping();
- build_and_send_ping();
-}
-
-void
-test_usrp_cs::build_and_send_ping()
-{
+ if(verbose)
+ std::cout << "[TEST_USRP_INBAND_TX] Transmitting...\n";
- d_tx->send(s_cmd_to_control_channel,
- pmt_list2(PMT_NIL, pmt_list1(pmt_list2(s_op_ping_fixed,
- pmt_list2(pmt_from_long(0),
- pmt_from_long(0))))));
-
- std::cout << "[TEST_USRP_INBAND_CS] Ping sent" << std::endl;
+ build_and_send_next_frame(); // fire off 4 to start pipeline
+ build_and_send_next_frame();
+ build_and_send_next_frame();
+ build_and_send_next_frame();
}
void
-test_usrp_cs::build_and_send_next_frame()
+test_usrp_tx::build_and_send_next_frame()
{
// allocate the uniform vector for the samples
// FIXME perhaps hold on to this between calls
@@ -421,23 +362,34 @@ test_usrp_cs::build_and_send_next_frame()
}
}
+ pmt_t tx_properties = pmt_make_dict();
+
pmt_t timestamp = pmt_from_long(0xffffffff); // NOW
d_tx->send(s_cmd_xmit_raw_frame,
- pmt_list4(pmt_from_long(d_nframes_xmitted), // invocation-handle
- d_tx_chan, // channel
+ pmt_list5(pmt_from_long(d_nframes_xmitted), // invocation-handle
+ d_tx_chan0, // channel
uvec, // the samples
- timestamp));
+ timestamp,
+ tx_properties));
+
+ // Resend on channel 1
+ d_tx->send(s_cmd_xmit_raw_frame,
+ pmt_list5(pmt_from_long(d_nframes_xmitted), // invocation-handle
+ d_tx_chan1, // channel
+ uvec, // the samples
+ timestamp,
+ tx_properties));
d_nsamples_xmitted += nsamples_this_frame;
d_nframes_xmitted++;
- if(verbose)
- std::cout << "[TEST_USRP_INBAND_CS] Transmitted frame\n";
+ if(verbose && 0)
+ std::cout << "[TEST_USRP_INBAND_TX] Transmitted frame\n";
}
void
-test_usrp_cs::handle_xmit_response(pmt_t handle)
+test_usrp_tx::handle_xmit_response(pmt_t handle)
{
if (d_done_sending &&
pmt_to_long(handle) == (d_nframes_xmitted - 1)){
@@ -445,21 +397,23 @@ test_usrp_cs::handle_xmit_response(pmt_t handle)
enter_closing_channel();
}
- //build_and_send_next_frame();
+ build_and_send_next_frame();
}
void
-test_usrp_cs::enter_closing_channel()
+test_usrp_tx::enter_closing_channel()
{
d_state = CLOSING_CHANNEL;
- d_tx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_tx_chan));
-
+ // Deallocate both channels
+ d_tx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_tx_chan0));
+ d_tx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_tx_chan1));
+
if(verbose)
- std::cout << "[TEST_USRP_INBAND_CS] Closing channel\n";
+ std::cout << "[TEST_USRP_INBAND_tX] Deallocating TX channel\n";
}
-REGISTER_MBLOCK_CLASS(test_usrp_cs);
+REGISTER_MBLOCK_CLASS(test_usrp_tx);
// ----------------------------------------------------------------
@@ -472,5 +426,5 @@ main (int argc, char **argv)
mb_runtime_sptr rt = mb_make_runtime();
pmt_t result = PMT_NIL;
- rt->run("top", "test_usrp_cs", PMT_F, &result);
+ rt->run("top", "test_usrp_tx", PMT_F, &result);
}
diff --git a/usrp/host/apps-inband/test_usrp_inband_overrun.cc b/usrp/host/apps-inband/test_usrp_inband_overrun.cc
index 9041a0984..107668b89 100644
--- a/usrp/host/apps-inband/test_usrp_inband_overrun.cc
+++ b/usrp/host/apps-inband/test_usrp_inband_overrun.cc
@@ -102,7 +102,7 @@ test_usrp_rx::test_usrp_rx(mb_runtime *runtime, const std::string &instance_name
// Specify the RBF to use
pmt_dict_set(usrp_dict,
pmt_intern("rbf"),
- pmt_intern("nanocell9.rbf"));
+ pmt_intern("inband_1rxhb_1tx.rbf"));
pmt_dict_set(usrp_dict,
pmt_intern("decim-rx"),
@@ -306,7 +306,8 @@ test_usrp_rx::handle_response_recv_raw_samples(pmt_t data)
pmt_t status = pmt_nth(1, data);
pmt_t v_samples = pmt_nth(2, data);
pmt_t timestamp = pmt_nth(3, data);
- pmt_t properties = pmt_nth(4, data);
+ pmt_t channel = pmt_nth(4, data);
+ pmt_t properties = pmt_nth(5, data);
d_samples_recvd += pmt_length(v_samples) / 4;
diff --git a/usrp/host/apps-inband/test_usrp_inband_registers.cc b/usrp/host/apps-inband/test_usrp_inband_registers.cc
index 017ccdbf5..a1d9cc141 100644
--- a/usrp/host/apps-inband/test_usrp_inband_registers.cc
+++ b/usrp/host/apps-inband/test_usrp_inband_registers.cc
@@ -118,7 +118,7 @@ test_usrp_inband_registers::test_usrp_inband_registers(mb_runtime *runtime, cons
// Specify the RBF to use
pmt_dict_set(usrp_dict,
pmt_intern("rbf"),
- pmt_intern("boe2.rbf"));
+ pmt_intern("inband_1rxhb_1tx.rbf"));
// Set TX and RX interpolations
pmt_dict_set(usrp_dict,
diff --git a/usrp/host/apps-inband/test_usrp_inband_rx.cc b/usrp/host/apps-inband/test_usrp_inband_rx.cc
index 0429951f3..cff2aa723 100644
--- a/usrp/host/apps-inband/test_usrp_inband_rx.cc
+++ b/usrp/host/apps-inband/test_usrp_inband_rx.cc
@@ -87,23 +87,30 @@ class test_usrp_rx : public mb_mblock
test_usrp_rx::test_usrp_rx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
: mb_mblock(runtime, instance_name, user_arg),
d_samples_recvd(0),
- d_samples_to_recv(5e6)
+ d_samples_to_recv(20e6)
{
-
d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
// Pass a dictionary to usrp_server which specifies which interface to use, the stub or USRP
pmt_t usrp_dict = pmt_make_dict();
+
+ // To test the application without a USRP
+ bool fake_usrp_p = false;
+ if(fake_usrp_p) {
+ pmt_dict_set(usrp_dict,
+ pmt_intern("fake-usrp"),
+ PMT_T);
+ }
// Specify the RBF to use
pmt_dict_set(usrp_dict,
pmt_intern("rbf"),
- pmt_intern("nanocell9.rbf"));
+ pmt_intern("inband_1rxhb_1tx.rbf"));
pmt_dict_set(usrp_dict,
pmt_intern("decim-rx"),
- pmt_from_long(128));
+ pmt_from_long(64));
define_component("server", "usrp_server", usrp_dict);
@@ -264,6 +271,7 @@ test_usrp_rx::open_usrp()
void
test_usrp_rx::close_usrp()
{
+
d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
d_state = CLOSING_USRP;
@@ -302,7 +310,8 @@ test_usrp_rx::handle_response_recv_raw_samples(pmt_t data)
pmt_t status = pmt_nth(1, data);
pmt_t v_samples = pmt_nth(2, data);
pmt_t timestamp = pmt_nth(3, data);
- pmt_t properties = pmt_nth(4, data);
+ pmt_t channel = pmt_nth(4, data);
+ pmt_t properties = pmt_nth(5, data);
d_samples_recvd += pmt_length(v_samples) / 4;
@@ -325,9 +334,7 @@ void
test_usrp_rx::enter_closing_channel()
{
d_state = CLOSING_CHANNEL;
-
- sleep(2);
-
+
d_rx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_rx_chan));
if(verbose)
@@ -342,10 +349,9 @@ REGISTER_MBLOCK_CLASS(test_usrp_rx);
int
main (int argc, char **argv)
{
- // handle any command line args here
-
mb_runtime_sptr rt = mb_make_runtime();
pmt_t result = PMT_NIL;
rt->run("top", "test_usrp_rx", PMT_F, &result);
+
}
diff --git a/usrp/host/apps-inband/test_usrp_inband_timestamps.cc b/usrp/host/apps-inband/test_usrp_inband_timestamps.cc
index 8824a72fe..297c7126a 100644
--- a/usrp/host/apps-inband/test_usrp_inband_timestamps.cc
+++ b/usrp/host/apps-inband/test_usrp_inband_timestamps.cc
@@ -147,7 +147,7 @@ test_usrp_inband_timestamps::test_usrp_inband_timestamps(mb_runtime *runtime, co
// Specify the RBF to use
pmt_dict_set(usrp_dict,
pmt_intern("rbf"),
- pmt_intern("tmac5.rbf"));
+ pmt_intern("inband_1rxhb_1tx.rbf"));
define_component("server", "usrp_server", usrp_dict);
diff --git a/usrp/host/apps-inband/test_usrp_inband_tx.cc b/usrp/host/apps-inband/test_usrp_inband_tx.cc
index 7118d2d0f..7f894a4c3 100644
--- a/usrp/host/apps-inband/test_usrp_inband_tx.cc
+++ b/usrp/host/apps-inband/test_usrp_inband_tx.cc
@@ -42,7 +42,7 @@
#include <symbols_usrp_low_level_cs.h>
#include <symbols_usrp_tx.h>
-static bool verbose = false;
+static bool verbose = true;
class test_usrp_tx : public mb_mblock
{
@@ -89,11 +89,9 @@ class test_usrp_tx : public mb_mblock
test_usrp_tx::test_usrp_tx(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
: mb_mblock(runtime, instance_name, user_arg),
- d_state(INIT), d_nsamples_to_send((long) 40e6),
+ d_state(INIT), d_nsamples_to_send((long) 80e6),
d_nsamples_xmitted(0),
d_nframes_xmitted(0),
- //d_samples_per_frame((long)(126)),
- //d_samples_per_frame((long)(126 * 3.5)), // non-full packet
d_samples_per_frame((long)(126 * 4)), // full packet
d_done_sending(false),
d_amplitude(16384)
@@ -119,18 +117,14 @@ test_usrp_tx::test_usrp_tx(mb_runtime *runtime, const std::string &instance_name
// Specify the RBF to use
pmt_dict_set(usrp_dict,
pmt_intern("rbf"),
- pmt_intern("cs1.rbf"));
+ pmt_intern("inband_1rxhb_1tx.rbf"));
// Set TX and RX interpolations
pmt_dict_set(usrp_dict,
pmt_intern("interp-tx"),
- pmt_from_long(128));
+ pmt_from_long(64));
pmt_dict_set(usrp_dict,
- pmt_intern("decim-rx"),
- pmt_from_long(16));
-
- pmt_dict_set(usrp_dict,
pmt_intern("rf-freq"),
pmt_from_long(10e6));
@@ -176,12 +170,12 @@ test_usrp_tx::handle_message(mb_message_sptr msg)
if (pmt_eq(event, s_response_open)){
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
- allocate_channel();
- return;
+ allocate_channel();
+ return;
}
else {
- error_msg = "failed to open usrp:";
- goto bail;
+ error_msg = "failed to open usrp:";
+ goto bail;
}
}
goto unhandled;
@@ -192,12 +186,12 @@ test_usrp_tx::handle_message(mb_message_sptr msg)
d_tx_chan = pmt_nth(2, data);
if (pmt_eq(status, PMT_T)){
- enter_transmitting();
- return;
+ enter_transmitting();
+ return;
}
else {
- error_msg = "failed to allocate channel:";
- goto bail;
+ error_msg = "failed to allocate channel:";
+ goto bail;
}
}
goto unhandled;
@@ -208,12 +202,12 @@ test_usrp_tx::handle_message(mb_message_sptr msg)
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
- handle_xmit_response(handle);
- return;
+ handle_xmit_response(handle);
+ return;
}
else {
- error_msg = "bad response-xmit-raw-frame:";
- goto bail;
+ error_msg = "bad response-xmit-raw-frame:";
+ goto bail;
}
}
goto unhandled;
@@ -223,12 +217,12 @@ test_usrp_tx::handle_message(mb_message_sptr msg)
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
- close_usrp();
- return;
+ close_usrp();
+ return;
}
else {
- error_msg = "failed to deallocate channel:";
- goto bail;
+ error_msg = "failed to deallocate channel:";
+ goto bail;
}
}
goto unhandled;
@@ -238,12 +232,12 @@ test_usrp_tx::handle_message(mb_message_sptr msg)
status = pmt_nth(1, data);
if (pmt_eq(status, PMT_T)){
- shutdown_all(PMT_T);
- return;
+ shutdown_all(PMT_T);
+ return;
}
else {
- error_msg = "failed to close USRP:";
- goto bail;
+ error_msg = "failed to close USRP:";
+ goto bail;
}
}
goto unhandled;
@@ -272,6 +266,9 @@ test_usrp_tx::open_usrp()
d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, which_usrp));
d_state = OPENING_USRP;
+
+ if(verbose)
+ std::cout << "[TEST_USRP_INBAND_TX] Opening the USRP\n";
}
void
@@ -279,6 +276,9 @@ test_usrp_tx::close_usrp()
{
d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
d_state = CLOSING_USRP;
+
+ if(verbose)
+ std::cout << "[TEST_USRP_INBAND_TX] Closing the USRP\n";
}
void
@@ -287,6 +287,9 @@ test_usrp_tx::allocate_channel()
long capacity = (long) 16e6;
d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(capacity)));
d_state = ALLOCATING_CHANNEL;
+
+ if(verbose)
+ std::cout << "[TEST_USRP_INBAND_TX] Requesting TX channel allocation\n";
}
void
@@ -295,15 +298,9 @@ test_usrp_tx::enter_transmitting()
d_state = TRANSMITTING;
d_nsamples_xmitted = 0;
- // FIXME: carrier sense hack
- d_tx->send(s_cmd_to_control_channel, // C/S packet
- pmt_list2(PMT_NIL, // invoc handle
- pmt_list1(
- pmt_list2(s_op_write_reg,
- pmt_list2(
- pmt_from_long(1),
- pmt_from_long(21))))));
-
+ if(verbose)
+ std::cout << "[TEST_USRP_INBAND_TX] Transmitting...\n";
+
build_and_send_next_frame(); // fire off 4 to start pipeline
build_and_send_next_frame();
build_and_send_next_frame();
@@ -356,9 +353,6 @@ test_usrp_tx::build_and_send_next_frame()
}
pmt_t tx_properties = pmt_make_dict();
- pmt_dict_set(tx_properties,
- pmt_intern("carrier-sense"),
- PMT_T);
pmt_t timestamp = pmt_from_long(0xffffffff); // NOW
d_tx->send(s_cmd_xmit_raw_frame,
@@ -371,7 +365,7 @@ test_usrp_tx::build_and_send_next_frame()
d_nsamples_xmitted += nsamples_this_frame;
d_nframes_xmitted++;
- if(verbose)
+ if(verbose && 0)
std::cout << "[TEST_USRP_INBAND_TX] Transmitted frame\n";
}
@@ -394,6 +388,9 @@ test_usrp_tx::enter_closing_channel()
d_state = CLOSING_CHANNEL;
d_tx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_tx_chan));
+
+ if(verbose)
+ std::cout << "[TEST_USRP_INBAND_tX] Deallocating TX channel\n";
}
REGISTER_MBLOCK_CLASS(test_usrp_tx);
diff --git a/usrp/host/apps-inband/test_usrp_inband_underrun.cc b/usrp/host/apps-inband/test_usrp_inband_underrun.cc
index 0404208b4..c9630cec2 100644
--- a/usrp/host/apps-inband/test_usrp_inband_underrun.cc
+++ b/usrp/host/apps-inband/test_usrp_inband_underrun.cc
@@ -127,7 +127,7 @@ test_usrp_inband_underrun::test_usrp_inband_underrun(mb_runtime *runtime, const
d_rx_chan(PMT_NIL),
d_which_usrp(pmt_from_long(0)),
d_state(INIT),
- d_nsamples_to_send((long) 20e6),
+ d_nsamples_to_send((long) 27e6),
d_nsamples_xmitted(0),
d_nframes_xmitted(0),
d_samples_per_frame(d_nsamples_to_send), // full packet
@@ -143,12 +143,12 @@ test_usrp_inband_underrun::test_usrp_inband_underrun(mb_runtime *runtime, const
// Specify the RBF to use
pmt_dict_set(usrp_dict,
pmt_intern("rbf"),
- pmt_intern("nanocell9.rbf"));
+ pmt_intern("inband_1rxhb_1tx.rbf"));
// Set TX and RX interpolations
pmt_dict_set(usrp_dict,
pmt_intern("interp-tx"),
- pmt_from_long(8));
+ pmt_from_long(64));
pmt_dict_set(usrp_dict,
pmt_intern("decim-rx"),
@@ -668,8 +668,6 @@ test_usrp_inband_underrun::closing_usrp()
{
d_state = CLOSING_USRP;
- sleep(2);
-
d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
}
diff --git a/usrp/host/lib/inband/Makefile.am b/usrp/host/lib/inband/Makefile.am
index 77d1f6699..a41ac18b8 100644
--- a/usrp/host/lib/inband/Makefile.am
+++ b/usrp/host/lib/inband/Makefile.am
@@ -76,7 +76,6 @@ include_HEADERS = \
usrp_usb_interface.h
noinst_HEADERS = \
- fake_usrp.h \
qa_inband.h \
qa_inband_packet_prims.h \
qa_inband_usrp_server.h \
@@ -109,14 +108,10 @@ libusrp_inband_qa_la_LIBADD = \
# ------------------------------------------------------------------------
noinst_PROGRAMS = \
- test_inband \
- test_usrp_inband
+ test_inband
test_inband_SOURCES = test_inband.cc
test_inband_LDADD = libusrp_inband-qa.la
-test_usrp_inband_SOURCES = test_usrp_inband.cc
-test_usrp_inband_LDADD = libusrp_inband-qa.la
-
MOSTLYCLEANFILES = \
$(BUILT_SOURCES) *~ *.pyc
diff --git a/usrp/host/lib/inband/fake_usrp.cc b/usrp/host/lib/inband/fake_usrp.cc
deleted file mode 100644
index 8a66d5c18..000000000
--- a/usrp/host/lib/inband/fake_usrp.cc
+++ /dev/null
@@ -1,135 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2007 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <fake_usrp.h>
-#include <iostream>
-#include <usrp_inband_usb_packet.h>
-#include <mb_class_registry.h>
-#include <vector>
-
-typedef usrp_inband_usb_packet transport_pkt; // makes conversion to gigabit easy
-
-fake_usrp::fake_usrp()
-{
- std::cout << "[fake_usrp] Initializing...\n";
-}
-
-fake_usrp::~fake_usrp() {}
-
-long
-fake_usrp::write_bus(transport_pkt *pkts, long n_bytes)
-{
- std::cout << "[fake_usrp] Bytes over bus: " << n_bytes << "\n";
-
- // I'm assuming that a control packet cannot exist in a burst of data packets,
- // therefore i read only the first packet's channel in the current burst
- if(pkts[0].chan() == 0x1f) {
- return control_block(pkts, n_bytes);
- } else {
- return data_block(pkts, n_bytes);
- }
-
-}
-
-long
-fake_usrp::data_block(transport_pkt *pkts, long n_bytes)
-{
- std::cout << "[fake_usrp] Entering data block\n";
-
- // Infer the number of packets from the byte count to do logical tests
- long n_pkts = static_cast<long>(std::ceil(n_bytes / (double)transport_pkt::max_pkt_size()));
-
- std::cout << "[fake_usrp] Number of packets: " << n_pkts << "\n";
-
- // The first packet should have the start of burst, and the last packet should have end of burst
- if(pkts[0].start_of_burst() && pkts[n_pkts-1].end_of_burst()) {
- std::cout << "[fake_usrp] Correct burst flags set\n";
- } else {
- std::cout << "[fake_usrp] Incorrect burst flags set!\n";
- return 0;
- }
-
- // All other flags should be set to 0 (e.g., overrun should not be set yet) on ALL packets
- for(int i=0; i < n_pkts; i++) {
- if(pkts[i].overrun()) {
- std::cout << "[fake_usrp] Incorrect set of overrun flag on transmit\n";
- return 0;
- } else if(pkts[i].underrun()) {
- std::cout << "[fake_usrp] Incorrect set of underrun flag on transmit\n";
- return 0;
- } else if(pkts[i].dropped()) {
- std::cout << "[fake_usrp] Incorrect set of drop flag on transmit\n";
- return 0;
- }
- }
- std::cout << "[fake_usrp] Correct overrun, underrun, and drop flags on transmit (initialized to 0)\n";
-
- // The first packet should have a timestamp, other packets should have "NOW"
- if(pkts[0].timestamp() != 0xffffffff) {
- std::cout << "[fake_usrp] Correct timestamp on first packet\n";
- } else {
- std::cout << "[fake_usrp] Initial packet should not have the 0xffffffff timestamp\n";
- return 0;
- }
-
- // Check that all of the other packets include the NOW timestamp
- int check_stamps=1;
- for(int i=1; i < n_pkts; i++) // start at 1 to skip the first packet
- if(pkts[i].timestamp() != 0xffffffff)
- check_stamps=0;
-
- if(check_stamps) {
- std::cout << "[fake_usrp] Correct NOW timestamps (0xffffffff) on intermediate burst packets\n";
- } else {
- std::cout << "[fake_usrp] Incorrect timestamps on intermediate burst packets\n";
- return 0;
- }
-
- // Since we are being transparent about samples, we do not ensure the payload is correct, however
- // it should be the case that if there are >1 packets, all packets except the last packet should
- // have a full payload size
- if(n_pkts > 1) {
- int check_size=1;
- for(int i=0; i < n_pkts-1; i++)
- if(pkts[i].payload_len() != transport_pkt::max_payload())
- check_size=0;
-
- if(check_size) {
- std::cout << "[fake_usrp] Correct payload size sanity check on packets\n";
- } else {
- std::cout << "[fake_usrp] Failed payload size sanity check\n";
- return 0;
- }
- }
-
- return 1;
-}
-
-long
-fake_usrp::control_block(transport_pkt *pkts, long n_bytes)
-{
- std::cout << "[fake_usrp] Entering control block\n";
-
- return 1;
-}
diff --git a/usrp/host/lib/inband/fake_usrp.h b/usrp/host/lib/inband/fake_usrp.h
deleted file mode 100644
index 818c5a506..000000000
--- a/usrp/host/lib/inband/fake_usrp.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2007 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef INCLUDED_FAKE_USRP_H
-#define INCLUDED_FAKE_USRP_H
-
-#include <usrp_inband_usb_packet.h>
-typedef usrp_inband_usb_packet transport_pkt;
-
-/*!
- * \brief Implements a fake USRP for testing without hardware
- */
-class fake_usrp
-{
- public:
- fake_usrp();
- ~fake_usrp();
- long write_bus(transport_pkt *pkts, long n_bytes);
-
- protected:
- long data_block(transport_pkt *pkts, long n_bytes);
- long control_block(transport_pkt *pkts, long n_bytes);
-};
-
-#endif /* INCLUDED_FAKE_USRP_H */
-
diff --git a/usrp/host/lib/inband/qa_inband_usrp_server.cc b/usrp/host/lib/inband/qa_inband_usrp_server.cc
index b01e74e00..e457e8d64 100644
--- a/usrp/host/lib/inband/qa_inband_usrp_server.cc
+++ b/usrp/host/lib/inband/qa_inband_usrp_server.cc
@@ -46,6 +46,8 @@ typedef usrp_inband_usb_packet transport_pkt; // makes conversion to gigabit e
static bool verbose = false;
+static pmt_t s_timeout = pmt_intern("%timeout");
+
// ----------------------------------------------------------------------------------------------
class qa_alloc_top : public mb_mblock
@@ -903,10 +905,10 @@ class qa_rx_top : public mb_mblock
long d_rx_chan;
- long d_got_response_recv;
+ bool d_got_response_recv;
- long d_nmsg_to_recv;
- long d_nmsg_recvd;
+ mb_time d_t0;
+ double d_delta_t;
public:
qa_rx_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
@@ -927,18 +929,19 @@ qa_rx_top::qa_rx_top(mb_runtime *runtime, const std::string &instance_name, pmt_
d_got_response_recv(false)
{
- d_nmsg_to_recv=12;
- d_nmsg_recvd=0;
-
d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
// Use the stub with the usrp_server
- pmt_t usrp_server_dict = pmt_make_dict();
- pmt_dict_set(usrp_server_dict, pmt_intern("fake-usrp"), PMT_T);
+ pmt_t usrp_dict = pmt_make_dict();
+ // Set TX and RX interpolations
+ pmt_dict_set(usrp_dict,
+ pmt_intern("decim-rx"),
+ pmt_from_long(128));
+ pmt_dict_set(usrp_dict, pmt_intern("fake-usrp"), PMT_T);
// Test the TX side
- define_component("server", "usrp_server", usrp_server_dict);
+ define_component("server", "usrp_server", usrp_dict);
connect("self", "rx0", "server", "rx0");
connect("self", "cs", "server", "cs");
}
@@ -967,17 +970,10 @@ qa_rx_top::run_tests()
pmt_list2(PMT_NIL,
pmt_from_long(0)));
- // A small sleep is used to ensure, if working properly, a recv
- // response comes through successfully before the close gets
- // through
- usleep(1000);
-
- d_rx->send(s_cmd_stop_recv_raw_samples,
- pmt_list2(PMT_NIL,
- pmt_from_long(0)));
-
- d_cs->send(s_cmd_close, pmt_list1(pmt_list2(s_response_close,PMT_T)));
-
+ // Schedule a small timeout in which we expect to have received at least one
+ // packet worth of samples from the stub
+ d_t0 = mb_time::time();
+ schedule_one_shot_timeout(d_t0 + 0.01, PMT_NIL);
}
@@ -992,26 +988,37 @@ qa_rx_top::handle_message(mb_message_sptr msg)
pmt_t expected = pmt_nth(0, data);
pmt_t status = pmt_nth(1, data);
+
+ // If we get a timeout we shutdown
+ if(pmt_eq(event, s_timeout)) {
+ if(verbose)
+ std::cout << "[qa_rx_top] Got timeout\n";
+ d_rx->send(s_cmd_stop_recv_raw_samples,
+ pmt_list2(PMT_NIL,
+ pmt_from_long(0)));
+
+ d_cs->send(s_cmd_close, pmt_list1(pmt_list2(s_response_close,PMT_T)));
+ return;
+ }
// For testing RX, an invocation handle is not generated by the stub,
// therefore the same approach for testing is not used. We simply
// expect all responses to be true.
if(pmt_eq(event, s_response_recv_raw_samples)) {
- if(!pmt_eqv(status, PMT_T)) {
- if(verbose)
- std::cout << "Got: " << status << " Expected: " << PMT_T << "\n";
- shutdown_all(PMT_F);
- return;
- }
- else {
+ if(pmt_eqv(status, PMT_T)) {
+
if(verbose)
std::cout << "[qa_rx_top] Received expected response for message "
- << d_nmsg_recvd
<< " (" << event << ")\n";
// All we want is 1 response receive! Can't guarantee exact numbers
d_got_response_recv = true;
}
+ else {
+ if(verbose)
+ std::cout << "Got: " << status << " Expected: " << PMT_T << "\n";
+ shutdown_all(PMT_F);
+ }
return;
}
@@ -1026,8 +1033,7 @@ qa_rx_top::handle_message(mb_message_sptr msg)
} else {
if(verbose)
std::cout << "[qa_rx_top] Received expected response for message "
- << d_nmsg_recvd
- << " (" << event << ")\n";
+ << " (" << event << ")\n";
}
if (pmt_eq(msg->port_id(), d_rx->port_symbol())) {
@@ -1051,12 +1057,7 @@ qa_rx_top::handle_message(mb_message_sptr msg)
std::cout << "[qa_rx_top] No response message before close\n";
return;
}
-
}
-
-
- d_nmsg_recvd++;
-
}
@@ -1079,6 +1080,160 @@ qa_rx_top::check_allocation(mb_message_sptr msg)
REGISTER_MBLOCK_CLASS(qa_rx_top);
+// ----------------------------------------------------------------------------------------------
+
+class qa_rid_top : public mb_mblock
+{
+ mb_port_sptr d_tx;
+ mb_port_sptr d_rx;
+ mb_port_sptr d_cs;
+
+ long d_npongs;
+ long d_tcycles;
+ long d_cycles;
+ long d_max_rid;
+
+ mb_time d_t0;
+ double d_delta_t;
+
+ public:
+ qa_rid_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+ ~qa_rid_top();
+ void initial_transition();
+ void handle_message(mb_message_sptr msg);
+
+ protected:
+ void run_tests();
+ void send_max_pings();
+};
+
+qa_rid_top::qa_rid_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+ : mb_mblock(runtime, instance_name, user_arg)
+{
+ d_npongs = 0;
+ d_tcycles = 3;
+ d_cycles = d_tcycles;
+ d_max_rid = usrp_server::D_MAX_RID;
+ d_delta_t = 0.1;
+
+
+ d_rx = define_port("rx0", "usrp-rx", false, mb_port::INTERNAL);
+ d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
+ d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
+
+ // Use the stub with the usrp_server
+ pmt_t usrp_server_dict = pmt_make_dict();
+ pmt_dict_set(usrp_server_dict, pmt_intern("fake-usrp"),PMT_T);
+
+ // Test the TX side
+ define_component("server", "usrp_server", usrp_server_dict);
+ connect("self", "tx0", "server", "tx0");
+ connect("self", "rx0", "server", "rx0");
+ connect("self", "cs", "server", "cs");
+
+}
+
+qa_rid_top::~qa_rid_top(){}
+
+void
+qa_rid_top::initial_transition()
+{
+ run_tests();
+}
+
+void
+qa_rid_top::run_tests()
+{
+ if(verbose)
+ std::cout << "[qa_rid_top] Starting tests...\n";
+
+ // Retrieve information about the USRP, then run tests
+ d_cs->send(s_cmd_open,
+ pmt_list2(pmt_list2(s_response_open, PMT_T),
+ pmt_from_long(0)));
+
+ // should be able to allocate 1 byte
+ d_tx->send(s_cmd_allocate_channel,
+ pmt_list2(pmt_list2(s_response_allocate_channel, PMT_T),
+ pmt_from_long(1)));
+
+ d_rx->send(s_cmd_allocate_channel,
+ pmt_list2(pmt_list2(s_response_allocate_channel, PMT_T),
+ pmt_from_long(1)));
+
+ // Need to start receiving to read from the USRP to get C/S responses
+ d_rx->send(s_cmd_start_recv_raw_samples,
+ pmt_list2(PMT_NIL,
+ pmt_from_long(0)));
+
+ // Build a subpacket of MAX_RID pings and wait a small amount for all of the
+ // responses and fire off another MAX_RID. If MAX_RID*2 responses are
+ // received, the RID recycling is working correctly.
+ // Schedule a timer in which we expect to have received all of the responses,
+ // which will send off another MAX_RID worth.
+ send_max_pings();
+ d_t0 = mb_time::time();
+ schedule_one_shot_timeout(d_t0 + d_delta_t, PMT_NIL);
+}
+
+void
+qa_rid_top::send_max_pings()
+{
+ pmt_t ping = pmt_list2(s_op_ping_fixed,
+ pmt_list2(pmt_from_long(0),
+ pmt_from_long(0)));
+
+ pmt_t sub_packets = PMT_NIL;
+
+ for(int i=0; i<d_max_rid; i++)
+ sub_packets = pmt_list_add(sub_packets, ping);
+
+ d_tx->send(s_cmd_to_control_channel,
+ pmt_list2(pmt_list2(s_response_from_control_channel, PMT_T),
+ sub_packets));
+}
+
+void
+qa_rid_top::handle_message(mb_message_sptr msg)
+{
+ pmt_t data = msg->data();
+ pmt_t event = msg->signal();
+
+ // If we get a timeout we ensure we got a maximum RID number of responses.
+ if(pmt_eq(event, s_timeout)) {
+ if(verbose)
+ std::cout << "[qa_rid_top] Got timeout, received so far: "
+ << d_npongs << "\n";
+
+ d_cycles--;
+
+ if(d_cycles==0 && d_npongs == d_max_rid*d_tcycles) {
+ shutdown_all(PMT_T);
+ }
+ else if(d_cycles==0) {
+
+ std::cout << "[qa_rid_top] d_npongs: " << d_npongs
+ << " expected: " << d_max_rid*d_tcycles
+ << std::endl;
+
+ shutdown_all(PMT_F);
+ }
+ else {
+ send_max_pings();
+ d_t0 = mb_time::time();
+ schedule_one_shot_timeout(d_t0 + d_delta_t, PMT_NIL);
+ }
+
+ }
+ else if(pmt_eq(event, s_response_from_control_channel))
+ {
+ d_npongs++;
+ }
+
+}
+
+REGISTER_MBLOCK_CLASS(qa_rid_top);
+
// ----------------------------------------------------------------------------------------------
@@ -1398,3 +1553,17 @@ qa_inband_usrp_server::test_cs()
CPPUNIT_ASSERT(pmt_equal(PMT_T, result));
}
+
+void
+qa_inband_usrp_server::test_rid()
+{
+ mb_runtime_sptr rt = mb_make_runtime();
+ pmt_t result = PMT_T;
+
+ // std::cout << "\n\n-----------------\n";
+ // std::cout << " RUNNING RID TESTS \n";
+
+ rt->run("top", "qa_rid_top", PMT_F, &result);
+
+ CPPUNIT_ASSERT(pmt_equal(PMT_T, result));
+}
diff --git a/usrp/host/lib/inband/qa_inband_usrp_server.h b/usrp/host/lib/inband/qa_inband_usrp_server.h
index 5db57c3ed..52a4a0b06 100644
--- a/usrp/host/lib/inband/qa_inband_usrp_server.h
+++ b/usrp/host/lib/inband/qa_inband_usrp_server.h
@@ -34,6 +34,7 @@ class qa_inband_usrp_server : public CppUnit::TestCase {
CPPUNIT_TEST(test_tx);
CPPUNIT_TEST(test_rx);
CPPUNIT_TEST(test_cs);
+ CPPUNIT_TEST(test_rid);
CPPUNIT_TEST_SUITE_END();
private:
@@ -43,6 +44,7 @@ class qa_inband_usrp_server : public CppUnit::TestCase {
void test_tx();
void test_rx();
void test_cs();
+ void test_rid();
};
#endif /* INCLUDED_QA_INBAND_USRP_SERVER_H */
diff --git a/usrp/host/lib/inband/test_usrp_inband.cc b/usrp/host/lib/inband/test_usrp_inband.cc
deleted file mode 100644
index 64fbf3a97..000000000
--- a/usrp/host/lib/inband/test_usrp_inband.cc
+++ /dev/null
@@ -1,298 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2007 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include <iostream>
-#include <usrp_inband_usb_packet.h>
-#include <mb_mblock.h>
-#include <mb_runtime.h>
-#include <mb_protocol_class.h>
-#include <mb_class_registry.h>
-#include <pmt.h>
-#include "usrp_standard.h"
-
-typedef usrp_inband_usb_packet transport_pkt;
-
-// Signal set for the USRP server
-static pmt_t s_cmd_open = pmt_intern("cmd-open");
-static pmt_t s_response_open = pmt_intern("response-open");
-static pmt_t s_cmd_close = pmt_intern("cmd-close");
-static pmt_t s_response_close = pmt_intern("response-close");
-static pmt_t s_cmd_allocate_channel = pmt_intern("cmd-allocate-channel");
-static pmt_t s_response_allocate_channel = pmt_intern("response-allocate-channel");
-static pmt_t s_send_allocate_channel = pmt_intern("send-allocate-channel");
-static pmt_t s_cmd_deallocate_channel = pmt_intern("cmd-deallocate-channel");
-static pmt_t s_response_deallocate_channel = pmt_intern("response-deallocate-channel");
-static pmt_t s_send_deallocate_channel = pmt_intern("send-deallocate-channel");
-static pmt_t s_cmd_max_capacity = pmt_intern("cmd-max-capacity");
-static pmt_t s_response_max_capacity = pmt_intern("response-max-capacity");
-static pmt_t s_cmd_ntx_chan = pmt_intern("cmd-ntx-chan");
-static pmt_t s_cmd_nrx_chan = pmt_intern("cmd-nrx-chan");
-static pmt_t s_response_ntx_chan = pmt_intern("response-ntx-chan");
-static pmt_t s_response_nrx_chan = pmt_intern("response-nrx-chan");
-static pmt_t s_cmd_current_capacity_allocation = pmt_intern("cmd-current-capacity-allocation");
-static pmt_t s_response_current_capacity_allocation = pmt_intern("response-current-capacity-allocation");
-static pmt_t s_cmd_xmit_raw_frame = pmt_intern("cmd-xmit-raw-frame");
-static pmt_t s_response_xmit_raw_frame = pmt_intern("response-xmit-raw-frame");
-
-bool loopback_p = false;
-bool counting_p = false;
-bool fake_usrp_p = false;
-char *prog_name;
-
-static void
-set_progname (char *path)
-{
- char *p = strrchr (path, '/');
- if (p != 0)
- prog_name = p+1;
- else
- prog_name = path;
-}
-
-static void
-usage()
-{
- fprintf (stderr, "usage: %s [-l]\n", prog_name);
- fprintf (stderr, " [-l] digital loopback in FPGA\n");
- fprintf (stderr, " [-c] counting in FPGA\n");
- fprintf (stderr, " [-f] fake usrp\n");
-
- exit(1);
-}
-
-int
-main(int argc, char **argv)
-{
- int ch;
-
- set_progname(argv[0]);
-
- mb_runtime_sptr rt = mb_make_runtime();
- pmt_t result = PMT_T;
-
- while ((ch = getopt(argc, argv, "flc")) != EOF) {
- switch(ch) {
-
- case 'l':
- loopback_p = true;
- break;
-
- case 'c':
- counting_p = true;
- break;
-
- case 'f':
- fake_usrp_p = true;
- break;
-
- default:
- usage();
- }
- }
-
-
- std::cout << "[test_usrp_inband] Starting...\n";
-
- rt->run("top", "test_usrp_inband_top", PMT_F, &result);
-}
-
-class test_usrp_inband_top : public mb_mblock
-{
- mb_port_sptr d_tx;
- mb_port_sptr d_cs;
-
- long d_tx_chan;
-
- public:
- test_usrp_inband_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
- ~test_usrp_inband_top();
- void initial_transition();
- void handle_message(mb_message_sptr msg);
-
- protected:
- void open_usrp();
- void close_usrp();
- void check_message(mb_message_sptr msg);
- void allocate_channel();
- void send_packets();
-};
-
-test_usrp_inband_top::test_usrp_inband_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
- : mb_mblock(runtime, instance_name, user_arg)
-{
- std::cout << "[TEST_USRP_INBAND_TOP] Initializing...\n";
-
- d_tx = define_port("tx0", "usrp-tx", false, mb_port::INTERNAL);
- d_cs = define_port("cs", "usrp-server-cs", false, mb_port::INTERNAL);
-
- // Test the TX side
-
- // Pass a dictionary to usrp_server which specifies which interface to use, the stub or USRP
- pmt_t usrp_server_dict = pmt_make_dict();
-
- if(fake_usrp_p)
- pmt_dict_set(usrp_server_dict, pmt_intern("usrp-interface"), pmt_intern("usrp_usb_interface_stub"));
-
- define_component("server", "usrp_server", usrp_server_dict);
- connect("self", "tx0", "server", "tx0");
- connect("self", "cs", "server", "cs");
-}
-
-test_usrp_inband_top::~test_usrp_inband_top()
-{
-}
-
-void
-test_usrp_inband_top::initial_transition()
-{
- open_usrp();
-}
-
-void
-test_usrp_inband_top::handle_message(mb_message_sptr msg)
-{
- pmt_t event = msg->signal(); // the "name" of the message
- pmt_t port_id = msg->port_id(); // which port it came in on
- pmt_t data = msg->data();
- pmt_t metadata = msg->metadata();
- pmt_t status;
-
- if (pmt_eq(port_id, d_cs->port_symbol())) { // message came in on our control/status port
-
- //---------- OPEN RESPONSE ----------//
- if (pmt_eq(event, s_response_open)) {
- status = pmt_nth(1, data);
-
- if(pmt_eq(status, PMT_T)) {
- std::cout << "[TEST_USRP_INBAND_TOP] Success opening USRP\n";
- }
- else {
- std::cout << "[TEST_USRP_INBAND_TOP] Received error message opening USRP\n";
- shutdown_all(PMT_F);
- }
-
- allocate_channel();
-
- return;
- }
- //--------- CLOSE RESPONSE -----------//
- else if (pmt_eq(event, s_response_close)) {
- status = pmt_nth(1, data);
-
- if(pmt_eq(status, PMT_T)) {
- std::cout << "[TEST_USRP_INBAND_TOP] Successfully closed USRP\n";
- }
- else {
- std::cout << "[TEST_USRP_INBAND_TOP] Received error message closing USRP\n";
- shutdown_all(PMT_F);
- }
-
- shutdown_all(PMT_T);
-
- return;
- }
- }
-
- if (pmt_eq(port_id, d_tx->port_symbol())) {
-
- //---------- ALLOCATE RESPONSE ---------//
- if(pmt_eq(event, s_response_allocate_channel)) {
- status = pmt_nth(1, data);
- pmt_t channel = pmt_nth(2, data);
-
- if(pmt_eq(status, PMT_T)) {
- d_tx_chan = pmt_to_long(channel);
- std::cout << "[TEST_USRP_INBAND_TOP] Received allocation on channel " << d_tx_chan << "\n";
- }
- else {
- std::cout << "[TEST_USRP_INBAND_TOP] Error allocating channel\n";
- shutdown_all(PMT_F);
- }
-
- send_packets();
-
- return;
- }
- //----------- XMIT RESPONSE ------------//
- else if(pmt_eq(event, s_response_xmit_raw_frame)) {
- status = pmt_nth(1, data);
-
- if(pmt_eq(status, PMT_T)) {
- std::cout << "[TEST_USRP_INBAND_TOP] Transmission successful\n";
- }
- else {
- std::cout << "[TEST_USRP_INBAND_TOP] Failed transmission\n";
- shutdown_all(PMT_F);
- }
-
- close_usrp();
-
- return;
- }
- }
-
- std::cout << "[TEST_USRP_INBAND_TOP] Received unhandled message: " << event << "\n";
-}
-
-void
-test_usrp_inband_top::allocate_channel()
-{
- std::cout << "[TEST_USRP_INBAND_TOP] Requesting channel allocation...\n";
-
- d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1)));
-}
-
-void
-test_usrp_inband_top::send_packets()
-{
- std::cout << "[TEST_USRP_INBAND_TOP] Sending single packet..\n";
- d_tx->send(s_cmd_xmit_raw_frame, pmt_list4(pmt_from_long(1), pmt_from_long(d_tx_chan), pmt_make_u32vector(transport_pkt::max_payload()/4, 0), pmt_from_long(0)));
-
-}
-
-void
-test_usrp_inband_top::open_usrp()
-{
- pmt_t usrp = pmt_from_long(0);
-
- long rx_mode = 0;
-
- if(loopback_p)
- rx_mode |= usrp_standard_rx::FPGA_MODE_LOOPBACK;
- if(counting_p)
- rx_mode |= usrp_standard_rx::FPGA_MODE_COUNTING;
-
- d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, usrp));
-}
-
-void
-test_usrp_inband_top::close_usrp()
-{
- d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
-}
-
-REGISTER_MBLOCK_CLASS(test_usrp_inband_top);
diff --git a/usrp/host/lib/inband/usrp_inband_usb_packet.cc b/usrp/host/lib/inband/usrp_inband_usb_packet.cc
index ee4cb22f3..2f02ecc3f 100644
--- a/usrp/host/lib/inband/usrp_inband_usb_packet.cc
+++ b/usrp/host/lib/inband/usrp_inband_usb_packet.cc
@@ -30,6 +30,14 @@
#include <stdio.h>
#include <string.h>
+/*!
+ * \brief Aligns the packet payload on a 32 bit boundary. This is essential to
+ * all control/status packets so that the inband FPGA code can parse them
+ * easily.
+ *
+ * \returns true if successful or if the packet was already aligned; false if it
+ * cannot be aligned.
+ */
bool usrp_inband_usb_packet::align32()
{
int p_len = payload_len();
@@ -44,18 +52,20 @@ bool usrp_inband_usb_packet::align32()
if((MAX_PAYLOAD - p_len) < bytes_needed)
return false;
- p_len += bytes_needed;
-
- int h_flags = flags();
- int h_chan = chan();
- int h_tag = tag();
- int h_payload_len = p_len;
-
- set_header(h_flags, h_chan, h_tag, h_payload_len);
+ incr_header_len(bytes_needed);
return true;
}
+/*!
+ * \brief Adds a ping command to the current control packet.
+ *
+ * The \p rid is the rid to be associated with the ping response and \p ping_val
+ * is currently unused.
+ *
+ * \returns true if adding the ping command was successful, false otherwise
+ * (i.e. no space in the current packet).
+ */
bool usrp_inband_usb_packet::cs_ping(long rid, long ping_val)
{
if(!align32())
@@ -78,17 +88,20 @@ bool usrp_inband_usb_packet::cs_ping(long rid, long ping_val)
*payload = host_to_usrp_u32(ping);
// Update payload length
- int h_flags = flags();
- int h_chan = chan();
- int h_tag = tag();
- int h_payload_len = payload_len() + CS_FIXED_LEN + CS_PING_LEN;
-
- set_header(h_flags, h_chan, h_tag, h_payload_len);
+ incr_header_len(CS_FIXED_LEN + CS_PING_LEN);
return true;
}
-
+/*!
+ * \brief Adds a ping response to the packet. This is used by the fake USRP
+ * code to generate fake responses for pings.
+ *
+ * The \p rid is the RID to be associated with the response and \p ping_val is
+ * currently unused.
+ *
+ * \returns true if the ping reply was added successfully, false otherwise.
+ */
bool usrp_inband_usb_packet::cs_ping_reply(long rid, long ping_val)
{
if(!align32())
@@ -111,16 +124,20 @@ bool usrp_inband_usb_packet::cs_ping_reply(long rid, long ping_val)
*payload = host_to_usrp_u32(ping);
// Update payload length
- int h_flags = flags();
- int h_chan = chan();
- int h_tag = tag();
- int h_payload_len = payload_len() + CS_FIXED_LEN + CS_PING_LEN;
-
- set_header(h_flags, h_chan, h_tag, h_payload_len);
+ incr_header_len(CS_FIXED_LEN + CS_PING_LEN);
return true;
}
+/*!
+ * \brief Adds a write register command to the packet.
+ *
+ * The \p reg_num is the register number for which the value \p val will be
+ * written to.
+ *
+ * \returns true if the command was added to the packet successfully, false
+ * otherwise.
+ */
bool usrp_inband_usb_packet::cs_write_reg(long reg_num, long val)
{
if(!align32())
@@ -149,16 +166,19 @@ bool usrp_inband_usb_packet::cs_write_reg(long reg_num, long val)
*payload = host_to_usrp_u32((uint32_t) val);
// Rebuild the header to update the payload length
- int h_flags = flags();
- int h_chan = chan();
- int h_tag = tag();
- int h_payload_len = payload_len() + CS_FIXED_LEN + CS_WRITEREG_LEN;
-
- set_header(h_flags, h_chan, h_tag, h_payload_len);
+ incr_header_len(CS_FIXED_LEN + CS_WRITEREG_LEN);
return true;
}
+/*!
+ * \brief Adds a write register masked command to the packet.
+ *
+ * The \p reg_num is the register number for which the value \p val will be
+ * written, masked by \p mask
+ *
+ * \returns true if the command was added to the packet, false otherwise.
+ */
bool usrp_inband_usb_packet::cs_write_reg_masked(long reg_num, long val, long mask)
{
if(!align32())
@@ -190,16 +210,19 @@ bool usrp_inband_usb_packet::cs_write_reg_masked(long reg_num, long val, long ma
*payload = host_to_usrp_u32((uint32_t) mask);
// Rebuild the header to update the payload length
- int h_flags = flags();
- int h_chan = chan();
- int h_tag = tag();
- int h_payload_len = payload_len() + CS_FIXED_LEN + CS_WRITEREGMASKED_LEN;
-
- set_header(h_flags, h_chan, h_tag, h_payload_len);
+ incr_header_len(CS_FIXED_LEN + CS_WRITEREGMASKED_LEN);
return true;
}
+/*!
+ * \brief Adds a read register message to the packet.
+ *
+ * The \p rid will be the associated RID returned with the response, and \p
+ * reg_num is the register to be read.
+ *
+ * \returns true if the command was added to the packet, false otherwise.
+ */
bool usrp_inband_usb_packet::cs_read_reg(long rid, long reg_num)
{
if(!align32())
@@ -222,16 +245,22 @@ bool usrp_inband_usb_packet::cs_read_reg(long rid, long reg_num)
*payload = host_to_usrp_u32(read_reg);
// Update payload length
- int h_flags = flags();
- int h_chan = chan();
- int h_tag = tag();
- int h_payload_len = payload_len() + CS_FIXED_LEN + CS_READREG_LEN;
-
- set_header(h_flags, h_chan, h_tag, h_payload_len);
+ incr_header_len(CS_FIXED_LEN + CS_READREG_LEN);
return true;
}
+/*!
+ * \brief Adds a read register reply response to the current packet. This is
+ * used by the fake USRP code to generate fake register read responses for
+ * testing.
+ *
+ * The \p rid is the associated RID to be included in the response, \p reg_num
+ * is the register the read is coming from, and \p reg_val is the value of the
+ * read.
+ *
+ * \returns true if the command was added to the packet, false otherwise.
+ */
bool usrp_inband_usb_packet::cs_read_reg_reply(long rid, long reg_num, long reg_val)
{
if(!align32())
@@ -258,16 +287,19 @@ bool usrp_inband_usb_packet::cs_read_reg_reply(long rid, long reg_num, long reg_
*payload = host_to_usrp_u32((uint32_t) reg_val);
// Update payload length
- int h_flags = flags();
- int h_chan = chan();
- int h_tag = tag();
- int h_payload_len = payload_len() + CS_FIXED_LEN + CS_READREGREPLY_LEN;
-
- set_header(h_flags, h_chan, h_tag, h_payload_len);
+ incr_header_len(CS_FIXED_LEN + CS_READREGREPLY_LEN);
return true;
}
+/*!
+ * \brief Adds a delay command to the current packet.
+ *
+ * The \p ticks parameter is the number of clock ticks the FPGA should delay
+ * parsing for, which is added to the packet.
+ *
+ * \returns true if the command was added to the packet, false otherwise.
+ */
bool usrp_inband_usb_packet::cs_delay(long ticks)
{
if(!align32())
@@ -289,16 +321,16 @@ bool usrp_inband_usb_packet::cs_delay(long ticks)
*payload = host_to_usrp_u32(delay);
// Update payload length
- int h_flags = flags();
- int h_chan = chan();
- int h_tag = tag();
- int h_payload_len = payload_len() + CS_FIXED_LEN + CS_DELAY_LEN;
-
- set_header(h_flags, h_chan, h_tag, h_payload_len);
+ incr_header_len(CS_FIXED_LEN + CS_DELAY_LEN);
return true;
}
+/*!
+ * \brief
+ *
+ * \returns true if the command was added to the packet, false otherwise.
+ */
bool usrp_inband_usb_packet::cs_i2c_write(long i2c_addr, uint8_t *i2c_data, size_t data_len)
{
if(!align32())
@@ -328,16 +360,20 @@ bool usrp_inband_usb_packet::cs_i2c_write(long i2c_addr, uint8_t *i2c_data, size
memcpy(payload, i2c_data, data_len);
// Update payload length
- int h_flags = flags();
- int h_chan = chan();
- int h_tag = tag();
- int h_payload_len = payload_len() + CS_FIXED_LEN + i2c_len;
-
- set_header(h_flags, h_chan, h_tag, h_payload_len);
+ incr_header_len(CS_FIXED_LEN + i2c_len);
return true;
}
+/*!
+ * \brief Adds an I2C read command to the current packet.
+ *
+ * The \p rid is the associated RID to return with the read response, \p
+ * i2c_addr is the address to read from on the I2C bus, and \p n_bytes is the
+ * number of bytes to be read from the bus.
+ *
+ * \returns true if the command was added to the packet, false otherwise.
+ */
bool usrp_inband_usb_packet::cs_i2c_read(long rid, long i2c_addr, long n_bytes)
{
if(!align32())
@@ -367,16 +403,20 @@ bool usrp_inband_usb_packet::cs_i2c_read(long rid, long i2c_addr, long n_bytes)
*payload = host_to_usrp_u32(word1);
// Update payload length
- int h_flags = flags();
- int h_chan = chan();
- int h_tag = tag();
- int h_payload_len = payload_len() + CS_FIXED_LEN + CS_I2CREAD_LEN;
-
- set_header(h_flags, h_chan, h_tag, h_payload_len);
+ incr_header_len(CS_FIXED_LEN + CS_I2CREAD_LEN);
return true;
}
+/*!
+ * \brief Adds an I2C read reply response to the current packet. This is used
+ * by the fake USRP code to generate fake I2C responses.
+ *
+ * The \p rid is the RID to be associated with the response, \p i2c_addr is the
+ * address on the I2C bus that the \p i2c_data of \p i2c_data_len was read from.
+ *
+ * \returns true if the command was added to the packet, false otherwise.
+ */
bool usrp_inband_usb_packet::cs_i2c_read_reply(long rid, long i2c_addr, uint8_t *i2c_data, long i2c_data_len)
{
if(!align32())
@@ -406,16 +446,16 @@ bool usrp_inband_usb_packet::cs_i2c_read_reply(long rid, long i2c_addr, uint8_t
memcpy(payload, i2c_data, i2c_data_len);
// Update payload length
- int h_flags = flags();
- int h_chan = chan();
- int h_tag = tag();
- int h_payload_len = payload_len() + CS_FIXED_LEN + i2c_len;
-
- set_header(h_flags, h_chan, h_tag, h_payload_len);
+ incr_header_len(CS_FIXED_LEN + i2c_len);
return true;
}
+/*!
+ * \brief Adds a SPI write command to the current packet.
+ *
+ * \returns true if the command was added to the packet, false otherwise.
+ */
bool usrp_inband_usb_packet::cs_spi_write(long enables, long format, long opt_header_bytes, uint8_t *spi_data, long spi_data_len)
{
if(!align32())
@@ -454,16 +494,16 @@ bool usrp_inband_usb_packet::cs_spi_write(long enables, long format, long opt_he
memcpy(payload, spi_data, spi_data_len);
// Update payload length
- int h_flags = flags();
- int h_chan = chan();
- int h_tag = tag();
- int h_payload_len = payload_len() + CS_FIXED_LEN + spi_len;
-
- set_header(h_flags, h_chan, h_tag, h_payload_len);
+ incr_header_len(CS_FIXED_LEN + spi_len);
return true;
}
+/*!
+ * \brief Adds a SPI bus read command to the packet.
+ *
+ * \returns true if the command was added to the packet, false otherwise.
+ */
bool usrp_inband_usb_packet::cs_spi_read(long rid, long enables, long format, long opt_header_bytes, long n_bytes)
{
if(!align32())
@@ -508,16 +548,17 @@ bool usrp_inband_usb_packet::cs_spi_read(long rid, long enables, long format, lo
*payload = host_to_usrp_u32(word);
// Update payload length
- int h_flags = flags();
- int h_chan = chan();
- int h_tag = tag();
- int h_payload_len = payload_len() + CS_FIXED_LEN + CS_SPIREAD_LEN;
+ incr_header_len(CS_FIXED_LEN + CS_SPIREAD_LEN);
- set_header(h_flags, h_chan, h_tag, h_payload_len);
-
return true;
}
+/*!
+ * \brief Adds an SPI read reply to the current packet. This is used by the
+ * fake USRP code to generate fake responses for SPI reads.
+ *
+ * \returns true if the command was added to the packet, false otherwise.
+ */
bool usrp_inband_usb_packet::cs_spi_read_reply(long rid, uint8_t *spi_data, long spi_data_len)
{
if(!align32())
@@ -546,30 +587,32 @@ bool usrp_inband_usb_packet::cs_spi_read_reply(long rid, uint8_t *spi_data, long
memcpy(payload, spi_data, spi_data_len);
// Update payload length
- int h_flags = flags();
- int h_chan = chan();
- int h_tag = tag();
- int h_payload_len = payload_len() + CS_FIXED_LEN + spi_len;
-
- set_header(h_flags, h_chan, h_tag, h_payload_len);
+ incr_header_len(CS_FIXED_LEN + spi_len);
return true;
}
-// Takes an offset to the beginning of a subpacket and extracts the
-// length of the subpacket
+/*!
+ * \brief Since all control packets contain subpackets which have the length of
+ * the subpacket at a uniform location in the subpacket, this will return the
+ * subpacket length given a byte offset of the start of the subpacket from the beginning of the packet.
+ *
+ * \returns the length of the subpacket
+ */
int usrp_inband_usb_packet::cs_len(int payload_offset) {
uint32_t subpkt = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset)));
return (subpkt >> CS_LEN_SHIFT) & CS_LEN_MASK;
}
-// The following method takes an offset within the packet payload to extract
-// a control/status subpacket and construct a pmt response which includes the
-// proper signal and arguments specified by usrp-low-level-cs. The USRP
-// server could therefore use this to read subpackets and pass them responses
-// back up to the application. It's arguable that only reply packets should
-// be parsed here, however we parse others for use in debugging or failure
-// reporting on the transmit side of packets.
+/*!
+ * \brief The following method takes an offset within the packet payload to
+ * extract a control/status subpacket and constructs a pmt response which
+ * includes the proper signal and arguments specified by usrp-low-level-cs. The
+ * USRP server could therefore use this to read subpackets and pass them
+ * responses back up to the application. It's arguable that only reply packets
+ * should be parsed here, however we parse others for use in debugging or
+ * failure reporting on the transmit side of packets.
+ */
pmt_t usrp_inband_usb_packet::read_subpacket(int payload_offset) {
uint32_t subpkt = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset)));
diff --git a/usrp/host/lib/inband/usrp_inband_usb_packet.h b/usrp/host/lib/inband/usrp_inband_usb_packet.h
index 8c19b1aeb..8f59d1b65 100644
--- a/usrp/host/lib/inband/usrp_inband_usb_packet.h
+++ b/usrp/host/lib/inband/usrp_inband_usb_packet.h
@@ -31,6 +31,7 @@
static const int USB_PKT_SIZE = 512; // bytes
static const int MAX_PAYLOAD = USB_PKT_SIZE-2*sizeof(uint32_t);
+static const int CONTROL_CHAN = 0x1f;
class usrp_inband_usb_packet {
//
@@ -150,6 +151,10 @@ public:
| ((payload_len & PAYLOAD_LEN_MASK) << PAYLOAD_LEN_SHIFT));
d_word0 = host_to_usrp_u32(word0);
}
+
+ void incr_header_len(int val) {
+ set_header(flags(), chan(), tag(), payload_len() + val);
+ }
uint32_t timestamp() const {
return usrp_to_host_u32(d_timestamp);
diff --git a/usrp/host/lib/inband/usrp_rx.cc b/usrp/host/lib/inband/usrp_rx.cc
index caa2d7175..71c042a50 100644
--- a/usrp/host/lib/inband/usrp_rx.cc
+++ b/usrp/host/lib/inband/usrp_rx.cc
@@ -40,25 +40,30 @@ typedef usrp_inband_usb_packet transport_pkt;
static const bool verbose = false;
+bool usrp_rx_stop;
+
usrp_rx::usrp_rx(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg)
: mb_mblock(rt, instance_name, user_arg),
- d_disk_write(false)
+ d_disk_write(false),
+ d_disk_write_pkt(false) // if true, writes full packet, else just the payload
{
d_cs = define_port("cs", "usrp-rx-cs", true, mb_port::EXTERNAL);
- //d_disk_write=true;
-
if(d_disk_write) {
- d_ofile.open("rx_data.dat",std::ios::binary|std::ios::out);
+ d_ofile0.open("rx_data_chan0.dat",std::ios::binary|std::ios::out);
+ d_ofile1.open("rx_data_chan1.dat",std::ios::binary|std::ios::out);
d_cs_ofile.open("rx_cs.dat",std::ios::binary|std::ios::out);
}
+
+ usrp_rx_stop = false;
}
usrp_rx::~usrp_rx()
{
if(d_disk_write) {
- d_ofile.close();
+ d_ofile0.close();
+ d_ofile1.close();
d_cs_ofile.close();
}
}
@@ -69,6 +74,12 @@ usrp_rx::initial_transition()
}
+/*!
+ * \brief Handles incoming signals to to the m-block, wihch should only ever be
+ * a single message: cmd-usrrp-rx-start-reading. There is no signal to stop
+ * reading as the m-block goes in to a forever loop to read inband packets from
+ * the bus.
+ */
void
usrp_rx::handle_message(mb_message_sptr msg)
{
@@ -85,6 +96,17 @@ usrp_rx::handle_message(mb_message_sptr msg)
}
}
+/*!
+ * \brief Performs the actual reading of data from the USB bus, called by
+ * handle_message() when a cmd-usrp-rx-start-reading signal is received.
+ *
+ * The method enters a forever loop where it continues to read data from the bus
+ * and generate read responses to the higher layer. Currently, shared memory is
+ * used to exit this loop.
+ *
+ * The \p data parameter is a PMT list which contains only a single element, an
+ * invocation handle which will be returned with all read respones.
+ */
void
usrp_rx::read_and_respond(pmt_t data)
{
@@ -104,7 +126,7 @@ usrp_rx::read_and_respond(pmt_t data)
std::cout << "[usrp_rx] Waiting for packets..\n";
// Read by 512 which is packet size and send them back up
- while(1) {
+ while(!usrp_rx_stop) {
pmt_t v_pkt = pmt_make_u8vector(pkt_size, 0);
transport_pkt *pkt =
@@ -124,19 +146,38 @@ usrp_rx::read_and_respond(pmt_t data)
d_cs->send(s_response_usrp_rx_read,
pmt_list3(PMT_NIL, PMT_T, v_pkt));
- if(verbose)
+ if(verbose && 0)
std::cout << "[usrp_rx] Read 1 packet\n";
if(d_disk_write) {
- if(pkt->chan() == 0x1f)
+ if(pkt->chan() == CONTROL_CHAN)
d_cs_ofile.write((const char *)pkt, transport_pkt::max_pkt_size());
- else
- d_ofile.write((const char *)pkt, transport_pkt::max_pkt_size());
+ else {
+ if(d_disk_write_pkt) {
+ if(pkt->chan() == 0)
+ d_ofile0.write((const char *)pkt, transport_pkt::max_pkt_size());
+ else if(pkt->chan() == 1)
+ d_ofile1.write((const char *)pkt, transport_pkt::max_pkt_size());
+ } else {
+ if(pkt->chan() == 0)
+ d_ofile0.write((const char *)pkt->payload(), transport_pkt::max_payload());
+ else if(pkt->chan() == 1)
+ d_ofile1.write((const char *)pkt->payload(), transport_pkt::max_payload());
+ }
+ }
d_cs_ofile.flush();
- d_ofile.flush();
+ d_ofile0.flush();
+ d_ofile1.flush();
}
}
+
+ usrp_rx_stop = false;
+
+ if(verbose) {
+ std::cout << "[USRP_RX] Stopping...\n";
+ fflush(stdout);
+ }
}
REGISTER_MBLOCK_CLASS(usrp_rx);
diff --git a/usrp/host/lib/inband/usrp_rx.h b/usrp/host/lib/inband/usrp_rx.h
index e1a90a781..10104bd66 100644
--- a/usrp/host/lib/inband/usrp_rx.h
+++ b/usrp/host/lib/inband/usrp_rx.h
@@ -26,6 +26,8 @@
class usrp_standard_rx;
+extern bool usrp_rx_stop; // used to communicate a 'stop' to the RX stub
+
/*!
* \brief Implements the low level usb interface to the USRP
*/
@@ -35,7 +37,9 @@ class usrp_rx : public mb_mblock
usrp_standard_rx *d_urx;
bool d_disk_write;
- std::ofstream d_ofile;
+ bool d_disk_write_pkt;
+ std::ofstream d_ofile0;
+ std::ofstream d_ofile1;
std::ofstream d_cs_ofile;
public:
diff --git a/usrp/host/lib/inband/usrp_rx_stub.cc b/usrp/host/lib/inband/usrp_rx_stub.cc
index 4bdb106b1..1c96b7a7a 100644
--- a/usrp/host/lib/inband/usrp_rx_stub.cc
+++ b/usrp/host/lib/inband/usrp_rx_stub.cc
@@ -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";
+ }
}
diff --git a/usrp/host/lib/inband/usrp_rx_stub.h b/usrp/host/lib/inband/usrp_rx_stub.h
index 5a75bf00a..9cf308a99 100644
--- a/usrp/host/lib/inband/usrp_rx_stub.h
+++ b/usrp/host/lib/inband/usrp_rx_stub.h
@@ -31,9 +31,12 @@
typedef usrp_inband_usb_packet transport_pkt;
-extern bool usrp_rx_stop; // used to communicate a 'stop' to the RX stub
+extern bool usrp_rx_stop_stub; // used to communicate a 'stop' to the RX stub
extern std::queue<pmt_t> d_cs_queue;
+static pmt_t s_timeout = pmt_intern("%timeout");
+static pmt_t s_done = pmt_intern("done");
+
/*!
* \brief Implements the low level usb interface to the USRP
*/
@@ -45,6 +48,10 @@ class usrp_rx_stub : public mb_mblock
usrp_standard_rx* d_urx;
long d_samples_per_frame;
+ long d_decim_rx;
+
+ mb_time d_t0;
+ double d_delta_t;
// for generating sine wave output
ui_nco<float,float> d_nco;
@@ -61,8 +68,9 @@ class usrp_rx_stub : public mb_mblock
void handle_message(mb_message_sptr msg);
private:
- void read_and_respond(pmt_t data);
+ void read_and_respond();
void read_data();
+ void start_packet_timer();
};
diff --git a/usrp/host/lib/inband/usrp_server.cc b/usrp/host/lib/inband/usrp_server.cc
index 1948a43b2..6a3643e56 100644
--- a/usrp/host/lib/inband/usrp_server.cc
+++ b/usrp/host/lib/inband/usrp_server.cc
@@ -29,6 +29,8 @@
#include <vector>
#include <usrp_usb_interface.h>
#include <string.h>
+#include <fpga_regs_common.h>
+#include <fpga_regs_standard.h>
#include <symbols_usrp_server_cs.h>
#include <symbols_usrp_channel.h>
@@ -53,13 +55,42 @@ str(long x)
usrp_server::usrp_server(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg)
: mb_mblock(rt, instance_name, user_arg),
+ d_fpga_debug(false),
+ d_interp_tx(128), // these should match the lower level defaults (rx also)
+ d_decim_rx(128),
d_fake_rx(false)
{
if(verbose)
std::cout << "[USRP_SERVER] Initializing...\n";
// Dictionary for arguments to all of the components
- pmt_t usrp_dict = user_arg;
+ d_usrp_dict = user_arg;
+
+ if (pmt_is_dict(d_usrp_dict)) {
+
+ if(pmt_t fpga_debug = pmt_dict_ref(d_usrp_dict,
+ pmt_intern("fpga-debug"),
+ PMT_NIL)) {
+ if(pmt_eqv(fpga_debug, PMT_T))
+ d_fpga_debug=true;
+ }
+
+ // Read the TX interpolations
+ if(pmt_t interp_tx = pmt_dict_ref(d_usrp_dict,
+ pmt_intern("interp-tx"),
+ PMT_NIL)) {
+ if(!pmt_eqv(interp_tx, PMT_NIL))
+ d_interp_tx = pmt_to_long(interp_tx);
+ }
+
+ // Read the RX decimation rate
+ if(pmt_t decim_rx = pmt_dict_ref(d_usrp_dict,
+ pmt_intern("decim-rx"),
+ PMT_NIL)) {
+ if(!pmt_eqv(decim_rx, PMT_NIL))
+ d_decim_rx = pmt_to_long(decim_rx);
+ }
+ }
// control & status port
d_cs = define_port("cs", "usrp-server-cs", true, mb_port::EXTERNAL);
@@ -82,7 +113,7 @@ usrp_server::usrp_server(mb_runtime *rt, const std::string &instance_name, pmt_t
mb_port::EXTERNAL));
}
- define_component("usrp", "usrp_usb_interface", usrp_dict);
+ define_component("usrp", "usrp_usb_interface", d_usrp_dict);
connect("self", "cs_usrp", "usrp", "cs");
d_defer=false;
@@ -108,6 +139,10 @@ usrp_server::usrp_server(mb_runtime *rt, const std::string &instance_name, pmt_t
//d_fake_rx=true;
}
+/*!
+ * \brief resets the assigned capacity and owners of each RX and TX channel from
+ * allocations.
+ */
void
usrp_server::reset_channels()
{
@@ -136,6 +171,11 @@ usrp_server::initial_transition()
// the initial transition
}
+/*!
+ * \brief Reads all incoming messages to USRP server from the TX, RX, and the CS
+ * ports. This drives the state of USRP server and dispatches based on the
+ * message.
+ */
void
usrp_server::handle_message(mb_message_sptr msg)
{
@@ -178,6 +218,9 @@ usrp_server::handle_message(mb_message_sptr msg)
pmt_t status = pmt_nth(1, data);
d_cs->send(s_response_open, pmt_list2(invocation_handle, status));
+ //reset_all_registers();
+ //initialize_registers();
+
if(pmt_eqv(status,PMT_T)) {
d_opened = true;
d_defer = false;
@@ -209,7 +252,7 @@ usrp_server::handle_message(mb_message_sptr msg)
// Do not report back responses if they were generated from a
// command packet
- if(channel == 0x1f)
+ if(channel == CONTROL_CHAN)
return;
// Find the port through the owner of the channel
@@ -470,7 +513,14 @@ usrp_server::handle_message(mb_message_sptr msg)
std::cout << "[USRP_SERVER] unhandled msg: " << msg << std::endl;
}
-// Return -1 if it is not an RX port, or an index
+/*!
+ * \brief Takes a port_symbol() as parameter \p port_id and is used to determine
+ * if the port is a TX port, or to find an index in the d_tx vector which stores
+ * the port.
+ *
+ * \returns -1 if \p port_id is not in the d_tx vector (i.e., it's not a TX
+ * port), otherwise returns an index in the d_tx vector which stores the port.
+ */
int usrp_server::tx_port_index(pmt_t port_id) {
for(int i=0; i < (int) d_tx.size(); i++)
@@ -480,7 +530,14 @@ int usrp_server::tx_port_index(pmt_t port_id) {
return -1;
}
-// Return -1 if it is not an RX port, or an index
+/*!
+ * \brief Takes a port_symbol() as parameter \p port_id and is used to determine
+ * if the port is an RX port, or to find an index in the d_rx vector which
+ * stores the port.
+ *
+ * \returns -1 if \p port_id is not in the d_rx vector (i.e., it's not an RX
+ * port), otherwise returns an index in the d_rx vector which stores the port.
+ */
int usrp_server::rx_port_index(pmt_t port_id) {
for(int i=0; i < (int) d_rx.size(); i++)
@@ -490,8 +547,12 @@ int usrp_server::rx_port_index(pmt_t port_id) {
return -1;
}
-// Go through all TX and RX channels, sum up the assigned capacity
-// and return it
+/*!
+ * \brief Determines the current total capacity allocated by all RX and TX
+ * channels.
+ *
+ * \returns the total allocated capacity
+ */
long usrp_server::current_capacity_allocation() {
long capacity = 0;
@@ -504,6 +565,14 @@ long usrp_server::current_capacity_allocation() {
return capacity;
}
+
+/*!
+ * \brief Called by the handle_message() method if the incoming message to
+ * usrp_server is to allocate a channel (cmd-allocate-channel). The method
+ * checks if the requested capacity exists and if so it will reserve it for the
+ * caller on the channel that is returned via a response-allocate-channel
+ * signal.
+ */
void
usrp_server::handle_cmd_allocate_channel(
mb_port_sptr port,
@@ -564,9 +633,13 @@ usrp_server::handle_cmd_allocate_channel(
return;
}
-// Check the port type and deallocate assigned capacity based on this, ensuring
-// that the owner of the method invocation is the owner of the port and that the
-// channel number is valid.
+/*!
+ * \brief Called by the handle_message() method if the incoming message to
+ * usrp_server is to deallocate a channel (cmd-deallocate-channel). The method
+ * ensures that the sender of the signal owns the channel and that the channel
+ * number is valid. A response-deallocate-channel signal is sent back with the
+ * result of the deallocation.
+ */
void
usrp_server::handle_cmd_deallocate_channel(
mb_port_sptr port,
@@ -591,8 +664,26 @@ usrp_server::handle_cmd_deallocate_channel(
return;
}
-void usrp_server::handle_cmd_xmit_raw_frame(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data) {
-
+/*!
+ * \brief Called by the handle_message() method if the incoming message to
+ * usrp_server is to transmit a frame (cmd-xmit-raw-frame). The method
+ * allocates enough memory to support a burst of packets which contain the frame
+ * over the bus of the frame, sets the packet headers, and sends a signal to the
+ * lower block for the data (packets) to be written to the bus.
+ *
+ * The \p port the command was sent on and the channel info (\p chan_info) of
+ * the channel the frame is to be transmitted on are passed to ensure that the
+ * caller owns the channel.
+ *
+ * The \p data parameter is in the format of a cmd-xmit-raw-frame signal.
+ *
+ * The properties
+ */
+void usrp_server::handle_cmd_xmit_raw_frame(
+ mb_port_sptr port,
+ std::vector<struct channel_info> &chan_info,
+ pmt_t data)
+{
size_t n_bytes, psize;
long max_payload_len = transport_pkt::max_payload();
@@ -667,7 +758,8 @@ void usrp_server::handle_cmd_xmit_raw_frame(mb_port_sptr port, std::vector<struc
<< invocation_handle << std::endl;
// The actual response to the write will be generated by a
- // s_response_usrp_write
+ // s_response_usrp_write since we cannot determine whether to transmit was
+ // successful until we hear from the lower layers.
d_cs_usrp->send(s_cmd_usrp_write,
pmt_list3(invocation_handle,
pmt_from_long(channel),
@@ -676,7 +768,29 @@ void usrp_server::handle_cmd_xmit_raw_frame(mb_port_sptr port, std::vector<struc
return;
}
-void usrp_server::handle_cmd_to_control_channel(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data)
+/*!
+ * \brief Called by the handle_message() method to parse incoming control/status
+ * signals (cmd-to-control-channel).
+ *
+ * The \p port the command was sent on and the channel info (\p chan_info) of
+ * the channel are passed to ensure that the caller owns the channel.
+ *
+ * The \p data parameter is in the format of a PMT list, where each element
+ * follows the format of a control/status signal (i.e. op-ping-fixed).
+ *
+ * The method will parse all of the C/S commands included in \p data and place
+ * the commands in to a lower level packet sent to the control channel. The
+ * method will pack as many commands as possible in t oa single packet, and once
+ * it is fill generate as many lower level packets as needed.
+ *
+ * Anything that needs to be returned to the sender of the signal (i.e. the
+ * value of a register) will be generated by the parse_control_pkt() method as
+ * the responses to the commands are read back from the USRP.
+ */
+void usrp_server::handle_cmd_to_control_channel(
+ mb_port_sptr port,
+ std::vector<struct channel_info> &chan_info,
+ pmt_t data)
{
pmt_t invocation_handle = pmt_nth(0, data);
@@ -687,7 +801,10 @@ void usrp_server::handle_cmd_to_control_channel(mb_port_sptr port, std::vector<s
size_t psize;
long payload_len = 0;
- long channel = 0x1f;
+ long channel = CONTROL_CHAN;
+
+ if(verbose)
+ std::cout << "[USRP_SERVER] Handling " << n_subpkts << " commands\n";
// The design of the following code is optimized for simplicity, not
// performance. To performance optimize this code, the total size in bytes
@@ -990,8 +1107,22 @@ void usrp_server::handle_cmd_to_control_channel(mb_port_sptr port, std::vector<s
return;
}
+/*!
+ * \brief Called by the handle_message() method when the incoming signal is a
+ * command to start reading samples from the USRP (cmd-start-recv-raw-samples).
+ *
+ * The \p port the command was sent on and the channel info (\p chan_info) of
+ * the channel are passed to ensure that the caller owns the channel.
+ *
+ * The \p data parameter should be in the format of a cmd-start-recv-raw-samples
+ * command where the first element in the list is an invocation handle, and the
+ * second is the channel the signal generator wants to receive the samples on.
+ */
void
-usrp_server::handle_cmd_start_recv_raw_samples(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data)
+usrp_server::handle_cmd_start_recv_raw_samples(
+ mb_port_sptr port,
+ std::vector<struct channel_info> &chan_info,
+ pmt_t data)
{
pmt_t invocation_handle = pmt_nth(0, data);
long channel = pmt_to_long(pmt_nth(1, data));
@@ -1032,6 +1163,18 @@ usrp_server::handle_cmd_start_recv_raw_samples(mb_port_sptr port, std::vector<st
return;
}
+/*!
+ * \brief Called by the handle_message() method when the incoming signal is to
+ * stop receiving samples from the USRP (cmd-stop-recv-raw-samples).
+ *
+ * The \p port the command was sent on and the channel info (\p chan_info) of
+ * the channel are passed to ensure that the caller owns the channel.
+ *
+ * The \p data parameter should be in the format of a cmd-stop-recv-raw-samples
+ * command where the first element in the list is an invocation handle, and the
+ * second is the channel the signal generator wants to stop receiving the
+ * samples from.
+ */
void
usrp_server::handle_cmd_stop_recv_raw_samples(
mb_port_sptr port,
@@ -1067,7 +1210,22 @@ usrp_server::handle_cmd_stop_recv_raw_samples(
return;
}
-// Read the packet header, determine the port by the channel owner
+/*!
+ * \brief Called by the handle_message() method when an incoming signal is
+ * generated to USRP server that contains raw samples from the USRP. This
+ * method generates the response-recv-raw-samples signals that are the result of
+ * a cmd-start-recv-raw-samples signal.
+ *
+ * The raw lower-level packet is extracted from \p data, where the format for \p
+ * data is a PMT list. The PMT \p data list should contain an invocation handle
+ * as the first element, the status of the lower-level read as the second
+ * element, and a uniform vector representation of the packets as the third
+ * element.
+ *
+ * The packet contains a channel field that the samples are destined to, and the
+ * method determines where to send the samples based on this channel since each
+ * channel has an associated port which allocated it.
+ */
void
usrp_server::handle_response_usrp_read(pmt_t data)
{
@@ -1106,7 +1264,7 @@ usrp_server::handle_response_usrp_read(pmt_t data)
return;
// If the packet is a C/S packet, parse it separately
- if(channel == 0x1f) {
+ if(channel == CONTROL_CHAN) {
parse_control_pkt(invocation_handle, pkt);
return;
}
@@ -1137,14 +1295,28 @@ usrp_server::handle_response_usrp_read(pmt_t data)
PMT_T);
d_rx[port]->send(s_response_recv_raw_samples,
- pmt_list5(invocation_handle,
+ pmt_list6(invocation_handle,
status,
v_samples,
pmt_from_long(pkt->timestamp()),
+ pmt_from_long(channel),
properties));
return;
}
+/*!
+ * \brief Called by handle_response_usrp_read() when the incoming packet has a
+ * channel of CONTROL_CHAN. This means that the incoming packet contains a
+ * response for a command sent to the control channel, which this method will
+ * parse.
+ *
+ * The \p pkt parameter is a pointer to the full packet (transport_pkt) in
+ * memory.
+ *
+ * Given that all commands sent to the control channel that require responses
+ * will carry an RID (request ID), the method will use the RID passed back with
+ * the response to determine which port the response should be sent on.
+ */
void
usrp_server::parse_control_pkt(pmt_t invocation_handle, transport_pkt *pkt)
{
@@ -1190,6 +1362,9 @@ usrp_server::parse_control_pkt(pmt_t invocation_handle, transport_pkt *pkt)
return;
pmt_t owner = d_rids[srid].owner;
+
+ // Return the RID
+ d_rids[srid].owner = PMT_NIL;
// FIXME: should be 1 response for all subpackets here ?
if((port = tx_port_index(owner)) != -1)
@@ -1225,6 +1400,9 @@ usrp_server::parse_control_pkt(pmt_t invocation_handle, transport_pkt *pkt)
return;
pmt_t owner = d_rids[srid].owner;
+
+ // Return the RID
+ d_rids[srid].owner = PMT_NIL;
// FIXME: should be 1 response for all subpackets here ?
if((port = tx_port_index(owner)) != -1)
@@ -1261,6 +1439,9 @@ usrp_server::parse_control_pkt(pmt_t invocation_handle, transport_pkt *pkt)
return;
pmt_t owner = d_rids[srid].owner;
+
+ // Return the RID
+ d_rids[srid].owner = PMT_NIL;
if((port = tx_port_index(owner)) != -1)
d_tx[port]->send(s_response_from_control_channel,
@@ -1294,6 +1475,9 @@ usrp_server::parse_control_pkt(pmt_t invocation_handle, transport_pkt *pkt)
return;
pmt_t owner = d_rids[srid].owner;
+
+ // Return the RID
+ d_rids[srid].owner = PMT_NIL;
if((port = tx_port_index(owner)) != -1)
d_tx[port]->send(s_response_from_control_channel,
@@ -1317,6 +1501,10 @@ usrp_server::parse_control_pkt(pmt_t invocation_handle, transport_pkt *pkt)
}
}
+/*!
+ * \brief Used to recall all incoming signals that were deferred when USRP
+ * server was in the initialization state.
+ */
void
usrp_server::recall_defer_queue()
{
@@ -1335,6 +1523,25 @@ usrp_server::recall_defer_queue()
return;
}
+/*!
+ * \brief Commonly called by any method which handles outgoing frames or control
+ * packets to the USRP to check if the port on which the signal was sent owns
+ * the channel the outgoing packet will be associated with. This helps ensure
+ * that applications do not send data on other application's ports.
+ *
+ * The \p port parameter is the port symbol that the caller wishes to determine
+ * owns the channel specified by \p chan_info.
+ *
+ * The \p signal_info parameter is a PMT list containing two elements: the
+ * response signal to use if the permissions are invalid, and the invocation
+ * handle that was passed. This allows the method to generate detailed failure
+ * responses to signals without having to return some sort of structured
+ * information which the caller must then parse and interpret to determine the
+ * failure type.
+ *
+ * \returns true if \p port owns the channel specified by \p chan_info, false
+ * otherwise.
+ */
bool
usrp_server::check_valid(mb_port_sptr port,
long channel,
@@ -1346,7 +1553,7 @@ usrp_server::check_valid(mb_port_sptr port,
pmt_t invocation_handle = pmt_nth(1, signal_info);
// not a valid channel number?
- if(channel >= (long)chan_info.size() && channel != 0x1f) {
+ if(channel >= (long)chan_info.size() && channel != CONTROL_CHAN) {
port->send(response_signal,
pmt_list2(invocation_handle,
s_err_channel_invalid));
@@ -1377,8 +1584,12 @@ usrp_server::check_valid(mb_port_sptr port,
return true;
}
-// Goes through the vector of RIDs and retreieves an
-// available one for use
+/*!
+ * \brief Finds the next available RID for internal USRP server use with control
+ * and status packets.
+ *
+ * \returns the next valid RID or -1 if no more RIDs are available.
+ */
long
usrp_server::next_rid()
{
@@ -1386,7 +1597,264 @@ usrp_server::next_rid()
if(pmt_eqv(d_rids[i].owner, PMT_NIL))
return i;
+ if(verbose)
+ std::cout << "[USRP_SERVER] No RIDs left\n";
return -1;
}
+/*!
+ * \brief Called by handle_message() when USRP server gets a response that the
+ * USRP was opened successfully to initialize the registers using the new
+ * register read/write control packets.
+ */
+void
+usrp_server::initialize_registers()
+{
+ // We use handle_cmd_to_control_channel() to create the register writes using
+ // PMT_NIL as the response port to tell usrp_server not to pass the response
+ // up to any application.
+ if(verbose)
+ std::cout << "[USRP_SERVER] Initializing registers...\n";
+
+ // RX mode to normal (0)
+ set_register(FR_MODE, 0);
+
+ // FPGA debugging?
+ if(d_fpga_debug) {
+ set_register(FR_DEBUG_EN, 1);
+ // FIXME: need to figure out exact register writes to control daughterboard
+ // pins that need to be written to
+ } else {
+ set_register(FR_DEBUG_EN, 0);
+ }
+
+ // Set the transmit sample rate divisor, which is 4-1
+ set_register(FR_TX_SAMPLE_RATE_DIV, 3);
+
+ // Dboard IO buffer and register settings
+ set_register(FR_OE_0, (0xffff << 16) | 0x0000);
+ set_register(FR_IO_0, (0xffff << 16) | 0x0000);
+ set_register(FR_OE_1, (0xffff << 16) | 0x0000);
+ set_register(FR_IO_1, (0xffff << 16) | 0x0000);
+ set_register(FR_OE_2, (0xffff << 16) | 0x0000);
+ set_register(FR_IO_2, (0xffff << 16) | 0x0000);
+ set_register(FR_OE_3, (0xffff << 16) | 0x0000);
+ set_register(FR_IO_3, (0xffff << 16) | 0x0000);
+
+ // zero Tx side Auto Transmit/Receive regs
+ set_register(FR_ATR_MASK_0, 0);
+ set_register(FR_ATR_TXVAL_0, 0);
+ set_register(FR_ATR_RXVAL_0, 0);
+ set_register(FR_ATR_MASK_1, 0);
+ set_register(FR_ATR_TXVAL_1, 0);
+ set_register(FR_ATR_RXVAL_1, 0);
+ set_register(FR_ATR_MASK_2, 0);
+ set_register(FR_ATR_TXVAL_2, 0);
+ set_register(FR_ATR_RXVAL_2, 0);
+ set_register(FR_ATR_MASK_3, 0);
+ set_register(FR_ATR_TXVAL_3, 0);
+ set_register(FR_ATR_RXVAL_3, 0);
+
+ // Configure TX mux, this is a hacked value
+ set_register(FR_TX_MUX, 0x00000081);
+
+ // Set the interpolation rate, which is the rate divided by 4, minus 1
+ set_register(FR_INTERP_RATE, (d_interp_tx/4)-1);
+
+ // Apparently this register changes again
+ set_register(FR_TX_MUX, 0x00000981);
+
+ // Set the receive sample rate divisor, which is 2-1
+ set_register(FR_RX_SAMPLE_RATE_DIV, 1);
+
+ // DC offset
+ set_register(FR_DC_OFFSET_CL_EN, 0x0000000f);
+
+ // Reset the DC correction offsets
+ set_register(FR_ADC_OFFSET_0, 0);
+ set_register(FR_ADC_OFFSET_1, 0);
+
+ // Some hard-coded RX configuration
+ set_register(FR_RX_FORMAT, 0x00000300);
+ set_register(FR_RX_MUX, 1);
+
+ // RX decimation rate is divided by two, then subtract 1
+ set_register(FR_DECIM_RATE, (d_decim_rx/2)-1);
+
+ // More hard coding
+ set_register(FR_RX_MUX, 0x000e4e41);
+
+ // Resetting RX registers
+ set_register(FR_RX_PHASE_0, 0);
+ set_register(FR_RX_PHASE_1, 0);
+ set_register(FR_RX_PHASE_2, 0);
+ set_register(FR_RX_PHASE_3, 0);
+ set_register(FR_RX_FREQ_0, 0x28000000);
+ set_register(FR_RX_FREQ_1, 0);
+ set_register(FR_RX_FREQ_2, 0);
+ set_register(FR_RX_FREQ_3, 0);
+
+ // Enable debug bus
+ set_register(FR_DEBUG_EN, 0xf);
+ set_register(FR_OE_0, -1);
+ set_register(FR_OE_1, -1);
+ set_register(FR_OE_2, -1);
+ set_register(FR_OE_3, -1);
+
+ // DEBUGGING
+ //check_register_initialization();
+}
+
+// FIXME: used for debugging to determine if all the registers are actually
+// being set correctly
+void
+usrp_server::check_register_initialization()
+{
+ // RX mode to normal (0)
+ read_register(FR_MODE);
+
+ // FPGA debugging?
+ if(d_fpga_debug) {
+ read_register(FR_DEBUG_EN);
+ // FIXME: need to figure out exact register writes to control daughterboard
+ // pins that need to be written to
+ } else {
+ read_register(FR_DEBUG_EN);
+ }
+
+ // Set the transmit sample rate divisor, which is 4-1
+ read_register(FR_TX_SAMPLE_RATE_DIV);
+
+ // Dboard IO buffer and register settings
+ read_register(FR_OE_0);
+ read_register(FR_IO_0);
+ read_register(FR_OE_1);
+ read_register(FR_IO_1);
+ read_register(FR_OE_2);
+ read_register(FR_IO_2);
+ read_register(FR_OE_3);
+ read_register(FR_IO_3);
+
+ // zero Tx side Auto Transmit/Receive regs
+ read_register(FR_ATR_MASK_0);
+ read_register(FR_ATR_TXVAL_0);
+ read_register(FR_ATR_RXVAL_0);
+ read_register(FR_ATR_MASK_1);
+ read_register(FR_ATR_TXVAL_1);
+ read_register(FR_ATR_RXVAL_1);
+ read_register(FR_ATR_MASK_2);
+ read_register(FR_ATR_TXVAL_2);
+ read_register(FR_ATR_RXVAL_2);
+ read_register(FR_ATR_MASK_3);
+ read_register(FR_ATR_TXVAL_3);
+ read_register(FR_ATR_RXVAL_3);
+
+ // Configure TX mux, this is a hacked value
+ read_register(FR_TX_MUX);
+
+ // Set the interpolation rate, which is the rate divided by 4, minus 1
+ read_register(FR_INTERP_RATE);
+
+ // Apparently this register changes again
+ read_register(FR_TX_MUX);
+
+ // Set the receive sample rate divisor, which is 2-1
+ read_register(FR_RX_SAMPLE_RATE_DIV);
+
+ // DC offset
+ read_register(FR_DC_OFFSET_CL_EN);
+
+ // Reset the DC correction offsets
+ read_register(FR_ADC_OFFSET_0);
+ read_register(FR_ADC_OFFSET_1);
+
+ // Some hard-coded RX configuration
+ read_register(FR_RX_FORMAT);
+ read_register(FR_RX_MUX);
+
+ // RX decimation rate is divided by two, then subtract 1
+ read_register(FR_DECIM_RATE);
+
+ // More hard coding
+ read_register(FR_RX_MUX);
+
+ // Resetting RX registers
+ read_register(FR_RX_PHASE_0);
+ read_register(FR_RX_PHASE_1);
+ read_register(FR_RX_PHASE_2);
+ read_register(FR_RX_PHASE_3);
+ read_register(FR_RX_FREQ_0);
+ read_register(FR_RX_FREQ_1);
+ read_register(FR_RX_FREQ_2);
+ read_register(FR_RX_FREQ_3);
+}
+
+/*!
+ * \brief Used to generate FPGA register write commands to reset all of the FPGA
+ * registers to a value of 0.
+ */
+void
+usrp_server::reset_all_registers()
+{
+ for(int i=0; i<64; i++)
+ set_register(i, 0);
+}
+
+/*!
+ * \brief Used internally by USRP server to generate a control/status packet
+ * which contains a register write.
+ *
+ * The \p reg parameter is the register number that the value \p val will be
+ * written to.
+ */
+void
+usrp_server::set_register(long reg, long val)
+{
+ size_t psize;
+ long payload_len = 0;
+
+ pmt_t v_packet = pmt_make_u8vector(sizeof(transport_pkt), 0);
+ transport_pkt *pkt = (transport_pkt *) pmt_u8vector_writeable_elements(v_packet, psize);
+
+ pkt->set_header(0, CONTROL_CHAN, 0, payload_len);
+ pkt->set_timestamp(0xffffffff);
+
+ pkt->cs_write_reg(reg, val);
+
+ d_cs_usrp->send(s_cmd_usrp_write,
+ pmt_list3(PMT_NIL,
+ pmt_from_long(CONTROL_CHAN),
+ v_packet));
+}
+
+/*!
+ * \brief Used internally by USRP server to generate a control/status packet
+ * which contains a register read. This is important to use internally so that
+ * USRP server can bypass the use of RIDs with register reads, as they are not
+ * needed and it would use up the finite number of RIDs available for use for
+ * applications to receive responses.
+ *
+ * The \p reg parameter is the register number that the value should be read
+ * from.
+ */
+void
+usrp_server::read_register(long reg)
+{
+ size_t psize;
+ long payload_len = 0;
+
+ pmt_t v_packet = pmt_make_u8vector(sizeof(transport_pkt), 0);
+ transport_pkt *pkt = (transport_pkt *) pmt_u8vector_writeable_elements(v_packet, psize);
+
+ pkt->set_header(0, CONTROL_CHAN, 0, payload_len);
+ pkt->set_timestamp(0xffffffff);
+
+ pkt->cs_read_reg(0, reg);
+
+ d_cs_usrp->send(s_cmd_usrp_write,
+ pmt_list3(PMT_NIL,
+ pmt_from_long(CONTROL_CHAN),
+ v_packet));
+}
+
REGISTER_MBLOCK_CLASS(usrp_server);
diff --git a/usrp/host/lib/inband/usrp_server.h b/usrp/host/lib/inband/usrp_server.h
index 81dceb1f4..09c82faac 100644
--- a/usrp/host/lib/inband/usrp_server.h
+++ b/usrp/host/lib/inband/usrp_server.h
@@ -51,6 +51,13 @@ public:
long d_ntx_chan;
long d_nrx_chan;
+ pmt_t d_usrp_dict;
+
+ bool d_fpga_debug;
+
+ long d_interp_tx;
+ long d_decim_rx;
+
// Keep track of the request IDs
struct rid_info {
pmt_t owner;
@@ -114,6 +121,11 @@ private:
bool check_valid(mb_port_sptr port, long channel, std::vector<struct channel_info> &chan_info, pmt_t signal_info);
void parse_control_pkt(pmt_t invocation_handle, transport_pkt *pkt);
long next_rid();
+ void initialize_registers();
+ void set_register(long reg, long val);
+ void read_register(long reg);
+ void check_register_initialization();
+ void reset_all_registers();
};
#endif /* INCLUDED_USRP_SERVER_H */
diff --git a/usrp/host/lib/inband/usrp_server.mbh b/usrp/host/lib/inband/usrp_server.mbh
index 3fd0db139..ed7943fc3 100644
--- a/usrp/host/lib/inband/usrp_server.mbh
+++ b/usrp/host/lib/inband/usrp_server.mbh
@@ -202,7 +202,7 @@
(:incoming
- (response-recv-raw-samples invocation-handle status samples timestamp properties)
+ (response-recv-raw-samples invocation-handle status samples timestamp channel properties)
;; samples is a uniform numeric vector. The contents of the sample
;; vector is treated as opaque and is passed from the FPGA
diff --git a/usrp/host/lib/inband/usrp_tx.cc b/usrp/host/lib/inband/usrp_tx.cc
index a7a5e4a89..da8777513 100644
--- a/usrp/host/lib/inband/usrp_tx.cc
+++ b/usrp/host/lib/inband/usrp_tx.cc
@@ -66,6 +66,10 @@ usrp_tx::initial_transition()
}
+/*!
+ * \brief Handles incoming signals to to the m-block, wihch should only ever be
+ * a single message: cmd-usrp-tx-write.
+ */
void
usrp_tx::handle_message(mb_message_sptr msg)
{
@@ -82,6 +86,14 @@ usrp_tx::handle_message(mb_message_sptr msg)
}
}
+/*!
+ * \brief Performs the actual writing of data to the USB bus, called by
+ * handle_message() when a cmd-usrp-tx-write signal is received.
+ *
+ * The \p data parameter is a PMT list which contains three mandatory elements,
+ * in the following order: an invocation handle, a channel, and a uniform vector
+ * of memory which contains the packets to be written to the bus.
+ */
void
usrp_tx::write(pmt_t data)
{
@@ -121,7 +133,7 @@ usrp_tx::write(pmt_t data)
for(int i=0; i < n_packets; i++) {
if(d_disk_write) {
- if(pkts[i].chan() == 0x1f)
+ if(pkts[i].chan() == CONTROL_CHAN)
d_cs_ofile.write((const char *)&pkts[i], transport_pkt::max_pkt_size());
else
d_ofile.write((const char *)&pkts[i], transport_pkt::max_pkt_size());
diff --git a/usrp/host/lib/inband/usrp_tx_stub.cc b/usrp/host/lib/inband/usrp_tx_stub.cc
index 7a9876322..6cff3b4ee 100644
--- a/usrp/host/lib/inband/usrp_tx_stub.cc
+++ b/usrp/host/lib/inband/usrp_tx_stub.cc
@@ -103,7 +103,7 @@ usrp_tx_stub::write(pmt_t data)
for(long i=0; i<n_packets; i++) {
if(d_disk_write) {
- if(pkts[i].chan() == 0x1f)
+ if(pkts[i].chan() == CONTROL_CHAN)
d_cs_ofile.write((const char *)&pkts[i], transport_pkt::max_pkt_size());
else
d_ofile.write((const char *)&pkts[i], transport_pkt::max_pkt_size());
@@ -112,7 +112,7 @@ usrp_tx_stub::write(pmt_t data)
d_ofile.flush();
}
- if(pkts[i].chan() == 0x1f)
+ if(pkts[i].chan() == CONTROL_CHAN)
parse_cs(invocation_handle, pkts[i]);
}
@@ -140,7 +140,7 @@ usrp_tx_stub::parse_cs(pmt_t invocation_handle, transport_pkt pkt)
transport_pkt *q_pkt =
(transport_pkt *) pmt_u8vector_writeable_elements(v_pkt, ignore);
- q_pkt->set_header(0, 0x1f, 0, 0);
+ q_pkt->set_header(0, CONTROL_CHAN, 0, 0);
q_pkt->set_timestamp(0xffffffff);
// We dispatch based on the control packet type, however we can extract the
diff --git a/usrp/host/lib/inband/usrp_usb_interface.cc b/usrp/host/lib/inband/usrp_usb_interface.cc
index 269ed2706..51b6d4646 100644
--- a/usrp/host/lib/inband/usrp_usb_interface.cc
+++ b/usrp/host/lib/inband/usrp_usb_interface.cc
@@ -47,12 +47,16 @@ static pmt_t s_shutdown = pmt_intern("%shutdown");
static const bool verbose = false;
-
-// need to take number of TX and RX channels as parameter
+/*!
+ * \brief Initializes the USB interface m-block.
+ *
+ * The \p user_arg should be a PMT dictionary which can contain optional
+ * arguments for the block, such as the decimatoin and interpolation rate.
+ */
usrp_usb_interface::usrp_usb_interface(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg)
: mb_mblock(rt, instance_name, user_arg),
- d_fpga_debug(false),
d_fake_usrp(false),
+ d_rx_reading(false),
d_interp_tx(128),
d_decim_rx(128),
d_rf_freq(10e6),
@@ -86,7 +90,7 @@ usrp_usb_interface::usrp_usb_interface(mb_runtime *rt, const std::string &instan
d_interp_tx = pmt_to_long(interp_tx);
}
- // Read the RX interpolations
+ // Read the RX decimation rate
if(pmt_t decim_rx = pmt_dict_ref(usrp_dict,
pmt_intern("decim-rx"),
PMT_NIL)) {
@@ -134,8 +138,8 @@ usrp_usb_interface::usrp_usb_interface(mb_runtime *rt, const std::string &instan
d_tx_cs = define_port("tx_cs", "usrp-tx-cs", false, mb_port::INTERNAL);
// Connect to TX and RX
- define_component("tx", tx_interface, PMT_F);
- define_component("rx", rx_interface, PMT_F);
+ define_component("tx", tx_interface, usrp_dict);
+ define_component("rx", rx_interface, usrp_dict);
connect("self", "rx_cs", "rx", "cs");
connect("self", "tx_cs", "tx", "cs");
@@ -146,8 +150,6 @@ usrp_usb_interface::usrp_usb_interface(mb_runtime *rt, const std::string &instan
d_utx = NULL;
d_urx = NULL;
- d_fpga_debug=true; // WARNING: DO NOT ENABLE WITH D'BOARDS OTHER THAN BASIC TX/RX
-
}
usrp_usb_interface::~usrp_usb_interface()
@@ -161,6 +163,10 @@ usrp_usb_interface::initial_transition()
}
+/*!
+ * \brief Handles all incoming signals to the block from the lowest m-blocks
+ * which read/write to the bus, or the higher m-block which is the USRP server.
+ */
void
usrp_usb_interface::handle_message(mb_message_sptr msg)
{
@@ -256,6 +262,13 @@ usrp_usb_interface::handle_message(mb_message_sptr msg)
std::cout << "[USRP_USB_INTERFACE] unhandled msg: " << msg << std::endl;
}
+/*!
+ * \brief Called by the handle_message() method when the incoming signal is to
+ * open a USB connection to the USRP (cmd-usrp-open).
+ *
+ * The \p data parameter is a PMT list, where the elements are an invocation
+ * handle and the USRP number.
+ */
void
usrp_usb_interface::handle_cmd_open(pmt_t data)
{
@@ -290,7 +303,7 @@ usrp_usb_interface::handle_cmd_open(pmt_t data)
return;
}
- if(!d_utx->set_tx_freq (0,d_rf_freq)) { // try setting center freq to 0
+ if(!d_utx->set_tx_freq (0,d_rf_freq) || !d_utx->set_tx_freq(1,d_rf_freq)) { // try setting center freq to 0
if (verbose)
std::cout << "[USRP_USB_INTERFACE] Failed to set center frequency on TX\n";
reply_data = pmt_list2(invocation_handle, PMT_F);
@@ -298,6 +311,14 @@ usrp_usb_interface::handle_cmd_open(pmt_t data)
return;
}
+ if(!d_utx->set_mux(0xBA98)) {
+ if (verbose)
+ std::cout << "[USRP_USB_INTERFACE] Failed to set TX mux\n";
+ reply_data = pmt_list2(invocation_handle, PMT_F);
+ d_cs->send(s_response_usrp_open, reply_data);
+ return;
+ }
+
d_utx->start();
if (verbose)
@@ -321,33 +342,44 @@ usrp_usb_interface::handle_cmd_open(pmt_t data)
return;
}
- if(!d_urx->set_rx_freq (0, d_rf_freq)) {
+ if(!d_urx->set_rx_freq (0, -d_rf_freq) || !d_urx->set_rx_freq(1, -d_rf_freq)) {
if (verbose)
std::cout << "[usrp_server] Failed to set center frequency on RX\n";
reply_data = pmt_list2(invocation_handle, PMT_F);
d_cs->send(s_response_usrp_open, reply_data);
return;
}
-
- if(d_fpga_debug) {
- d_utx->_write_fpga_reg(FR_DEBUG_EN,0xf);
- d_utx->_write_oe(0, 0xffff, 0xffff);
- d_urx->_write_oe(0, 0xffff, 0xffff);
- d_utx->_write_oe(1, 0xffff, 0xffff);
- d_urx->_write_oe(1, 0xffff, 0xffff);
-
-// while(1){
-// for(int i=0; i<0xffff; i++)
-// d_urx->write_io(0, i, 0xffff);
-// }
- }
+ // Two channels ... this really needs to end up being set correctly by
+ // querying for what dboards are connected
+ if(!d_urx->set_mux(0x32103210)) {
+ if (verbose)
+ std::cout << "[USRP_USB_INTERFACE] Failed to set RX mux\n";
+ reply_data = pmt_list2(invocation_handle, PMT_F);
+ d_cs->send(s_response_usrp_open, reply_data);
+ return;
+ }
+
if (verbose)
std::cout << "[USRP_USB_INTERFACE] Setup RX channel\n";
+
+// d_utx->_write_fpga_reg(FR_DEBUG_EN,0xf);
+// d_utx->_write_oe(0, 0xffff, 0xffff);
+// d_urx->_write_oe(0, 0xffff, 0xffff);
+// d_utx->_write_oe(1, 0xffff, 0xffff);
+// d_urx->_write_oe(1, 0xffff, 0xffff);
d_cs->send(s_response_usrp_open, pmt_list2(invocation_handle, PMT_T));
}
+/*!
+ * \brief Called by the handle_message() method when the incoming signal is to
+ * write data to the USB bus (cmd-usrp-write).
+ *
+ * The \p data parameter is a PMT list containing 3 mandatory elements in the
+ * following order: an invocation handle, channel, and a uniform vector
+ * representation of the packets.
+ */
void
usrp_usb_interface::handle_cmd_write(pmt_t data)
{
@@ -366,6 +398,13 @@ usrp_usb_interface::handle_cmd_write(pmt_t data)
return;
}
+/*!
+ * \brief Called by the handle_message() method when the incoming signal is to
+ * start reading data from the USB bus (cmd-usrp-start-reading).
+ *
+ * The \p data parameter is a PMT list with a single element: an invocation
+ * handle which can be returned with the response.
+ */
void
usrp_usb_interface::handle_cmd_start_reading(pmt_t data)
{
@@ -381,9 +420,18 @@ usrp_usb_interface::handle_cmd_start_reading(pmt_t data)
d_rx_cs->send(s_cmd_usrp_rx_start_reading, pmt_list2(PMT_NIL, rx_handle));
+ d_rx_reading = true;
+
return;
}
+/*!
+ * \brief Called by the handle_message() method when the incoming signal is to
+ * stop reading data from the USB bus (cmd-usrp-stop-reading).
+ *
+ * The \p data parameter is a PMT list with a single element: an invocation
+ * handle which can be returned with the response.
+ */
void
usrp_usb_interface::handle_cmd_stop_reading(pmt_t data)
{
@@ -392,22 +440,40 @@ usrp_usb_interface::handle_cmd_stop_reading(pmt_t data)
if(!d_fake_usrp) {
if(verbose)
std::cout << "[USRP_USB_INTERFACE] Stopping RX...\n";
+ usrp_rx_stop = true;
+
+ // Used to allow a read() being called by a lower layer to complete before
+ // stopping, else there can be partial data left on the bus and can generate
+ // errors.
+ while(usrp_rx_stop) {usleep(1);}
d_urx->stop();
}
else {
if(verbose)
std::cout << "[USRP_USB_INTERFACE] Stopping fake RX...\n";
- usrp_rx_stop = true; // extern to communicate with stub to wait
+ usrp_rx_stop_stub = true; // extern to communicate with stub to wait
}
+ d_rx_reading = false;
+
return;
}
+/*!
+ * \brief Called by the handle_message() method when the incoming signal is to
+ * close the USB connection to the USRP.
+ *
+ * The \p data parameter is a PMT list with a single element: an invocation
+ * handle which can be returned with the response.
+ */
void
usrp_usb_interface::handle_cmd_close(pmt_t data)
{
pmt_t invocation_handle = pmt_nth(0, data);
+ if(d_rx_reading)
+ handle_cmd_stop_reading(PMT_NIL);
+
if(d_fake_usrp) {
d_cs->send(s_response_usrp_close, pmt_list2(invocation_handle, PMT_T));
return;
diff --git a/usrp/host/lib/inband/usrp_usb_interface.h b/usrp/host/lib/inband/usrp_usb_interface.h
index 8efce2ff6..6c2c15768 100644
--- a/usrp/host/lib/inband/usrp_usb_interface.h
+++ b/usrp/host/lib/inband/usrp_usb_interface.h
@@ -42,10 +42,10 @@ class usrp_usb_interface : public mb_mblock
long d_ntx_chan;
long d_nrx_chan;
- long d_fpga_debug;
-
bool d_fake_usrp;
+ bool d_rx_reading;
+
long d_interp_tx;
long d_decim_rx;
diff --git a/usrp/host/lib/legacy/fusb_linux.cc b/usrp/host/lib/legacy/fusb_linux.cc
index 60687a149..6dce8d9e0 100644
--- a/usrp/host/lib/legacy/fusb_linux.cc
+++ b/usrp/host/lib/legacy/fusb_linux.cc
@@ -386,14 +386,6 @@ fusb_ephandle_linux::stop ()
{
if (!d_started)
return true;
-
- d_devhandle->_cancel_pending_rqsts (this);
- d_devhandle->_reap (false);
-
-
- usbdevfs_urb *urb;
- while ((urb = completed_list_get ()) != 0)
- free_list_add (urb);
if (d_write_work_in_progress){
free_list_add (d_write_work_in_progress);
@@ -407,11 +399,19 @@ fusb_ephandle_linux::stop ()
d_read_buffer_end = 0;
}
- if (d_free_list.size () != (unsigned) d_nblocks)
- fprintf (stderr, "d_free_list.size () = %d, d_nblocks = %d\n",
- d_free_list.size (), d_nblocks);
-
- assert (d_free_list.size () == (unsigned) d_nblocks);
+ d_devhandle->_cancel_pending_rqsts (this);
+ d_devhandle->_reap (false);
+
+ while (1){
+ usbdevfs_urb *urb;
+ while ((urb = completed_list_get ()) != 0)
+ free_list_add (urb);
+
+ if (d_free_list.size () == (unsigned) d_nblocks)
+ break;
+
+ d_devhandle->_reap(true);
+ }
d_started = false;
return true;