summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.common4
-rw-r--r--pmt/src/lib/pmt.cc26
-rw-r--r--pmt/src/lib/pmt.h12
-rw-r--r--pmt/src/lib/qa_pmt_prims.cc12
-rwxr-xr-xusrp/fpga/inband_lib/chan_fifo_reader.v356
-rw-r--r--usrp/fpga/inband_lib/channel_demux.v78
-rwxr-xr-xusrp/fpga/inband_lib/channel_ram.v114
-rwxr-xr-xusrp/fpga/inband_lib/cmd_reader.v292
-rwxr-xr-xusrp/fpga/inband_lib/data_packet_fifo.v118
-rwxr-xr-xusrp/fpga/inband_lib/packet_builder.v132
-rwxr-xr-xusrp/fpga/inband_lib/register_io.v60
-rwxr-xr-xusrp/fpga/inband_lib/rx_buffer_inband.v175
-rwxr-xr-xusrp/fpga/inband_lib/tx_buffer_inband.v386
-rw-r--r--usrp/fpga/inband_lib/tx_packer.v119
-rwxr-xr-xusrp/fpga/inband_lib/usb_fifo_reader.v146
-rwxr-xr-xusrp/fpga/inband_lib/usb_fifo_writer.v183
-rwxr-xr-xusrp/fpga/inband_lib/usb_packet_fifo2.v119
-rwxr-xr-xusrp/fpga/megacells/fifo_2k_1clk.v (renamed from usrp/fpga/megacells/fifo_512.v)157
-rwxr-xr-xusrp/fpga/megacells/fifo_2kx16.bsf99
-rwxr-xr-xusrp/fpga/megacells/fifo_2kx16.cmp (renamed from usrp/fpga/megacells/fifo_512.cmp)18
-rwxr-xr-xusrp/fpga/megacells/fifo_2kx16.inc (renamed from usrp/fpga/megacells/fifo_512.inc)16
-rwxr-xr-xusrp/fpga/megacells/fifo_2kx16.v167
-rwxr-xr-xusrp/fpga/megacells/fifo_2kx16_bb.v (renamed from usrp/fpga/megacells/fifo_512_bb.v)103
-rwxr-xr-xusrp/fpga/megacells/fifo_2kx16_inst.v11
-rwxr-xr-xusrp/fpga/megacells/fifo_4kx16.bsf99
-rwxr-xr-xusrp/fpga/megacells/fifo_4kx16.cmp29
-rwxr-xr-xusrp/fpga/megacells/fifo_4kx16.inc30
-rwxr-xr-xusrp/fpga/megacells/fifo_4kx16.v167
-rwxr-xr-xusrp/fpga/megacells/fifo_4kx16_bb.v122
-rwxr-xr-xusrp/fpga/megacells/fifo_4kx16_inst.v11
-rwxr-xr-xusrp/fpga/megacells/fifo_512.bsf116
-rw-r--r--usrp/fpga/toplevel/usrp_inband_usb/config.vh2
-rw-r--r--usrp/fpga/toplevel/usrp_inband_usb/usrp_inband_usb.qsf15
-rw-r--r--usrp/fpga/toplevel/usrp_inband_usb/usrp_inband_usb.v68
-rw-r--r--usrp/host/apps/Makefile.am39
-rw-r--r--usrp/host/apps/read_packets.cc103
-rw-r--r--usrp/host/apps/test_usrp_inband_cs.cc478
-rw-r--r--usrp/host/apps/test_usrp_inband_ping.cc376
-rw-r--r--usrp/host/apps/test_usrp_inband_registers.cc436
-rw-r--r--usrp/host/apps/test_usrp_inband_rx.cc356
-rw-r--r--usrp/host/apps/test_usrp_inband_timestamps.cc508
-rw-r--r--usrp/host/apps/test_usrp_inband_tx.cc409
-rw-r--r--usrp/host/apps/ui_nco.h202
-rw-r--r--usrp/host/apps/ui_sincos.c81
-rw-r--r--usrp/host/apps/ui_sincos.h39
-rw-r--r--usrp/host/lib/inband/Makefile.am53
-rw-r--r--usrp/host/lib/inband/fake_usrp.cc135
-rw-r--r--usrp/host/lib/inband/fake_usrp.h43
-rwxr-xr-xusrp/host/lib/inband/gen_test_packets.py3
-rw-r--r--usrp/host/lib/inband/qa_inband_usrp_server.cc1151
-rw-r--r--usrp/host/lib/inband/qa_inband_usrp_server.h10
-rw-r--r--usrp/host/lib/inband/symbols_usrp_channel.h40
-rw-r--r--usrp/host/lib/inband/symbols_usrp_interface_cs.h43
-rw-r--r--usrp/host/lib/inband/symbols_usrp_low_level_cs.h47
-rw-r--r--usrp/host/lib/inband/symbols_usrp_rx.h36
-rw-r--r--usrp/host/lib/inband/symbols_usrp_rx_cs.h32
-rw-r--r--usrp/host/lib/inband/symbols_usrp_server_cs.h47
-rw-r--r--usrp/host/lib/inband/symbols_usrp_tx.h32
-rw-r--r--usrp/host/lib/inband/symbols_usrp_tx_cs.h32
-rw-r--r--usrp/host/lib/inband/test_usrp_inband.cc297
-rw-r--r--usrp/host/lib/inband/usrp_inband_usb_packet.cc749
-rw-r--r--usrp/host/lib/inband/usrp_inband_usb_packet.h95
-rw-r--r--usrp/host/lib/inband/usrp_interface.mbh88
-rw-r--r--usrp/host/lib/inband/usrp_rx.cc142
-rw-r--r--usrp/host/lib/inband/usrp_rx.h55
-rw-r--r--usrp/host/lib/inband/usrp_rx_stub.cc183
-rw-r--r--usrp/host/lib/inband/usrp_rx_stub.h71
-rw-r--r--usrp/host/lib/inband/usrp_server.cc1342
-rw-r--r--usrp/host/lib/inband/usrp_server.h65
-rw-r--r--usrp/host/lib/inband/usrp_server.mbh15
-rw-r--r--usrp/host/lib/inband/usrp_tx.cc138
-rw-r--r--usrp/host/lib/inband/usrp_tx.h53
-rw-r--r--usrp/host/lib/inband/usrp_tx_stub.cc344
-rw-r--r--usrp/host/lib/inband/usrp_tx_stub.h61
-rw-r--r--usrp/host/lib/inband/usrp_usb_interface.cc431
-rw-r--r--usrp/host/lib/inband/usrp_usb_interface.h72
76 files changed, 11215 insertions, 1279 deletions
diff --git a/Makefile.common b/Makefile.common
index 2976e36dc..33a3a7c2a 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -76,7 +76,9 @@ GNURADIO_I = $(top_srcdir)/gnuradio-core/src/lib/swig/gnuradio.i
USRP_INCLUDES = -I$(top_srcdir)/usrp/host/lib/legacy \
-I$(top_srcdir)/usrp/host/lib/inband \
-I$(top_srcdir)/usrp/firmware/include
-USRP_LA = $(top_builddir)/usrp/host/lib/legacy/libusrp.la
+USRP_LA = \
+ $(top_builddir)/usrp/host/lib/legacy/libusrp.la \
+ $(top_builddir)/usrp/host/lib/inband/libusrp_inband.la
# How to link the PMT library from inside the tree
PMT_INCLUDES = -I$(top_srcdir)/pmt/src/lib
diff --git a/pmt/src/lib/pmt.cc b/pmt/src/lib/pmt.cc
index b896adaa2..b2c04b390 100644
--- a/pmt/src/lib/pmt.cc
+++ b/pmt/src/lib/pmt.cc
@@ -748,7 +748,19 @@ pmt_length(pmt_t x)
if (x->is_uniform_vector())
return _uniform_vector(x)->length();
- // FIXME list length
+ if (x->is_pair() || x->is_null()) {
+ size_t length=0;
+ while (pmt_is_pair(x)){
+ length++;
+ x = pmt_cdr(x);
+ }
+ if (pmt_is_null(x))
+ return length;
+
+ // not a proper list
+ throw pmt_wrong_type("pmt_length", x);
+ }
+
// FIXME dictionary length (number of entries)
throw pmt_wrong_type("pmt_length", x);
@@ -938,6 +950,18 @@ pmt_list4(pmt_t x1, pmt_t x2, pmt_t x3, pmt_t x4)
}
pmt_t
+pmt_list5(pmt_t x1, pmt_t x2, pmt_t x3, pmt_t x4, pmt_t x5)
+{
+ return pmt_cons(x1, pmt_cons(x2, pmt_cons(x3, pmt_cons(x4, pmt_cons(x5, PMT_NIL)))));
+}
+
+pmt_t
+pmt_list6(pmt_t x1, pmt_t x2, pmt_t x3, pmt_t x4, pmt_t x5, pmt_t x6)
+{
+ return pmt_cons(x1, pmt_cons(x2, pmt_cons(x3, pmt_cons(x4, pmt_cons(x5, pmt_cons(x6, PMT_NIL))))));
+}
+
+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 6aeae773b..fa368a6a1 100644
--- a/pmt/src/lib/pmt.h
+++ b/pmt/src/lib/pmt.h
@@ -598,6 +598,18 @@ pmt_t pmt_list3(pmt_t x1, pmt_t x2, pmt_t x3);
*/
pmt_t pmt_list4(pmt_t x1, pmt_t x2, pmt_t x3, pmt_t x4);
+/*!
+ * \brief Return a list of length 5 containing \p x1, \p x2, \p x3, \p x4, \p x5
+ */
+pmt_t pmt_list5(pmt_t x1, pmt_t x2, pmt_t x3, pmt_t x4, pmt_t x5);
+
+/*!
+ * \brief Return a list of length 6 containing \p x1, \p x2, \p x3, \p x4, \p
+ * x5, \p x6
+ */
+pmt_t pmt_list6(pmt_t x1, pmt_t x2, pmt_t x3, pmt_t x4, pmt_t x5, pmt_t x6);
+
+
/*
* ------------------------------------------------------------------------
* read / write
diff --git a/pmt/src/lib/qa_pmt_prims.cc b/pmt/src/lib/qa_pmt_prims.cc
index c36a5e972..26b3e26d3 100644
--- a/pmt/src/lib/qa_pmt_prims.cc
+++ b/pmt/src/lib/qa_pmt_prims.cc
@@ -138,11 +138,17 @@ qa_pmt_prims::test_pairs()
pmt_t s2 = pmt_string_to_symbol("s2");
pmt_t s3 = pmt_string_to_symbol("s3");
+
+ CPPUNIT_ASSERT_EQUAL((size_t)0, pmt_length(PMT_NIL));
+ CPPUNIT_ASSERT_THROW(pmt_length(s1), pmt_wrong_type);
+ CPPUNIT_ASSERT_THROW(pmt_length(pmt_from_double(42)), pmt_wrong_type);
+
pmt_t c1 = pmt_cons(s1, PMT_NIL);
CPPUNIT_ASSERT(pmt_is_pair(c1));
CPPUNIT_ASSERT(!pmt_is_pair(s1));
CPPUNIT_ASSERT_EQUAL(s1, pmt_car(c1));
CPPUNIT_ASSERT_EQUAL(PMT_NIL, pmt_cdr(c1));
+ CPPUNIT_ASSERT_EQUAL((size_t) 1, pmt_length(c1));
pmt_t c3 = pmt_cons(s3, PMT_NIL);
pmt_t c2 = pmt_cons(s2, c3);
@@ -150,7 +156,9 @@ qa_pmt_prims::test_pairs()
CPPUNIT_ASSERT_EQUAL(c2, pmt_cdr(c1));
pmt_set_car(c1, s3);
CPPUNIT_ASSERT_EQUAL(s3, pmt_car(c1));
-
+ CPPUNIT_ASSERT_EQUAL((size_t)1, pmt_length(c3));
+ CPPUNIT_ASSERT_EQUAL((size_t)2, pmt_length(c2));
+
CPPUNIT_ASSERT_THROW(pmt_cdr(PMT_NIL), pmt_wrong_type);
CPPUNIT_ASSERT_THROW(pmt_car(PMT_NIL), pmt_wrong_type);
CPPUNIT_ASSERT_THROW(pmt_set_car(s1, PMT_NIL), pmt_wrong_type);
@@ -228,8 +236,6 @@ qa_pmt_prims::test_equivalence()
void
qa_pmt_prims::test_misc()
{
- CPPUNIT_ASSERT_THROW(pmt_length(PMT_NIL), pmt_wrong_type);
-
pmt_t k0 = pmt_string_to_symbol("k0");
pmt_t k1 = pmt_string_to_symbol("k1");
pmt_t k2 = pmt_string_to_symbol("k2");
diff --git a/usrp/fpga/inband_lib/chan_fifo_reader.v b/usrp/fpga/inband_lib/chan_fifo_reader.v
index 2b3178da7..9392bf151 100755
--- a/usrp/fpga/inband_lib/chan_fifo_reader.v
+++ b/usrp/fpga/inband_lib/chan_fifo_reader.v
@@ -1,197 +1,219 @@
module chan_fifo_reader
- ( input reset,
- input tx_clock,
- input tx_strobe,
- input [31:0]adc_clock,
- input [3:0] samples_format,
- input [15:0] fifodata,
- input pkt_waiting,
- output reg rdreq,
- output reg skip,
- output reg [15:0]tx_q,
- output reg [15:0]tx_i,
- output reg overrun,
- output reg underrun) ;
-
+ ( reset, tx_clock, tx_strobe, adc_time, samples_format,
+ fifodata, pkt_waiting, rdreq, skip, tx_q, tx_i,
+ underrun, tx_empty, debug, rssi, threshhold) ;
+
+ 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;
+
+ 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
- `define JITTER 5
+ // Used only to debug
+ `define JITTER 5
//Samples format
// 16 bits interleaved complex samples
- `define QI16 4'b0
+ `define QI16 4'b0
// States
- `define IDLE 4'd0
- `define READ 4'd1
- `define HEADER1 4'd2
- `define HEADER2 4'd3
- `define TIMESTAMP1 4'd4
- `define TIMESTAMP2 4'd5
- `define WAIT 4'd6
- `define WAITSTROBE 4'd7
- `define SENDWAIT 4'd8
- `define SEND 4'd9
- `define FEED 4'd10
- `define DISCARD 4'd11
+ parameter IDLE = 3'd0;
+ parameter HEADER = 3'd1;
+ parameter TIMESTAMP = 3'd2;
+ parameter WAIT = 3'd3;
+ parameter WAITSTROBE = 3'd4;
+ parameter SEND = 3'd5;
- // State registers
- reg[3:0] reader_state;
- reg[3:0] reader_next_state;
+ // Header format
+ `define PAYLOAD 8:2
+ `define ENDOFBURST 27
+ `define STARTOFBURST 28
+ `define RSSI_FLAG 15
+
+
+ /* State registers */
+ reg [2:0] reader_state;
+
+ reg [6:0] payload_len;
+ reg [6:0] read_len;
+ reg [31:0] timestamp;
+ reg burst;
+ reg trash;
+ reg rssi_flag;
- //Variables
- reg[8:0] payload_len;
- reg[8:0] read_len;
- reg[31:0] timestamp;
- reg burst;
- reg qsample;
- always @(posedge tx_clock)
- begin
- if (reset)
+ always @(posedge tx_clock)
+ begin
+ if (reset)
begin
- reader_state <= `IDLE;
- reader_next_state <= `IDLE;
- rdreq <= 0;
- skip <= 0;
- overrun <= 0;
- underrun <= 0;
- burst <= 0;
- qsample <= 1;
- end
+ 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;
+ end
else
- begin
- reader_state = reader_next_state;
+ begin
case (reader_state)
- `IDLE:
- begin
- if (pkt_waiting == 1)
- begin
- reader_next_state <= `READ;
- rdreq <= 1;
- underrun <= 0;
- end
- else if (burst == 1)
+ 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;
+ if (pkt_waiting == 1)
+ begin
+ reader_state <= HEADER;
+ rdreq <= 1;
+ underrun <= 0;
+ end
+ else if (burst == 1)
underrun <= 1;
- end
-
- // Just wait for the fifo data to arrive
- `READ:
- begin
- reader_next_state <= `HEADER1;
- end
-
- // First part of the header
- `HEADER1:
- begin
- reader_next_state <= `HEADER2;
-
- //Check Start burst flag
- if (fifodata[3] == 1)
- burst <= 1;
- if (fifodata[4] == 1)
- burst <= 0;
- end
+ if (tx_strobe == 1)
+ tx_empty <= 1 ;
+ end
- // Read payload length
- `HEADER2:
- begin
- payload_len <= (fifodata & 16'h1FF);
- read_len <= 9'd0;
- reader_next_state <= `TIMESTAMP1;
- end
+ /* Process header */
+ HEADER:
+ begin
+ if (tx_strobe == 1)
+ tx_empty <= 1 ;
+
+ rssi_flag <= fifodata[`RSSI_FLAG]&fifodata[`STARTOFBURST];
+ //Check Start/End burst flag
+ if (fifodata[`STARTOFBURST] == 1
+ && fifodata[`ENDOFBURST] == 1)
+ burst <= 0;
+ else if (fifodata[`STARTOFBURST] == 1)
+ burst <= 1;
+ else if (fifodata[`ENDOFBURST] == 1)
+ burst <= 0;
- `TIMESTAMP1:
- begin
- timestamp <= {fifodata, 16'b0};
- rdreq <= 0;
- reader_next_state <= `TIMESTAMP2;
- end
-
- `TIMESTAMP2:
- begin
- timestamp <= timestamp + fifodata;
- reader_next_state <= `WAIT;
- 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
+ timestamp <= fifodata;
+ reader_state <= WAIT;
+ if (tx_strobe == 1)
+ tx_empty <= 1 ;
+ rdreq <= 0;
+ end
- // Decide if we wait, send or discard samples
- `WAIT:
- begin
- // Wait a little bit more
- if (timestamp > adc_clock + `JITTER)
- reader_next_state <= `WAIT;
+ // Decide if we wait, send or discard samples
+ WAIT:
+ begin
+ if (tx_strobe == 1)
+ tx_empty <= 1 ;
+
// Let's send it
- else if ((timestamp < adc_clock + `JITTER
- && timestamp > adc_clock)
- || timestamp == 32'hFFFFFFFF)
- begin
- reader_next_state <= `WAITSTROBE;
- end
+ if ((timestamp <= adc_time + `JITTER
+ && timestamp > adc_time)
+ || timestamp == 32'hFFFFFFFF)
+ begin
+ if (rssi <= threshhold || rssi_flag == 0)
+ begin
+ trash <= 0;
+ reader_state <= WAITSTROBE;
+ end
+ else
+ reader_state <= WAIT;
+ end
+ // Wait a little bit more
+ else if (timestamp > adc_time + `JITTER)
+ reader_state <= WAIT;
// Outdated
- else if (timestamp < adc_clock)
- begin
- reader_next_state <= `DISCARD;
- skip <= 1;
+ else if (timestamp < adc_time)
+ begin
+ trash <= 1;
+ reader_state <= IDLE;
+ skip <= 1;
end
- end
+ end
- // Wait for the transmit chain to be ready
- `WAITSTROBE:
- begin
- // If end of payload...
- if (read_len == payload_len)
+ // Wait for the transmit chain to be ready
+ WAITSTROBE:
+ begin
+ // If end of payload...
+ if (read_len == payload_len)
+ begin
+ reader_state <= IDLE;
+ skip <= 1;
+ if (tx_strobe == 1)
+ tx_empty <= 1 ;
+ end
+ else if (tx_strobe == 1)
+ begin
+ reader_state <= SEND;
+ rdreq <= 1;
+ end
+ end
+
+ // Send the samples to the tx_chain
+ SEND:
+ begin
+ reader_state <= WAITSTROBE;
+ read_len <= read_len + 7'd1;
+ tx_empty <= 0;
+ rdreq <= 0;
+
+ case(samples_format)
+ `QI16:
begin
- reader_next_state <= `DISCARD;
- skip <= (payload_len < 508);
+ tx_i <= fifodata[15:0];
+ tx_q <= fifodata[31:16];
end
-
- if (tx_strobe == 1)
- reader_next_state <= `SENDWAIT;
- end
-
- `SENDWAIT:
- begin
- rdreq <= 1;
- reader_next_state <= `SEND;
- end
-
- // Send the samples to the tx_chain
- `SEND:
- begin
- reader_next_state <= `WAITSTROBE;
- rdreq <= 0;
- read_len <= read_len + 2;
- case(samples_format)
- `QI16:
- begin
- tx_q <= qsample ? fifodata : 16'bZ;
- tx_i <= ~qsample ? fifodata : 16'bZ;
- qsample <= ~ qsample;
- end
+
+ // Assume 16 bits complex samples by default
default:
- begin
- // Assume 16 bits complex samples by default
- $display ("Error unknown samples format");
- tx_q <= qsample ? fifodata : 16'bZ;
- tx_i <= ~qsample ? fifodata : 16'bZ;
- qsample <= ~ qsample;
- end
- endcase
- end
-
- `DISCARD:
- begin
- skip <= 0;
- reader_next_state <= `IDLE;
- end
+ begin
+ tx_i <= fifodata[15:0];
+ tx_q <= fifodata[31:16];
+ end
+ endcase
+ end
default:
- begin
- $display ("Error unknown state");
- reader_state <= `IDLE;
- reader_next_state <= `IDLE;
- end
+ begin
+ //error handling
+ reader_state <= IDLE;
+ end
endcase
end
end
-endmodule \ No newline at end of file
+endmodule
diff --git a/usrp/fpga/inband_lib/channel_demux.v b/usrp/fpga/inband_lib/channel_demux.v
new file mode 100644
index 000000000..d46be9397
--- /dev/null
+++ b/usrp/fpga/inband_lib/channel_demux.v
@@ -0,0 +1,78 @@
+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 ;
+
+ // States
+ parameter IDLE = 3'd0;
+ parameter HEADER = 3'd1;
+ parameter WAIT = 3'd2;
+ parameter FORWARD = 3'd3;
+
+ `define CHANNEL 20:16
+ `define PKT_SIZE 127
+ wire [4:0] true_channel;
+ assign true_channel = (usbdata_final[`CHANNEL] == 5'h1f) ?
+ NUM_CHAN : (usbdata_final[`CHANNEL]);
+
+ always @(posedge txclk)
+ begin
+ if (reset)
+ begin
+ reader_state <= IDLE;
+ 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 <= true_channel;
+ WR_channel[true_channel] <= 1;
+ ram_data <= usbdata_final;
+ read_length <= 7'd0 ;
+
+ 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 + 7'd1;
+
+ reader_state <= WAIT;
+ end
+
+ default:
+ begin
+ //error handling
+ reader_state <= IDLE;
+ end
+ endcase
+ end
+endmodule
diff --git a/usrp/fpga/inband_lib/channel_ram.v b/usrp/fpga/inband_lib/channel_ram.v
new file mode 100755
index 000000000..40e0efc01
--- /dev/null
+++ b/usrp/fpga/inband_lib/channel_ram.v
@@ -0,0 +1,114 @@
+module channel_ram
+ ( // 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);
+
+ 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] 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;
+
+ // 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'd2)) ram2[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)
+ which_ram_wr <= 0;
+ else if (wr_done_int)
+ which_ram_wr <= which_ram_wr + 2'd1;
+
+ 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];
+
+ 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;
+
+ 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 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);
+
+ 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
diff --git a/usrp/fpga/inband_lib/cmd_reader.v b/usrp/fpga/inband_lib/cmd_reader.v
new file mode 100755
index 000000000..7604321e4
--- /dev/null
+++ b/usrp/fpga/inband_lib/cmd_reader.v
@@ -0,0 +1,292 @@
+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
+ );
+
+ // 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
+
+ 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
+
+ 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
+
+ HEADER : begin
+ payload <= fifodata[`PAYLOAD];
+ state <= TIMESTAMP;
+ 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;
+ 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
+
+ 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
+
+ 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_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
+
+ default : begin
+ //error state handling
+ state <= IDLE;
+ end
+ endcase
+endmodule \ No newline at end of file
diff --git a/usrp/fpga/inband_lib/data_packet_fifo.v b/usrp/fpga/inband_lib/data_packet_fifo.v
index 5b37b14ea..a9bcbdae7 100755
--- a/usrp/fpga/inband_lib/data_packet_fifo.v
+++ b/usrp/fpga/inband_lib/data_packet_fifo.v
@@ -1,128 +1,118 @@
module data_packet_fifo
( input reset,
input clock,
- input [15:0]ram_data_in,
+ input [31:0]ram_data_in,
input write_enable,
output reg have_space,
- output reg [15:0]ram_data_out,
+ 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 = 16 ;
+ parameter DATA_WIDTH = 32 ;
+ parameter PKT_DEPTH = 128 ;
parameter NUM_PACKETS = 4 ;
/* Create the RAM here */
- reg [DATA_WIDTH-1:0] usb_ram [256*NUM_PACKETS-1:0] ;
+ reg [DATA_WIDTH-1:0] usb_ram [PKT_DEPTH*NUM_PACKETS-1:0] ;
/* Create the address signals */
- reg [7:0] usb_ram_offset_out ;
- reg [1:0] usb_ram_packet_out ;
- reg [7:0] usb_ram_offset_in ;
- reg [1:0] usb_ram_packet_in ;
+ 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 [7-2+NUM_PACKETS:0] usb_ram_aout ;
- wire [7-2+NUM_PACKETS:0] usb_ram_ain ;
- reg isfull;
+ 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)
+ always @(usb_ram_ain, usb_ram_aout, isfull)
begin
- if (reset)
- pkt_waiting <= 0;
- else if (usb_ram_ain >= usb_ram_aout)
- pkt_waiting <= usb_ram_ain - usb_ram_aout >= 256;
+ 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'b1111111111 - usb_ram_aout) >= 256;
+ 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)
+ always @(usb_ram_ain, usb_ram_aout, isfull)
begin
- if (reset)
- have_space <= 1;
- else if (usb_ram_ain == usb_ram_aout)
+ 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) <= 256 * (NUM_PACKETS - 1);
+ 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) >= 256;
+ have_space <= (usb_ram_aout - usb_ram_ain) >= PKT_DEPTH;
end
- /* RAM Write Address process */
- always @(posedge clock)
- begin
- if( reset )
- begin
- usb_ram_offset_in <= 0 ;
- usb_ram_packet_in <= 0 ;
- end
- else
- if( pkt_complete )
- begin
- usb_ram_packet_in <= usb_ram_packet_in + 1;
- usb_ram_offset_in <= 0;
- end
- else if( write_enable )
- begin
- if (usb_ram_offset_in == 8'b11111111)
- begin
- usb_ram_offset_in <= 0;
- usb_ram_packet_in <= usb_ram_packet_in + 1;
- end
- else
- usb_ram_offset_in <= usb_ram_offset_in + 1 ;
- if (usb_ram_ain + 1 == usb_ram_aout)
- isfull <= 1;
- end
- end
- /* RAM Writing process */
+
+ /* 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 Read Address process */
+ /* 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 == 8'b11111111 )
+ 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 (usb_ram_ain == usb_ram_aout)
- isfull <= 0;
- end
-
- /* RAM Reading Process */
- always @(posedge clock)
- begin
- ram_data_out <= usb_ram[usb_ram_aout] ;
+ 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
new file mode 100755
index 000000000..205293479
--- /dev/null
+++ b/usrp/fpga/inband_lib/packet_builder.v
@@ -0,0 +1,132 @@
+module packet_builder #(parameter NUM_CHAN = 1)(
+ // System
+ input rxclk,
+ input reset,
+ input [31:0] adctime,
+ input [3:0] channels,
+ // ADC side
+ input [15:0]chan_fifodata,
+ input [NUM_CHAN:0]chan_empty,
+ input [9:0]chan_usedw,
+ output reg [3:0]rd_select,
+ output reg chan_rdreq,
+ // FX2 side
+ 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);
+
+
+ // States
+ `define IDLE 3'd0
+ `define HEADER1 3'd1
+ `define HEADER2 3'd2
+ `define TIMESTAMP 3'd3
+ `define FORWARD 3'd4
+
+ `define MAXPAYLOAD 504
+
+ `define PAYLOAD_LEN 8:0
+ `define TAG 12:9
+ `define MBZ 15:13
+
+ `define CHAN 4:0
+ `define RSSI 10:5
+ `define BURST 12:11
+ `define DROPPED 13
+ `define UNDERRUN 14
+ `define OVERRUN 15
+
+ reg [2:0] state;
+ reg [8:0] read_length;
+ reg [8:0] payload_len;
+ reg tstamp_complete;
+ reg [3:0] check_next;
+ wire [8:0] chan_used;
+ wire [31:0] true_rssi;
+
+ assign debugbus = {state, chan_empty[0], chan_empty[1], 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) :
+ ((rd_select[0]) ? rssi_1:rssi_0);
+ always @(posedge rxclk)
+ begin
+ if (reset)
+ begin
+ WR <= 0;
+ rd_select <= 0;
+ chan_rdreq <= 0;
+ tstamp_complete <= 0;
+ check_next <= 0;
+ state <= `IDLE;
+ end
+ else case (state)
+ `IDLE: begin
+ 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
+ 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[`TAG] <= #1 0;
+ fifodata[`MBZ] <= #1 0;
+ WR <= #1 1;
+
+ state <= #1 `HEADER2;
+ read_length <= #1 0;
+ end
+
+ `HEADER2: begin
+ fifodata[`CHAN] <= #1 (check_next == 4'd0 ? 5'h1f : {1'd0, check_next - 4'd1});
+ fifodata[`RSSI] <= #1 true_rssi[5:0];
+ fifodata[`BURST] <= #1 0;
+ fifodata[`DROPPED] <= #1 0;
+ fifodata[`UNDERRUN] <= #1 0;
+ fifodata[`OVERRUN] <= #1 0;
+
+ state <= #1 `TIMESTAMP;
+ end
+
+ `TIMESTAMP: begin
+ fifodata <= #1 (tstamp_complete ? adctime[31:16] : adctime[15:0]);
+ tstamp_complete <= #1 ~tstamp_complete;
+
+ if (~tstamp_complete)
+ chan_rdreq <= #1 1;
+
+ state <= #1 (tstamp_complete ? `FORWARD : `TIMESTAMP);
+ end
+
+ `FORWARD: begin
+ read_length <= #1 read_length + 9'd2;
+ fifodata <= #1 (read_length >= payload_len ? 16'hDEAD : chan_fifodata);
+
+ if (read_length >= `MAXPAYLOAD)
+ begin
+ WR <= #1 0;
+ state <= #1 `IDLE;
+ end
+ else if (read_length == payload_len - 4)
+ chan_rdreq <= #1 0;
+ end
+
+ default: begin
+ //handling error state
+ state <= `IDLE;
+ end
+ endcase
+ end
+endmodule
+
diff --git a/usrp/fpga/inband_lib/register_io.v b/usrp/fpga/inband_lib/register_io.v
new file mode 100755
index 000000000..63a26549c
--- /dev/null
+++ b/usrp/fpga/inband_lib/register_io.v
@@ -0,0 +1,60 @@
+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);
+
+ reg strobe;
+ wire [31:0] out[7:0];
+ assign debugbus = {clk, enable, addr[2:0], datain[4:0], dataout[4:0]};
+ assign threshhold = out[1];
+
+ always @(*)
+ if (reset | ~enable[1])
+ begin
+ strobe <= 0;
+ dataout <= 0;
+ end
+ else
+ begin
+ 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
+ else
+ begin
+ //write
+ dataout <= dataout;
+ strobe <= 1;
+ 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
diff --git a/usrp/fpga/inband_lib/rx_buffer_inband.v b/usrp/fpga/inband_lib/rx_buffer_inband.v
new file mode 100755
index 000000000..c23ce09b7
--- /dev/null
+++ b/usrp/fpga/inband_lib/rx_buffer_inband.v
@@ -0,0 +1,175 @@
+//`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
+ );
+
+ 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));
+
+ // 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];
+
+ 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_2kx16 rx_chan_fifo (
+ .aclr ( reset ),
+ .clock ( rxclk ),
+ .data ( ch[i] ),
+ .rdreq ( rdreq ),
+ .wrreq ( ~rx_full[i] & rxstrobe),
+ .empty ( ),
+ .full ( rx_full[i] ),
+ .q ( dataout[i]),
+ .usedw ( usedw[i] )
+ );
+ end
+ endgenerate
+ wire [7:0] debug;
+ fifo_2kx16 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 = {wrusedw, have_space, RD, read_count[8], rxclk};
+endmodule
diff --git a/usrp/fpga/inband_lib/tx_buffer_inband.v b/usrp/fpga/inband_lib/tx_buffer_inband.v
index 56c07807a..af7ed394a 100755
--- a/usrp/fpga/inband_lib/tx_buffer_inband.v
+++ b/usrp/fpga/inband_lib/tx_buffer_inband.v
@@ -1,183 +1,227 @@
module tx_buffer_inband
- ( input usbclk,
- input bus_reset, // Used here for the 257-Hack to fix the FX2 bug
- input reset, // standard DSP-side reset
- input [15:0] usbdata,
- input wire WR,
- output wire have_space,
- output reg tx_underrun,
- input wire [3:0] channels,
- output [15:0] tx_i_0,
- output [15:0] tx_q_0,
- output [15:0] tx_i_1,
- output [15:0] tx_q_1,
- //NOT USED
- output reg [15:0] tx_i_2,
- output reg [15:0] tx_q_2,
- output reg [15:0] tx_i_3,
- output reg [15:0] tx_q_3,
- input txclk,
- input txstrobe,
- input clear_status,
- output wire tx_empty,
- output [11:0] debugbus
- );
+ ( usbclk, bus_reset, reset, usbdata, WR, have_space,
+ tx_underrun, 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, threshhold
+ );
- wire [15:0] tx_data_bus;
+ //CHAN_WIDTH is the width of the channel
+ //NUM_CHAN is the number of data channel (index from 0 to NUM_CHAN-1)
+ //index NUM_CHAN is reserved for command
+
+ parameter CHAN_WIDTH = 2 ;
+ parameter NUM_CHAN = 2 ;
+ /* Debug paramters */
+ parameter STROBE_RATE_0 = 8'd1 ;
+ parameter STROBE_RATE_1 = 8'd2 ;
+
+ 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;
- wire WR_chan_0;
- wire chan_0_done;
- wire OR0;
- wire UR0;
-
- wire WR_chan_1;
- wire chan_1_done;
- wire OR1;
- wire UR1;
-
- // NOT USED yet
- wire WR_cmd;
- wire cmd_done;
-
- //EXTERNAL REGISTER
- //TODO: increment it
- reg [31:0] time_counter;
- reg [7:0] txstrobe_rate_0;
- reg [7:0] txstrobe_rate_1;
-
-
- //Usb block
- wire [15:0] tupf_fifodata;
- wire tupf_pkt_waiting;
- wire tupf_rdreq;
- wire tupf_skip;
- wire tupf_have_space;
+ output wire have_space ;
+ output wire tx_underrun ;
+ 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;
+
+ /* To generate channel readers */
+ genvar i ;
+
+ /* These will eventually be external register */
+ reg [31:0] adc_time ;
+ wire [7:0] txstrobe_rate [CHAN_WIDTH-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;
- usb_packet_fifo2 tx_usb_packet_fifo
- ( .reset (reset),
- .usb_clock (usbclk),
- .fpga_clock (txclk),
- .write_data (usbdata),
- .write_enable (WR),
- .read_data (tupf_fifodata),
- .pkt_waiting (tupf_pkt_waiting),
- .read_enable (tupf_rdreq),
- .skip_packet (tupf_skip),
- .have_space (tupf_have_space),
- .tx_empty (tx_empty)
- );
+ always @(posedge txclk)
+ if (reset)
+ adc_time <= 0;
+ else if (txstrobe)
+ adc_time <= adc_time + 1;
+
+
+ /* Connections between tx_usb_fifo_reader and
+ cnannel/command processing blocks */
+ wire [31:0] tx_data_bus ;
+ wire [CHAN_WIDTH:0] chan_WR ;
+ wire [CHAN_WIDTH:0] chan_done ;
+
+ /* Connections between data block and the
+ FX2/TX chains */
+ wire [CHAN_WIDTH:0] chan_underrun ;
+ wire [CHAN_WIDTH:0] chan_txempty ;
- usb_fifo_reader tx_usb_packet_reader (
- .reset(reset),
- .tx_clock(txclk),
- .tx_data_bus(tx_data_bus),
- .WR_chan_0(WR_chan_0),
- .WR_chan_1(WR_chan_1),
- .WR_cmd(WR_cmd),
- .chan_0_done(chan_0_done),
- .chan_1_done(chan_1_done),
- .cmd_done(cmd_done),
- .rdreq(tupf_rdreq),
- .skip(tupf_skip),
- .pkt_waiting(tupf_pkt_waiting),
- .fifodata(tupf_fifodata)
+ /* Conections between tx_data_packet_fifo and
+ its reader + strobe generator */
+ wire [31:0] chan_fifodata [CHAN_WIDTH:0] ;
+ wire chan_pkt_waiting [CHAN_WIDTH:0] ;
+ wire chan_rdreq [CHAN_WIDTH:0] ;
+ wire chan_skip [CHAN_WIDTH:0] ;
+ wire [CHAN_WIDTH:0] chan_have_space ;
+ wire chan_txstrobe [CHAN_WIDTH-1:0] ;
+
+ wire [14:0] debug;
+
+ /* Outputs to transmit chains */
+ wire [15:0] tx_i [CHAN_WIDTH-1:0] ;
+ wire [15:0] tx_q [CHAN_WIDTH-1: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_underrun = chan_underrun[0] | chan_underrun[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 debugbus = {debug, txclk};
+
+ 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)
+ );
+
+ 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)
);
+
+ generate for (i = 0 ; i < NUM_CHAN; i = i + 1)
+ begin : generate_channel_readers
+ 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),
+ .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)
+ );
+
+ end
+ endgenerate
- //Channel 0 block
- wire [15:0] tdpf_fifodata_0;
- wire tdpf_pkt_waiting_0;
- wire tdpf_rdreq_0;
- wire tdpf_skip_0;
- wire tdpf_have_space_0;
- wire txstrobe_chan_0;
- data_packet_fifo tx_data_packet_fifo_0
- ( .reset(reset),
- .clock(txclk),
- .ram_data_in(tx_data_bus),
- .write_enable(WR_chan_0),
- .ram_data_out(tdpf_fifodata_0),
- .pkt_waiting(tdpf_pkt_waiting_0),
- .read_enable(tdpf_rdreq_0),
- .pkt_complete(chan_0_done),
- .skip_packet(tdpf_skip_0),
- .have_space(tdpf_have_space_0)
- );
-
- strobe_gen strobe_gen_0
- ( .clock(txclk),
- .reset(reset),
- .enable(1'b1),
- .rate(txstrobe_rate_0),
- .strobe_in(txstrobe),
- .strobe(txstrobe_chan_0)
- );
-
- chan_fifo_reader tx_chan_0_reader (
- .reset(reset),
- .tx_clock(txclk),
- .tx_strobe(txstrobe),
- //.tx_strobe(txstrobe_chan_0),
- .adc_clock(time_counter),
- .samples_format(4'b0),
- .tx_q(tx_q_0),
- .tx_i(tx_i_0),
- .overrun(OR0),
- .underrun(UR0),
- .skip(tdpf_skip_0),
- .rdreq(tdpf_rdreq_0),
- .fifodata(tdpf_fifodata_0),
- .pkt_waiting(tdpf_pkt_waiting_0)
- );
-
-
- //Channel 1 block
- wire [15:0] tdpf_fifodata_1;
- wire tdpf_pkt_waiting_1;
- wire tdpf_rdreq_1;
- wire tdpf_skip_1;
- wire tdpf_have_space_1;
- wire txstrobe_chan_1;
-
- data_packet_fifo tx_data_packet_fifo_1
- ( .reset(reset),
- .clock(txclk),
- .ram_data_in(tx_data_bus),
- .write_enable(WR_chan_1),
- .ram_data_out(tdpf_fifodata_1),
- .pkt_waiting(tdpf_pkt_waiting_1),
- .read_enable(tdpf_rdreq_1),
- .pkt_complete(chan_1_done),
- .skip_packet(tdpf_skip_1),
- .have_space(tdpf_have_space_1)
- );
-
- strobe_gen strobe_gen_1
- ( .clock(txclk),
- .reset(reset),
- .enable(1'b1),
- .rate(txstrobe_rate_1),
- .strobe_in(txstrobe),
- .strobe(txstrobe_chan_1)
- );
-
- chan_fifo_reader tx_chan_1_reader (
- .reset(reset),
- .tx_clock(txclk),
- .tx_strobe(txstrobe),
- //.tx_strobe(txstrobe_chan_1),
- .adc_clock(time_counter),
- .samples_format(4'b0),
- .tx_q(tx_q_1),
- .tx_i(tx_i_1),
- .overrun(OR1),
- .underrun(UR1),
- .skip(tdpf_skip_1),
- .rdreq(tdpf_rdreq_1),
- .fifodata(tdpf_fifodata_1),
- .pkt_waiting(tdpf_pkt_waiting_1)
- );
+ 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)
+ );
+
+
endmodule // tx_buffer
diff --git a/usrp/fpga/inband_lib/tx_packer.v b/usrp/fpga/inband_lib/tx_packer.v
new file mode 100644
index 000000000..2f19b21f3
--- /dev/null
+++ b/usrp/fpga/inband_lib/tx_packer.v
@@ -0,0 +1,119 @@
+module tx_packer
+ ( //FX2 Side
+ input bus_reset,
+ input usbclk,
+ input WR_fx2,
+ input [15:0]usbdata,
+
+ // TX Side
+ input reset,
+ input txclk,
+ output reg [31:0] usbdata_final,
+ output reg WR_final);
+
+ reg [8:0] write_count;
+
+ /* Fix FX2 bug */
+ always @(posedge usbclk)
+ begin
+ 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;
+ end
+
+ 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 [15:0] usbdata_delayed ;
+ reg writing ;
+ wire [31: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 [31:0] usbdata_tx ;
+ reg WR_tx;
+ reg WR_1;
+ reg WR_2;
+
+ 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
+
+endmodule
diff --git a/usrp/fpga/inband_lib/usb_fifo_reader.v b/usrp/fpga/inband_lib/usb_fifo_reader.v
index 170c70fd4..d002d90ff 100755
--- a/usrp/fpga/inband_lib/usb_fifo_reader.v
+++ b/usrp/fpga/inband_lib/usb_fifo_reader.v
@@ -1,134 +1,24 @@
-module usb_fifo_reader (tx_clock, fifodata, pkt_waiting, reset,
- rdreq, skip, done_chan, WR_chan, tx_data_bus);
+module usb_fifo_reader (
+ input usbclk,
+ input bus_reset,
+ input RD,
+ output rdreq,
+ );
- /* Module parameters */
- parameter NUM_CHAN = 2 ;
- parameter WIDTH = 32 ;
+ // 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];
- input wire tx_clock ;
- input wire reset ;
- input wire [WIDTH-1:0] fifodata ;
- input wire pkt_waiting ;
- output reg rdreq ;
- output reg skip ;
- output reg [NUM_CHAN:0] done_chan ;
- output reg [NUM_CHAN:0] WR_chan ;
- output reg [WIDTH-1:0] tx_data_bus ;
-
-
-
- /* States definition */
- `define IDLE 3'd0
- `define WAIT 3'd1
- `define READ_HEADER 3'd2
- `define FORWARD_DATA 3'd3
- `define SKIP_REST 3'd4
-
- /* Channel Ids */
- `define TXCHAN0 5'h0
- `define TXCHAN1 5'h1
- `define TXCMD 5'h1F
-
- /* Local registers */
- reg [2:0] reader_state ;
- reg [2:0] reader_next_state ;
- reg [4:0] channel ;
- reg [8:0] pkt_length ;
- reg [8:0] read_length ;
- /* State Machine */
- always @(posedge tx_clock)
- begin
- if (reset)
- begin
- reader_state <= `IDLE ;
- reader_next_state <= `IDLE ;
- rdreq <= 0 ;
- skip <= 0 ;
- WR_chan <= {NUM_CHAN+1{1'b0}} ;
- done_chan <= {NUM_CHAN+1{1'b0}} ;
- end
- else
- begin
- reader_state = reader_next_state ;
-
- case(reader_state)
- `IDLE:
- begin
- reader_next_state <= pkt_waiting ? `WAIT : `IDLE ;
- rdreq <= pkt_waiting ;
- end
-
- /* Wait for the fifo's data to show up */
- `WAIT:
- begin
- reader_next_state <= `READ_HEADER ;
- end
-
- `READ_HEADER:
- begin
- reader_next_state <= `FORWARD_DATA ;
-
- /* Read header fields */
- channel <= (fifodata & 32'h1F0000) ;
- pkt_length <= (fifodata & 16'h1FF) + 4 ;
- read_length <= 9'd0 ;
-
- /* Forward data */
- case (channel)
- `TXCHAN0: WR_chan[0] <= 1 ;
- `TXCHAN1: WR_chan[1] <= 1 ;
- `TXCMD: WR_chan[2] <= 1 ;
- default: WR_chan <= 1 ;
- endcase
- tx_data_bus <= fifodata ;
- end
-
- `FORWARD_DATA:
- begin
- read_length <= read_length + 4 ;
-
- // If end of payload...
- if (read_length == pkt_length)
- begin
- reader_next_state <= `SKIP_REST ;
- /* If the packet is 512 bytes, don't skip */
- skip <= pkt_length < 506 ;
-
- /* Data pushing done */
- WR_chan <= {NUM_CHAN+1{1'b0}} ;
-
- /* Notify next block */
- case (channel)
- `TXCHAN0: done_chan[0] <= 1 ;
- `TXCHAN1: done_chan[1] <= 1 ;
- `TXCMD: done_chan[2] <= 1 ;
- default: done_chan[0] <= 1 ;
- endcase
- end
- else if (read_length == pkt_length - 4)
- rdreq <= 0 ;
-
- /* Forward data */
- tx_data_bus <= fifodata ;
- end
-
- `SKIP_REST:
- begin
- reader_next_state <= pkt_waiting ? `READ_HEADER : `IDLE ;
- done_chan <= {NUM_CHAN+1{1'b0}} ;
- rdreq <= pkt_waiting ;
- skip <= 0 ;
- end
-
- default:
- begin
- reader_state <= `IDLE;
- reader_next_state <= `IDLE;
- end
- endcase
- end
- end
+
endmodule
diff --git a/usrp/fpga/inband_lib/usb_fifo_writer.v b/usrp/fpga/inband_lib/usb_fifo_writer.v
new file mode 100755
index 000000000..abe1dd567
--- /dev/null
+++ b/usrp/fpga/inband_lib/usb_fifo_writer.v
@@ -0,0 +1,183 @@
+
+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/inband_lib/usb_packet_fifo2.v b/usrp/fpga/inband_lib/usb_packet_fifo2.v
deleted file mode 100755
index d815e4e37..000000000
--- a/usrp/fpga/inband_lib/usb_packet_fifo2.v
+++ /dev/null
@@ -1,119 +0,0 @@
-`default_nettype none
-
-module usb_packet_fifo2(reset, usb_clock, fpga_clock, write_enable, write_data,
- read_enable, skip_packet, read_data, have_space, pkt_waiting, tx_empty) ;
-
- /* Module parameters */
- parameter LOG2_N = 2 ;
- parameter BUS_WIDTH = 16 ;
- parameter FIFO_WIDTH = 32 ;
-
- input wire reset;
- input wire usb_clock ;
- input wire fpga_clock ;
- input wire write_enable ;
- input wire [BUS_WIDTH-1:0] write_data ;
- input wire read_enable ;
- input wire skip_packet ;
- output wire [FIFO_WIDTH-1:0] read_data ;
- output wire have_space ;
- output wire pkt_waiting ;
- output wire tx_empty;
-
-
- /* Variable for generate statement */
- genvar i ;
-
- /* Local wires for FIFO connections */
- wire [2**LOG2_N-1:0] fifo_resets ;
- reg [2**LOG2_N-1:0] fifo_we ;
- wire [2**LOG2_N-1:0] fifo_re ;
- reg [FIFO_WIDTH-1:0] fifo_wdata[2**LOG2_N-1:0] ;
- wire [FIFO_WIDTH-1:0] fifo_rdata[2**LOG2_N-1:0] ;
- wire [2**LOG2_N-1:0] fifo_rempty ;
- wire [2**LOG2_N-1:0] fifo_rfull ;
- wire [2**LOG2_N-1:0] fifo_wempty ;
- wire [2**LOG2_N-1:0] fifo_wfull ;
-
- /* FIFO Select for read and write ports */
- reg [LOG2_N-1:0] fifo_rselect ;
- reg [LOG2_N-1:0] fifo_wselect ;
-
- /* Used to convert 16 bits usbdata to the 32 bits wide fifo */
- reg word_complete ;
- reg [BUS_WIDTH-1:0] write_data_delayed ;
-
- /* Assign have_space to empty flag of currently selected write FIFO */
- assign have_space = fifo_wempty[fifo_wselect] ;
-
- /* Assign pkt_waiting to full flag of currently selected read FIFO */
- assign pkt_waiting = fifo_rfull[fifo_rselect] ;
-
- /* Assign the read_data to the output of the currently selected FIFO */
- assign read_data = fifo_rdata[fifo_rselect] ;
-
- /* Figure out if we're all empty */
- assign tx_empty = !(~fifo_rempty) ;
-
- /* Increment fifo_rselect here */
- always @(posedge fpga_clock)
- begin
- if (reset)
- fifo_rselect <= {2**LOG2_N{1'b0}} ;
-
- if (fifo_rempty[fifo_rselect])
- fifo_rselect <= fifo_rselect + 1 ;
-
- if (skip_packet)
- fifo_rselect <= fifo_rselect + 1 ;
- end
-
- /* Increment fifo_wselect and pack data into 32 bits block */
- always @(posedge usb_clock, reset)
- begin
- if (reset)
- begin
- fifo_wselect <= {2**LOG2_N{1'b0}} ;
- word_complete <= 0;
- end
-
- if (fifo_wfull[fifo_wselect])
- fifo_wselect <= fifo_wselect + 1 ;
-
- if (write_enable)
- begin
- word_complete <= ~word_complete ;
-
- if (word_complete)
- fifo_wdata[fifo_wselect] <= {write_data_delayed, write_data} ;
- else
- write_data_delayed <= write_data ;
-
- /* Avoid to continue to write in the previous fifo when we have
- just swichted to the next one */
- fifo_we[fifo_wselect-1] <= 0 ;
-
- fifo_we[fifo_wselect] <= write_enable & word_complete ;
- end
- end
-
- /* Generate all the single packet FIFOs */
- generate
- for( i = 0 ; i < 2**LOG2_N ; i = i + 1 )
- begin : generate_single_packet_fifos
- assign fifo_re[i] = (fifo_rselect == i) ? read_enable : 1'b0 ;
- assign fifo_resets[i] = (fifo_rselect == i) ? skip_packet : 1'b0 ;
- fifo_512 single_packet_fifo(.wrclk ( usb_clock ),
- .rdclk ( fpga_clock ),
- .aclr ( fifo_resets[i] ),
- .wrreq ( fifo_we[i] ),
- .data ( fifo_wdata[i] ),
- .rdreq ( fifo_re[i] ),
- .q ( fifo_rdata[i] ),
- .rdfull ( fifo_rfull[i] ),
- .rdempty( fifo_rempty[i] ),
- .wrfull ( fifo_wfull[i] ),
- .wrempty( fifo_wempty[i] ) ) ;
- end
- endgenerate
-endmodule \ No newline at end of file
diff --git a/usrp/fpga/megacells/fifo_512.v b/usrp/fpga/megacells/fifo_2k_1clk.v
index b034b4ddc..095615bb8 100755
--- a/usrp/fpga/megacells/fifo_512.v
+++ b/usrp/fpga/megacells/fifo_2k_1clk.v
@@ -1,12 +1,12 @@
// megafunction wizard: %LPM_FIFO+%
// GENERATION: STANDARD
// VERSION: WM1.0
-// MODULE: dcfifo
+// MODULE: scfifo
// ============================================================
-// File Name: fifo_512.v
+// File Name: fifo_2k_1clk.v
// Megafunction Name(s):
-// dcfifo
+// scfifo
// ============================================================
// ************************************************************
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
@@ -33,73 +33,65 @@
// synopsys translate_off
`timescale 1 ps / 1 ps
// synopsys translate_on
-module fifo_512 (
+module fifo_2k_1clk (
aclr,
+ clock,
data,
- rdclk,
rdreq,
- wrclk,
wrreq,
+ empty,
+ full,
q,
- rdempty,
- rdfull,
- wrempty,
- wrfull);
+ usedw);
input aclr;
- input [31:0] data;
- input rdclk;
+ input clock;
+ input [15:0] data;
input rdreq;
- input wrclk;
input wrreq;
- output [31:0] q;
- output rdempty;
- output rdfull;
- output wrempty;
- output wrfull;
+ output empty;
+ output full;
+ output [15:0] q;
+ output [9:0] usedw;
- wire sub_wire0;
+ wire [9:0] sub_wire0;
wire sub_wire1;
- wire sub_wire2;
+ wire [15:0] sub_wire2;
wire sub_wire3;
- wire [31:0] sub_wire4;
- wire rdfull = sub_wire0;
- wire rdempty = sub_wire1;
- wire wrfull = sub_wire2;
- wire wrempty = sub_wire3;
- wire [31:0] q = sub_wire4[31:0];
+ wire [9:0] usedw = sub_wire0[9:0];
+ wire empty = sub_wire1;
+ wire [15:0] q = sub_wire2[15:0];
+ wire full = sub_wire3;
- dcfifo dcfifo_component (
- .wrclk (wrclk),
+ scfifo scfifo_component (
.rdreq (rdreq),
.aclr (aclr),
- .rdclk (rdclk),
+ .clock (clock),
.wrreq (wrreq),
.data (data),
- .rdfull (sub_wire0),
- .rdempty (sub_wire1),
- .wrfull (sub_wire2),
- .wrempty (sub_wire3),
- .q (sub_wire4)
+ .usedw (sub_wire0),
+ .empty (sub_wire1),
+ .q (sub_wire2),
+ .full (sub_wire3)
// synopsys translate_off
,
- .rdusedw (),
- .wrusedw ()
+ .almost_empty (),
+ .sclr (),
+ .almost_full ()
// synopsys translate_on
);
defparam
- dcfifo_component.add_ram_output_register = "OFF",
- dcfifo_component.clocks_are_synchronized = "FALSE",
- dcfifo_component.intended_device_family = "Cyclone",
- dcfifo_component.lpm_hint = "RAM_BLOCK_TYPE=M4K",
- dcfifo_component.lpm_numwords = 128,
- dcfifo_component.lpm_showahead = "OFF",
- dcfifo_component.lpm_type = "dcfifo",
- dcfifo_component.lpm_width = 32,
- dcfifo_component.lpm_widthu = 7,
- dcfifo_component.overflow_checking = "ON",
- dcfifo_component.underflow_checking = "ON",
- dcfifo_component.use_eab = "ON";
+ scfifo_component.add_ram_output_register = "OFF",
+ scfifo_component.intended_device_family = "Cyclone",
+ scfifo_component.lpm_hint = "RAM_BLOCK_TYPE=M4K",
+ scfifo_component.lpm_numwords = 1024,
+ scfifo_component.lpm_showahead = "OFF",
+ scfifo_component.lpm_type = "scfifo",
+ scfifo_component.lpm_width = 16,
+ scfifo_component.lpm_widthu = 10,
+ scfifo_component.overflow_checking = "ON",
+ scfifo_component.underflow_checking = "ON",
+ scfifo_component.use_eab = "ON";
endmodule
@@ -112,8 +104,8 @@ endmodule
// Retrieval info: PRIVATE: AlmostFull NUMERIC "0"
// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1"
// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0"
-// Retrieval info: PRIVATE: Clock NUMERIC "4"
-// Retrieval info: PRIVATE: Depth NUMERIC "128"
+// Retrieval info: PRIVATE: Clock NUMERIC "0"
+// Retrieval info: PRIVATE: Depth NUMERIC "1024"
// Retrieval info: PRIVATE: Empty NUMERIC "1"
// Retrieval info: PRIVATE: Full NUMERIC "1"
// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone"
@@ -125,56 +117,51 @@ endmodule
// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "2"
// Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0"
// Retrieval info: PRIVATE: UsedW NUMERIC "1"
-// Retrieval info: PRIVATE: Width NUMERIC "32"
-// Retrieval info: PRIVATE: dc_aclr NUMERIC "1"
+// Retrieval info: PRIVATE: Width NUMERIC "16"
+// Retrieval info: PRIVATE: dc_aclr NUMERIC "0"
// Retrieval info: PRIVATE: rsEmpty NUMERIC "1"
-// Retrieval info: PRIVATE: rsFull NUMERIC "1"
+// Retrieval info: PRIVATE: rsFull NUMERIC "0"
// Retrieval info: PRIVATE: rsUsedW NUMERIC "0"
-// Retrieval info: PRIVATE: sc_aclr NUMERIC "0"
+// Retrieval info: PRIVATE: sc_aclr NUMERIC "1"
// Retrieval info: PRIVATE: sc_sclr NUMERIC "0"
-// Retrieval info: PRIVATE: wsEmpty NUMERIC "1"
+// Retrieval info: PRIVATE: wsEmpty NUMERIC "0"
// Retrieval info: PRIVATE: wsFull NUMERIC "1"
// Retrieval info: PRIVATE: wsUsedW NUMERIC "0"
// Retrieval info: CONSTANT: ADD_RAM_OUTPUT_REGISTER STRING "OFF"
-// Retrieval info: CONSTANT: CLOCKS_ARE_SYNCHRONIZED STRING "FALSE"
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone"
// Retrieval info: CONSTANT: LPM_HINT STRING "RAM_BLOCK_TYPE=M4K"
-// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "128"
+// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "1024"
// Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "OFF"
-// Retrieval info: CONSTANT: LPM_TYPE STRING "dcfifo"
-// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "32"
-// Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "7"
+// Retrieval info: CONSTANT: LPM_TYPE STRING "scfifo"
+// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "16"
+// Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "10"
// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON"
// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON"
// Retrieval info: CONSTANT: USE_EAB STRING "ON"
-// Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT GND aclr
-// Retrieval info: USED_PORT: data 0 0 32 0 INPUT NODEFVAL data[31..0]
-// Retrieval info: USED_PORT: q 0 0 32 0 OUTPUT NODEFVAL q[31..0]
-// Retrieval info: USED_PORT: rdclk 0 0 0 0 INPUT NODEFVAL rdclk
-// Retrieval info: USED_PORT: rdempty 0 0 0 0 OUTPUT NODEFVAL rdempty
-// Retrieval info: USED_PORT: rdfull 0 0 0 0 OUTPUT NODEFVAL rdfull
+// Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT NODEFVAL aclr
+// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL clock
+// Retrieval info: USED_PORT: data 0 0 16 0 INPUT NODEFVAL data[15..0]
+// Retrieval info: USED_PORT: empty 0 0 0 0 OUTPUT NODEFVAL empty
+// Retrieval info: USED_PORT: full 0 0 0 0 OUTPUT NODEFVAL full
+// Retrieval info: USED_PORT: q 0 0 16 0 OUTPUT NODEFVAL q[15..0]
// Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL rdreq
-// Retrieval info: USED_PORT: wrclk 0 0 0 0 INPUT NODEFVAL wrclk
-// Retrieval info: USED_PORT: wrempty 0 0 0 0 OUTPUT NODEFVAL wrempty
-// Retrieval info: USED_PORT: wrfull 0 0 0 0 OUTPUT NODEFVAL wrfull
+// Retrieval info: USED_PORT: usedw 0 0 10 0 OUTPUT NODEFVAL usedw[9..0]
// Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL wrreq
-// Retrieval info: CONNECT: @data 0 0 32 0 data 0 0 32 0
-// Retrieval info: CONNECT: q 0 0 32 0 @q 0 0 32 0
+// Retrieval info: CONNECT: @data 0 0 16 0 data 0 0 16 0
+// Retrieval info: CONNECT: q 0 0 16 0 @q 0 0 16 0
// Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0
// Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0
-// Retrieval info: CONNECT: @rdclk 0 0 0 0 rdclk 0 0 0 0
-// Retrieval info: CONNECT: @wrclk 0 0 0 0 wrclk 0 0 0 0
-// Retrieval info: CONNECT: rdfull 0 0 0 0 @rdfull 0 0 0 0
-// Retrieval info: CONNECT: rdempty 0 0 0 0 @rdempty 0 0 0 0
-// Retrieval info: CONNECT: wrfull 0 0 0 0 @wrfull 0 0 0 0
-// Retrieval info: CONNECT: wrempty 0 0 0 0 @wrempty 0 0 0 0
+// Retrieval info: CONNECT: @clock 0 0 0 0 clock 0 0 0 0
+// Retrieval info: CONNECT: full 0 0 0 0 @full 0 0 0 0
+// Retrieval info: CONNECT: empty 0 0 0 0 @empty 0 0 0 0
+// Retrieval info: CONNECT: usedw 0 0 10 0 @usedw 0 0 10 0
// Retrieval info: CONNECT: @aclr 0 0 0 0 aclr 0 0 0 0
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
-// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512.v TRUE
-// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512.inc TRUE
-// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512.cmp TRUE
-// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512.bsf TRUE
-// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512_inst.v TRUE
-// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512_bb.v TRUE
-// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512_waveforms.html TRUE
-// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512_wave*.jpg FALSE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2k_1clk.v TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2k_1clk.inc TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2k_1clk.cmp TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2k_1clk.bsf TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2k_1clk_inst.v TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2k_1clk_bb.v TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2k_1clk_waveforms.html FALSE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2k_1clk_wave*.jpg FALSE
diff --git a/usrp/fpga/megacells/fifo_2kx16.bsf b/usrp/fpga/megacells/fifo_2kx16.bsf
new file mode 100755
index 000000000..1067991fb
--- /dev/null
+++ b/usrp/fpga/megacells/fifo_2kx16.bsf
@@ -0,0 +1,99 @@
+/*
+WARNING: Do NOT edit the input and output ports in this file in a text
+editor if you plan to continue editing the block that represents it in
+the Block Editor! File corruption is VERY likely to occur.
+*/
+/*
+Copyright (C) 1991-2006 Altera Corporation
+Your use of Altera Corporation's design tools, logic functions
+and other software and tools, and its AMPP partner logic
+functions, and any output files any of the foregoing
+(including device programming or simulation files), and any
+associated documentation or information are expressly subject
+to the terms and conditions of the Altera Program License
+Subscription Agreement, Altera MegaCore Function License
+Agreement, or other applicable license agreement, including,
+without limitation, that your use is for the sole purpose of
+programming logic devices manufactured by Altera and sold by
+Altera or its authorized distributors. Please refer to the
+applicable agreement for further details.
+*/
+(header "symbol" (version "1.1"))
+(symbol
+ (rect 0 0 160 144)
+ (text "fifo_2kx16" (rect 51 1 119 17)(font "Arial" (font_size 10)))
+ (text "inst" (rect 8 128 25 140)(font "Arial" ))
+ (port
+ (pt 0 32)
+ (input)
+ (text "data[15..0]" (rect 0 0 60 14)(font "Arial" (font_size 8)))
+ (text "data[15..0]" (rect 20 26 71 39)(font "Arial" (font_size 8)))
+ (line (pt 0 32)(pt 16 32)(line_width 3))
+ )
+ (port
+ (pt 0 56)
+ (input)
+ (text "wrreq" (rect 0 0 35 14)(font "Arial" (font_size 8)))
+ (text "wrreq" (rect 20 50 45 63)(font "Arial" (font_size 8)))
+ (line (pt 0 56)(pt 16 56)(line_width 1))
+ )
+ (port
+ (pt 0 72)
+ (input)
+ (text "rdreq" (rect 0 0 30 14)(font "Arial" (font_size 8)))
+ (text "rdreq" (rect 20 66 44 79)(font "Arial" (font_size 8)))
+ (line (pt 0 72)(pt 16 72)(line_width 1))
+ )
+ (port
+ (pt 0 96)
+ (input)
+ (text "clock" (rect 0 0 29 14)(font "Arial" (font_size 8)))
+ (text "clock" (rect 26 90 49 103)(font "Arial" (font_size 8)))
+ (line (pt 0 96)(pt 16 96)(line_width 1))
+ )
+ (port
+ (pt 0 120)
+ (input)
+ (text "aclr" (rect 0 0 21 14)(font "Arial" (font_size 8)))
+ (text "aclr" (rect 20 114 37 127)(font "Arial" (font_size 8)))
+ (line (pt 0 120)(pt 16 120)(line_width 1))
+ )
+ (port
+ (pt 160 32)
+ (output)
+ (text "q[15..0]" (rect 0 0 42 14)(font "Arial" (font_size 8)))
+ (text "q[15..0]" (rect 105 26 141 39)(font "Arial" (font_size 8)))
+ (line (pt 160 32)(pt 144 32)(line_width 3))
+ )
+ (port
+ (pt 160 56)
+ (output)
+ (text "full" (rect 0 0 16 14)(font "Arial" (font_size 8)))
+ (text "full" (rect 127 50 142 63)(font "Arial" (font_size 8)))
+ (line (pt 160 56)(pt 144 56)(line_width 1))
+ )
+ (port
+ (pt 160 72)
+ (output)
+ (text "empty" (rect 0 0 34 14)(font "Arial" (font_size 8)))
+ (text "empty" (rect 112 66 141 79)(font "Arial" (font_size 8)))
+ (line (pt 160 72)(pt 144 72)(line_width 1))
+ )
+ (port
+ (pt 160 88)
+ (output)
+ (text "usedw[10..0]" (rect 0 0 75 14)(font "Arial" (font_size 8)))
+ (text "usedw[10..0]" (rect 77 82 136 95)(font "Arial" (font_size 8)))
+ (line (pt 160 88)(pt 144 88)(line_width 3))
+ )
+ (drawing
+ (text "16 bits x 2048 words" (rect 58 116 144 128)(font "Arial" ))
+ (line (pt 16 16)(pt 144 16)(line_width 1))
+ (line (pt 144 16)(pt 144 128)(line_width 1))
+ (line (pt 144 128)(pt 16 128)(line_width 1))
+ (line (pt 16 128)(pt 16 16)(line_width 1))
+ (line (pt 16 108)(pt 144 108)(line_width 1))
+ (line (pt 16 90)(pt 22 96)(line_width 1))
+ (line (pt 22 96)(pt 16 102)(line_width 1))
+ )
+)
diff --git a/usrp/fpga/megacells/fifo_512.cmp b/usrp/fpga/megacells/fifo_2kx16.cmp
index 86fc07846..96c34d8d7 100755
--- a/usrp/fpga/megacells/fifo_512.cmp
+++ b/usrp/fpga/megacells/fifo_2kx16.cmp
@@ -13,19 +13,17 @@
--applicable agreement for further details.
-component fifo_512
+component fifo_2kx16
PORT
(
- aclr : IN STD_LOGIC := '0';
- data : IN STD_LOGIC_VECTOR (31 DOWNTO 0);
- rdclk : IN STD_LOGIC ;
+ aclr : IN STD_LOGIC ;
+ clock : IN STD_LOGIC ;
+ data : IN STD_LOGIC_VECTOR (15 DOWNTO 0);
rdreq : IN STD_LOGIC ;
- wrclk : IN STD_LOGIC ;
wrreq : IN STD_LOGIC ;
- q : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);
- rdempty : OUT STD_LOGIC ;
- rdfull : OUT STD_LOGIC ;
- wrempty : OUT STD_LOGIC ;
- wrfull : OUT STD_LOGIC
+ empty : OUT STD_LOGIC ;
+ full : OUT STD_LOGIC ;
+ q : OUT STD_LOGIC_VECTOR (15 DOWNTO 0);
+ usedw : OUT STD_LOGIC_VECTOR (10 DOWNTO 0)
);
end component;
diff --git a/usrp/fpga/megacells/fifo_512.inc b/usrp/fpga/megacells/fifo_2kx16.inc
index 9ae1e3af4..3d72c6601 100755
--- a/usrp/fpga/megacells/fifo_512.inc
+++ b/usrp/fpga/megacells/fifo_2kx16.inc
@@ -13,20 +13,18 @@
--applicable agreement for further details.
-FUNCTION fifo_512
+FUNCTION fifo_2kx16
(
aclr,
- data[31..0],
- rdclk,
+ clock,
+ data[15..0],
rdreq,
- wrclk,
wrreq
)
RETURNS (
- q[31..0],
- rdempty,
- rdfull,
- wrempty,
- wrfull
+ empty,
+ full,
+ q[15..0],
+ usedw[10..0]
);
diff --git a/usrp/fpga/megacells/fifo_2kx16.v b/usrp/fpga/megacells/fifo_2kx16.v
new file mode 100755
index 000000000..eb229769d
--- /dev/null
+++ b/usrp/fpga/megacells/fifo_2kx16.v
@@ -0,0 +1,167 @@
+// megafunction wizard: %FIFO%
+// GENERATION: STANDARD
+// VERSION: WM1.0
+// MODULE: scfifo
+
+// ============================================================
+// File Name: fifo_2kx16.v
+// Megafunction Name(s):
+// scfifo
+// ============================================================
+// ************************************************************
+// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
+//
+// 5.1 Build 213 01/19/2006 SP 1 SJ Web Edition
+// ************************************************************
+
+
+//Copyright (C) 1991-2006 Altera Corporation
+//Your use of Altera Corporation's design tools, logic functions
+//and other software and tools, and its AMPP partner logic
+//functions, and any output files any of the foregoing
+//(including device programming or simulation files), and any
+//associated documentation or information are expressly subject
+//to the terms and conditions of the Altera Program License
+//Subscription Agreement, Altera MegaCore Function License
+//Agreement, or other applicable license agreement, including,
+//without limitation, that your use is for the sole purpose of
+//programming logic devices manufactured by Altera and sold by
+//Altera or its authorized distributors. Please refer to the
+//applicable agreement for further details.
+
+
+// synopsys translate_off
+`timescale 1 ps / 1 ps
+// synopsys translate_on
+module fifo_2kx16 (
+ aclr,
+ clock,
+ data,
+ rdreq,
+ wrreq,
+ empty,
+ full,
+ q,
+ usedw);
+
+ input aclr;
+ input clock;
+ input [15:0] data;
+ input rdreq;
+ input wrreq;
+ output empty;
+ output full;
+ output [15:0] q;
+ output [10:0] usedw;
+
+ wire [10:0] sub_wire0;
+ wire sub_wire1;
+ wire [15:0] sub_wire2;
+ wire sub_wire3;
+ wire [10:0] usedw = sub_wire0[10:0];
+ wire empty = sub_wire1;
+ wire [15:0] q = sub_wire2[15:0];
+ wire full = sub_wire3;
+
+ scfifo scfifo_component (
+ .rdreq (rdreq),
+ .aclr (aclr),
+ .clock (clock),
+ .wrreq (wrreq),
+ .data (data),
+ .usedw (sub_wire0),
+ .empty (sub_wire1),
+ .q (sub_wire2),
+ .full (sub_wire3)
+ // synopsys translate_off
+ ,
+ .almost_empty (),
+ .sclr (),
+ .almost_full ()
+ // synopsys translate_on
+ );
+ defparam
+ scfifo_component.add_ram_output_register = "OFF",
+ scfifo_component.intended_device_family = "Cyclone",
+ scfifo_component.lpm_hint = "RAM_BLOCK_TYPE=M4K",
+ scfifo_component.lpm_numwords = 2048,
+ scfifo_component.lpm_showahead = "OFF",
+ scfifo_component.lpm_type = "scfifo",
+ scfifo_component.lpm_width = 16,
+ scfifo_component.lpm_widthu = 11,
+ scfifo_component.overflow_checking = "ON",
+ scfifo_component.underflow_checking = "ON",
+ scfifo_component.use_eab = "ON";
+
+
+endmodule
+
+// ============================================================
+// CNX file retrieval info
+// ============================================================
+// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0"
+// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1"
+// Retrieval info: PRIVATE: AlmostFull NUMERIC "0"
+// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1"
+// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0"
+// Retrieval info: PRIVATE: Clock NUMERIC "0"
+// Retrieval info: PRIVATE: Depth NUMERIC "2048"
+// Retrieval info: PRIVATE: Empty NUMERIC "1"
+// Retrieval info: PRIVATE: Full NUMERIC "1"
+// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone"
+// Retrieval info: PRIVATE: LE_BasedFIFO NUMERIC "0"
+// Retrieval info: PRIVATE: LegacyRREQ NUMERIC "1"
+// Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0"
+// Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "0"
+// Retrieval info: PRIVATE: Optimize NUMERIC "2"
+// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "2"
+// Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0"
+// Retrieval info: PRIVATE: UsedW NUMERIC "1"
+// Retrieval info: PRIVATE: Width NUMERIC "16"
+// Retrieval info: PRIVATE: dc_aclr NUMERIC "0"
+// Retrieval info: PRIVATE: rsEmpty NUMERIC "1"
+// Retrieval info: PRIVATE: rsFull NUMERIC "0"
+// Retrieval info: PRIVATE: rsUsedW NUMERIC "0"
+// Retrieval info: PRIVATE: sc_aclr NUMERIC "1"
+// Retrieval info: PRIVATE: sc_sclr NUMERIC "0"
+// Retrieval info: PRIVATE: wsEmpty NUMERIC "0"
+// Retrieval info: PRIVATE: wsFull NUMERIC "1"
+// Retrieval info: PRIVATE: wsUsedW NUMERIC "0"
+// Retrieval info: CONSTANT: ADD_RAM_OUTPUT_REGISTER STRING "OFF"
+// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone"
+// Retrieval info: CONSTANT: LPM_HINT STRING "RAM_BLOCK_TYPE=M4K"
+// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "2048"
+// Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "OFF"
+// Retrieval info: CONSTANT: LPM_TYPE STRING "scfifo"
+// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "16"
+// Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "11"
+// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON"
+// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON"
+// Retrieval info: CONSTANT: USE_EAB STRING "ON"
+// Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT NODEFVAL aclr
+// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL clock
+// Retrieval info: USED_PORT: data 0 0 16 0 INPUT NODEFVAL data[15..0]
+// Retrieval info: USED_PORT: empty 0 0 0 0 OUTPUT NODEFVAL empty
+// Retrieval info: USED_PORT: full 0 0 0 0 OUTPUT NODEFVAL full
+// Retrieval info: USED_PORT: q 0 0 16 0 OUTPUT NODEFVAL q[15..0]
+// Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL rdreq
+// Retrieval info: USED_PORT: usedw 0 0 11 0 OUTPUT NODEFVAL usedw[10..0]
+// Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL wrreq
+// Retrieval info: CONNECT: @data 0 0 16 0 data 0 0 16 0
+// Retrieval info: CONNECT: q 0 0 16 0 @q 0 0 16 0
+// Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0
+// Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0
+// Retrieval info: CONNECT: @clock 0 0 0 0 clock 0 0 0 0
+// Retrieval info: CONNECT: full 0 0 0 0 @full 0 0 0 0
+// Retrieval info: CONNECT: empty 0 0 0 0 @empty 0 0 0 0
+// Retrieval info: CONNECT: usedw 0 0 11 0 @usedw 0 0 11 0
+// Retrieval info: CONNECT: @aclr 0 0 0 0 aclr 0 0 0 0
+// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2kx16.v TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2kx16.inc TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2kx16.cmp TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2kx16.bsf TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2kx16_inst.v TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2kx16_bb.v TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2kx16_waveforms.html TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2kx16_wave*.jpg FALSE
diff --git a/usrp/fpga/megacells/fifo_512_bb.v b/usrp/fpga/megacells/fifo_2kx16_bb.v
index b11803159..507bac073 100755
--- a/usrp/fpga/megacells/fifo_512_bb.v
+++ b/usrp/fpga/megacells/fifo_2kx16_bb.v
@@ -1,12 +1,12 @@
-// megafunction wizard: %LPM_FIFO+%VBB%
+// megafunction wizard: %FIFO%VBB%
// GENERATION: STANDARD
// VERSION: WM1.0
-// MODULE: dcfifo
+// MODULE: scfifo
// ============================================================
-// File Name: fifo_512.v
+// File Name: fifo_2kx16.v
// Megafunction Name(s):
-// dcfifo
+// scfifo
// ============================================================
// ************************************************************
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
@@ -28,30 +28,26 @@
//Altera or its authorized distributors. Please refer to the
//applicable agreement for further details.
-module fifo_512 (
+module fifo_2kx16 (
aclr,
+ clock,
data,
- rdclk,
rdreq,
- wrclk,
wrreq,
+ empty,
+ full,
q,
- rdempty,
- rdfull,
- wrempty,
- wrfull);
+ usedw);
input aclr;
- input [31:0] data;
- input rdclk;
+ input clock;
+ input [15:0] data;
input rdreq;
- input wrclk;
input wrreq;
- output [31:0] q;
- output rdempty;
- output rdfull;
- output wrempty;
- output wrfull;
+ output empty;
+ output full;
+ output [15:0] q;
+ output [10:0] usedw;
endmodule
@@ -63,8 +59,8 @@ endmodule
// Retrieval info: PRIVATE: AlmostFull NUMERIC "0"
// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1"
// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0"
-// Retrieval info: PRIVATE: Clock NUMERIC "4"
-// Retrieval info: PRIVATE: Depth NUMERIC "128"
+// Retrieval info: PRIVATE: Clock NUMERIC "0"
+// Retrieval info: PRIVATE: Depth NUMERIC "2048"
// Retrieval info: PRIVATE: Empty NUMERIC "1"
// Retrieval info: PRIVATE: Full NUMERIC "1"
// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone"
@@ -76,56 +72,51 @@ endmodule
// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "2"
// Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0"
// Retrieval info: PRIVATE: UsedW NUMERIC "1"
-// Retrieval info: PRIVATE: Width NUMERIC "32"
-// Retrieval info: PRIVATE: dc_aclr NUMERIC "1"
+// Retrieval info: PRIVATE: Width NUMERIC "16"
+// Retrieval info: PRIVATE: dc_aclr NUMERIC "0"
// Retrieval info: PRIVATE: rsEmpty NUMERIC "1"
-// Retrieval info: PRIVATE: rsFull NUMERIC "1"
+// Retrieval info: PRIVATE: rsFull NUMERIC "0"
// Retrieval info: PRIVATE: rsUsedW NUMERIC "0"
-// Retrieval info: PRIVATE: sc_aclr NUMERIC "0"
+// Retrieval info: PRIVATE: sc_aclr NUMERIC "1"
// Retrieval info: PRIVATE: sc_sclr NUMERIC "0"
-// Retrieval info: PRIVATE: wsEmpty NUMERIC "1"
+// Retrieval info: PRIVATE: wsEmpty NUMERIC "0"
// Retrieval info: PRIVATE: wsFull NUMERIC "1"
// Retrieval info: PRIVATE: wsUsedW NUMERIC "0"
// Retrieval info: CONSTANT: ADD_RAM_OUTPUT_REGISTER STRING "OFF"
-// Retrieval info: CONSTANT: CLOCKS_ARE_SYNCHRONIZED STRING "FALSE"
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone"
// Retrieval info: CONSTANT: LPM_HINT STRING "RAM_BLOCK_TYPE=M4K"
-// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "128"
+// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "2048"
// Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "OFF"
-// Retrieval info: CONSTANT: LPM_TYPE STRING "dcfifo"
-// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "32"
-// Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "7"
+// Retrieval info: CONSTANT: LPM_TYPE STRING "scfifo"
+// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "16"
+// Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "11"
// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON"
// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON"
// Retrieval info: CONSTANT: USE_EAB STRING "ON"
-// Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT GND aclr
-// Retrieval info: USED_PORT: data 0 0 32 0 INPUT NODEFVAL data[31..0]
-// Retrieval info: USED_PORT: q 0 0 32 0 OUTPUT NODEFVAL q[31..0]
-// Retrieval info: USED_PORT: rdclk 0 0 0 0 INPUT NODEFVAL rdclk
-// Retrieval info: USED_PORT: rdempty 0 0 0 0 OUTPUT NODEFVAL rdempty
-// Retrieval info: USED_PORT: rdfull 0 0 0 0 OUTPUT NODEFVAL rdfull
+// Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT NODEFVAL aclr
+// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL clock
+// Retrieval info: USED_PORT: data 0 0 16 0 INPUT NODEFVAL data[15..0]
+// Retrieval info: USED_PORT: empty 0 0 0 0 OUTPUT NODEFVAL empty
+// Retrieval info: USED_PORT: full 0 0 0 0 OUTPUT NODEFVAL full
+// Retrieval info: USED_PORT: q 0 0 16 0 OUTPUT NODEFVAL q[15..0]
// Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL rdreq
-// Retrieval info: USED_PORT: wrclk 0 0 0 0 INPUT NODEFVAL wrclk
-// Retrieval info: USED_PORT: wrempty 0 0 0 0 OUTPUT NODEFVAL wrempty
-// Retrieval info: USED_PORT: wrfull 0 0 0 0 OUTPUT NODEFVAL wrfull
+// Retrieval info: USED_PORT: usedw 0 0 11 0 OUTPUT NODEFVAL usedw[10..0]
// Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL wrreq
-// Retrieval info: CONNECT: @data 0 0 32 0 data 0 0 32 0
-// Retrieval info: CONNECT: q 0 0 32 0 @q 0 0 32 0
+// Retrieval info: CONNECT: @data 0 0 16 0 data 0 0 16 0
+// Retrieval info: CONNECT: q 0 0 16 0 @q 0 0 16 0
// Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0
// Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0
-// Retrieval info: CONNECT: @rdclk 0 0 0 0 rdclk 0 0 0 0
-// Retrieval info: CONNECT: @wrclk 0 0 0 0 wrclk 0 0 0 0
-// Retrieval info: CONNECT: rdfull 0 0 0 0 @rdfull 0 0 0 0
-// Retrieval info: CONNECT: rdempty 0 0 0 0 @rdempty 0 0 0 0
-// Retrieval info: CONNECT: wrfull 0 0 0 0 @wrfull 0 0 0 0
-// Retrieval info: CONNECT: wrempty 0 0 0 0 @wrempty 0 0 0 0
+// Retrieval info: CONNECT: @clock 0 0 0 0 clock 0 0 0 0
+// Retrieval info: CONNECT: full 0 0 0 0 @full 0 0 0 0
+// Retrieval info: CONNECT: empty 0 0 0 0 @empty 0 0 0 0
+// Retrieval info: CONNECT: usedw 0 0 11 0 @usedw 0 0 11 0
// Retrieval info: CONNECT: @aclr 0 0 0 0 aclr 0 0 0 0
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
-// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512.v TRUE
-// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512.inc TRUE
-// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512.cmp TRUE
-// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512.bsf TRUE
-// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512_inst.v TRUE
-// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512_bb.v TRUE
-// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512_waveforms.html TRUE
-// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_512_wave*.jpg FALSE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2kx16.v TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2kx16.inc TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2kx16.cmp TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2kx16.bsf TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2kx16_inst.v TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2kx16_bb.v TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2kx16_waveforms.html TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_2kx16_wave*.jpg FALSE
diff --git a/usrp/fpga/megacells/fifo_2kx16_inst.v b/usrp/fpga/megacells/fifo_2kx16_inst.v
new file mode 100755
index 000000000..6185c6fe6
--- /dev/null
+++ b/usrp/fpga/megacells/fifo_2kx16_inst.v
@@ -0,0 +1,11 @@
+fifo_2kx16 fifo_2kx16_inst (
+ .aclr ( aclr_sig ),
+ .clock ( clock_sig ),
+ .data ( data_sig ),
+ .rdreq ( rdreq_sig ),
+ .wrreq ( wrreq_sig ),
+ .empty ( empty_sig ),
+ .full ( full_sig ),
+ .q ( q_sig ),
+ .usedw ( usedw_sig )
+ );
diff --git a/usrp/fpga/megacells/fifo_4kx16.bsf b/usrp/fpga/megacells/fifo_4kx16.bsf
new file mode 100755
index 000000000..4d988c5e9
--- /dev/null
+++ b/usrp/fpga/megacells/fifo_4kx16.bsf
@@ -0,0 +1,99 @@
+/*
+WARNING: Do NOT edit the input and output ports in this file in a text
+editor if you plan to continue editing the block that represents it in
+the Block Editor! File corruption is VERY likely to occur.
+*/
+/*
+Copyright (C) 1991-2006 Altera Corporation
+Your use of Altera Corporation's design tools, logic functions
+and other software and tools, and its AMPP partner logic
+functions, and any output files any of the foregoing
+(including device programming or simulation files), and any
+associated documentation or information are expressly subject
+to the terms and conditions of the Altera Program License
+Subscription Agreement, Altera MegaCore Function License
+Agreement, or other applicable license agreement, including,
+without limitation, that your use is for the sole purpose of
+programming logic devices manufactured by Altera and sold by
+Altera or its authorized distributors. Please refer to the
+applicable agreement for further details.
+*/
+(header "symbol" (version "1.1"))
+(symbol
+ (rect 0 0 160 144)
+ (text "fifo_4kx16" (rect 51 1 119 17)(font "Arial" (font_size 10)))
+ (text "inst" (rect 8 128 25 140)(font "Arial" ))
+ (port
+ (pt 0 32)
+ (input)
+ (text "data[15..0]" (rect 0 0 60 14)(font "Arial" (font_size 8)))
+ (text "data[15..0]" (rect 20 26 71 39)(font "Arial" (font_size 8)))
+ (line (pt 0 32)(pt 16 32)(line_width 3))
+ )
+ (port
+ (pt 0 56)
+ (input)
+ (text "wrreq" (rect 0 0 35 14)(font "Arial" (font_size 8)))
+ (text "wrreq" (rect 20 50 45 63)(font "Arial" (font_size 8)))
+ (line (pt 0 56)(pt 16 56)(line_width 1))
+ )
+ (port
+ (pt 0 72)
+ (input)
+ (text "rdreq" (rect 0 0 30 14)(font "Arial" (font_size 8)))
+ (text "rdreq" (rect 20 66 44 79)(font "Arial" (font_size 8)))
+ (line (pt 0 72)(pt 16 72)(line_width 1))
+ )
+ (port
+ (pt 0 96)
+ (input)
+ (text "clock" (rect 0 0 29 14)(font "Arial" (font_size 8)))
+ (text "clock" (rect 26 90 49 103)(font "Arial" (font_size 8)))
+ (line (pt 0 96)(pt 16 96)(line_width 1))
+ )
+ (port
+ (pt 0 120)
+ (input)
+ (text "aclr" (rect 0 0 21 14)(font "Arial" (font_size 8)))
+ (text "aclr" (rect 20 114 37 127)(font "Arial" (font_size 8)))
+ (line (pt 0 120)(pt 16 120)(line_width 1))
+ )
+ (port
+ (pt 160 32)
+ (output)
+ (text "q[15..0]" (rect 0 0 42 14)(font "Arial" (font_size 8)))
+ (text "q[15..0]" (rect 105 26 141 39)(font "Arial" (font_size 8)))
+ (line (pt 160 32)(pt 144 32)(line_width 3))
+ )
+ (port
+ (pt 160 56)
+ (output)
+ (text "full" (rect 0 0 16 14)(font "Arial" (font_size 8)))
+ (text "full" (rect 127 50 142 63)(font "Arial" (font_size 8)))
+ (line (pt 160 56)(pt 144 56)(line_width 1))
+ )
+ (port
+ (pt 160 72)
+ (output)
+ (text "empty" (rect 0 0 34 14)(font "Arial" (font_size 8)))
+ (text "empty" (rect 112 66 141 79)(font "Arial" (font_size 8)))
+ (line (pt 160 72)(pt 144 72)(line_width 1))
+ )
+ (port
+ (pt 160 88)
+ (output)
+ (text "usedw[11..0]" (rect 0 0 75 14)(font "Arial" (font_size 8)))
+ (text "usedw[11..0]" (rect 77 82 136 95)(font "Arial" (font_size 8)))
+ (line (pt 160 88)(pt 144 88)(line_width 3))
+ )
+ (drawing
+ (text "16 bits x 4096 words" (rect 58 116 144 128)(font "Arial" ))
+ (line (pt 16 16)(pt 144 16)(line_width 1))
+ (line (pt 144 16)(pt 144 128)(line_width 1))
+ (line (pt 144 128)(pt 16 128)(line_width 1))
+ (line (pt 16 128)(pt 16 16)(line_width 1))
+ (line (pt 16 108)(pt 144 108)(line_width 1))
+ (line (pt 16 90)(pt 22 96)(line_width 1))
+ (line (pt 22 96)(pt 16 102)(line_width 1))
+ )
+)
diff --git a/usrp/fpga/megacells/fifo_4kx16.cmp b/usrp/fpga/megacells/fifo_4kx16.cmp
new file mode 100755
index 000000000..7bc6941d7
--- /dev/null
+++ b/usrp/fpga/megacells/fifo_4kx16.cmp
@@ -0,0 +1,29 @@
+--Copyright (C) 1991-2006 Altera Corporation
+--Your use of Altera Corporation's design tools, logic functions
+--and other software and tools, and its AMPP partner logic
+--functions, and any output files any of the foregoing
+--(including device programming or simulation files), and any
+--associated documentation or information are expressly subject
+--to the terms and conditions of the Altera Program License
+--Subscription Agreement, Altera MegaCore Function License
+--Agreement, or other applicable license agreement, including,
+--without limitation, that your use is for the sole purpose of
+--programming logic devices manufactured by Altera and sold by
+--Altera or its authorized distributors. Please refer to the
+--applicable agreement for further details.
+
+
+component fifo_4kx16
+ PORT
+ (
+ aclr : IN STD_LOGIC ;
+ clock : IN STD_LOGIC ;
+ data : IN STD_LOGIC_VECTOR (15 DOWNTO 0);
+ rdreq : IN STD_LOGIC ;
+ wrreq : IN STD_LOGIC ;
+ empty : OUT STD_LOGIC ;
+ full : OUT STD_LOGIC ;
+ q : OUT STD_LOGIC_VECTOR (15 DOWNTO 0);
+ usedw : OUT STD_LOGIC_VECTOR (11 DOWNTO 0)
+ );
+end component;
diff --git a/usrp/fpga/megacells/fifo_4kx16.inc b/usrp/fpga/megacells/fifo_4kx16.inc
new file mode 100755
index 000000000..db5d4f29e
--- /dev/null
+++ b/usrp/fpga/megacells/fifo_4kx16.inc
@@ -0,0 +1,30 @@
+--Copyright (C) 1991-2006 Altera Corporation
+--Your use of Altera Corporation's design tools, logic functions
+--and other software and tools, and its AMPP partner logic
+--functions, and any output files any of the foregoing
+--(including device programming or simulation files), and any
+--associated documentation or information are expressly subject
+--to the terms and conditions of the Altera Program License
+--Subscription Agreement, Altera MegaCore Function License
+--Agreement, or other applicable license agreement, including,
+--without limitation, that your use is for the sole purpose of
+--programming logic devices manufactured by Altera and sold by
+--Altera or its authorized distributors. Please refer to the
+--applicable agreement for further details.
+
+
+FUNCTION fifo_4kx16
+(
+ aclr,
+ clock,
+ data[15..0],
+ rdreq,
+ wrreq
+)
+
+RETURNS (
+ empty,
+ full,
+ q[15..0],
+ usedw[11..0]
+);
diff --git a/usrp/fpga/megacells/fifo_4kx16.v b/usrp/fpga/megacells/fifo_4kx16.v
new file mode 100755
index 000000000..c5ecfbae7
--- /dev/null
+++ b/usrp/fpga/megacells/fifo_4kx16.v
@@ -0,0 +1,167 @@
+// megafunction wizard: %FIFO%
+// GENERATION: STANDARD
+// VERSION: WM1.0
+// MODULE: scfifo
+
+// ============================================================
+// File Name: fifo_4kx16.v
+// Megafunction Name(s):
+// scfifo
+// ============================================================
+// ************************************************************
+// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
+//
+// 5.1 Build 213 01/19/2006 SP 1 SJ Web Edition
+// ************************************************************
+
+
+//Copyright (C) 1991-2006 Altera Corporation
+//Your use of Altera Corporation's design tools, logic functions
+//and other software and tools, and its AMPP partner logic
+//functions, and any output files any of the foregoing
+//(including device programming or simulation files), and any
+//associated documentation or information are expressly subject
+//to the terms and conditions of the Altera Program License
+//Subscription Agreement, Altera MegaCore Function License
+//Agreement, or other applicable license agreement, including,
+//without limitation, that your use is for the sole purpose of
+//programming logic devices manufactured by Altera and sold by
+//Altera or its authorized distributors. Please refer to the
+//applicable agreement for further details.
+
+
+// synopsys translate_off
+`timescale 1 ps / 1 ps
+// synopsys translate_on
+module fifo_4kx16 (
+ aclr,
+ clock,
+ data,
+ rdreq,
+ wrreq,
+ empty,
+ full,
+ q,
+ usedw);
+
+ input aclr;
+ input clock;
+ input [15:0] data;
+ input rdreq;
+ input wrreq;
+ output empty;
+ output full;
+ output [15:0] q;
+ output [11:0] usedw;
+
+ wire [11:0] sub_wire0;
+ wire sub_wire1;
+ wire [15:0] sub_wire2;
+ wire sub_wire3;
+ wire [11:0] usedw = sub_wire0[11:0];
+ wire empty = sub_wire1;
+ wire [15:0] q = sub_wire2[15:0];
+ wire full = sub_wire3;
+
+ scfifo scfifo_component (
+ .rdreq (rdreq),
+ .aclr (aclr),
+ .clock (clock),
+ .wrreq (wrreq),
+ .data (data),
+ .usedw (sub_wire0),
+ .empty (sub_wire1),
+ .q (sub_wire2),
+ .full (sub_wire3)
+ // synopsys translate_off
+ ,
+ .almost_empty (),
+ .sclr (),
+ .almost_full ()
+ // synopsys translate_on
+ );
+ defparam
+ scfifo_component.add_ram_output_register = "OFF",
+ scfifo_component.intended_device_family = "Cyclone",
+ scfifo_component.lpm_hint = "RAM_BLOCK_TYPE=M4K",
+ scfifo_component.lpm_numwords = 4096,
+ scfifo_component.lpm_showahead = "OFF",
+ scfifo_component.lpm_type = "scfifo",
+ scfifo_component.lpm_width = 16,
+ scfifo_component.lpm_widthu = 12,
+ scfifo_component.overflow_checking = "ON",
+ scfifo_component.underflow_checking = "ON",
+ scfifo_component.use_eab = "ON";
+
+
+endmodule
+
+// ============================================================
+// CNX file retrieval info
+// ============================================================
+// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0"
+// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1"
+// Retrieval info: PRIVATE: AlmostFull NUMERIC "0"
+// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1"
+// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0"
+// Retrieval info: PRIVATE: Clock NUMERIC "0"
+// Retrieval info: PRIVATE: Depth NUMERIC "4096"
+// Retrieval info: PRIVATE: Empty NUMERIC "1"
+// Retrieval info: PRIVATE: Full NUMERIC "1"
+// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone"
+// Retrieval info: PRIVATE: LE_BasedFIFO NUMERIC "0"
+// Retrieval info: PRIVATE: LegacyRREQ NUMERIC "1"
+// Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0"
+// Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "0"
+// Retrieval info: PRIVATE: Optimize NUMERIC "2"
+// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "2"
+// Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0"
+// Retrieval info: PRIVATE: UsedW NUMERIC "1"
+// Retrieval info: PRIVATE: Width NUMERIC "16"
+// Retrieval info: PRIVATE: dc_aclr NUMERIC "0"
+// Retrieval info: PRIVATE: rsEmpty NUMERIC "1"
+// Retrieval info: PRIVATE: rsFull NUMERIC "0"
+// Retrieval info: PRIVATE: rsUsedW NUMERIC "0"
+// Retrieval info: PRIVATE: sc_aclr NUMERIC "1"
+// Retrieval info: PRIVATE: sc_sclr NUMERIC "0"
+// Retrieval info: PRIVATE: wsEmpty NUMERIC "0"
+// Retrieval info: PRIVATE: wsFull NUMERIC "1"
+// Retrieval info: PRIVATE: wsUsedW NUMERIC "0"
+// Retrieval info: CONSTANT: ADD_RAM_OUTPUT_REGISTER STRING "OFF"
+// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone"
+// Retrieval info: CONSTANT: LPM_HINT STRING "RAM_BLOCK_TYPE=M4K"
+// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "4096"
+// Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "OFF"
+// Retrieval info: CONSTANT: LPM_TYPE STRING "scfifo"
+// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "16"
+// Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "12"
+// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON"
+// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON"
+// Retrieval info: CONSTANT: USE_EAB STRING "ON"
+// Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT NODEFVAL aclr
+// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL clock
+// Retrieval info: USED_PORT: data 0 0 16 0 INPUT NODEFVAL data[15..0]
+// Retrieval info: USED_PORT: empty 0 0 0 0 OUTPUT NODEFVAL empty
+// Retrieval info: USED_PORT: full 0 0 0 0 OUTPUT NODEFVAL full
+// Retrieval info: USED_PORT: q 0 0 16 0 OUTPUT NODEFVAL q[15..0]
+// Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL rdreq
+// Retrieval info: USED_PORT: usedw 0 0 12 0 OUTPUT NODEFVAL usedw[11..0]
+// Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL wrreq
+// Retrieval info: CONNECT: @data 0 0 16 0 data 0 0 16 0
+// Retrieval info: CONNECT: q 0 0 16 0 @q 0 0 16 0
+// Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0
+// Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0
+// Retrieval info: CONNECT: @clock 0 0 0 0 clock 0 0 0 0
+// Retrieval info: CONNECT: full 0 0 0 0 @full 0 0 0 0
+// Retrieval info: CONNECT: empty 0 0 0 0 @empty 0 0 0 0
+// Retrieval info: CONNECT: usedw 0 0 12 0 @usedw 0 0 12 0
+// Retrieval info: CONNECT: @aclr 0 0 0 0 aclr 0 0 0 0
+// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4kx16.v TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4kx16.inc TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4kx16.cmp TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4kx16.bsf TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4kx16_inst.v TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4kx16_bb.v TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4kx16_waveforms.html TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4kx16_wave*.jpg FALSE
diff --git a/usrp/fpga/megacells/fifo_4kx16_bb.v b/usrp/fpga/megacells/fifo_4kx16_bb.v
new file mode 100755
index 000000000..d41e9f090
--- /dev/null
+++ b/usrp/fpga/megacells/fifo_4kx16_bb.v
@@ -0,0 +1,122 @@
+// megafunction wizard: %FIFO%VBB%
+// GENERATION: STANDARD
+// VERSION: WM1.0
+// MODULE: scfifo
+
+// ============================================================
+// File Name: fifo_4kx16.v
+// Megafunction Name(s):
+// scfifo
+// ============================================================
+// ************************************************************
+// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
+//
+// 5.1 Build 213 01/19/2006 SP 1 SJ Web Edition
+// ************************************************************
+
+//Copyright (C) 1991-2006 Altera Corporation
+//Your use of Altera Corporation's design tools, logic functions
+//and other software and tools, and its AMPP partner logic
+//functions, and any output files any of the foregoing
+//(including device programming or simulation files), and any
+//associated documentation or information are expressly subject
+//to the terms and conditions of the Altera Program License
+//Subscription Agreement, Altera MegaCore Function License
+//Agreement, or other applicable license agreement, including,
+//without limitation, that your use is for the sole purpose of
+//programming logic devices manufactured by Altera and sold by
+//Altera or its authorized distributors. Please refer to the
+//applicable agreement for further details.
+
+module fifo_4kx16 (
+ aclr,
+ clock,
+ data,
+ rdreq,
+ wrreq,
+ empty,
+ full,
+ q,
+ usedw);
+
+ input aclr;
+ input clock;
+ input [15:0] data;
+ input rdreq;
+ input wrreq;
+ output empty;
+ output full;
+ output [15:0] q;
+ output [11:0] usedw;
+
+endmodule
+
+// ============================================================
+// CNX file retrieval info
+// ============================================================
+// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0"
+// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1"
+// Retrieval info: PRIVATE: AlmostFull NUMERIC "0"
+// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1"
+// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0"
+// Retrieval info: PRIVATE: Clock NUMERIC "0"
+// Retrieval info: PRIVATE: Depth NUMERIC "4096"
+// Retrieval info: PRIVATE: Empty NUMERIC "1"
+// Retrieval info: PRIVATE: Full NUMERIC "1"
+// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone"
+// Retrieval info: PRIVATE: LE_BasedFIFO NUMERIC "0"
+// Retrieval info: PRIVATE: LegacyRREQ NUMERIC "1"
+// Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0"
+// Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "0"
+// Retrieval info: PRIVATE: Optimize NUMERIC "2"
+// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "2"
+// Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0"
+// Retrieval info: PRIVATE: UsedW NUMERIC "1"
+// Retrieval info: PRIVATE: Width NUMERIC "16"
+// Retrieval info: PRIVATE: dc_aclr NUMERIC "0"
+// Retrieval info: PRIVATE: rsEmpty NUMERIC "1"
+// Retrieval info: PRIVATE: rsFull NUMERIC "0"
+// Retrieval info: PRIVATE: rsUsedW NUMERIC "0"
+// Retrieval info: PRIVATE: sc_aclr NUMERIC "1"
+// Retrieval info: PRIVATE: sc_sclr NUMERIC "0"
+// Retrieval info: PRIVATE: wsEmpty NUMERIC "0"
+// Retrieval info: PRIVATE: wsFull NUMERIC "1"
+// Retrieval info: PRIVATE: wsUsedW NUMERIC "0"
+// Retrieval info: CONSTANT: ADD_RAM_OUTPUT_REGISTER STRING "OFF"
+// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone"
+// Retrieval info: CONSTANT: LPM_HINT STRING "RAM_BLOCK_TYPE=M4K"
+// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "4096"
+// Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "OFF"
+// Retrieval info: CONSTANT: LPM_TYPE STRING "scfifo"
+// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "16"
+// Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "12"
+// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON"
+// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON"
+// Retrieval info: CONSTANT: USE_EAB STRING "ON"
+// Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT NODEFVAL aclr
+// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL clock
+// Retrieval info: USED_PORT: data 0 0 16 0 INPUT NODEFVAL data[15..0]
+// Retrieval info: USED_PORT: empty 0 0 0 0 OUTPUT NODEFVAL empty
+// Retrieval info: USED_PORT: full 0 0 0 0 OUTPUT NODEFVAL full
+// Retrieval info: USED_PORT: q 0 0 16 0 OUTPUT NODEFVAL q[15..0]
+// Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL rdreq
+// Retrieval info: USED_PORT: usedw 0 0 12 0 OUTPUT NODEFVAL usedw[11..0]
+// Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL wrreq
+// Retrieval info: CONNECT: @data 0 0 16 0 data 0 0 16 0
+// Retrieval info: CONNECT: q 0 0 16 0 @q 0 0 16 0
+// Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0
+// Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0
+// Retrieval info: CONNECT: @clock 0 0 0 0 clock 0 0 0 0
+// Retrieval info: CONNECT: full 0 0 0 0 @full 0 0 0 0
+// Retrieval info: CONNECT: empty 0 0 0 0 @empty 0 0 0 0
+// Retrieval info: CONNECT: usedw 0 0 12 0 @usedw 0 0 12 0
+// Retrieval info: CONNECT: @aclr 0 0 0 0 aclr 0 0 0 0
+// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4kx16.v TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4kx16.inc TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4kx16.cmp TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4kx16.bsf TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4kx16_inst.v TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4kx16_bb.v TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4kx16_waveforms.html TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_4kx16_wave*.jpg FALSE
diff --git a/usrp/fpga/megacells/fifo_4kx16_inst.v b/usrp/fpga/megacells/fifo_4kx16_inst.v
new file mode 100755
index 000000000..eb260acaa
--- /dev/null
+++ b/usrp/fpga/megacells/fifo_4kx16_inst.v
@@ -0,0 +1,11 @@
+fifo_4kx16 fifo_4kx16_inst (
+ .aclr ( aclr_sig ),
+ .clock ( clock_sig ),
+ .data ( data_sig ),
+ .rdreq ( rdreq_sig ),
+ .wrreq ( wrreq_sig ),
+ .empty ( empty_sig ),
+ .full ( full_sig ),
+ .q ( q_sig ),
+ .usedw ( usedw_sig )
+ );
diff --git a/usrp/fpga/megacells/fifo_512.bsf b/usrp/fpga/megacells/fifo_512.bsf
deleted file mode 100755
index a955b5655..000000000
--- a/usrp/fpga/megacells/fifo_512.bsf
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
-WARNING: Do NOT edit the input and output ports in this file in a text
-editor if you plan to continue editing the block that represents it in
-the Block Editor! File corruption is VERY likely to occur.
-*/
-/*
-Copyright (C) 1991-2006 Altera Corporation
-Your use of Altera Corporation's design tools, logic functions
-and other software and tools, and its AMPP partner logic
-functions, and any output files any of the foregoing
-(including device programming or simulation files), and any
-associated documentation or information are expressly subject
-to the terms and conditions of the Altera Program License
-Subscription Agreement, Altera MegaCore Function License
-Agreement, or other applicable license agreement, including,
-without limitation, that your use is for the sole purpose of
-programming logic devices manufactured by Altera and sold by
-Altera or its authorized distributors. Please refer to the
-applicable agreement for further details.
-*/
-(header "symbol" (version "1.1"))
-(symbol
- (rect 0 0 160 184)
- (text "fifo_512" (rect 58 1 109 17)(font "Arial" (font_size 10)))
- (text "inst" (rect 8 168 25 180)(font "Arial" ))
- (port
- (pt 0 32)
- (input)
- (text "data[31..0]" (rect 0 0 60 14)(font "Arial" (font_size 8)))
- (text "data[31..0]" (rect 20 26 71 39)(font "Arial" (font_size 8)))
- (line (pt 0 32)(pt 16 32)(line_width 3))
- )
- (port
- (pt 0 56)
- (input)
- (text "wrreq" (rect 0 0 35 14)(font "Arial" (font_size 8)))
- (text "wrreq" (rect 20 50 45 63)(font "Arial" (font_size 8)))
- (line (pt 0 56)(pt 16 56)(line_width 1))
- )
- (port
- (pt 0 72)
- (input)
- (text "wrclk" (rect 0 0 31 14)(font "Arial" (font_size 8)))
- (text "wrclk" (rect 26 66 48 79)(font "Arial" (font_size 8)))
- (line (pt 0 72)(pt 16 72)(line_width 1))
- )
- (port
- (pt 0 104)
- (input)
- (text "rdreq" (rect 0 0 30 14)(font "Arial" (font_size 8)))
- (text "rdreq" (rect 20 98 44 111)(font "Arial" (font_size 8)))
- (line (pt 0 104)(pt 16 104)(line_width 1))
- )
- (port
- (pt 0 120)
- (input)
- (text "rdclk" (rect 0 0 27 14)(font "Arial" (font_size 8)))
- (text "rdclk" (rect 26 114 47 127)(font "Arial" (font_size 8)))
- (line (pt 0 120)(pt 16 120)(line_width 1))
- )
- (port
- (pt 0 160)
- (input)
- (text "aclr" (rect 0 0 21 14)(font "Arial" (font_size 8)))
- (text "aclr" (rect 20 154 37 167)(font "Arial" (font_size 8)))
- (line (pt 0 160)(pt 16 160)(line_width 1))
- )
- (port
- (pt 160 40)
- (output)
- (text "wrfull" (rect 0 0 33 14)(font "Arial" (font_size 8)))
- (text "wrfull" (rect 113 34 138 47)(font "Arial" (font_size 8)))
- (line (pt 160 40)(pt 144 40)(line_width 1))
- )
- (port
- (pt 160 56)
- (output)
- (text "wrempty" (rect 0 0 50 14)(font "Arial" (font_size 8)))
- (text "wrempty" (rect 98 50 137 63)(font "Arial" (font_size 8)))
- (line (pt 160 56)(pt 144 56)(line_width 1))
- )
- (port
- (pt 160 96)
- (output)
- (text "q[31..0]" (rect 0 0 42 14)(font "Arial" (font_size 8)))
- (text "q[31..0]" (rect 105 90 141 103)(font "Arial" (font_size 8)))
- (line (pt 160 96)(pt 144 96)(line_width 3))
- )
- (port
- (pt 160 120)
- (output)
- (text "rdfull" (rect 0 0 28 14)(font "Arial" (font_size 8)))
- (text "rdfull" (rect 117 114 141 127)(font "Arial" (font_size 8)))
- (line (pt 160 120)(pt 144 120)(line_width 1))
- )
- (port
- (pt 160 136)
- (output)
- (text "rdempty" (rect 0 0 46 14)(font "Arial" (font_size 8)))
- (text "rdempty" (rect 102 130 140 143)(font "Arial" (font_size 8)))
- (line (pt 160 136)(pt 144 136)(line_width 1))
- )
- (drawing
- (text "32 bits x 128 words" (rect 63 156 144 168)(font "Arial" ))
- (line (pt 16 16)(pt 144 16)(line_width 1))
- (line (pt 144 16)(pt 144 168)(line_width 1))
- (line (pt 144 168)(pt 16 168)(line_width 1))
- (line (pt 16 168)(pt 16 16)(line_width 1))
- (line (pt 16 84)(pt 144 84)(line_width 1))
- (line (pt 16 148)(pt 144 148)(line_width 1))
- (line (pt 16 66)(pt 22 72)(line_width 1))
- (line (pt 22 72)(pt 16 78)(line_width 1))
- (line (pt 16 114)(pt 22 120)(line_width 1))
- (line (pt 22 120)(pt 16 126)(line_width 1))
- )
-)
diff --git a/usrp/fpga/toplevel/usrp_inband_usb/config.vh b/usrp/fpga/toplevel/usrp_inband_usb/config.vh
index 2d1929439..3291dc10b 100644
--- a/usrp/fpga/toplevel/usrp_inband_usb/config.vh
+++ b/usrp/fpga/toplevel/usrp_inband_usb/config.vh
@@ -1,4 +1,4 @@
-// -*- verilog -*-
+ // -*- verilog -*-
//
// USRP - Universal Software Radio Peripheral
//
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 8296a453e..6b4764078 100644
--- a/usrp/fpga/toplevel/usrp_inband_usb/usrp_inband_usb.qsf
+++ b/usrp/fpga/toplevel/usrp_inband_usb/usrp_inband_usb.qsf
@@ -372,11 +372,16 @@ set_instance_assignment -name CLOCK_SETTINGS master_clk -to master_clk
set_instance_assignment -name PARTITION_HIERARCHY no_file_for_top_partition -to | -section_id Top
set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
set_global_assignment -name FITTER_AUTO_EFFORT_DESIRED_SLACK_MARGIN "100 ps"
+set_global_assignment -name VERILOG_FILE ../../inband_lib/channel_demux.v
+set_global_assignment -name VERILOG_FILE ../../inband_lib/tx_packer.v
+set_global_assignment -name VERILOG_FILE ../../inband_lib/cmd_reader.v
+set_global_assignment -name VERILOG_FILE ../../megacells/fifo_2k_1clk.v
+set_global_assignment -name VERILOG_FILE ../../inband_lib/packet_builder.v
+set_global_assignment -name VERILOG_FILE ../../inband_lib/rx_buffer_inband.v
+set_global_assignment -name VERILOG_FILE ../../sdr_lib/atr_delay.v
+set_global_assignment -name VERILOG_FILE ../../megacells/fifo_1k.v
set_global_assignment -name VERILOG_FILE ../../inband_lib/tx_buffer_inband.v
-set_global_assignment -name VERILOG_FILE ../../inband_lib/usb_packet_fifo.v
set_global_assignment -name VERILOG_FILE ../../inband_lib/chan_fifo_reader.v
-set_global_assignment -name VERILOG_FILE ../../inband_lib/data_packet_fifo.v
-set_global_assignment -name VERILOG_FILE ../../inband_lib/usb_fifo_reader.v
set_global_assignment -name VERILOG_FILE ../../sdr_lib/cic_dec_shifter.v
set_global_assignment -name VERILOG_FILE ../../sdr_lib/rssi.v
set_global_assignment -name VERILOG_FILE ../../sdr_lib/ram16.v
@@ -412,4 +417,6 @@ set_global_assignment -name VERILOG_FILE usrp_inband_usb.v
set_global_assignment -name VERILOG_FILE ../../sdr_lib/clk_divider.v
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 \ No newline at end of file
+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
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 cc7490c5a..3bfdda56b 100644
--- a/usrp/fpga/toplevel/usrp_inband_usb/usrp_inband_usb.v
+++ b/usrp/fpga/toplevel/usrp_inband_usb/usrp_inband_usb.v
@@ -19,7 +19,8 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Boston, MA 02110-1301 USA
//
-`define IN_BAND
+`define TX_IN_BAND
+`define RX_IN_BAND
`include "config.vh"
`include "../../../firmware/include/fpga_regs_common.v"
@@ -115,6 +116,12 @@ module usrp_inband_usb
reg [15:0] debug_counter;
reg [15:0] loopback_i_0,loopback_q_0;
+
+ //Connection RX inband <-> TX inband
+ wire rx_WR;
+ wire [15:0] rx_databus;
+ wire rx_WR_done;
+ wire rx_WR_enabled;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Transmit Side
`ifdef TX_ON
@@ -123,7 +130,17 @@ module usrp_inband_usb
assign bb_tx_i1 = ch2tx;
assign bb_tx_q1 = ch3tx;
-`ifdef IN_BAND
+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;
+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));
+
+`ifdef TX_IN_BAND
tx_buffer_inband tx_buffer
( .usbclk(usbclk),.bus_reset(tx_bus_reset),.reset(tx_dsp_reset),
.usbdata(usbdata),.WR(WR),.have_space(have_space),.tx_underrun(tx_underrun),
@@ -135,7 +152,17 @@ module usrp_inband_usb
.txclk(clk64),.txstrobe(strobe_interp),
.clear_status(clear_status),
.tx_empty(tx_empty),
- .debugbus(tx_debugbus) );
+ .rx_WR(rx_WR),
+ .rx_databus(rx_databus),
+ .rx_WR_done(rx_WR_done),
+ .rx_WR_enabled(rx_WR_enabled),
+ .reg_addr(reg_addr),
+ .reg_data_out(reg_data_out),
+ .reg_data_in(reg_data_in),
+ .reg_io_enable(reg_io_enable),
+ .debugbus(tx_debugbus),
+ .rssi_0(rssi_0), .rssi_1(rssi_1), .rssi_2(rssi_2),
+ .rssi_3(rssi_3), .threshhold(rssi_threshhold));
`else
tx_buffer tx_buffer
( .usbclk(usbclk),.bus_reset(tx_bus_reset),.reset(tx_dsp_reset),
@@ -147,8 +174,7 @@ module usrp_inband_usb
.tx_i_3(),.tx_q_3(),
.txclk(clk64),.txstrobe(strobe_interp),
.clear_status(clear_status),
- .tx_empty(tx_empty),
- .debugbus(tx_debugbus) );
+ .tx_empty(tx_empty));
`endif
`ifdef TX_EN_0
@@ -226,7 +252,6 @@ module usrp_inband_usb
wire [15:0] ddc0_in_i,ddc0_in_q,ddc1_in_i,ddc1_in_q,ddc2_in_i,ddc2_in_q,ddc3_in_i,ddc3_in_q;
wire [31:0] rssi_0,rssi_1,rssi_2,rssi_3;
-
adc_interface adc_interface(.clock(clk64),.reset(rx_dsp_reset),.enable(1'b1),
.serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe),
.rx_a_a(rx_a_a),.rx_b_a(rx_b_a),.rx_a_b(rx_a_b),.rx_b_b(rx_b_b),
@@ -234,9 +259,9 @@ module usrp_inband_usb
.ddc0_in_i(ddc0_in_i),.ddc0_in_q(ddc0_in_q),
.ddc1_in_i(ddc1_in_i),.ddc1_in_q(ddc1_in_q),
.ddc2_in_i(ddc2_in_i),.ddc2_in_q(ddc2_in_q),
- .ddc3_in_i(ddc3_in_i),.ddc3_in_q(ddc3_in_q),.rx_numchan(rx_numchan) );
-
- rx_buffer rx_buffer
+ .ddc3_in_i(ddc3_in_i),.ddc3_in_q(ddc3_in_q),.rx_numchan(rx_numchan));
+ `ifdef RX_IN_BAND
+ rx_buffer_inband rx_buffer
( .usbclk(usbclk),.bus_reset(rx_bus_reset),.reset(rx_dsp_reset),
.reset_regs(rx_dsp_reset),
.usbdata(usbdata_out),.RD(RD),.have_pkt_rdy(have_pkt_rdy),.rx_overrun(rx_overrun),
@@ -248,7 +273,27 @@ module usrp_inband_usb
.rxclk(clk64),.rxstrobe(hb_strobe),
.clear_status(clear_status),
.serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe),
- .debugbus(rx_debugbus) );
+ .rx_WR(rx_WR),
+ .rx_databus(rx_databus),
+ .rx_WR_done(rx_WR_done),
+ .rx_WR_enabled(rx_WR_enabled),
+ .debugbus(rx_debugbus),
+ .rssi_0(rssi_0), .rssi_1(rssi_1), .rssi_2(rssi_2), .rssi_3(rssi_3));
+ `else
+ rx_buffer rx_buffer
+ ( .usbclk(usbclk),.bus_reset(rx_bus_reset),.reset(rx_dsp_reset),
+ .reset_regs(rx_dsp_reset),
+ .usbdata(usbdata_out),.RD(RD),.have_pkt_rdy(have_pkt_rdy),.rx_overrun(rx_overrun),
+ .channels(rx_numchan),
+ .ch_0(ch0rx),.ch_1(ch1rx),
+ .ch_2(ch2rx),.ch_3(ch3rx),
+ .ch_4(ch4rx),.ch_5(ch5rx),
+ .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)/*,
+ .debugbus(rx_debugbus)*/);
+ `endif
`ifdef RX_EN_0
rx_chain #(`FR_RX_FREQ_0,`FR_RX_PHASE_0) rx_chain_0
@@ -305,7 +350,6 @@ module usrp_inband_usb
assign capabilities[3] = `RX_CAP_HB;
assign capabilities[2:0] = `RX_CAP_NCHAN;
-
serial_io serial_io
( .master_clk(clk64),.serial_clock(SCLK),.serial_data_in(SDI),
.enable(SEN_FPGA),.reset(1'b0),.serial_data_out(SDO),
@@ -326,7 +370,7 @@ module usrp_inband_usb
.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(rx_debugbus),.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,rx_overrun,decim_rate}),
.reg_0(reg_0),.reg_1(reg_1),.reg_2(reg_2),.reg_3(reg_3) );
diff --git a/usrp/host/apps/Makefile.am b/usrp/host/apps/Makefile.am
index f920ce59a..e0f5b8cf4 100644
--- a/usrp/host/apps/Makefile.am
+++ b/usrp/host/apps/Makefile.am
@@ -21,7 +21,10 @@
include $(top_srcdir)/Makefile.common
-INCLUDES = $(USRP_INCLUDES) $(BOOST_CFLAGS)
+INCLUDES = \
+ $(DEFINES) $(OMNITHREAD_INCLUDES) $(PMT_INCLUDES) $(MBLOCK_INCLUDES) \
+ $(USRP_INCLUDES) $(BOOST_CFLAGS) $(CPPUNIT_INCLUDES)
+
bin_PROGRAMS = \
usrper \
@@ -29,11 +32,20 @@ bin_PROGRAMS = \
noinst_PROGRAMS = \
check_order_quickly \
+ test_usrp_inband_cs \
+ test_usrp_inband_ping \
+ test_usrp_inband_registers \
+ test_usrp_inband_rx \
+ test_usrp_inband_tx \
+ test_usrp_inband_timestamps \
test_usrp_standard_rx \
- test_usrp_standard_tx
+ test_usrp_standard_tx \
+ read_packets
noinst_HEADERS = \
- time_stuff.h
+ time_stuff.h \
+ ui_nco.h \
+ ui_sincos.h
noinst_PYTHON = \
burn-db-eeprom \
@@ -53,3 +65,24 @@ usrper_LDADD = $(USRP_LA)
usrp_cal_dc_offset_SOURCES = usrp_cal_dc_offset.cc
usrp_cal_dc_offset_LDADD = $(USRP_LA)
+
+test_usrp_inband_cs_SOURCES = test_usrp_inband_cs.cc time_stuff.c ui_sincos.c
+test_usrp_inband_cs_LDADD = $(USRP_LA)
+
+test_usrp_inband_ping_SOURCES = test_usrp_inband_ping.cc time_stuff.c
+test_usrp_inband_ping_LDADD = $(USRP_LA)
+
+test_usrp_inband_tx_SOURCES = test_usrp_inband_tx.cc time_stuff.c ui_sincos.c
+test_usrp_inband_tx_LDADD = $(USRP_LA)
+
+test_usrp_inband_timestamps_SOURCES = test_usrp_inband_timestamps.cc time_stuff.c ui_sincos.c
+test_usrp_inband_timestamps_LDADD = $(USRP_LA)
+
+test_usrp_inband_registers_SOURCES = test_usrp_inband_registers.cc time_stuff.c ui_sincos.c
+test_usrp_inband_registers_LDADD = $(USRP_LA)
+
+test_usrp_inband_rx_SOURCES = test_usrp_inband_rx.cc time_stuff.c ui_sincos.c
+test_usrp_inband_rx_LDADD = $(USRP_LA)
+
+read_packets_SOURCES = read_packets.cc
+read_packets_LDADD = $(USRP_LA)
diff --git a/usrp/host/apps/read_packets.cc b/usrp/host/apps/read_packets.cc
new file mode 100644
index 000000000..92d8baf0d
--- /dev/null
+++ b/usrp/host/apps/read_packets.cc
@@ -0,0 +1,103 @@
+/* -*- 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 <iostream>
+#include <usrp_inband_usb_packet.h>
+#include <mb_class_registry.h>
+#include <vector>
+#include <usrp_usb_interface.h>
+#include <fstream>
+
+typedef usrp_inband_usb_packet transport_pkt; // makes conversion to gigabit easy
+
+int main(int argc, char *argv[]) {
+
+ if(argc !=2) {
+ std::cout << "Usage: ./read_packets <data_file>\n";
+ return -1;
+ }
+
+ std::ifstream infile;
+ std::ofstream outfile;
+
+ unsigned int pkt_size = transport_pkt::max_pkt_size();
+ unsigned int pkt_num=0;
+
+ transport_pkt *pkt;
+ char pkt_data[pkt_size]; // allocate the number of bytes for a single packet
+
+ pkt = (transport_pkt *)pkt_data; // makes operations cleaner to read
+
+ // Open the file and read the packets, dumping information
+ infile.open(argv[1], std::ios::binary|std::ios::in);
+ if(!infile.is_open())
+ exit(-1);
+
+ //outfile.open("dump.dat",std::ios::out|std::ios::binary);
+
+ // read 1 packet in to the memory
+ infile.read(pkt_data, pkt_size);
+
+ while(!infile.eof()) {
+
+ printf("Packet %u\n", pkt_num);
+
+ if(pkt->start_of_burst())
+ printf("\tstart of burst\n");
+
+ if(pkt->end_of_burst())
+ printf("\tend of burst\n");
+
+// if(pkt->carrier_sense())
+// printf("\tcarrier sense\n");
+
+ printf("\tchannel: \t0x%x\n", pkt->chan());
+ printf("\ttimestamp: \t0x%x\n", pkt->timestamp());
+ //printf("\ttimestamp: \t%u\n", pkt->timestamp());
+ printf("\tlength: \t%u\n", pkt->payload_len());
+ printf("\trssi: \t%u\n", pkt->rssi());
+
+ printf("\tpayload: \n");
+ for(int i=0; i < pkt->payload_len(); i++)
+ //for(int i=0; i < pkt->max_payload(); i++)
+ {
+ printf("\t%d\t0x%x\n", i, *(pkt->payload()+i));
+ //outfile.write((const char*)(pkt->payload()+i),1);
+ //printf("\t\t0x%x\n", pkt->payload()+i);
+
+ }
+ printf("\n\n");
+
+ pkt_num++;
+
+ // read 1 packet in to the memory
+ infile.read(pkt_data, pkt_size);
+
+ }
+
+ infile.close();
+ //outfile.close();
+
+}
diff --git a/usrp/host/apps/test_usrp_inband_cs.cc b/usrp/host/apps/test_usrp_inband_cs.cc
new file mode 100644
index 000000000..1d70341fe
--- /dev/null
+++ b/usrp/host/apps/test_usrp_inband_cs.cc
@@ -0,0 +1,478 @@
+/* -*- 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 <ui_nco.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+#include <iostream>
+
+#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>
+
+#define NBPING 10
+
+static bool verbose = false;
+
+class test_usrp_cs : 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];
+
+ enum state_t {
+ INIT,
+ OPENING_USRP,
+ ALLOCATING_CHANNEL,
+ TRANSMITTING,
+ CLOSING_CHANNEL,
+ CLOSING_USRP,
+ };
+
+ 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_usrp_cs(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+ ~test_usrp_cs();
+ 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 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)
+ : 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_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";
+
+ 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;
+ bool fake_usrp_p = false;
+
+ // Test the TX side
+
+ pmt_t usrp_dict = pmt_make_dict();
+
+ if(fake_usrp_p) {
+ pmt_dict_set(usrp_dict,
+ pmt_intern("fake-usrp"),
+ PMT_T);
+ }
+
+ // Set TX and RX interpolations
+ pmt_dict_set(usrp_dict,
+ pmt_intern("interp-tx"),
+ pmt_from_long(128));
+
+ pmt_dict_set(usrp_dict,
+ pmt_intern("interp-rx"),
+ pmt_from_long(16));
+
+ // Specify the RBF to use
+ pmt_dict_set(usrp_dict,
+ pmt_intern("rbf"),
+ pmt_intern("boe.rbf"));
+
+ define_component("server", "usrp_server", usrp_dict);
+
+ connect("self", "tx0", "server", "tx0");
+ connect("self", "rx0", "server", "rx0");
+ connect("self", "cs", "server", "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);
+
+ // FIXME need to somehow set the interp rate in the USRP.
+ // for now, we'll have the low-level code hardwire it.
+}
+
+test_usrp_cs::~test_usrp_cs()
+{
+}
+
+void
+test_usrp_cs::initial_transition()
+{
+ open_usrp();
+}
+
+void
+test_usrp_cs::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;
+ std::string error_msg;
+
+ //std::cout << msg << std::endl;
+
+ switch(d_state){
+ 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;
+
+ case ALLOCATING_CHANNEL:
+ if (pmt_eq(event, s_response_allocate_channel)){
+
+ 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(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;
+ }
+ }
+ }
+ goto unhandled;
+
+ case TRANSMITTING:
+ if (pmt_eq(event, s_response_xmit_raw_frame)){
+ 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-xmit-raw-frame:";
+ goto bail;
+ }
+ }
+ goto unhandled;
+
+ 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;
+ }
+ }
+ goto unhandled;
+
+ case CLOSING_USRP:
+ if (pmt_eq(event, s_response_close)){
+ status = pmt_nth(1, data);
+
+ if (pmt_eq(status, PMT_T)){
+ shutdown_all(PMT_T);
+ return;
+ }
+ else {
+ error_msg = "failed to close USRP:";
+ goto bail;
+ }
+ }
+ goto unhandled;
+
+ default:
+ goto unhandled;
+ }
+ return;
+
+ bail:
+ std::cerr << error_msg << data
+ << "status = " << status << std::endl;
+ shutdown_all(PMT_F);
+ return;
+
+ unhandled:
+ if(verbose)
+ std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
+ << "in state "<< d_state << std::endl;
+}
+
+
+void
+test_usrp_cs::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;
+}
+
+void
+test_usrp_cs::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";
+}
+
+void
+test_usrp_cs::allocate_channel()
+{
+ long capacity = (long) 16e6;
+ 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;
+}
+
+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()
+{
+ 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()
+{
+
+ 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;
+}
+
+void
+test_usrp_cs::build_and_send_next_frame()
+{
+ // allocate the uniform vector for the samples
+ // FIXME perhaps hold on to this between calls
+
+#if 1
+ 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();
+ }
+ }
+
+ 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
+ uvec, // the samples
+ timestamp));
+
+ d_nsamples_xmitted += nsamples_this_frame;
+ d_nframes_xmitted++;
+
+ if(verbose)
+ std::cout << "[TEST_USRP_INBAND_CS] Transmitted frame\n";
+}
+
+
+void
+test_usrp_cs::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
+ enter_closing_channel();
+ }
+
+ //build_and_send_next_frame();
+}
+
+void
+test_usrp_cs::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_CS] Closing channel\n";
+}
+
+REGISTER_MBLOCK_CLASS(test_usrp_cs);
+
+
+// ----------------------------------------------------------------
+
+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_cs", PMT_F, &result);
+}
diff --git a/usrp/host/apps/test_usrp_inband_ping.cc b/usrp/host/apps/test_usrp_inband_ping.cc
new file mode 100644
index 000000000..a68f49272
--- /dev/null
+++ b/usrp/host/apps/test_usrp_inband_ping.cc
@@ -0,0 +1,376 @@
+/* -*- 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 <sys/time.h>
+#include <iostream>
+
+// 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_tx.h>
+#include <symbols_usrp_rx.h>
+
+static bool verbose = false;
+
+class test_usrp_inband_ping : public mb_mblock
+{
+
+ mb_port_sptr d_tx; // Ports connected to the USRP server
+ mb_port_sptr d_rx;
+ mb_port_sptr d_cs;
+
+ pmt_t d_tx_chan; // Returned channel from TX allocation
+ pmt_t d_rx_chan; // Returned channel from RX allocation
+
+ pmt_t d_which_usrp; // The USRP to use for the test
+
+ long d_warm_msgs; // The number of messages to 'warm' the USRP
+ long d_warm_recvd; // The number of msgs received in the 'warm' state
+
+ // Keep track of current state
+ enum state_t {
+ INIT,
+ OPENING_USRP,
+ ALLOCATING_CHANNELS,
+ WARMING_USRP,
+ PINGING,
+ CLOSING_CHANNELS,
+ CLOSING_USRP,
+ };
+ state_t d_state;
+
+ public:
+ test_usrp_inband_ping(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+ ~test_usrp_inband_ping();
+ void initial_transition();
+ void handle_message(mb_message_sptr msg);
+
+ protected:
+ void opening_usrp();
+ void allocating_channels();
+ void enter_warming_usrp();
+ void enter_pinging();
+ void build_and_send_ping();
+ void closing_channels();
+ void closing_usrp();
+};
+
+
+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_inband_ping", PMT_F, &result);
+}
+
+
+test_usrp_inband_ping::test_usrp_inband_ping(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_which_usrp(pmt_from_long(0)),
+ d_state(INIT)
+{
+
+ // A dictionary is used to pass parameters to the USRP
+ pmt_t usrp_dict = pmt_make_dict();
+
+ // Specify the RBF to use
+ pmt_dict_set(usrp_dict,
+ pmt_intern("rbf"),
+ pmt_intern("fixed1.rbf"));
+
+ // Set TX and RX interpolations
+ pmt_dict_set(usrp_dict,
+ pmt_intern("interp-tx"),
+ pmt_from_long(128));
+
+ pmt_dict_set(usrp_dict,
+ pmt_intern("interp-rx"),
+ pmt_from_long(16));
+
+ 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);
+
+ // Create an instance of USRP server and connect ports
+ define_component("server", "usrp_server", usrp_dict);
+ connect("self", "tx0", "server", "tx0");
+ connect("self", "rx0", "server", "rx0");
+ connect("self", "cs", "server", "cs");
+
+}
+
+test_usrp_inband_ping::~test_usrp_inband_ping()
+{
+}
+
+void
+test_usrp_inband_ping::initial_transition()
+{
+ opening_usrp();
+}
+
+// Handle message reads all incoming messages from USRP server which will be
+// initialization and ping responses. We perform actions based on the current
+// state and the event (ie, ping response)
+void
+test_usrp_inband_ping::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;
+ std::string error_msg;
+
+ // Dispatch based on state
+ 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); // failed/succes
+
+ if(pmt_eq(status, PMT_T)) {
+ allocating_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:
+
+ // A TX allocation response
+ if(pmt_eq(event, s_response_allocate_channel)
+ && pmt_eq(d_tx->port_symbol(), port_id))
+ {
+ status = pmt_nth(1, data);
+
+ // If successful response, extract the channel
+ if(pmt_eq(status, PMT_T)) {
+
+ d_tx_chan = pmt_nth(2, data);
+
+ if(verbose)
+ std::cout << "[TEST_USRP_INBAND_PING] Received TX allocation"
+ << " on channel " << d_tx_chan << std::endl;
+
+ // If the RX has also been allocated already, we can continue
+ if(!pmt_eqv(d_rx_chan, PMT_NIL))
+ enter_warming_usrp();
+
+ return;
+ }
+ else { // TX allocation failed
+ error_msg = "failed to allocate TX channel:";
+ goto bail;
+ }
+ }
+
+ // A RX allocation response
+ if(pmt_eq(event, s_response_allocate_channel)
+ && pmt_eq(d_rx->port_symbol(), port_id))
+ {
+ status = pmt_nth(1, data);
+
+ // If successful response, extract the channel
+ if(pmt_eq(status, PMT_T)) {
+
+ d_rx_chan = pmt_nth(2, data);
+
+ if(verbose)
+ std::cout << "[TEST_USRP_INBAND_PING] Received RX allocation"
+ << " on channel " << d_rx_chan << std::endl;
+
+ // If the TX has also been allocated already, we can continue
+ if(!pmt_eqv(d_tx_chan, PMT_NIL))
+ enter_warming_usrp();
+
+ return;
+ }
+ else { // RX allocation failed
+ error_msg = "failed to allocate RX channel:";
+ goto bail;
+ }
+ }
+
+ goto unhandled;
+
+ //----------------------- WARMING USRP --------------------//
+ // The FX2 seems to need some amount of data to be buffered
+ // before it begins reading. We use this state to simply
+ // warm up the USRP before benchmarking pings.
+ case WARMING_USRP:
+
+ // We really don't care about the responses from the
+ // control channel in the warming stage, but once we receive
+ // the proper number of responses we switch states.
+ if(pmt_eq(event, s_response_from_control_channel)
+ && pmt_eq(d_rx->port_symbol(), port_id))
+ {
+ d_warm_recvd++;
+
+ if(d_warm_recvd > d_warm_msgs)
+ enter_pinging();
+
+ return;
+ }
+
+ goto unhandled;
+
+ case PINGING:
+ goto unhandled;
+
+ case CLOSING_CHANNELS:
+ goto unhandled;
+
+ case CLOSING_USRP:
+ goto unhandled;
+
+ case INIT:
+ 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)
+ std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
+ << "in state "<< d_state << std::endl;
+
+}
+
+
+// Sends a command to USRP server to open up a connection to the
+// specified USRP, which is defaulted to USRP 0 on the system
+void
+test_usrp_inband_ping::opening_usrp()
+{
+
+ if(verbose)
+ std::cout << "[TEST_USRP_INBAND_PING] Opening USRP "
+ << d_which_usrp << std::endl;
+
+ d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, d_which_usrp));
+ d_state = OPENING_USRP;
+}
+
+// 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
+test_usrp_inband_ping::allocating_channels()
+{
+ d_state = ALLOCATING_CHANNELS;
+
+ long capacity = (long) 16e6;
+ 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)));
+}
+
+// The USRP needs some amount of initial data to pass a buffering point such
+// that it begins to pull and read data from the FX2. We send an arbitrary
+// amount of data to start the pipeline, which are just pings.
+void
+test_usrp_inband_ping::enter_warming_usrp()
+{
+ d_state = WARMING_USRP;
+
+ for(int i=0; i < d_warm_msgs; i++)
+ build_and_send_ping();
+}
+
+void
+test_usrp_inband_ping::enter_pinging()
+{
+ d_state = PINGING;
+
+ if(verbose)
+ std::cout << "[TEST_USRP_INBAND_PING] Running ping tests\n";
+
+}
+
+// Pings are sent over the TX channel using the signal 'cmd-to-control-channel'
+// to the USRP server. Within this message there can be infinite subpackets
+// stored as a list (the second parameter) and sent. The only subpacket we send
+// is a ping, interpreted by the 'op-ping-fixed' signal.
+void
+test_usrp_inband_ping::build_and_send_ping()
+{
+
+ d_tx->send(s_cmd_to_control_channel, // USRP server signal
+ pmt_list2(PMT_NIL, // invocation handle
+ pmt_list1(pmt_list3(s_op_ping_fixed,
+ pmt_from_long(0),
+ pmt_from_long(0)))));
+
+ if(verbose)
+ std::cout << "[TEST_USRP_INBAND_PING] Ping!!" << std::endl;
+}
+
+REGISTER_MBLOCK_CLASS(test_usrp_inband_ping);
diff --git a/usrp/host/apps/test_usrp_inband_registers.cc b/usrp/host/apps/test_usrp_inband_registers.cc
new file mode 100644
index 000000000..922b6215d
--- /dev/null
+++ b/usrp/host/apps/test_usrp_inband_registers.cc
@@ -0,0 +1,436 @@
+/* -*- 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 <sys/time.h>
+#include <iostream>
+
+// 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_tx.h>
+#include <symbols_usrp_rx.h>
+
+static bool verbose = true;
+
+class test_usrp_inband_registers : public mb_mblock
+{
+
+ mb_port_sptr d_tx; // Ports connected to the USRP server
+ mb_port_sptr d_rx;
+ mb_port_sptr d_cs;
+
+ pmt_t d_tx_chan; // Returned channel from TX allocation
+ pmt_t d_rx_chan; // Returned channel from RX allocation
+
+ pmt_t d_which_usrp; // The USRP to use for the test
+
+ long d_warm_msgs; // The number of messages to 'warm' the USRP
+ long d_warm_recvd; // The number of msgs received in the 'warm' state
+
+ // Keep track of current state
+ enum state_t {
+ INIT,
+ OPENING_USRP,
+ ALLOCATING_CHANNELS,
+ WRITE_REGISTER,
+ READ_REGISTER,
+ CLOSING_CHANNELS,
+ CLOSING_USRP,
+ };
+ state_t d_state;
+
+ public:
+ test_usrp_inband_registers(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+ ~test_usrp_inband_registers();
+ void initial_transition();
+ void handle_message(mb_message_sptr msg);
+
+ protected:
+ void opening_usrp();
+ void allocating_channels();
+ void write_register();
+ void read_register();
+ void closing_channels();
+ void closing_usrp();
+ void enter_receiving();
+ void build_and_send_ping();
+};
+
+
+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_inband_registers", PMT_F, &result);
+}
+
+
+test_usrp_inband_registers::test_usrp_inband_registers(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_which_usrp(pmt_from_long(0)),
+ d_state(INIT)
+{
+
+ // A dictionary is used to pass parameters to the USRP
+ pmt_t usrp_dict = pmt_make_dict();
+
+ // Specify the RBF to use
+ pmt_dict_set(usrp_dict,
+ pmt_intern("rbf"),
+ pmt_intern("boe2.rbf"));
+
+ // Set TX and RX interpolations
+ pmt_dict_set(usrp_dict,
+ pmt_intern("interp-tx"),
+ pmt_from_long(128));
+
+ pmt_dict_set(usrp_dict,
+ pmt_intern("interp-rx"),
+ pmt_from_long(16));
+
+ 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);
+
+ // Create an instance of USRP server and connect ports
+ define_component("server", "usrp_server", usrp_dict);
+ connect("self", "tx0", "server", "tx0");
+ connect("self", "rx0", "server", "rx0");
+ connect("self", "cs", "server", "cs");
+
+}
+
+test_usrp_inband_registers::~test_usrp_inband_registers()
+{
+}
+
+void
+test_usrp_inband_registers::initial_transition()
+{
+ opening_usrp();
+}
+
+// Handle message reads all incoming messages from USRP server which will be
+// initialization and ping responses. We perform actions based on the current
+// state and the event (ie, ping response)
+void
+test_usrp_inband_registers::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;
+ std::string error_msg;
+
+ // Dispatch based on state
+ 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); // failed/succes
+
+ if(pmt_eq(status, PMT_T)) {
+ allocating_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:
+
+ // A TX allocation response
+ if(pmt_eq(event, s_response_allocate_channel)
+ && pmt_eq(d_tx->port_symbol(), port_id))
+ {
+ status = pmt_nth(1, data);
+
+ // If successful response, extract the channel
+ if(pmt_eq(status, PMT_T)) {
+
+ d_tx_chan = pmt_nth(2, data);
+
+ if(verbose)
+ std::cout << "[TEST_USRP_INBAND_PING] Received TX allocation"
+ << " on channel " << d_tx_chan << std::endl;
+
+ // If the RX has also been allocated already, we can continue
+ if(!pmt_eqv(d_rx_chan, PMT_NIL)) {
+ enter_receiving();
+ write_register();
+ }
+
+ return;
+ }
+ else { // TX allocation failed
+ error_msg = "failed to allocate TX channel:";
+ goto bail;
+ }
+ }
+
+ // A RX allocation response
+ if(pmt_eq(event, s_response_allocate_channel)
+ && pmt_eq(d_rx->port_symbol(), port_id))
+ {
+ status = pmt_nth(1, data);
+
+ // If successful response, extract the channel
+ if(pmt_eq(status, PMT_T)) {
+
+ d_rx_chan = pmt_nth(2, data);
+
+ if(verbose)
+ std::cout << "[TEST_USRP_INBAND_PING] Received RX allocation"
+ << " on channel " << d_rx_chan << std::endl;
+
+ // If the TX has also been allocated already, we can continue
+ if(!pmt_eqv(d_tx_chan, PMT_NIL)) {
+ enter_receiving();
+ write_register();
+ }
+
+ return;
+ }
+ else { // RX allocation failed
+ error_msg = "failed to allocate RX channel:";
+ goto bail;
+ }
+ }
+
+ goto unhandled;
+
+ //-------------------------- WRITE REGISTER ----------------------------//
+ // In the write register state, we do not expect to receive any messages
+ // since the write does not directly generate a response until the USRP
+ // responds.
+ case WRITE_REGISTER:
+ goto unhandled;
+
+ //-------------------------- READ REGISTER ----------------------------//
+ // In the read register state, we only expect a read register response back
+ // that has the value we expect to have in it. We read the response, ensure
+ // that the read was successful and display the register value.
+ case READ_REGISTER:
+
+ if(pmt_eq(event, s_response_from_control_channel)
+ && pmt_eq(d_tx->port_symbol(), port_id))
+ {
+ status = pmt_nth(1, data);
+
+ // If the read was successful, we extract the subpacket information
+ if(pmt_eq(status, PMT_T)) {
+
+ pmt_t subp = pmt_nth(2, data); // subpacket should be the read reg reply
+
+ pmt_t subp_sig = pmt_nth(0, subp);
+ pmt_t subp_data = pmt_nth(1, subp);
+
+ if(!pmt_eqv(subp_sig, s_op_read_reg_reply)) {
+ error_msg = "received improper subpacket when expecting reg reply.";
+ goto bail;
+ }
+
+ pmt_t rid = pmt_nth(0, subp_data);
+ pmt_t reg_num = pmt_nth(1, subp_data);
+ pmt_t reg_val = pmt_nth(2, subp_data);
+
+ if(verbose)
+ std::cout << "[TEST_USRP_INBAND_REGISTERS] Received read reg reply "
+ << "("
+ << "RID: " << rid << ", "
+ << "Reg: " << reg_num << ", "
+ << "Val: " << reg_val
+ << ")\n";
+
+ // read_register(); FIX ME STATE TRANSITION
+ return;
+
+ } else { // bail on unsuccessful write
+ error_msg = "failed to write to register.";
+ goto bail;
+ }
+ }
+ goto unhandled;
+
+ case CLOSING_CHANNELS:
+ goto unhandled;
+
+ case CLOSING_USRP:
+ goto unhandled;
+
+ case INIT:
+ 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, s_response_recv_raw_samples))
+ std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
+ << "in state "<< d_state << std::endl;
+
+}
+
+
+// Sends a command to USRP server to open up a connection to the
+// specified USRP, which is defaulted to USRP 0 on the system
+void
+test_usrp_inband_registers::opening_usrp()
+{
+
+ if(verbose)
+ std::cout << "[TEST_USRP_INBAND_PING] Opening USRP "
+ << d_which_usrp << std::endl;
+
+ d_cs->send(s_cmd_open, pmt_list2(PMT_NIL, d_which_usrp));
+ d_state = OPENING_USRP;
+}
+
+// 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
+test_usrp_inband_registers::allocating_channels()
+{
+ d_state = ALLOCATING_CHANNELS;
+
+ long capacity = (long) 16e6;
+ 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)));
+}
+
+// After allocating the channels, a write register command will be sent to the
+// USRP.
+void
+test_usrp_inband_registers::write_register()
+{
+ d_state = WRITE_REGISTER;
+
+ long reg = 0;
+
+ 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(reg),
+ pmt_from_long(0xbeef))))));
+
+ if(verbose)
+ std::cout << "[TEST_USRP_INBAND_REGISTERS] Writing 0xbeef to "
+ << reg << std::endl;
+
+ read_register(); // immediately transition to read the register
+}
+
+// Temporary: for testing pings
+void
+test_usrp_inband_registers::build_and_send_ping()
+{
+
+ 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;
+}
+
+// After writing to the register, we want to read the value back and ensure that
+// it is the same value that we wrote.
+void
+test_usrp_inband_registers::read_register()
+{
+ d_state = READ_REGISTER;
+
+ long reg = 9;
+
+ d_tx->send(s_cmd_to_control_channel, // C/S packet
+ pmt_list2(PMT_NIL, // invoc handle
+ pmt_list1(
+ pmt_list2(s_op_read_reg,
+ pmt_list2(
+ pmt_from_long(0), // rid
+ pmt_from_long(reg))))));
+ if(verbose)
+ std::cout << "[TEST_USRP_INBAND_REGISTERS] Reading from register "
+ << reg << std::endl;
+}
+
+// Used to enter the receiving state
+void
+test_usrp_inband_registers::enter_receiving()
+{
+ d_rx->send(s_cmd_start_recv_raw_samples,
+ pmt_list2(PMT_F,
+ d_rx_chan));
+}
+
+REGISTER_MBLOCK_CLASS(test_usrp_inband_registers);
diff --git a/usrp/host/apps/test_usrp_inband_rx.cc b/usrp/host/apps/test_usrp_inband_rx.cc
new file mode 100644
index 000000000..4820c2d4e
--- /dev/null
+++ b/usrp/host/apps/test_usrp_inband_rx.cc
@@ -0,0 +1,356 @@
+/* -*- 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>
+
+// Signal set for the USRP server
+static pmt_t s_cmd_allocate_channel = pmt_intern("cmd-allocate-channel");
+static pmt_t s_cmd_close = pmt_intern("cmd-close");
+static pmt_t s_cmd_deallocate_channel = pmt_intern("cmd-deallocate-channel");
+static pmt_t s_cmd_open = pmt_intern("cmd-open");
+static pmt_t s_cmd_start_recv_raw_samples = pmt_intern("cmd-start-recv-raw-samples");
+static pmt_t s_cmd_stop_recv_raw_samples = pmt_intern("cmd-stop-recv-raw-samples");
+static pmt_t s_cmd_to_control_channel = pmt_intern("cmd-to-control-channel");
+static pmt_t s_cmd_xmit_raw_frame = pmt_intern("cmd-xmit-raw-frame");
+static pmt_t s_cmd_max_capacity = pmt_intern("cmd-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_cmd_current_capacity_allocation = pmt_intern("cmd-current-capacity-allocation");
+static pmt_t s_response_allocate_channel = pmt_intern("response-allocate-channel");
+static pmt_t s_response_close = pmt_intern("response-close");
+static pmt_t s_response_deallocate_channel = pmt_intern("response-deallocate-channel");
+static pmt_t s_response_from_control_channel = pmt_intern("response-from-control-channel");
+static pmt_t s_response_open = pmt_intern("response-open");
+static pmt_t s_response_recv_raw_samples = pmt_intern("response-recv-raw-samples");
+static pmt_t s_response_xmit_raw_frame = pmt_intern("response-xmit-raw-frame");
+static pmt_t s_response_max_capacity = pmt_intern("response-max-capacity");
+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_response_current_capacity_allocation = pmt_intern("response-current-capacity-allocation");
+
+static bool verbose = false;
+
+class test_usrp_rx : public mb_mblock
+{
+ mb_port_sptr d_rx;
+ mb_port_sptr d_cs;
+ pmt_t d_rx_chan; // returned tx channel handle
+
+ bool d_disk_write;
+
+ enum state_t {
+ INIT,
+ OPENING_USRP,
+ ALLOCATING_CHANNEL,
+ RECEIVING,
+ CLOSING_CHANNEL,
+ CLOSING_USRP,
+ };
+
+ state_t d_state;
+
+ std::ofstream d_ofile;
+
+ 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_disk_write(false)
+{
+
+ 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;
+ bool fake_usrp_p = false;
+
+ d_disk_write = true;
+
+ // Test the TX side
+
+ // Pass a dictionary to usrp_server which specifies which interface to use, the stub or USRP
+ pmt_t usrp_dict = pmt_make_dict();
+
+ 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("tmac6.rbf"));
+
+ // Set TX and RX interpolations
+ pmt_dict_set(usrp_dict,
+ pmt_intern("interp-tx"),
+ pmt_from_long(128));
+
+ pmt_dict_set(usrp_dict,
+ pmt_intern("interp-rx"),
+ pmt_from_long(16));
+
+ define_component("server", "usrp_server", usrp_dict);
+
+ connect("self", "rx0", "server", "rx0");
+ connect("self", "cs", "server", "cs");
+
+ if(d_disk_write)
+ d_ofile.open("pdump_rx.dat",std::ios::binary|std::ios::out);
+}
+
+test_usrp_rx::~test_usrp_rx()
+{
+ if(d_disk_write)
+ d_ofile.close();
+}
+
+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){
+ 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;
+
+ case ALLOCATING_CHANNEL:
+ if (pmt_eq(event, s_response_allocate_channel)){
+ status = pmt_nth(1, data);
+ d_rx_chan = pmt_nth(2, data);
+
+ if (pmt_eq(status, PMT_T)){
+ enter_receiving();
+ return;
+ }
+ else {
+ error_msg = "failed to allocate channel:";
+ goto bail;
+ }
+ }
+ goto unhandled;
+
+ 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;
+
+ 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;
+ }
+ }
+ goto unhandled;
+
+ case CLOSING_USRP:
+ if (pmt_eq(event, s_response_close)){
+ status = pmt_nth(1, data);
+
+ if (pmt_eq(status, PMT_T)){
+ shutdown_all(PMT_T);
+ return;
+ }
+ else {
+ error_msg = "failed to close USRP:";
+ goto bail;
+ }
+ }
+ goto unhandled;
+
+ default:
+ goto unhandled;
+ }
+ return;
+
+ bail:
+ std::cerr << error_msg << data
+ << "status = " << status << std::endl;
+ shutdown_all(PMT_F);
+ return;
+
+ unhandled:
+ std::cout << "test_usrp_inband_rx: 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;
+}
+
+void
+test_usrp_rx::close_usrp()
+{
+ d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
+ d_state = CLOSING_USRP;
+}
+
+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_state = ALLOCATING_CHANNEL;
+}
+
+void
+test_usrp_rx::enter_receiving()
+{
+ d_state = RECEIVING;
+
+ d_rx->send(s_cmd_start_recv_raw_samples,
+ pmt_list2(PMT_F,
+ d_rx_chan));
+}
+
+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 properties = pmt_nth(4, data);
+
+ size_t n_bytes;
+
+ const char *samples = (const char *) pmt_uniform_vector_elements(v_samples, n_bytes);
+
+ if(d_disk_write)
+ d_ofile.write(samples, n_bytes);
+
+ if(verbose)
+ std::cout << ".";
+
+ if (pmt_is_dict(properties)) {
+ // Read the RSSI
+ if(pmt_t rssi = pmt_dict_ref(properties,
+ pmt_intern("rssi"),
+ PMT_NIL)) {
+ if(!pmt_eqv(rssi, PMT_NIL))
+ std::cout << "RSSI: " << rssi << std::endl;
+ }
+ }
+
+
+}
+
+void
+test_usrp_rx::enter_closing_channel()
+{
+ d_state = CLOSING_CHANNEL;
+
+ d_rx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_rx_chan));
+}
+
+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/test_usrp_inband_timestamps.cc b/usrp/host/apps/test_usrp_inband_timestamps.cc
new file mode 100644
index 000000000..d48c2a789
--- /dev/null
+++ b/usrp/host/apps/test_usrp_inband_timestamps.cc
@@ -0,0 +1,508 @@
+/* -*- 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 <ui_nco.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+#include <iostream>
+
+#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>
+
+#define NBPING 10
+
+static bool verbose = true;
+bool bskip = false;
+long bstep = 10000;
+long bcurr = 0;
+long incr = 0x500;
+long ptime = 0x000;
+
+class test_usrp_inband_timestamps : 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];
+
+ enum state_t {
+ INIT,
+ OPENING_USRP,
+ ALLOCATING_CHANNEL,
+ TRANSMITTING,
+ CLOSING_CHANNEL,
+ CLOSING_USRP,
+ };
+
+ 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_usrp_inband_timestamps(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+ ~test_usrp_inband_timestamps();
+ 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 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_inband_timestamps::test_usrp_inband_timestamps(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_nsamples_xmitted(0),
+ d_nframes_xmitted(0),
+ //d_samples_per_frame((long)(126)),
+ d_samples_per_frame((long)(126 * 2)), // non-full packet
+ //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_TIMESTAMPS] 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 = false;
+
+ // Test the TX side
+
+ pmt_t usrp_dict = pmt_make_dict();
+
+ if(fake_usrp_p) {
+ pmt_dict_set(usrp_dict,
+ pmt_intern("fake-usrp"),
+ PMT_T);
+ }
+
+ // Set TX and RX interpolations
+ pmt_dict_set(usrp_dict,
+ pmt_intern("interp-tx"),
+ pmt_from_long(128));
+
+ pmt_dict_set(usrp_dict,
+ pmt_intern("interp-rx"),
+ pmt_from_long(16));
+
+ // Specify the RBF to use
+ pmt_dict_set(usrp_dict,
+ pmt_intern("rbf"),
+ pmt_intern("tmac5.rbf"));
+
+ define_component("server", "usrp_server", usrp_dict);
+
+ connect("self", "tx0", "server", "tx0");
+ connect("self", "rx0", "server", "rx0");
+ connect("self", "cs", "server", "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_usrp_inband_timestamps::~test_usrp_inband_timestamps()
+{
+}
+
+void
+test_usrp_inband_timestamps::initial_transition()
+{
+ open_usrp();
+}
+
+void
+test_usrp_inband_timestamps::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;
+ std::string error_msg;
+
+ //std::cout << msg << std::endl;
+
+ switch(d_state){
+ 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;
+
+ case ALLOCATING_CHANNEL:
+ if (pmt_eq(event, s_response_allocate_channel)){
+
+ 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_TIMESTAMPS] 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(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_TIMESTAMPS] 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;
+ }
+ }
+ }
+ goto unhandled;
+
+ case TRANSMITTING:
+ if (pmt_eq(event, s_response_xmit_raw_frame)){
+ 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-xmit-raw-frame:";
+ goto bail;
+ }
+ }
+
+ if (pmt_eq(event, s_response_from_control_channel)) {
+ std::cout << "ping response!\n";
+ }
+ goto unhandled;
+
+ 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;
+ }
+ }
+ goto unhandled;
+
+ case CLOSING_USRP:
+ if (pmt_eq(event, s_response_close)){
+ status = pmt_nth(1, data);
+
+ if (pmt_eq(status, PMT_T)){
+ shutdown_all(PMT_T);
+ return;
+ }
+ else {
+ error_msg = "failed to close USRP:";
+ goto bail;
+ }
+ }
+ goto unhandled;
+
+ default:
+ goto unhandled;
+ }
+ return;
+
+ bail:
+ std::cerr << error_msg << data
+ << "status = " << status << std::endl;
+ shutdown_all(PMT_F);
+ return;
+
+ unhandled:
+ if(verbose && 0)
+ std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
+ << "in state "<< d_state << std::endl;
+}
+
+
+void
+test_usrp_inband_timestamps::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;
+}
+
+void
+test_usrp_inband_timestamps::close_usrp()
+{
+ d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
+ d_state = CLOSING_USRP;
+
+ if(verbose)
+ std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Closing USRP\n";
+}
+
+void
+test_usrp_inband_timestamps::allocate_channel()
+{
+ long capacity = (long) 16e6;
+ 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;
+}
+
+void
+test_usrp_inband_timestamps::enter_receiving()
+{
+ d_rx->send(s_cmd_start_recv_raw_samples,
+ pmt_list2(PMT_F,
+ d_rx_chan));
+}
+
+void
+test_usrp_inband_timestamps::enter_transmitting()
+{
+ d_state = TRANSMITTING;
+ d_nsamples_xmitted = 0;
+
+ if(verbose)
+ std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Beginning transmission\n";
+
+ sleep(1);
+
+ build_and_send_next_frame();
+ build_and_send_next_frame();
+ build_and_send_next_frame();
+ build_and_send_next_frame();
+
+}
+
+void
+test_usrp_inband_timestamps::build_and_send_ping()
+{
+
+ 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))))));
+ if(verbose && 0)
+ std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Ping sent" << std::endl;
+}
+
+void
+test_usrp_inband_timestamps::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();
+ }
+ }
+
+ pmt_t timestamp;
+
+ if(bskip) {
+ timestamp = pmt_from_long(0x0); // throw away
+ bcurr++;
+ if(bcurr == bstep) {
+ bskip = false;
+ bcurr = 0;
+ }
+ } else {
+ timestamp = pmt_from_long(0xffffffff); // NOW
+ timestamp = pmt_from_long(ptime);
+ ptime += incr;
+ bcurr++;
+ if(bcurr == bstep) {
+ //bskip = true;
+ bcurr = 0;
+ }
+ }
+
+ std::cout << bskip << " -- " << bcurr << std::endl;
+
+ d_tx->send(s_cmd_xmit_raw_frame,
+ pmt_list4(pmt_from_long(d_nframes_xmitted), // invocation-handle
+ d_tx_chan, // channel
+ uvec, // the samples
+ timestamp));
+
+ d_nsamples_xmitted += nsamples_this_frame;
+ d_nframes_xmitted++;
+
+ if(verbose && 0)
+ std::cout << "[TEST_USRP_INBAND_TIMESTAMPS] Transmitted frame\n";
+
+ //build_and_send_next_frame();
+}
+
+
+void
+test_usrp_inband_timestamps::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
+ enter_closing_channel();
+ }
+
+ build_and_send_next_frame();
+ //build_and_send_ping();
+}
+
+void
+test_usrp_inband_timestamps::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_TIMESTAMPS] Closing channel\n";
+}
+
+REGISTER_MBLOCK_CLASS(test_usrp_inband_timestamps);
+
+
+// ----------------------------------------------------------------
+
+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_inband_timestamps", PMT_F, &result);
+}
diff --git a/usrp/host/apps/test_usrp_inband_tx.cc b/usrp/host/apps/test_usrp_inband_tx.cc
new file mode 100644
index 000000000..18d36213b
--- /dev/null
+++ b/usrp/host/apps/test_usrp_inband_tx.cc
@@ -0,0 +1,409 @@
+/* -*- 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 <ui_nco.h>
+#include <stdio.h>
+#include <string.h>
+#include <iostream>
+
+#include <symbols_usrp_server_cs.h>
+#include <symbols_usrp_channel.h>
+#include <symbols_usrp_low_level_cs.h>
+#include <symbols_usrp_tx.h>
+
+static bool verbose = false;
+
+class test_usrp_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,
+ OPENING_USRP,
+ ALLOCATING_CHANNEL,
+ TRANSMITTING,
+ CLOSING_CHANNEL,
+ CLOSING_USRP,
+ };
+
+ 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_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);
+
+ 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_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_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)
+{
+ // std::cout << "[TEST_USRP_TX] 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);
+
+ //bool fake_usrp_p = true;
+ bool fake_usrp_p = false;
+
+ // Test the TX side
+
+ pmt_t usrp_dict = pmt_make_dict();
+
+ 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("boe3.rbf"));
+
+ // Set TX and RX interpolations
+ pmt_dict_set(usrp_dict,
+ pmt_intern("interp-tx"),
+ pmt_from_long(128));
+
+ pmt_dict_set(usrp_dict,
+ pmt_intern("interp-rx"),
+ pmt_from_long(16));
+
+ pmt_dict_set(usrp_dict,
+ pmt_intern("rf-freq"),
+ pmt_from_long(10e6));
+
+ define_component("server", "usrp_server", usrp_dict);
+
+ connect("self", "tx0", "server", "tx0");
+ connect("self", "cs", "server", "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);
+
+ // FIXME need to somehow set the interp rate in the USRP.
+ // for now, we'll have the low-level code hardwire it.
+}
+
+test_usrp_tx::~test_usrp_tx()
+{
+}
+
+void
+test_usrp_tx::initial_transition()
+{
+ open_usrp();
+}
+
+void
+test_usrp_tx::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;
+
+ //std::cout << msg << std::endl;
+
+ switch(d_state){
+ 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;
+
+ case ALLOCATING_CHANNEL:
+ if (pmt_eq(event, s_response_allocate_channel)){
+ status = pmt_nth(1, data);
+ d_tx_chan = pmt_nth(2, data);
+
+ if (pmt_eq(status, PMT_T)){
+ enter_transmitting();
+ return;
+ }
+ else {
+ error_msg = "failed to allocate channel:";
+ goto bail;
+ }
+ }
+ goto unhandled;
+
+ case TRANSMITTING:
+ if (pmt_eq(event, s_response_xmit_raw_frame)){
+ 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-xmit-raw-frame:";
+ goto bail;
+ }
+ }
+ goto unhandled;
+
+ 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;
+ }
+ }
+ goto unhandled;
+
+ case CLOSING_USRP:
+ if (pmt_eq(event, s_response_close)){
+ status = pmt_nth(1, data);
+
+ if (pmt_eq(status, PMT_T)){
+ shutdown_all(PMT_T);
+ return;
+ }
+ else {
+ error_msg = "failed to close USRP:";
+ goto bail;
+ }
+ }
+ goto unhandled;
+
+ default:
+ goto unhandled;
+ }
+ return;
+
+ bail:
+ std::cerr << error_msg << data
+ << "status = " << status << std::endl;
+ shutdown_all(PMT_F);
+ return;
+
+ unhandled:
+ std::cout << "test_usrp_inband_tx: unhandled msg: " << msg
+ << "in state "<< d_state << std::endl;
+}
+
+
+void
+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;
+}
+
+void
+test_usrp_tx::close_usrp()
+{
+ d_cs->send(s_cmd_close, pmt_list1(PMT_NIL));
+ d_state = CLOSING_USRP;
+}
+
+void
+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;
+}
+
+void
+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(0))))));
+
+ 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_tx::build_and_send_next_frame()
+{
+ // allocate the uniform vector for the samples
+ // FIXME perhaps hold on to this between calls
+
+#if 1
+ 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();
+ }
+ }
+
+ 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
+ uvec, // the samples
+ timestamp));
+
+ d_nsamples_xmitted += nsamples_this_frame;
+ d_nframes_xmitted++;
+
+ if(verbose)
+ std::cout << "[TEST_USRP_INBAND_TX] Transmitted frame\n";
+}
+
+
+void
+test_usrp_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
+ enter_closing_channel();
+ }
+
+ build_and_send_next_frame();
+}
+
+void
+test_usrp_tx::enter_closing_channel()
+{
+ d_state = CLOSING_CHANNEL;
+
+ d_tx->send(s_cmd_deallocate_channel, pmt_list2(PMT_NIL, d_tx_chan));
+}
+
+REGISTER_MBLOCK_CLASS(test_usrp_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("top", "test_usrp_tx", PMT_F, &result);
+}
diff --git a/usrp/host/apps/ui_nco.h b/usrp/host/apps/ui_nco.h
new file mode 100644
index 000000000..e6d7814ab
--- /dev/null
+++ b/usrp/host/apps/ui_nco.h
@@ -0,0 +1,202 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef INCLUDED_UI_NCO_H
+#define INCLUDED_UI_NCO_H
+
+
+#include <vector>
+#include <ui_sincos.h>
+#include <cmath>
+
+#include <complex>
+typedef std::complex<float> gr_complex;
+
+
+/*!
+ * \brief base class template for Numerically Controlled Oscillator (NCO)
+ */
+
+
+//FIXME Eventually generalize this to fixed point
+
+template<class o_type, class i_type>
+class ui_nco {
+public:
+ ui_nco () : phase (0), phase_inc(0) {}
+
+ virtual ~ui_nco () {}
+
+ // radians
+ void set_phase (double angle) {
+ phase = angle;
+ }
+
+ void adjust_phase (double delta_phase) {
+ phase += delta_phase;
+ }
+
+
+ // angle_rate is in radians / step
+ void set_freq (double angle_rate){
+ phase_inc = angle_rate;
+ }
+
+ // angle_rate is a delta in radians / step
+ void adjust_freq (double delta_angle_rate)
+ {
+ phase_inc += delta_angle_rate;
+ }
+
+ // increment current phase angle
+
+ void step ()
+ {
+ phase += phase_inc;
+ if (fabs (phase) > M_PI){
+
+ while (phase > M_PI)
+ phase -= 2*M_PI;
+
+ while (phase < -M_PI)
+ phase += 2*M_PI;
+ }
+ }
+
+ void step (int n)
+ {
+ phase += phase_inc * n;
+ if (fabs (phase) > M_PI){
+
+ while (phase > M_PI)
+ phase -= 2*M_PI;
+
+ while (phase < -M_PI)
+ phase += 2*M_PI;
+ }
+ }
+
+ // units are radians / step
+ double get_phase () const { return phase; }
+ double get_freq () const { return phase_inc; }
+
+ // compute sin and cos for current phase angle
+ void sincos (float *sinx, float *cosx) const;
+
+ // compute cos or sin for current phase angle
+ float cos () const { return std::cos (phase); }
+ float sin () const { return std::sin (phase); }
+
+ // compute a block at a time
+ void sin (float *output, int noutput_items, double ampl = 1.0);
+ void cos (float *output, int noutput_items, double ampl = 1.0);
+ void sincos (gr_complex *output, int noutput_items, double ampl = 1.0);
+ void sin (short *output, int noutput_items, double ampl = 1.0);
+ void cos (short *output, int noutput_items, double ampl = 1.0);
+ void sin (int *output, int noutput_items, double ampl = 1.0);
+ void cos (int *output, int noutput_items, double ampl = 1.0);
+
+protected:
+ double phase;
+ double phase_inc;
+};
+
+template<class o_type, class i_type>
+void
+ui_nco<o_type,i_type>::sincos (float *sinx, float *cosx) const
+{
+ ui_sincosf (phase, sinx, cosx);
+}
+
+template<class o_type, class i_type>
+void
+ui_nco<o_type,i_type>::sin (float *output, int noutput_items, double ampl)
+{
+ for (int i = 0; i < noutput_items; i++){
+ output[i] = (float)(sin () * ampl);
+ step ();
+ }
+}
+
+template<class o_type, class i_type>
+void
+ui_nco<o_type,i_type>::cos (float *output, int noutput_items, double ampl)
+{
+ for (int i = 0; i < noutput_items; i++){
+ output[i] = (float)(cos () * ampl);
+ step ();
+ }
+}
+
+template<class o_type, class i_type>
+void
+ui_nco<o_type,i_type>::sin (short *output, int noutput_items, double ampl)
+{
+ for (int i = 0; i < noutput_items; i++){
+ output[i] = (short)(sin() * ampl);
+ step ();
+ }
+}
+
+template<class o_type, class i_type>
+void
+ui_nco<o_type,i_type>::cos (short *output, int noutput_items, double ampl)
+{
+ for (int i = 0; i < noutput_items; i++){
+ output[i] = (short)(cos () * ampl);
+ step ();
+ }
+}
+
+template<class o_type, class i_type>
+void
+ui_nco<o_type,i_type>::sin (int *output, int noutput_items, double ampl)
+{
+ for (int i = 0; i < noutput_items; i++){
+ output[i] = (int)(sin () * ampl);
+ step ();
+ }
+}
+
+template<class o_type, class i_type>
+void
+ui_nco<o_type,i_type>::cos (int *output, int noutput_items, double ampl)
+{
+ for (int i = 0; i < noutput_items; i++){
+ output[i] = (int)(cos () * ampl);
+ step ();
+ }
+}
+
+template<class o_type, class i_type>
+void
+ui_nco<o_type,i_type>::sincos (gr_complex *output, int noutput_items, double ampl)
+{
+ for (int i = 0; i < noutput_items; i++){
+ float cosx, sinx;
+ sincos (&sinx, &cosx);
+ output[i] = gr_complex(cosx * ampl, sinx * ampl);
+ step ();
+ }
+}
+
+#endif /* INCLUDED_UI_NCO_H */
+
diff --git a/usrp/host/apps/ui_sincos.c b/usrp/host/apps/ui_sincos.c
new file mode 100644
index 000000000..36ca89c7d
--- /dev/null
+++ b/usrp/host/apps/ui_sincos.c
@@ -0,0 +1,81 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define _GNU_SOURCE // ask for GNU extensions if available
+
+#include <ui_sincos.h>
+#include <math.h>
+
+// ----------------------------------------------------------------
+
+#if defined (HAVE_SINCOS)
+
+void
+ui_sincos (double x, double *sinx, double *cosx)
+{
+ sincos (x, sinx, cosx);
+}
+
+#else
+
+void
+ui_sincos (double x, double *sinx, double *cosx)
+{
+ *sinx = sin (x);
+ *cosx = cos (x);
+}
+
+#endif
+
+// ----------------------------------------------------------------
+
+#if defined (HAVE_SINCOSF)
+
+void
+ui_sincosf (float x, float *sinx, float *cosx)
+{
+ sincosf (x, sinx, cosx);
+}
+
+#elif defined (HAVE_SINF) && defined (HAVE_COSF)
+
+void
+ui_sincosf (float x, float *sinx, float *cosx)
+{
+ *sinx = sinf (x);
+ *cosx = cosf (x);
+}
+
+#else
+
+void
+ui_sincosf (float x, float *sinx, float *cosx)
+{
+ *sinx = sin (x);
+ *cosx = cos (x);
+}
+
+#endif
diff --git a/usrp/host/apps/ui_sincos.h b/usrp/host/apps/ui_sincos.h
new file mode 100644
index 000000000..d2d6e4b76
--- /dev/null
+++ b/usrp/host/apps/ui_sincos.h
@@ -0,0 +1,39 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2002,2004 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_UI_SINCOS_H
+#define INCLUDED_UI_SINCOS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// compute sine and cosine at the same time
+
+void ui_sincos (double x, double *sin, double *cos);
+void ui_sincosf (float x, float *sin, float *cos);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* INCLUDED_UI_SINCOS_H */
diff --git a/usrp/host/lib/inband/Makefile.am b/usrp/host/lib/inband/Makefile.am
index 017c5c489..76e769fbe 100644
--- a/usrp/host/lib/inband/Makefile.am
+++ b/usrp/host/lib/inband/Makefile.am
@@ -22,46 +22,74 @@ include $(top_srcdir)/Makefile.common
INCLUDES = \
$(DEFINES) $(OMNITHREAD_INCLUDES) $(PMT_INCLUDES) $(MBLOCK_INCLUDES) \
- $(USRP_INCLUDES) $(BOOST_CFLAGS) $(CPPUNIT_INCLUDES)
+ $(USRP_INCLUDES) $(BOOST_CFLAGS) $(CPPUNIT_INCLUDES) \
+ -I$(srcdir)/../../apps
TESTS = test_inband
EXTRA_DIST = \
- usrp_server.mbh
+ usrp_server.mbh \
+ usrp_interface.mbh
+
lib_LTLIBRARIES = \
libusrp_inband.la \
- libusrp_inband-qa.la
+ libusrp_inband-qa.la
# ------------------------------------------------------------------------
# Build the inband library
BUILT_SOURCES = \
- usrp_server_mbh.cc
+ usrp_server_mbh.cc \
+ usrp_interface_mbh.cc
usrp_server_mbh.cc : usrp_server.mbh
$(COMPILE_MBH) $(srcdir)/usrp_server.mbh usrp_server_mbh.cc
+usrp_interface_mbh.cc : usrp_interface.mbh
+ $(COMPILE_MBH) usrp_interface.mbh usrp_interface_mbh.cc
+
libusrp_inband_la_SOURCES = \
$(BUILT_SOURCES) \
- usrp_server.cc
+ ../../apps/ui_sincos.c \
+ usrp_inband_usb_packet.cc \
+ usrp_rx.cc \
+ usrp_rx_stub.cc \
+ usrp_server.cc \
+ usrp_tx.cc \
+ usrp_tx_stub.cc \
+ usrp_usb_interface.cc
libusrp_inband_la_LDFLAGS = $(NO_UNDEFINED) -version-info 0:0:0
libusrp_inband_la_LIBADD = \
$(MBLOCK_LA) \
+ ../legacy/libusrp.la \
-lstdc++
-
include_HEADERS = \
- usrp_server.h
+ usrp_inband_usb_packet.h \
+ usrp_rx.h \
+ usrp_rx_stub.h \
+ usrp_server.h \
+ usrp_tx.h \
+ usrp_tx_stub.h \
+ usrp_usb_interface.h
noinst_HEADERS = \
+ fake_usrp.h \
qa_inband.h \
qa_inband_packet_prims.h \
qa_inband_usrp_server.h \
- usrp_inband_usb_packet.h
+ symbols_usrp_channel.h \
+ symbols_usrp_interface_cs.h \
+ symbols_usrp_low_level_cs.h \
+ symbols_usrp_rx.h \
+ symbols_usrp_rx_cs.h \
+ symbols_usrp_server_cs.h \
+ symbols_usrp_tx.h \
+ symbols_usrp_tx_cs.h
# ------------------------------------------------------------------------
@@ -79,17 +107,22 @@ libusrp_inband_qa_la_LDFLAGS = $(NO_UNDEFINED) -avoid-version
libusrp_inband_qa_la_LIBADD = \
libusrp_inband.la \
$(CPPUNIT_LIBS) \
+ ../legacy/libusrp.la \
+ libusrp_inband.la \
-lstdc++
# ------------------------------------------------------------------------
noinst_PROGRAMS = \
- test_inband
+ test_inband \
+ test_usrp_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
new file mode 100644
index 000000000..8a66d5c18
--- /dev/null
+++ b/usrp/host/lib/inband/fake_usrp.cc
@@ -0,0 +1,135 @@
+/* -*- 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
new file mode 100644
index 000000000..818c5a506
--- /dev/null
+++ b/usrp/host/lib/inband/fake_usrp.h
@@ -0,0 +1,43 @@
+/* -*- 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/gen_test_packets.py b/usrp/host/lib/inband/gen_test_packets.py
index 1e22722d2..2ee646384 100755
--- a/usrp/host/lib/inband/gen_test_packets.py
+++ b/usrp/host/lib/inband/gen_test_packets.py
@@ -70,7 +70,7 @@ def gen_all_valid_packet_lengths_2_channels(output_file):
lengths = gen_shuffled_lengths()
npkts = len(lengths) # number of packets we'll generator on each stream
pkt_gen_0 = packet_sequence_generator(0, lengths)
- pkt_gen_1 = packet_sequence_generator(1, gen_shuffled_lengths())
+ pkt_gen_1 = packet_sequence_generator(0x1f, gen_shuffled_lengths())
pkt_gen = (pkt_gen_0, pkt_gen_1)
which_gen = (npkts * [0]) + (npkts * [1])
@@ -83,5 +83,6 @@ def gen_all_valid_packet_lengths_2_channels(output_file):
assert pkt_gen_1.next() == 16002 # 2*sum(1, 2, ..., 126) == 126 * 127
if __name__ == '__main__':
+ random.seed(0)
gen_all_valid_packet_lengths_1_channel(open("all_valid_packet_lengths_1_channel.dat", "w"))
gen_all_valid_packet_lengths_2_channels(open("all_valid_packet_lengths_2_channels.dat", "w"))
diff --git a/usrp/host/lib/inband/qa_inband_usrp_server.cc b/usrp/host/lib/inband/qa_inband_usrp_server.cc
index 324d9ee11..b01e74e00 100644
--- a/usrp/host/lib/inband/qa_inband_usrp_server.cc
+++ b/usrp/host/lib/inband/qa_inband_usrp_server.cc
@@ -23,6 +23,7 @@
#include <config.h>
#endif
+#include <usrp_inband_usb_packet.h>
#include <qa_inband_usrp_server.h>
#include <cppunit/TestAssert.h>
#include <stdio.h>
@@ -33,22 +34,17 @@
#include <mb_class_registry.h>
#include <vector>
#include <iostream>
+#include <pmt.h>
-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");
+#include <symbols_usrp_server_cs.h>
+#include <symbols_usrp_tx.h>
+#include <symbols_usrp_rx.h>
+#include <symbols_usrp_channel.h>
+#include <symbols_usrp_low_level_cs.h>
+typedef usrp_inband_usb_packet transport_pkt; // makes conversion to gigabit easy
+
+static bool verbose = false;
// ----------------------------------------------------------------------------------------------
@@ -82,16 +78,20 @@ qa_alloc_top::qa_alloc_top(mb_runtime *runtime, const std::string &instance_name
: mb_mblock(runtime, instance_name, user_arg)
{
d_nrecvd=0;
- d_nmsgs_to_recv = 7;
+ d_nmsgs_to_recv = 6;
d_nstatus=0;
- d_nstatus_to_recv = 3;
+ d_nstatus_to_recv = 50;
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", PMT_F);
+ define_component("server", "usrp_server", usrp_server_dict);
connect("self", "tx0", "server", "tx0");
connect("self", "rx0", "server", "rx0");
connect("self", "cs", "server", "cs");
@@ -103,42 +103,86 @@ qa_alloc_top::~qa_alloc_top(){}
void
qa_alloc_top::initial_transition()
{
+ // Allocations should fail before open
+ d_tx->send(s_cmd_allocate_channel,
+ pmt_list2(pmt_list2(s_response_allocate_channel,
+ s_err_usrp_not_opened),
+ pmt_from_long(1)));
+
+ d_rx->send(s_cmd_allocate_channel,
+ pmt_list2(pmt_list2(s_response_allocate_channel,
+ s_err_usrp_not_opened),
+ pmt_from_long(1)));
+
// Retrieve information about the USRP, then run tests
- d_cs->send(s_cmd_max_capacity, pmt_list1(PMT_F));
- d_cs->send(s_cmd_ntx_chan, pmt_list1(PMT_F));
- d_cs->send(s_cmd_nrx_chan, pmt_list1(PMT_F));
+ d_cs->send(s_cmd_open,
+ pmt_list2(pmt_list2(s_response_open, PMT_T),
+ pmt_from_long(0)));
+
+ d_cs->send(s_cmd_max_capacity,
+ pmt_list1(pmt_list2(s_response_max_capacity, PMT_T)));
+
+ d_cs->send(s_cmd_ntx_chan,
+ pmt_list1(pmt_list2(s_response_ntx_chan, PMT_T)));
+
+ d_cs->send(s_cmd_nrx_chan,
+ pmt_list1(pmt_list2(s_response_nrx_chan,PMT_T)));
}
void
qa_alloc_top::run_tests()
{
- std::cout << "[qa_alloc_top] Starting tests...\n";
+ if(verbose)
+ std::cout << "[qa_alloc_top] Starting tests...\n";
+
// should be able to allocate 1 byte
- d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1)));
+ d_tx->send(s_cmd_allocate_channel,
+ pmt_list2(PMT_T, pmt_from_long(1)));
// should not be able to allocate max capacity after 100 bytes were allocated
- d_tx->send(s_cmd_allocate_channel, pmt_list2(pmt_from_long(usrp_server::RQSTD_CAPACITY_UNAVAIL), pmt_from_long(d_max_capacity)));
+ d_tx->send(s_cmd_allocate_channel,
+ pmt_list2(s_err_requested_capacity_unavailable,
+ pmt_from_long(d_max_capacity)));
- // keep allocating a little more until all of the channels are used and test the error response
- // we start at 1 since we've already allocated 1 channel
+ // keep allocating a little more until all of the channels are used and test
+ // the error response we start at 1 since we've already allocated 1 channel
for(int i=1; i < d_ntx_chan; i++) {
+
+ if(verbose)
+ std::cout << "[qa_alloc_top] Sent allocation request...\n";
+
d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1)));
+
d_nmsgs_to_recv++;
}
- d_tx->send(s_cmd_allocate_channel, pmt_list2(pmt_from_long(usrp_server::CHANNEL_UNAVAIL), pmt_from_long(1)));
+
+ // No more channels after allocating all of them is expected
+ d_tx->send(s_cmd_allocate_channel,
+ pmt_list2(s_err_channel_unavailable,
+ pmt_from_long(1)));
// test out the same on the RX side
d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1)));
- d_rx->send(s_cmd_allocate_channel, pmt_list2(pmt_from_long(usrp_server::RQSTD_CAPACITY_UNAVAIL), pmt_from_long(d_max_capacity)));
+
+ d_rx->send(s_cmd_allocate_channel,
+ pmt_list2(s_err_requested_capacity_unavailable,
+ pmt_from_long(d_max_capacity)));
for(int i=1; i < d_nrx_chan; i++) {
+
d_rx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1)));
+
d_nmsgs_to_recv++;
}
- d_rx->send(s_cmd_allocate_channel, pmt_list2(pmt_from_long(usrp_server::CHANNEL_UNAVAIL), pmt_from_long(1)));
- // when all is said and done, there should be d_ntx_chan+d_ntx_chan bytes allocated
- d_cs->send(s_cmd_current_capacity_allocation, pmt_list1(pmt_from_long(d_ntx_chan+d_nrx_chan)));
+ d_rx->send(s_cmd_allocate_channel,
+ pmt_list2(s_err_channel_unavailable,
+ pmt_from_long(1)));
+
+ // when all is said and done, there should be d_ntx_chan+d_ntx_chan bytes
+ // allocated
+ d_cs->send(s_cmd_current_capacity_allocation,
+ pmt_list1(pmt_from_long(d_ntx_chan+d_nrx_chan)));
}
void
@@ -154,16 +198,22 @@ qa_alloc_top::handle_message(mb_message_sptr msg)
if (pmt_eq(msg->port_id(), d_cs->port_symbol())) {
if(pmt_eq(msg->signal(), s_response_max_capacity)) {
- d_max_capacity = pmt_to_long(pmt_nth(1, data));
- std::cout << "[qa_alloc_top] USRP has max capacity of " << d_max_capacity << "\n";
+ d_max_capacity = pmt_to_long(pmt_nth(2, data));
+ if(verbose)
+ std::cout << "[qa_alloc_top] USRP has max capacity of "
+ << d_max_capacity << "\n";
}
else if(pmt_eq(msg->signal(), s_response_ntx_chan)) {
- d_ntx_chan = pmt_to_long(pmt_nth(1, data));
- std::cout << "[qa_alloc_top] USRP tx channels: " << d_ntx_chan << "\n";
+ d_ntx_chan = pmt_to_long(pmt_nth(2, data));
+ if(verbose)
+ std::cout << "[qa_alloc_top] USRP tx channels: "
+ << d_ntx_chan << "\n";
}
else if(pmt_eq(msg->signal(), s_response_nrx_chan)) {
- d_nrx_chan = pmt_to_long(pmt_nth(1, data));
- std::cout << "[qa_alloc_top] USRP rx channels: " << d_nrx_chan << "\n";
+ d_nrx_chan = pmt_to_long(pmt_nth(2, data));
+ if(verbose)
+ std::cout << "[qa_alloc_top] USRP rx channels: "
+ << d_nrx_chan << "\n";
}
else if(pmt_eq(msg->signal(), s_response_current_capacity_allocation)) {
check_message(msg);
@@ -171,6 +221,8 @@ qa_alloc_top::handle_message(mb_message_sptr msg)
d_nstatus++;
+ check_message(msg);
+
if(d_nstatus==d_nstatus_to_recv)
run_tests();
}
@@ -180,18 +232,26 @@ void
qa_alloc_top::check_message(mb_message_sptr msg)
{
pmt_t data = msg->data();
+ pmt_t event = msg->signal();
+
+ pmt_t expected = pmt_nth(0, data);
+ pmt_t status = pmt_nth(1, data);
- pmt_t expected_result = pmt_nth(0, data);
- pmt_t result = pmt_nth(1, data);
+ pmt_t e_event = pmt_nth(0, expected);
+ pmt_t e_status = pmt_nth(1, expected);
d_nrecvd++;
- if(!pmt_eqv(expected_result, result)) {
- std::cout << "Got: " << result << " Expected: " << expected_result << "\n";
+ if(!pmt_eqv(e_status, status) || !pmt_eqv(e_event, event)) {
+ if(verbose)
+ std::cout << "Got: " << status << " Expected: " << e_status << "\n";
shutdown_all(PMT_F);
+ return;
} else {
- std::cout << "[qa_alloc_top] Received expected response for message " << d_nrecvd << "\n";
+ if(verbose)
+ std::cout << "[qa_alloc_top] Received expected response for message "
+ << d_nrecvd << " (" << event << ")\n";
}
if(d_nrecvd == d_nmsgs_to_recv)
@@ -242,16 +302,20 @@ qa_dealloc_top::qa_dealloc_top(mb_runtime *runtime, const std::string &instance_
d_ndealloc_recvd=0;
d_ndealloc_to_recv = 0;
d_nalloc_recvd=0;
- d_nalloc_to_recv = 0;
+ d_nalloc_to_recv = 0; // auto-set
d_nstatus=0;
- d_nstatus_to_recv = 3;
+ d_nstatus_to_recv = 4;
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", PMT_F);
+ define_component("server", "usrp_server", usrp_server_dict);
connect("self", "tx0", "server", "tx0");
connect("self", "rx0", "server", "rx0");
connect("self", "cs", "server", "cs");
@@ -262,26 +326,46 @@ qa_dealloc_top::~qa_dealloc_top(){}
void
qa_dealloc_top::initial_transition()
{
+
+ if(verbose)
+ std::cout << "[qa_dealloc_top] Initializing...\n";
+
// Retrieve information about the USRP, then run tests
- d_cs->send(s_cmd_max_capacity, pmt_list1(PMT_F));
- d_cs->send(s_cmd_ntx_chan, pmt_list1(PMT_F));
- d_cs->send(s_cmd_nrx_chan, pmt_list1(PMT_F));
+ d_cs->send(s_cmd_open,
+ pmt_list2(pmt_list2(s_response_open,PMT_T),
+ pmt_from_long(0)));
+
+ d_cs->send(s_cmd_max_capacity,
+ pmt_list1(pmt_list2(s_response_max_capacity,PMT_T)));
+
+ d_cs->send(s_cmd_ntx_chan,
+ pmt_list1(pmt_list2(s_response_ntx_chan,PMT_T)));
+
+ d_cs->send(s_cmd_nrx_chan,
+ pmt_list1(pmt_list2(s_response_nrx_chan,PMT_T)));
}
void
qa_dealloc_top::allocate_max()
{
- std::cout << "[qa_dealloc_top] Max allocating...\n";
// Keep allocating until we hit the maximum number of channels
for(int i=0; i < d_ntx_chan; i++) {
- d_tx->send(s_cmd_allocate_channel, pmt_list2(PMT_T, pmt_from_long(1)));
+ d_tx->send(s_cmd_allocate_channel,
+ pmt_list2(pmt_list2(s_response_allocate_channel,PMT_T),
+ pmt_from_long(1))); // 1 byte is good enough
+
d_nalloc_to_recv++;
}
+
for(int i=0; i < d_nrx_chan; i++) {
- d_rx->send(s_cmd_allocate_channel, pmt_list2(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)));
+
d_nalloc_to_recv++;
}
+
}
void
@@ -289,40 +373,103 @@ qa_dealloc_top::deallocate_all() {
// Deallocate all of the channels that were allocated from allocate_max()
for(int i=0; i < (int)d_tx_chans.size(); i++) {
- d_tx->send(s_cmd_deallocate_channel, pmt_list2(PMT_T, pmt_from_long(d_tx_chans[i])));
+
+ if(verbose)
+ std::cout << "[qa_dealloc_top] Trying to dealloc TX "
+ << d_tx_chans[i] << std::endl;
+
+ d_tx->send(s_cmd_deallocate_channel,
+ pmt_list2(pmt_list2(s_response_deallocate_channel,PMT_T),
+ pmt_from_long(d_tx_chans[i])));
+
d_ndealloc_to_recv++;
}
+
+ // Deallocate the RX side now
for(int i=0; i < (int)d_rx_chans.size(); i++) {
- d_rx->send(s_cmd_deallocate_channel, pmt_list2(PMT_T, pmt_from_long(d_rx_chans[i])));
+
+ if(verbose)
+ std::cout << "[qa_dealloc_top] Trying to dealloc RX "
+ << d_tx_chans[i] << std::endl;
+
+ d_rx->send(s_cmd_deallocate_channel,
+ pmt_list2(pmt_list2(s_response_deallocate_channel,PMT_T),
+ pmt_from_long(d_rx_chans[i])));
+
d_ndealloc_to_recv++;
}
- // Should get permission denied errors trying to re-dealloc the channels, as we no
- // longer have permission to them after deallocating
+ // Should get permission denied errors trying to re-dealloc the channels, as
+ // we no longer have permission to them after deallocating
for(int i=0; i < (int)d_tx_chans.size(); i++) {
- d_tx->send(s_cmd_deallocate_channel, pmt_list2(pmt_from_long(usrp_server::PERMISSION_DENIED), pmt_from_long(d_tx_chans[i])));
+
+ d_tx->send(s_cmd_deallocate_channel,
+ pmt_list2(pmt_list2(s_response_deallocate_channel,
+ s_err_channel_permission_denied),
+ pmt_from_long(d_tx_chans[i])));
+
d_ndealloc_to_recv++;
}
+
+ // Same for RX
for(int i=0; i < (int)d_rx_chans.size(); i++) {
- d_rx->send(s_cmd_deallocate_channel, pmt_list2(pmt_from_long(usrp_server::PERMISSION_DENIED), pmt_from_long(d_rx_chans[i])));
+
+ d_rx->send(s_cmd_deallocate_channel,
+ pmt_list2(pmt_list2(s_response_deallocate_channel,
+ s_err_channel_permission_denied),
+ pmt_from_long(d_rx_chans[i])));
+
d_ndealloc_to_recv++;
}
- // Try to deallocate a channel that doesn't exist on both sides, the last element in the vectors
- // is the highest channel number, so we take that plus 1
+ // Try to deallocate a channel that doesn't exist on both sides, the last
+ // element in the vectors is the highest channel number, so we take that plus
+ // 1
d_ndealloc_to_recv+=2;
- d_tx->send(s_cmd_deallocate_channel, pmt_list2(pmt_from_long(usrp_server::CHANNEL_INVALID), pmt_from_long(d_rx_chans.back()+1)));
- d_rx->send(s_cmd_deallocate_channel, pmt_list2(pmt_from_long(usrp_server::CHANNEL_INVALID), pmt_from_long(d_rx_chans.back()+1)));
+ d_tx->send(s_cmd_deallocate_channel,
+ pmt_list2(pmt_list2(s_response_deallocate_channel,
+ s_err_channel_invalid),
+ pmt_from_long(d_rx_chans.back()+1)));
+
+ d_rx->send(s_cmd_deallocate_channel,
+ pmt_list2(pmt_list2(s_response_deallocate_channel,
+ s_err_channel_invalid),
+ pmt_from_long(d_rx_chans.back()+1)));
// The used capacity should be back to 0 now that we've deallocated everything
- d_cs->send(s_cmd_current_capacity_allocation, pmt_list1(pmt_from_long(0)));
+ d_cs->send(s_cmd_current_capacity_allocation,
+ pmt_list1(pmt_list2(s_response_current_capacity_allocation,
+ PMT_T)));
}
void
qa_dealloc_top::handle_message(mb_message_sptr msg)
{
pmt_t data = msg->data();
+ pmt_t event = msg->signal();
+
+ if(pmt_eq(event, pmt_intern("%shutdown")))
+ return;
+
+ pmt_t expected = pmt_nth(0, data);
+ pmt_t status = pmt_nth(1, data);
+
+ pmt_t e_event = pmt_nth(0, expected);
+ pmt_t e_status = pmt_nth(1, expected);
+
+ if(!pmt_eqv(e_status, status) || !pmt_eqv(e_event, event)) {
+ if(verbose)
+ std::cout << "Got: " << status << " Expected: " << e_status << "\n";
+ shutdown_all(PMT_F);
+ return;
+ } else {
+ if(verbose)
+ std::cout << "[qa_alloc_top] Received expected response for message "
+ << d_ndealloc_recvd
+ << " (" << event << ")\n";
+ }
+
if (pmt_eq(msg->port_id(), d_tx->port_symbol())
|| pmt_eq(msg->port_id(), d_rx->port_symbol())) {
@@ -330,34 +477,32 @@ qa_dealloc_top::handle_message(mb_message_sptr msg)
check_allocation(msg);
}
- if(pmt_eq(msg->signal(), s_response_deallocate_channel)){
- check_deallocation(msg);
- }
}
if (pmt_eq(msg->port_id(), d_cs->port_symbol())) {
if(pmt_eq(msg->signal(), s_response_max_capacity)) {
- d_max_capacity = pmt_to_long(pmt_nth(1, data));
- std::cout << "[qa_dealloc_top] USRP has max capacity of " << d_max_capacity << "\n";
+ d_max_capacity = pmt_to_long(pmt_nth(2, data));
}
else if(pmt_eq(msg->signal(), s_response_ntx_chan)) {
- d_ntx_chan = pmt_to_long(pmt_nth(1, data));
- std::cout << "[qa_dealloc_top] USRP tx channels: " << d_ntx_chan << "\n";
+ d_ntx_chan = pmt_to_long(pmt_nth(2, data));
}
else if(pmt_eq(msg->signal(), s_response_nrx_chan)) {
- d_nrx_chan = pmt_to_long(pmt_nth(1, data));
- std::cout << "[qa_dealloc_top] USRP rx channels: " << d_nrx_chan << "\n";
+ d_nrx_chan = pmt_to_long(pmt_nth(2, data));
}
else if(pmt_eq(msg->signal(), s_response_current_capacity_allocation)) {
- // the final command is a capacity check which should be 0, then we shutdown
- pmt_t expected_result = pmt_nth(0, data);
- pmt_t result = pmt_nth(1, data);
+ // the final command is a capacity check which should be 0, then we
+ // shutdown
+ pmt_t expected_result = pmt_from_long(0);
+ pmt_t result = pmt_nth(2, data);
- if(pmt_eqv(expected_result, result))
+ if(pmt_eqv(expected_result, result)) {
shutdown_all(PMT_T);
- else
+ return;
+ } else {
shutdown_all(PMT_F);
+ return;
+ }
}
d_nstatus++;
@@ -367,72 +512,833 @@ qa_dealloc_top::handle_message(mb_message_sptr msg)
}
}
+
void
-qa_dealloc_top::check_deallocation(mb_message_sptr msg)
+qa_dealloc_top::check_allocation(mb_message_sptr msg)
{
pmt_t data = msg->data();
+ pmt_t event = msg->signal();
- pmt_t expected_result = pmt_nth(0, data);
- pmt_t result = pmt_nth(1, data);
+ pmt_t expected = pmt_nth(0, data);
+ pmt_t status = pmt_nth(1, data);
+ pmt_t channel = pmt_nth(2, data);
- d_ndealloc_recvd++;
+ d_nalloc_recvd++;
- if(!pmt_eqv(expected_result, result)) {
- std::cout << "Got: " << result << " Expected: " << expected_result << "\n";
+ if(!pmt_eqv(status, PMT_T)) {
shutdown_all(PMT_F);
+ return;
} else {
- std::cout << "[qa_dealloc_top] Received expected deallocation response for message " << d_ndealloc_recvd << "\n";
+ // store all of the allocate channel numbers
+ if(pmt_eq(msg->port_id(), d_tx->port_symbol()))
+ d_tx_chans.push_back(pmt_to_long(channel));
+ if(pmt_eq(msg->port_id(), d_rx->port_symbol()))
+ d_rx_chans.push_back(pmt_to_long(channel));
}
+
+ if(d_nalloc_recvd == d_nalloc_to_recv) {
+
+ if(verbose) {
+ std::cout << "[qa_dealloc_top] Allocated TX channels: ";
+ for(int i=0; i < (int)d_tx_chans.size(); i++)
+ std::cout << d_tx_chans[i] << " ";
+
+ std::cout << "\n[qa_dealloc_top] Allocated RX channels: ";
+ for(int i=0; i < (int)d_rx_chans.size(); i++)
+ std::cout << d_rx_chans[i] << " ";
+ std::cout << "\n";
+ }
+
+ deallocate_all(); // once we've allocated all of our channels, try to
+ // dealloc them
+ }
+}
+
+REGISTER_MBLOCK_CLASS(qa_dealloc_top);
+
+// ----------------------------------------------------------------------------------------------
+
+class qa_open_close_top : public mb_mblock
+{
+ mb_port_sptr d_cs;
+
+ long d_max_capacity;
+
+ long d_nmsg_to_recv;
+ long d_nmsg_recvd;
+
+ public:
+ qa_open_close_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+ ~qa_open_close_top();
+ void initial_transition();
+ void handle_message(mb_message_sptr msg);
+
+ protected:
+ void check_cs(mb_message_sptr msg);
+ void run_tests();
+};
+
+qa_open_close_top::qa_open_close_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+ : mb_mblock(runtime, instance_name, user_arg)
+{
+
+ d_nmsg_to_recv=7;
+ d_nmsg_recvd=0;
+
+ 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", "cs", "server", "cs");
}
+qa_open_close_top::~qa_open_close_top(){}
+
void
-qa_dealloc_top::check_allocation(mb_message_sptr msg)
+qa_open_close_top::initial_transition()
+{
+ run_tests();
+}
+
+void
+qa_open_close_top::run_tests()
+{
+ // std::cout << "[qa_open_close_top] Starting tests\n";
+
+ // A close before an open should fail
+ d_cs->send(s_cmd_close, pmt_list1(pmt_list2(s_response_close,
+ s_err_usrp_already_closed)));
+
+ // Perform an open, and a second open which should fail
+ d_cs->send(s_cmd_open,
+ pmt_list2(pmt_list2(s_response_open,PMT_T),
+ pmt_from_long(0)));
+
+ d_cs->send(s_cmd_open,
+ pmt_list2(pmt_list2(s_response_open,
+ s_err_usrp_already_opened),
+ pmt_from_long(0)));
+
+ // A close should now be successful since the interface is open
+ d_cs->send(s_cmd_close, pmt_list1(pmt_list2(s_response_close,PMT_T)));
+
+ // But, a second close should fail
+ d_cs->send(s_cmd_close, pmt_list1(pmt_list2(s_response_close,
+ s_err_usrp_already_closed)));
+
+ // Just to be thorough, try an open and close again
+ d_cs->send(s_cmd_open,
+ pmt_list2(pmt_list2(s_response_open,PMT_T),
+ pmt_from_long(0)));
+
+ d_cs->send(s_cmd_close, pmt_list1(pmt_list2(s_response_close,PMT_T)));
+
+}
+
+
+void
+qa_open_close_top::handle_message(mb_message_sptr msg)
{
pmt_t data = msg->data();
- pmt_t invocation_handle = pmt_nth(0, data);
+ if (pmt_eq(msg->port_id(), d_cs->port_symbol())) {
+ check_cs(msg);
+ }
+
+ d_nmsg_recvd++;
+
+ if(d_nmsg_to_recv == d_nmsg_recvd)
+ shutdown_all(PMT_T);
+}
+
+void
+qa_open_close_top::check_cs(mb_message_sptr msg)
+{
+ pmt_t data = msg->data();
+ pmt_t event = msg->signal();
+
+ pmt_t expected = pmt_nth(0, data);
pmt_t status = pmt_nth(1, data);
- pmt_t channel = pmt_nth(2, data);
+
+ pmt_t e_event = pmt_nth(0, expected);
+ pmt_t e_status = pmt_nth(1, expected);
+
+ if(!pmt_eqv(e_status, status) || !pmt_eqv(e_event, event)) {
+
+ if(verbose)
+ std::cout << "[qa_open_close_top] FAILED check_cs... Got: " << status
+ << " Expected: " << e_status
+ << " for event " << event << "\n";
+
+ shutdown_all(PMT_F);
+ } else {
+ if(verbose)
+ std::cout << "[qa_open_close_top] Received expected CS response ("
+ << event << ")\n";
+ }
+
+}
+
+REGISTER_MBLOCK_CLASS(qa_open_close_top);
+
+// ----------------------------------------------------------------------------------------------
+
+class qa_tx_top : public mb_mblock
+{
+ mb_port_sptr d_tx;
+ mb_port_sptr d_rx;
+ mb_port_sptr d_cs;
- d_nalloc_recvd++;
+ long d_max_capacity;
+ long d_ntx_chan, d_nrx_chan;
+
+ long d_tx_chan;
+ long d_rx_chan;
+
+ long d_nmsg_to_recv;
+ long d_nmsg_recvd;
+
+ public:
+ qa_tx_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+ ~qa_tx_top();
+ void initial_transition();
+ void handle_message(mb_message_sptr msg);
+
+ protected:
+ void check_allocation(mb_message_sptr msg);
+ void check_deallocation(mb_message_sptr msg);
+ void check_xmit(mb_message_sptr msg);
+ void check_cs(mb_message_sptr msg);
+ void run_tests();
+};
- if(pmt_eqv(status, PMT_F)) {
- std::cout << "[qa_dealloc_top] Unexpected error response when allocating channels\n";
+qa_tx_top::qa_tx_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+ : mb_mblock(runtime, instance_name, user_arg)
+{
+
+ d_nmsg_to_recv=10;
+ d_nmsg_recvd=0;
+
+ 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_tx_top::~qa_tx_top(){}
+
+void
+qa_tx_top::initial_transition()
+{
+ run_tests();
+}
+
+void
+qa_tx_top::run_tests()
+{
+ if(verbose)
+ std::cout << "[qa_tx_top] Starting tests\n";
+
+ // A transmit before an open should fail
+ d_tx->send(s_cmd_xmit_raw_frame,
+ pmt_list4(pmt_list2(s_response_xmit_raw_frame,
+ s_err_usrp_not_opened),
+ pmt_from_long(0),
+ pmt_make_u32vector(transport_pkt::max_payload()/4, 0),
+ pmt_from_long(0)));
+
+ // Now open
+ d_cs->send(s_cmd_open,
+ pmt_list2(pmt_list2(s_response_open,PMT_T),
+ pmt_from_long(0)));
+
+ // Try to transmit on a channel that we have no allocation for
+ d_tx->send(s_cmd_xmit_raw_frame,
+ pmt_list4(pmt_list2(s_response_xmit_raw_frame,
+ s_err_channel_permission_denied),
+ pmt_from_long(0),
+ pmt_make_u32vector(transport_pkt::max_payload()/4, 0),
+ pmt_from_long(0)));
+
+ // Get a channel allocation and send on it, we assume 0 (FIXME) until 'defer'
+ // is implemented for simplicity
+ d_tx->send(s_cmd_allocate_channel,
+ pmt_list2(pmt_list2(s_response_allocate_channel, PMT_T),
+ pmt_from_long(1)));
+
+ d_tx->send(s_cmd_xmit_raw_frame,
+ pmt_list4(pmt_list2(s_response_xmit_raw_frame, PMT_T),
+ pmt_from_long(0),
+ pmt_make_u32vector(transport_pkt::max_payload()/4, 0),
+ pmt_from_long(0)));
+
+ // Close should be successful
+ d_cs->send(s_cmd_close, pmt_list1(pmt_list2(s_response_close,PMT_T)));
+
+ // After closing, a new transmit raw frame should fail again
+ d_tx->send(s_cmd_xmit_raw_frame,
+ pmt_list4(pmt_list2(s_response_xmit_raw_frame,
+ s_err_usrp_not_opened),
+ pmt_from_long(0),
+ pmt_make_u32vector(transport_pkt::max_payload()/4, 0),
+ pmt_from_long(0)));
+
+ // Reopen and retry before getting an allocation, the first xmit should fail,
+ // after we allocate it should work again
+ d_cs->send(s_cmd_open,
+ pmt_list2(pmt_list2(s_response_open, PMT_T),
+ pmt_from_long(0)));
+
+ d_tx->send(s_cmd_xmit_raw_frame,
+ pmt_list4(pmt_list2(s_response_xmit_raw_frame,
+ s_err_channel_permission_denied),
+ pmt_from_long(0),
+ pmt_make_u32vector(transport_pkt::max_payload()/4, 0),
+ pmt_from_long(0)));
+
+ d_tx->send(s_cmd_allocate_channel,
+ pmt_list2(pmt_list2(s_response_allocate_channel, PMT_T),
+ pmt_from_long(1)));
+
+ d_tx->send(s_cmd_xmit_raw_frame,
+ pmt_list4(pmt_list2(s_response_xmit_raw_frame,PMT_T),
+ pmt_from_long(0),
+ pmt_make_u32vector(transport_pkt::max_payload()/4, 0),
+ pmt_from_long(0)));
+
+ // A final close which should be successful
+ d_cs->send(s_cmd_close, pmt_list1(pmt_list2(s_response_close,PMT_T)));
+
+}
+
+
+void
+qa_tx_top::handle_message(mb_message_sptr msg)
+{
+ pmt_t data = msg->data();
+ pmt_t event = msg->signal();
+
+ if(pmt_eq(event, pmt_intern("%shutdown")))
+ return;
+
+ pmt_t expected = pmt_nth(0, data);
+ pmt_t status = pmt_nth(1, data);
+
+ pmt_t e_event = pmt_nth(0, expected);
+ pmt_t e_status = pmt_nth(1, expected);
+
+ if(!pmt_eqv(e_status, status) || !pmt_eqv(e_event, event)) {
+ if(verbose)
+ std::cout << "[qa_xmit_top] Got: " << status
+ << " Expected: " << e_status
+ << "For signal: " << event << "\n";
shutdown_all(PMT_F);
+ return;
} else {
+ if(verbose)
+ std::cout << "[qa_xmit_top] Received expected response for message "
+ << d_nmsg_recvd
+ << " (" << event << ")\n";
+ }
+
+ if (pmt_eq(msg->port_id(), d_tx->port_symbol())
+ || pmt_eq(msg->port_id(), d_rx->port_symbol())) {
+
+ if(pmt_eq(msg->signal(), s_response_allocate_channel))
+ check_allocation(msg);
+
+ }
+
+ d_nmsg_recvd++;
+
+ if(d_nmsg_to_recv == d_nmsg_recvd){
+ shutdown_all(PMT_T);
+ return;
+ }
+}
+
+void
+qa_tx_top::check_allocation(mb_message_sptr msg)
+{
+ pmt_t data = msg->data();
+ pmt_t event = msg->signal();
+
+ pmt_t expected = pmt_nth(0, data);
+ pmt_t status = pmt_nth(1, data);
+ pmt_t channel = pmt_nth(2, data);
+
+ if(pmt_eqv(status, PMT_T)) {
// store all of the allocate channel numbers
if(pmt_eq(msg->port_id(), d_tx->port_symbol()))
- d_tx_chans.push_back(pmt_to_long(channel));
+ d_tx_chan = pmt_to_long(channel);
if(pmt_eq(msg->port_id(), d_rx->port_symbol()))
- d_rx_chans.push_back(pmt_to_long(channel));
+ d_rx_chan = pmt_to_long(channel);
}
+}
- if(d_nalloc_recvd == d_nalloc_to_recv) {
+REGISTER_MBLOCK_CLASS(qa_tx_top);
+
+// ----------------------------------------------------------------------------------------------
+
+class qa_rx_top : public mb_mblock
+{
+ mb_port_sptr d_rx;
+ mb_port_sptr d_cs;
+
+ long d_max_capacity;
+ long d_ntx_chan, d_nrx_chan;
+
+ long d_rx_chan;
+
+ long d_got_response_recv;
+
+ long d_nmsg_to_recv;
+ long d_nmsg_recvd;
+
+ public:
+ qa_rx_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+ ~qa_rx_top();
+ void initial_transition();
+ void handle_message(mb_message_sptr msg);
+
+ protected:
+ void check_allocation(mb_message_sptr msg);
+ void check_deallocation(mb_message_sptr msg);
+ void check_xmit(mb_message_sptr msg);
+ void check_cs(mb_message_sptr msg);
+ void run_tests();
+};
+
+qa_rx_top::qa_rx_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+ : mb_mblock(runtime, instance_name, user_arg),
+ 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);
+
+ // Test the TX side
+ define_component("server", "usrp_server", usrp_server_dict);
+ connect("self", "rx0", "server", "rx0");
+ connect("self", "cs", "server", "cs");
+}
+
+qa_rx_top::~qa_rx_top(){}
+
+void
+qa_rx_top::initial_transition()
+{
+ run_tests();
+}
+
+void
+qa_rx_top::run_tests()
+{
+ if(verbose)
+ std::cout << "[qa_rx_top] Starting tests\n";
+
+ d_cs->send(s_cmd_open, pmt_list2(pmt_list2(s_response_open,PMT_T), pmt_from_long(0)));
+
+ d_rx->send(s_cmd_allocate_channel,
+ pmt_list2(pmt_list2(s_response_allocate_channel,PMT_T),
+ pmt_from_long(1)));
+
+ d_rx->send(s_cmd_start_recv_raw_samples,
+ 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)));
+
+}
+
+
+void
+qa_rx_top::handle_message(mb_message_sptr msg)
+{
+ pmt_t data = msg->data();
+ pmt_t event = msg->signal();
+
+ if(pmt_eq(event, pmt_intern("%shutdown")))
+ return;
+
+ pmt_t expected = pmt_nth(0, data);
+ pmt_t status = pmt_nth(1, data);
+
+ // 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(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;
+ }
+ return;
+ }
+
+ pmt_t e_event = pmt_nth(0, expected);
+ pmt_t e_status = pmt_nth(1, expected);
+
+ if(!pmt_eqv(e_status, status) || !pmt_eqv(e_event, event)) {
+ if(verbose)
+ std::cout << "Got: " << status << " Expected: " << e_status << "\n";
+ shutdown_all(PMT_F);
+ return;
+ } else {
+ if(verbose)
+ std::cout << "[qa_rx_top] Received expected response for message "
+ << d_nmsg_recvd
+ << " (" << event << ")\n";
+ }
+
+ if (pmt_eq(msg->port_id(), d_rx->port_symbol())) {
+
+ if(pmt_eq(msg->signal(), s_response_allocate_channel))
+ check_allocation(msg);
+
+ }
+
+ // We stop when we get a close, we are successful if we
+ // got a response from recv, fail if we never got a recv response
+ if(pmt_eq(msg->signal(), s_response_close)) {
- std::cout << "[qa_dealloc_top] Allocated TX channels: ";
- for(int i=0; i < (int)d_tx_chans.size(); i++)
- std::cout << d_tx_chans[i] << " ";
+ if(d_got_response_recv) {
+ shutdown_all(PMT_T);
+ return;
+ }
+ else {
+ shutdown_all(PMT_F);
+ if(verbose)
+ std::cout << "[qa_rx_top] No response message before close\n";
+ return;
+ }
+
+ }
+
+
+ d_nmsg_recvd++;
+
+}
- std::cout << "\n[qa_dealloc_top] Allocated RX channels: ";
- for(int i=0; i < (int)d_rx_chans.size(); i++)
- std::cout << d_rx_chans[i] << " ";
- std::cout << "\n";
- deallocate_all(); // once we've allocated all of our channels, try to dealloc them
+void
+qa_rx_top::check_allocation(mb_message_sptr msg)
+{
+ pmt_t data = msg->data();
+ pmt_t event = msg->signal();
+
+ pmt_t expected = pmt_nth(0, data);
+ pmt_t status = pmt_nth(1, data);
+ pmt_t channel = pmt_nth(2, data);
+
+ if(pmt_eqv(status, PMT_T)) {
+ // store all of the allocate channel numbers
+ if(pmt_eq(msg->port_id(), d_rx->port_symbol()))
+ d_rx_chan = pmt_to_long(channel);
}
}
-REGISTER_MBLOCK_CLASS(qa_dealloc_top);
+REGISTER_MBLOCK_CLASS(qa_rx_top);
+
+
+// ----------------------------------------------------------------------------------------------
+
+class qa_cs_top : public mb_mblock
+{
+ mb_port_sptr d_tx;
+ mb_port_sptr d_rx;
+ mb_port_sptr d_cs;
+
+ long d_nmsgs_to_recv;
+ long d_nrecvd;
+
+ long d_max_capacity;
+ long d_ntx_chan, d_nrx_chan;
+
+ long d_nstatus;
+ long d_nstatus_to_recv;
+
+ public:
+ qa_cs_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+ ~qa_cs_top();
+ void initial_transition();
+ void handle_message(mb_message_sptr msg);
+
+ protected:
+ void check_message(mb_message_sptr msg);
+ void run_tests();
+};
+
+qa_cs_top::qa_cs_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+ : mb_mblock(runtime, instance_name, user_arg)
+{
+ d_nrecvd=0;
+ d_nmsgs_to_recv = 8;
+ d_nstatus=0;
+ d_nstatus_to_recv = 50;
+
+ 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_cs_top::~qa_cs_top(){}
+
+void
+qa_cs_top::initial_transition()
+{
+ run_tests();
+}
+
+void
+qa_cs_top::run_tests()
+{
+ if(verbose)
+ std::cout << "[qa_cs_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)));
+
+ d_tx->send(s_cmd_to_control_channel,
+ pmt_list2(pmt_list2(s_response_from_control_channel, PMT_T),
+ pmt_list1(
+ pmt_list2(s_op_ping_fixed,
+ pmt_list2(pmt_from_long(3),
+ pmt_from_long(0))))));
+
+ d_tx->send(s_cmd_to_control_channel,
+ pmt_list2(pmt_list2(s_response_from_control_channel, PMT_T),
+ pmt_list1(
+ pmt_list2(s_op_write_reg,
+ pmt_list2(
+ pmt_from_long(0x3),
+ pmt_from_long(0x4))))));
+
+ d_tx->send(s_cmd_to_control_channel,
+ pmt_list2(pmt_list2(s_response_from_control_channel, PMT_T),
+ pmt_list1(
+ pmt_list2(s_op_write_reg_masked,
+ pmt_list3(
+ pmt_from_long(0x3),
+ pmt_from_long(0x4),
+ pmt_from_long(0x5))))));
+
+ d_tx->send(s_cmd_to_control_channel,
+ pmt_list2(pmt_list2(s_response_from_control_channel, PMT_T),
+ pmt_list1(
+ pmt_list2(s_op_read_reg,
+ pmt_list2(pmt_from_long(0),
+ pmt_from_long(0x6))))));
+
+ d_tx->send(s_cmd_to_control_channel,
+ pmt_list2(pmt_list2(s_response_from_control_channel, PMT_T),
+ pmt_list1(
+ pmt_list2(s_op_delay,
+ pmt_list1(pmt_from_long(0x7))))));
+
+ pmt_t subpackets = pmt_list5(
+ pmt_list2(s_op_ping_fixed, pmt_list2(pmt_from_long(0), pmt_from_long(0))),
+ pmt_list2(s_op_delay, pmt_list1(pmt_from_long(0x7))),
+ pmt_list2(s_op_write_reg_masked, pmt_list3(pmt_from_long(3),
+ pmt_from_long(4),
+ pmt_from_long(5))),
+ pmt_list2(s_op_write_reg, pmt_list2(pmt_from_long(3),
+ pmt_from_long(4))),
+ pmt_list2(s_op_read_reg, pmt_list2(pmt_from_long(0),
+ pmt_from_long(6)))
+ );
+
+ d_tx->send(s_cmd_to_control_channel,
+ pmt_list2(pmt_list2(s_response_from_control_channel, PMT_T),
+ subpackets));
+
+ pmt_t i2c_data = pmt_make_u8vector(8, 0xff);
+
+ subpackets = pmt_list2(
+ pmt_list2(s_op_i2c_write,
+ pmt_list2(pmt_from_long(8), i2c_data)),
+ pmt_list2(s_op_i2c_read,
+ pmt_list3(pmt_from_long(0), pmt_from_long(9), pmt_from_long(1)))
+
+ );
+
+ d_tx->send(s_cmd_to_control_channel,
+ pmt_list2(pmt_list2(s_response_from_control_channel, PMT_T),
+ subpackets));
+
+}
+
+void
+qa_cs_top::handle_message(mb_message_sptr msg)
+{
+ pmt_t data = msg->data();
+
+ if ((pmt_eq(msg->port_id(), d_tx->port_symbol())
+ || pmt_eq(msg->port_id(), d_rx->port_symbol()))
+ && pmt_eq(msg->signal(), s_response_allocate_channel))
+ check_message(msg);
+
+ if (pmt_eq(msg->port_id(), d_tx->port_symbol())
+ && pmt_eq(msg->signal(), s_response_from_control_channel))
+ check_message(msg);
+
+ if (pmt_eq(msg->port_id(), d_cs->port_symbol())) {
+
+ if(pmt_eq(msg->signal(), s_response_max_capacity)) {
+ d_max_capacity = pmt_to_long(pmt_nth(2, data));
+ if(verbose)
+ std::cout << "[qa_cs_top] USRP has max capacity of "
+ << d_max_capacity << "\n";
+ }
+ else if(pmt_eq(msg->signal(), s_response_ntx_chan)) {
+ d_ntx_chan = pmt_to_long(pmt_nth(2, data));
+ if(verbose)
+ std::cout << "[qa_cs_top] USRP tx channels: "
+ << d_ntx_chan << "\n";
+ }
+ else if(pmt_eq(msg->signal(), s_response_nrx_chan)) {
+ d_nrx_chan = pmt_to_long(pmt_nth(2, data));
+ if(verbose)
+ std::cout << "[qa_cs_top] USRP rx channels: "
+ << d_nrx_chan << "\n";
+ }
+ else if(pmt_eq(msg->signal(), s_response_current_capacity_allocation)) {
+ check_message(msg);
+ }
+
+ d_nstatus++;
+
+ check_message(msg);
+
+ if(d_nstatus==d_nstatus_to_recv)
+ run_tests();
+ }
+}
+
+void
+qa_cs_top::check_message(mb_message_sptr msg)
+{
+ pmt_t data = msg->data();
+ pmt_t event = msg->signal();
+
+ pmt_t expected = pmt_nth(0, data);
+ pmt_t status = pmt_nth(1, data);
+
+ pmt_t e_event = pmt_nth(0, expected);
+ pmt_t e_status = pmt_nth(1, expected);
+
+ d_nrecvd++;
+
+
+ if(!pmt_eqv(e_status, status) || !pmt_eqv(e_event, event)) {
+ if(verbose)
+ std::cout << "[qa_cs_top] Got: " << status << " Expected: " << e_status << "\n";
+ shutdown_all(PMT_F);
+ return;
+ } else {
+ if(verbose)
+ std::cout << "[qa_cs_top] Received expected response for message "
+ << d_nrecvd << " (" << event << ")\n";
+ }
+
+ if(d_nrecvd == d_nmsgs_to_recv)
+ shutdown_all(PMT_T);
+}
+
+REGISTER_MBLOCK_CLASS(qa_cs_top);
// ----------------------------------------------------------------------------------------------
void
+qa_inband_usrp_server::test_open_close()
+{
+ mb_runtime_sptr rt = mb_make_runtime();
+ pmt_t result = PMT_T;
+
+ // std::cout << "\n\n----------------------------\n";
+ // std::cout << " RUNNING OPEN/CLOSE TESTS \n";
+
+ rt->run("top", "qa_open_close_top", PMT_F, &result);
+
+ CPPUNIT_ASSERT(pmt_equal(PMT_T, result));
+}
+
+void
qa_inband_usrp_server::test_chan_allocation()
{
mb_runtime_sptr rt = mb_make_runtime();
pmt_t result = PMT_T;
- rt->run("top", "qa_alloc_top", PMT_F, &result);
+ // std::cout << "\n\n----------------------------\n";
+ // std::cout << " RUNNING ALLOCATION TESTS \n";
+
+ rt->run("qa_alloc_top", "qa_alloc_top", PMT_F, &result);
CPPUNIT_ASSERT(pmt_equal(PMT_T, result));
}
@@ -443,13 +1349,52 @@ qa_inband_usrp_server::test_chan_deallocation()
mb_runtime_sptr rt = mb_make_runtime();
pmt_t result = PMT_T;
- rt->run("top", "qa_dealloc_top", PMT_F, &result);
+ // std::cout << "\n\n----------------------------\n";
+ // std::cout << " RUNNING DEALLOCATION TESTS \n";
+
+ rt->run("qa_dealloc_top", "qa_dealloc_top", PMT_F, &result);
+
+ CPPUNIT_ASSERT(pmt_equal(PMT_T, result));
+}
+
+void
+qa_inband_usrp_server::test_tx()
+{
+ mb_runtime_sptr rt = mb_make_runtime();
+ pmt_t result = PMT_T;
+
+ // std::cout << "\n\n-----------------\n";
+ // std::cout << " RUNNING TX TESTS \n";
+
+ rt->run("top", "qa_tx_top", PMT_F, &result);
+
+ CPPUNIT_ASSERT(pmt_equal(PMT_T, result));
+}
+
+void
+qa_inband_usrp_server::test_rx()
+{
+ mb_runtime_sptr rt = mb_make_runtime();
+ pmt_t result = PMT_T;
+
+ // std::cout << "\n\n-----------------\n";
+ // std::cout << " RUNNING RX TESTS \n";
+
+ rt->run("top", "qa_rx_top", PMT_F, &result);
CPPUNIT_ASSERT(pmt_equal(PMT_T, result));
}
void
-qa_inband_usrp_server::test_fragmentation()
+qa_inband_usrp_server::test_cs()
{
+ mb_runtime_sptr rt = mb_make_runtime();
+ pmt_t result = PMT_T;
+
+ // std::cout << "\n\n-----------------\n";
+ // std::cout << " RUNNING CS TESTS \n";
+
+ rt->run("top", "qa_cs_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 91cf7d87c..5db57c3ed 100644
--- a/usrp/host/lib/inband/qa_inband_usrp_server.h
+++ b/usrp/host/lib/inband/qa_inband_usrp_server.h
@@ -28,15 +28,21 @@
class qa_inband_usrp_server : public CppUnit::TestCase {
CPPUNIT_TEST_SUITE(qa_inband_usrp_server);
+ CPPUNIT_TEST(test_open_close);
CPPUNIT_TEST(test_chan_allocation);
CPPUNIT_TEST(test_chan_deallocation);
- CPPUNIT_TEST(test_fragmentation);
+ CPPUNIT_TEST(test_tx);
+ CPPUNIT_TEST(test_rx);
+ CPPUNIT_TEST(test_cs);
CPPUNIT_TEST_SUITE_END();
private:
void test_chan_allocation();
void test_chan_deallocation();
- void test_fragmentation();
+ void test_open_close();
+ void test_tx();
+ void test_rx();
+ void test_cs();
};
#endif /* INCLUDED_QA_INBAND_USRP_SERVER_H */
diff --git a/usrp/host/lib/inband/symbols_usrp_channel.h b/usrp/host/lib/inband/symbols_usrp_channel.h
new file mode 100644
index 000000000..a0114cf3c
--- /dev/null
+++ b/usrp/host/lib/inband/symbols_usrp_channel.h
@@ -0,0 +1,40 @@
+/* -*- 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_SYMBOLS_USRP_CHANNEL_H
+#define INCLUDED_SYMBOLS_USRP_CHANNEL_H
+
+#include <pmt.h>
+
+// Outgoing
+static pmt_t s_cmd_allocate_channel = pmt_intern("cmd-allocate-channel");
+static pmt_t s_cmd_deallocate_channel = pmt_intern("cmd-deallocate-channel");
+
+// Incoming
+static pmt_t s_response_allocate_channel = pmt_intern("response-allocate-channel");
+static pmt_t s_response_deallocate_channel = pmt_intern("response-deallocate-channel");
+
+// Errors
+static pmt_t s_err_requested_capacity_unavailable = pmt_intern("err-requested-capacity-unavailable");
+static pmt_t s_err_channel_unavailable = pmt_intern("err-channel-unavailable");
+static pmt_t s_err_channel_invalid = pmt_intern("err-channel-invalid");
+static pmt_t s_err_channel_permission_denied = pmt_intern("err-channel-permission-denied");
+
+#endif /* INCLUDED_SYMBOLS_USRP_CHANNEL_H */
diff --git a/usrp/host/lib/inband/symbols_usrp_interface_cs.h b/usrp/host/lib/inband/symbols_usrp_interface_cs.h
new file mode 100644
index 000000000..72c8fcc91
--- /dev/null
+++ b/usrp/host/lib/inband/symbols_usrp_interface_cs.h
@@ -0,0 +1,43 @@
+/* -*- 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_SYMBOLS_USRP_INTERFACE_CS_H
+#define INCLUDED_SYMBOLS_USRP_INTERFACE_CS_H
+
+#include <pmt.h>
+
+// Outgoing
+static pmt_t s_cmd_usrp_open = pmt_intern("cmd-usrp-open");
+static pmt_t s_cmd_usrp_close = pmt_intern("cmd-usrp-close");
+static pmt_t s_cmd_usrp_ntx_chan = pmt_intern("cmd-usrp-ntx-chan");
+static pmt_t s_cmd_usrp_nrx_chan = pmt_intern("cmd-usrp-nrx-chan");
+static pmt_t s_cmd_usrp_write = pmt_intern("cmd-usrp-write");
+static pmt_t s_cmd_usrp_start_reading = pmt_intern("cmd-usrp-start-reading");
+static pmt_t s_cmd_usrp_stop_reading = pmt_intern("cmd-usrp-stop-reading");
+
+// Incoming
+static pmt_t s_response_usrp_open = pmt_intern("response-usrp-open");
+static pmt_t s_response_usrp_close = pmt_intern("response-usrp-close");
+static pmt_t s_response_usrp_ntx_chan = pmt_intern("response-usrp-ntx-chan");
+static pmt_t s_response_usrp_nrx_chan = pmt_intern("response-usrp-nrx-chan");
+static pmt_t s_response_usrp_write = pmt_intern("response-usrp-write");
+static pmt_t s_response_usrp_read = pmt_intern("response-usrp-read");
+
+#endif /* INCLUDED_SYMBOLS_USRP_INTERFACE_CS_H */
diff --git a/usrp/host/lib/inband/symbols_usrp_low_level_cs.h b/usrp/host/lib/inband/symbols_usrp_low_level_cs.h
new file mode 100644
index 000000000..a7260603a
--- /dev/null
+++ b/usrp/host/lib/inband/symbols_usrp_low_level_cs.h
@@ -0,0 +1,47 @@
+/* -*- 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_SYMBOLS_USRP_LOW_LEVEL_CS_H
+#define INCLUDED_SYMBOLS_USRP_LOW_LEVEL_CS_H
+
+#include <pmt.h>
+
+// Outgoing
+static pmt_t s_cmd_to_control_channel = pmt_intern("cmd-to-control-channel");
+
+// Incoming
+static pmt_t s_response_from_control_channel = pmt_intern("response-from-control-channel");
+
+// Subpackets
+static pmt_t s_op_ping_fixed = pmt_intern("op-ping-fixed");
+static pmt_t s_op_ping_fixed_reply = pmt_intern("op-ping-fixed-reply");
+static pmt_t s_op_write_reg = pmt_intern("op-write-reg");
+static pmt_t s_op_write_reg_masked = pmt_intern("op-write-reg-masked");
+static pmt_t s_op_read_reg = pmt_intern("op-read-reg");
+static pmt_t s_op_read_reg_reply = pmt_intern("op-read-reg-reply");
+static pmt_t s_op_i2c_write = pmt_intern("op-i2c-write");
+static pmt_t s_op_i2c_read = pmt_intern("op-i2c-read");
+static pmt_t s_op_i2c_read_reply = pmt_intern("op-i2c-read-reply");
+static pmt_t s_op_spi_write = pmt_intern("op-spi-write");
+static pmt_t s_op_spi_read = pmt_intern("op-spi-read");
+static pmt_t s_op_spi_read_reply = pmt_intern("op-spi-read-reply");
+static pmt_t s_op_delay = pmt_intern("op-delay");
+
+#endif /* INCLUDED_SYMBOLS_USRP_LOW_LEVEL_CS_H */
diff --git a/usrp/host/lib/inband/symbols_usrp_rx.h b/usrp/host/lib/inband/symbols_usrp_rx.h
new file mode 100644
index 000000000..07d58a3f5
--- /dev/null
+++ b/usrp/host/lib/inband/symbols_usrp_rx.h
@@ -0,0 +1,36 @@
+/* -*- 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_SYMBOLS_USRP_RX_H
+#define INCLUDED_SYMBOLS_USRP_RX_H
+
+#include <pmt.h>
+
+// Outgoing
+static pmt_t s_cmd_start_recv_raw_samples = pmt_intern("cmd-start-recv-raw-samples");
+static pmt_t s_cmd_stop_recv_raw_samples = pmt_intern("cmd-stop-recv-raw-samples");
+
+// Incoming
+static pmt_t s_response_recv_raw_samples = pmt_intern("response-recv-raw-samples");
+
+// Errors
+static pmt_t s_err_already_receiving = pmt_intern("err-already-receiving");
+
+#endif /* INCLUDED_SYMBOLS_USRP_RX_H */
diff --git a/usrp/host/lib/inband/symbols_usrp_rx_cs.h b/usrp/host/lib/inband/symbols_usrp_rx_cs.h
new file mode 100644
index 000000000..bf4f0338b
--- /dev/null
+++ b/usrp/host/lib/inband/symbols_usrp_rx_cs.h
@@ -0,0 +1,32 @@
+/* -*- 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_SYMBOLS_USRP_RX_CS_H
+#define INCLUDED_SYMBOLS_USRP_RX_CS_H
+
+#include <pmt.h>
+
+// Outgoing
+static pmt_t s_cmd_usrp_rx_start_reading = pmt_intern("cmd-usrp-rx-start-reading");
+
+// Incoming
+static pmt_t s_response_usrp_rx_read = pmt_intern("response-usrp-rx-read");
+
+#endif /* INCLUDED_SYMBOLS_USRP_RX_CS_H */
diff --git a/usrp/host/lib/inband/symbols_usrp_server_cs.h b/usrp/host/lib/inband/symbols_usrp_server_cs.h
new file mode 100644
index 000000000..e612e24ea
--- /dev/null
+++ b/usrp/host/lib/inband/symbols_usrp_server_cs.h
@@ -0,0 +1,47 @@
+/* -*- 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_SYMBOLS_USRP_SERVER_CS_H
+#define INCLUDED_SYMBOLS_USRP_SERVER_CS_H
+
+#include <pmt.h>
+
+// Outgoing
+static pmt_t s_cmd_open = pmt_intern("cmd-open");
+static pmt_t s_cmd_close = pmt_intern("cmd-close");
+static pmt_t s_cmd_max_capacity = pmt_intern("cmd-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_cmd_current_capacity_allocation = pmt_intern("cmd-current-capacity-allocation");
+
+// Incoming
+static pmt_t s_response_open = pmt_intern("response-open");
+static pmt_t s_response_close = pmt_intern("response-close");
+static pmt_t s_response_max_capacity = pmt_intern("response-max-capacity");
+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_response_current_capacity_allocation = pmt_intern("response-current-capacity-allocation");
+
+// Errors
+static pmt_t s_err_usrp_not_opened = pmt_intern("err-usrp-not-opened");
+static pmt_t s_err_usrp_already_opened = pmt_intern("err-usrp-already-opened");
+static pmt_t s_err_usrp_already_closed = pmt_intern("err-usrp-already-closed");
+
+#endif /* INCLUDED_SYMBOLS_USRP_SERVER_CS_H */
diff --git a/usrp/host/lib/inband/symbols_usrp_tx.h b/usrp/host/lib/inband/symbols_usrp_tx.h
new file mode 100644
index 000000000..4e58e2cf9
--- /dev/null
+++ b/usrp/host/lib/inband/symbols_usrp_tx.h
@@ -0,0 +1,32 @@
+/* -*- 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_SYMBOLS_USRP_TX_H
+#define INCLUDED_SYMBOLS_USRP_TX_H
+
+#include <pmt.h>
+
+// Outgoing
+static pmt_t s_cmd_xmit_raw_frame = pmt_intern("cmd-xmit-raw-frame");
+
+// Incoming
+static pmt_t s_response_xmit_raw_frame = pmt_intern("response-xmit-raw-frame");
+
+#endif /* INCLUDED_SYMBOLS_USRP_TX_H */
diff --git a/usrp/host/lib/inband/symbols_usrp_tx_cs.h b/usrp/host/lib/inband/symbols_usrp_tx_cs.h
new file mode 100644
index 000000000..d02ef1d26
--- /dev/null
+++ b/usrp/host/lib/inband/symbols_usrp_tx_cs.h
@@ -0,0 +1,32 @@
+/* -*- 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_SYMBOLS_USRP_TX_CS_H
+#define INCLUDED_SYMBOLS_USRP_TX_CS_H
+
+#include <pmt.h>
+
+// Outgoing
+static pmt_t s_cmd_usrp_tx_write = pmt_intern("cmd-usrp-tx-write");
+
+// Incoming
+static pmt_t s_response_usrp_tx_write = pmt_intern("response-usrp-tx-write");
+
+#endif /* INCLUDED_SYMBOLS_USRP_TX_CS_H */
diff --git a/usrp/host/lib/inband/test_usrp_inband.cc b/usrp/host/lib/inband/test_usrp_inband.cc
new file mode 100644
index 000000000..dd8d46f84
--- /dev/null
+++ b/usrp/host/lib/inband/test_usrp_inband.cc
@@ -0,0 +1,297 @@
+/* -*- 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 <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
new file mode 100644
index 000000000..b8befa493
--- /dev/null
+++ b/usrp/host/lib/inband/usrp_inband_usb_packet.cc
@@ -0,0 +1,749 @@
+/* -*- 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 <usrp_inband_usb_packet.h>
+
+#include <usrp_bytesex.h>
+#include <iostream>
+#include <stdio.h>
+
+bool usrp_inband_usb_packet::align32()
+{
+ int p_len = payload_len();
+
+ int bytes_needed = 4 - (p_len % 4);
+
+ if(bytes_needed == 4)
+ return true;
+
+ // If the room left in the packet is less than the number of bytes
+ // needed, return false to indicate no room to align
+ 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);
+
+ return true;
+}
+
+bool usrp_inband_usb_packet::cs_ping(long rid, long ping_val)
+{
+ if(!align32())
+ return false;
+
+ int p_len = payload_len();
+
+ if((MAX_PAYLOAD - p_len) < (CS_PING_LEN + CS_FIXED_LEN))
+ return false;
+
+ uint32_t ping = (
+ ((OP_PING_FIXED & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
+ | ((CS_PING_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
+ | ((rid & CS_RID_MASK) << CS_RID_SHIFT)
+ | (ping_val & CS_PINGVAL_MASK)
+
+ );
+
+ uint32_t *payload = (uint32_t *) (d_payload + p_len);
+ *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);
+
+ return true;
+}
+
+
+bool usrp_inband_usb_packet::cs_ping_reply(long rid, long ping_val)
+{
+ if(!align32())
+ return false;
+
+ int p_len = payload_len();
+
+ if((MAX_PAYLOAD - p_len) < (CS_PING_LEN + CS_FIXED_LEN))
+ return false;
+
+ uint32_t ping = (
+ ((OP_PING_FIXED_REPLY & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
+ | ((CS_PING_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
+ | ((rid & CS_RID_MASK) << CS_RID_SHIFT)
+ | ((ping_val & CS_PINGVAL_MASK) << CS_PINGVAL_SHIFT)
+
+ );
+
+ uint32_t *payload = (uint32_t *) (d_payload + p_len);
+ *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);
+
+ return true;
+}
+
+bool usrp_inband_usb_packet::cs_write_reg(long reg_num, long val)
+{
+ if(!align32())
+ return false;
+
+ int p_len = payload_len();
+
+ if((MAX_PAYLOAD - p_len) < (CS_WRITEREG_LEN + CS_FIXED_LEN))
+ return false;
+
+ uint32_t word0 = 0;
+
+ // Build the first word which includes the register number
+ word0 = (
+ ((OP_WRITE_REG & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
+ | ((CS_WRITEREG_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
+ | ((reg_num & CS_REGNUM_MASK) << CS_REGNUM_SHIFT)
+ );
+
+ uint32_t *payload = (uint32_t *) (d_payload + p_len);
+ *payload = host_to_usrp_u32(word0);
+
+ // The second word is solely the register value to be written
+ // FIXME: should this be unsigned?
+ payload += 1;
+ *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);
+
+ return true;
+}
+
+bool usrp_inband_usb_packet::cs_write_reg_masked(long reg_num, long val, long mask)
+{
+ if(!align32())
+ return false;
+
+ int p_len = payload_len();
+
+ if((MAX_PAYLOAD - p_len) < (CS_WRITEREGMASKED_LEN + CS_FIXED_LEN))
+ return false;
+
+ uint32_t word0 = 0;
+
+ // Build the first word which includes the register number
+ word0 = (
+ ((OP_WRITE_REG_MASKED & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
+ | ((CS_WRITEREGMASKED_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
+ | ((reg_num & CS_REGNUM_MASK) << CS_REGNUM_SHIFT)
+ );
+
+ uint32_t *payload = (uint32_t *) (d_payload + p_len);
+ *payload = host_to_usrp_u32(word0);
+
+ // Skip over the first word and write the register value
+ payload += 1;
+ *payload = host_to_usrp_u32((uint32_t) val);
+
+ // Skip over the register value and write the mask
+ payload += 1;
+ *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);
+
+ return true;
+}
+
+bool usrp_inband_usb_packet::cs_read_reg(long rid, long reg_num)
+{
+ if(!align32())
+ return false;
+
+ int p_len = payload_len();
+
+ if((MAX_PAYLOAD - p_len) < (CS_READREG_LEN + CS_FIXED_LEN))
+ return false;
+
+ uint32_t read_reg = (
+ ((OP_READ_REG & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
+ | ((CS_READREG_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
+ | ((rid & CS_RID_MASK) << CS_RID_SHIFT)
+ | ((reg_num & CS_REGNUM_MASK) << CS_REGNUM_SHIFT)
+
+ );
+
+ uint32_t *payload = (uint32_t *) (d_payload + p_len);
+ *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);
+
+ return true;
+}
+
+bool usrp_inband_usb_packet::cs_read_reg_reply(long rid, long reg_num, long reg_val)
+{
+ if(!align32())
+ return false;
+
+ int p_len = payload_len();
+
+ if((MAX_PAYLOAD - p_len) < (CS_READREGREPLY_LEN + CS_FIXED_LEN))
+ return false;
+
+ uint32_t word0 = (
+ ((OP_READ_REG_REPLY & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
+ | ((CS_READREGREPLY_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
+ | ((rid & CS_RID_MASK) << CS_RID_SHIFT)
+ | ((reg_num & CS_REGNUM_MASK) << CS_REGNUM_SHIFT)
+
+ );
+
+ uint32_t *payload = (uint32_t *) (d_payload + p_len);
+ *payload = host_to_usrp_u32(word0);
+
+ // Hop to the next word and write the reg value
+ payload += 1;
+ *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);
+
+ return true;
+}
+
+bool usrp_inband_usb_packet::cs_delay(long ticks)
+{
+ if(!align32())
+ return false;
+
+ int p_len = payload_len();
+
+ if((MAX_PAYLOAD - p_len) < (CS_DELAY_LEN + CS_FIXED_LEN))
+ return false;
+
+ uint32_t delay = (
+ ((OP_DELAY & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
+ | ((CS_DELAY_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
+ | ((ticks & CS_DELAY_MASK) << CS_DELAY_SHIFT)
+
+ );
+
+ uint32_t *payload = (uint32_t *) (d_payload + p_len);
+ *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);
+
+ return true;
+}
+
+bool usrp_inband_usb_packet::cs_i2c_write(long i2c_addr, uint8_t *i2c_data, size_t data_len)
+{
+ if(!align32())
+ return false;
+
+ int p_len = payload_len();
+
+ int i2c_len = data_len + 2; // 2 bytes between mbz and addr
+
+ if((MAX_PAYLOAD - p_len) < (i2c_len + CS_FIXED_LEN))
+ return false;
+
+ uint32_t word0 = 0;
+
+ word0 = (
+ ((OP_I2C_WRITE & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
+ | ((i2c_len & CS_LEN_MASK) << CS_LEN_SHIFT)
+ | ((i2c_addr & CS_I2CADDR_MASK) << CS_I2CADDR_SHIFT)
+ );
+
+ uint32_t *payload = (uint32_t *) (d_payload + p_len);
+ *payload = host_to_usrp_u32(word0);
+
+ // Jump over the first word and write the data
+ // FIXME: Should the data be changed to usrp byte order?
+ payload += 1;
+ 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);
+
+ return true;
+}
+
+bool usrp_inband_usb_packet::cs_i2c_read(long rid, long i2c_addr, long n_bytes)
+{
+ if(!align32())
+ return false;
+
+ int p_len = payload_len();
+
+ if((MAX_PAYLOAD - p_len) < (CS_I2CREAD_LEN + CS_FIXED_LEN))
+ return false;
+
+ uint32_t word0 = 0;
+
+ word0 = (
+ ((OP_I2C_READ & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
+ | ((CS_I2CREAD_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
+ | ((rid & CS_RID_MASK) << CS_RID_SHIFT)
+ | ((i2c_addr & CS_I2CADDR_MASK) << CS_I2CADDR_SHIFT)
+ );
+
+ uint32_t *payload = (uint32_t *) (d_payload + p_len);
+ *payload = host_to_usrp_u32(word0);
+
+ // Jump a word and write the number of bytes to read
+ payload += 1;
+ uint32_t word1 =
+ (n_bytes & CS_I2CREADBYTES_MASK) << CS_I2CREADBYTES_SHIFT;
+ *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);
+
+ return true;
+}
+
+bool usrp_inband_usb_packet::cs_i2c_read_reply(long rid, long i2c_addr, uint8_t *i2c_data, long i2c_data_len)
+{
+ if(!align32())
+ return false;
+
+ int p_len = payload_len();
+
+ int i2c_len = i2c_data_len + 2;
+
+ if((MAX_PAYLOAD - p_len) < (i2c_len + CS_FIXED_LEN))
+ return false;
+
+ uint32_t word0 = 0;
+
+ word0 = (
+ ((OP_I2C_READ_REPLY & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
+ | ((i2c_len & CS_LEN_MASK) << CS_LEN_SHIFT)
+ | ((rid & CS_RID_MASK) << CS_RID_SHIFT)
+ | ((i2c_addr & CS_I2CADDR_MASK) << CS_I2CADDR_SHIFT)
+ );
+
+ uint32_t *payload = (uint32_t *) (d_payload + p_len);
+ *payload = host_to_usrp_u32(word0);
+
+ // Jump a word and write the actual data
+ payload += 1;
+ 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);
+
+ return true;
+}
+
+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())
+ return false;
+
+ int p_len = payload_len();
+
+ int spi_len = spi_data_len + 6;
+
+ if((MAX_PAYLOAD - p_len) < (spi_len + CS_FIXED_LEN))
+ return false;
+
+ uint32_t word = 0;
+
+ // First word contains the opcode and length, then mbz
+ word = (
+ ((OP_SPI_WRITE & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
+ | ((spi_len & CS_LEN_MASK) << CS_LEN_SHIFT)
+ );
+ uint32_t *payload = (uint32_t *) (d_payload + p_len);
+ *payload = host_to_usrp_u32(word);
+
+ payload += 1;
+
+ // Second word contains the enables, format, and optional tx bytes
+ word = 0;
+ word = (
+ ((enables & CS_SPIENABLES_MASK) << CS_SPIENABLES_SHIFT)
+ | ((format & CS_SPIFORMAT_MASK) << CS_SPIFORMAT_SHIFT)
+ | ((opt_header_bytes & CS_SPIOPT_MASK) << CS_SPIOPT_SHIFT)
+ );
+ payload = (uint32_t *) (d_payload + p_len);
+ *payload = host_to_usrp_u32(word);
+
+ payload += 1;
+ 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);
+
+ return true;
+}
+
+bool usrp_inband_usb_packet::cs_spi_read(long rid, long enables, long format, long opt_header_bytes, long n_bytes)
+{
+ if(!align32())
+ return false;
+
+ int p_len = payload_len();
+
+ if((MAX_PAYLOAD - p_len) < (CS_SPIREAD_LEN + CS_FIXED_LEN))
+ return false;
+
+ uint32_t word = 0;
+
+ // First word contains the opcode, length, and RID
+ word = (
+ ((OP_SPI_READ & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
+ | ((CS_SPIREAD_LEN & CS_LEN_MASK) << CS_LEN_SHIFT)
+ | ((rid & CS_RID_MASK) << CS_RID_SHIFT)
+ );
+ uint32_t *payload = (uint32_t *) (d_payload + p_len);
+ *payload = host_to_usrp_u32(word);
+
+ payload += 1;
+
+ // Second word contains the enables, format, and optional tx bytes
+ word = 0;
+ word = (
+ ((enables & CS_SPIENABLES_MASK) << CS_SPIENABLES_SHIFT)
+ | ((format & CS_SPIFORMAT_MASK) << CS_SPIFORMAT_SHIFT)
+ | ((opt_header_bytes & CS_SPIOPT_MASK) << CS_SPIOPT_SHIFT)
+ );
+ payload = (uint32_t *) (d_payload + p_len);
+ *payload = host_to_usrp_u32(word);
+
+ payload += 1;
+
+ // The third word contains the number of bytes
+ word = 0;
+ word = (
+ ((n_bytes & CS_SPINBYTES_MASK) << CS_SPINBYTES_SHIFT)
+ );
+ payload = (uint32_t *) (d_payload + p_len);
+ *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;
+
+ set_header(h_flags, h_chan, h_tag, h_payload_len);
+
+ return true;
+}
+
+bool usrp_inband_usb_packet::cs_spi_read_reply(long rid, uint8_t *spi_data, long spi_data_len)
+{
+ if(!align32())
+ return false;
+
+ int p_len = payload_len();
+
+ int spi_len = spi_data_len + 2;
+
+ if((MAX_PAYLOAD - p_len) < (spi_len + CS_FIXED_LEN))
+ return false;
+
+ uint32_t word = 0;
+
+ // First word contains the opcode, length, and RID
+ word = (
+ ((OP_SPI_READ_REPLY & CS_OPCODE_MASK) << CS_OPCODE_SHIFT)
+ | ((spi_len & CS_LEN_MASK) << CS_LEN_SHIFT)
+ | ((rid & CS_RID_MASK) << CS_RID_SHIFT)
+ );
+ uint32_t *payload = (uint32_t *) (d_payload + p_len);
+ *payload = host_to_usrp_u32(word);
+
+ // Jump a word and write the actual data
+ payload += 1;
+ 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);
+
+ return true;
+}
+
+// Takes an offset to the beginning of a subpacket and extracts 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.
+pmt_t usrp_inband_usb_packet::read_subpacket(int payload_offset) {
+
+ uint32_t subpkt = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset)));
+ uint32_t opcode = (subpkt >> CS_OPCODE_SHIFT) & CS_OPCODE_MASK;
+ uint32_t len = (subpkt >> CS_LEN_SHIFT) & CS_LEN_MASK;
+
+ switch(opcode) {
+
+ case OP_PING_FIXED_REPLY:
+ {
+ pmt_t rid = pmt_from_long((subpkt >> CS_RID_SHIFT) & CS_RID_MASK);
+ pmt_t pingval = pmt_from_long((subpkt >> CS_PINGVAL_SHIFT) & CS_PINGVAL_MASK);
+ return pmt_list3(s_op_ping_fixed_reply, rid, pingval);
+ }
+
+ case OP_READ_REG_REPLY:
+ {
+ pmt_t rid = pmt_from_long((subpkt >> CS_RID_SHIFT) & CS_RID_MASK);
+ pmt_t reg_num = pmt_from_long((subpkt >> CS_REGNUM_SHIFT) & CS_REGNUM_MASK);
+
+ // To get the register value we just read the next 32 bits
+ uint32_t val = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset + 4)));
+ pmt_t reg_val = pmt_from_long(val);
+
+ return pmt_list4(s_op_read_reg_reply, rid, reg_num, reg_val);
+ }
+
+ case OP_I2C_READ_REPLY:
+ {
+ pmt_t rid = pmt_from_long((subpkt >> CS_RID_SHIFT) & CS_RID_MASK);
+ pmt_t i2c_addr = pmt_from_long((subpkt >> CS_I2CADDR_SHIFT) & CS_I2CADDR_MASK);
+
+ // Make a u8 vector to dump the data from the packet into
+ size_t i2c_data_len;
+ pmt_t i2c_data = pmt_make_u8vector(len - 2, 0); // skip rid+mbz+addr = 2 bytes
+ uint8_t *w_data =
+ (uint8_t *) pmt_u8vector_writeable_elements(i2c_data, i2c_data_len);
+
+ memcpy(w_data, d_payload + payload_offset + 4, i2c_data_len); // skip first word
+
+ return pmt_list4(s_op_i2c_read_reply, rid, i2c_addr, i2c_data);
+ }
+
+ case OP_SPI_READ_REPLY:
+ {
+ pmt_t rid = pmt_from_long((subpkt >> CS_RID_SHIFT) & CS_RID_MASK);
+
+ // Make a u8 vector to dump the data from the packet into
+ size_t spi_data_len;
+ pmt_t spi_data = pmt_make_u8vector(len - 2, 0); // skip rid+mbz+addr = 2 bytes
+ uint8_t *w_data =
+ (uint8_t *) pmt_u8vector_writeable_elements(spi_data, spi_data_len);
+
+ memcpy(w_data, d_payload + payload_offset + 4, spi_data_len); // skip first word
+
+ return pmt_list3(s_op_spi_read_reply, rid, spi_data);
+ }
+
+ case OP_PING_FIXED:
+ {
+ pmt_t rid = pmt_from_long((subpkt >> CS_RID_SHIFT) & CS_RID_MASK);
+ pmt_t pingval = pmt_from_long((subpkt >> CS_PINGVAL_SHIFT) & CS_PINGVAL_MASK);
+ return pmt_list3(s_op_ping_fixed, rid, pingval);
+ }
+
+ case OP_WRITE_REG:
+ {
+ pmt_t reg_num = pmt_from_long((subpkt >> CS_REGNUM_SHIFT) & CS_REGNUM_MASK);
+
+ // To get the register value we just read the next 32 bits
+ uint32_t val = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset + 4)));
+ pmt_t reg_val = pmt_from_long(val);
+
+ return pmt_list3(s_op_write_reg, reg_num, reg_val);
+ }
+
+ case OP_WRITE_REG_MASKED:
+ {
+ pmt_t reg_num = pmt_from_long((subpkt >> CS_REGNUM_SHIFT) & CS_REGNUM_MASK);
+
+ // To get the register value we just read the next 32 bits
+ uint32_t val = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset + 4)));
+ pmt_t reg_val = pmt_from_long(val);
+
+ // The mask is the next 32 bits
+ uint32_t mask = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset + 8)));
+ pmt_t reg_mask = pmt_from_long(mask);
+
+ return pmt_list4(s_op_write_reg_masked, reg_num, reg_val, reg_mask);
+ }
+
+ case OP_READ_REG:
+ {
+ pmt_t rid = pmt_from_long((subpkt >> CS_RID_SHIFT) & CS_RID_MASK);
+ pmt_t reg_num = pmt_from_long((subpkt >> CS_REGNUM_SHIFT) & CS_REGNUM_MASK);
+
+ return pmt_list3(s_op_read_reg, rid, reg_num);
+ }
+
+ case OP_I2C_WRITE:
+ {
+ pmt_t i2c_addr = pmt_from_long((subpkt >> CS_I2CADDR_SHIFT) & CS_I2CADDR_MASK);
+
+ // The length includes an extra 2 bytes for storing the mbz and addr
+ pmt_t i2c_data = pmt_make_u8vector(len-2, 0);
+
+ // Get a writeable address to copy the data from the packet
+ size_t ignore;
+ uint8_t *w_data = (uint8_t *) pmt_u8vector_writeable_elements(i2c_data, ignore);
+ memcpy(w_data, d_payload + payload_offset + 4, len-2);
+
+
+ return pmt_list3(s_op_i2c_write, i2c_addr, i2c_data);
+ }
+
+ case OP_I2C_READ:
+ {
+ pmt_t rid = pmt_from_long((subpkt >> CS_RID_SHIFT) & CS_RID_MASK);
+ pmt_t i2c_addr = pmt_from_long((subpkt >> CS_I2CADDR_SHIFT) & CS_I2CADDR_MASK);
+
+ // The number of bytes is in the next word
+ uint32_t bytes = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset + 4)));
+ bytes = (bytes >> CS_I2CREADBYTES_SHIFT) & CS_I2CREADBYTES_MASK;
+ pmt_t i2c_bytes = pmt_from_long(bytes);
+
+ return pmt_list4(s_op_i2c_read, rid, i2c_addr, i2c_bytes);
+ }
+
+ case OP_SPI_WRITE:
+ {
+ // Nothing interesting in the first word, skip to the next
+ uint32_t word = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset + 4)));
+ pmt_t enables = pmt_from_long((word >> CS_SPIENABLES_SHIFT) & CS_SPIENABLES_MASK);
+ pmt_t format = pmt_from_long((word >> CS_SPIFORMAT_SHIFT) & CS_SPIFORMAT_MASK);
+ pmt_t opt = pmt_from_long((word >> CS_SPIOPT_SHIFT) & CS_SPIOPT_MASK);
+
+ // From the next word and on is data
+ size_t spi_data_len;
+ pmt_t spi_data = pmt_make_u8vector(len - 6, 0); // skip rid+mbz+addr = 2 bytes
+ uint8_t *w_data =
+ (uint8_t *) pmt_u8vector_writeable_elements(spi_data, spi_data_len);
+
+ memcpy(w_data, d_payload + payload_offset + 8, spi_data_len); // skip first 2 words
+
+ return pmt_list5(s_op_spi_write, enables, format, opt, spi_data);
+ }
+
+ case OP_SPI_READ:
+ {
+ // Read the RID from the first word, the rest is mbz
+ pmt_t rid = pmt_from_long((subpkt >> CS_RID_SHIFT) & CS_RID_MASK);
+
+ // Continue at the next word...
+ uint32_t word = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset + 4)));
+ pmt_t enables = pmt_from_long((word >> CS_SPIENABLES_SHIFT) & CS_SPIENABLES_MASK);
+ pmt_t format = pmt_from_long((word >> CS_SPIFORMAT_SHIFT) & CS_SPIFORMAT_MASK);
+ pmt_t opt = pmt_from_long((word >> CS_SPIOPT_SHIFT) & CS_SPIOPT_MASK);
+
+ // The number of bytes is the only thing to read in the next word
+ word = usrp_to_host_u32(*((uint32_t *)(d_payload + payload_offset + 8)));
+ pmt_t n_bytes = pmt_from_long((word >> CS_SPINBYTES_SHIFT) & CS_SPINBYTES_MASK);
+
+ return pmt_list6(s_op_spi_read, rid, enables, format, opt, n_bytes);
+ }
+
+ case OP_DELAY:
+ {
+ pmt_t ticks = pmt_from_long((subpkt >> CS_DELAY_SHIFT) & CS_DELAY_MASK);
+
+ return pmt_list2(s_op_delay, ticks);
+ }
+
+ default:
+ return PMT_NIL;
+
+ }
+}
+
diff --git a/usrp/host/lib/inband/usrp_inband_usb_packet.h b/usrp/host/lib/inband/usrp_inband_usb_packet.h
index e22b567fa..9290f55ae 100644
--- a/usrp/host/lib/inband/usrp_inband_usb_packet.h
+++ b/usrp/host/lib/inband/usrp_inband_usb_packet.h
@@ -24,6 +24,10 @@
#include <usrp_bytesex.h>
#include <mb_mblock.h>
+#include <pmt.h>
+#include <iostream>
+
+#include <symbols_usrp_low_level_cs.h>
static const int USB_PKT_SIZE = 512; // bytes
static const int MAX_PAYLOAD = USB_PKT_SIZE-2*sizeof(uint32_t);
@@ -38,12 +42,28 @@ class usrp_inband_usb_packet {
public:
+ enum opcodes {
+ OP_PING_FIXED = 0x00,
+ OP_PING_FIXED_REPLY = 0x01,
+ OP_WRITE_REG = 0x02,
+ OP_WRITE_REG_MASKED = 0x03,
+ OP_READ_REG = 0x04,
+ OP_READ_REG_REPLY = 0x05,
+ OP_I2C_WRITE = 0x06,
+ OP_I2C_READ = 0x07,
+ OP_I2C_READ_REPLY = 0x08,
+ OP_SPI_WRITE = 0x09,
+ OP_SPI_READ = 0x0a,
+ OP_SPI_READ_REPLY = 0x0b,
+ OP_DELAY = 0x0c
+ };
+
enum flags {
FL_OVERRUN = 0x80000000,
FL_UNDERRUN = 0x40000000,
FL_DROPPED = 0x20000000,
- FL_END_OF_BURST = 0x10000000,
- FL_START_OF_BURST = 0x08000000,
+ FL_START_OF_BURST = 0x10000000,
+ FL_END_OF_BURST = 0x08000000,
FL_ALL_FLAGS = 0xf8000000
};
@@ -51,8 +71,8 @@ public:
static const int FL_OVERRUN_SHIFT = 31;
static const int FL_UNDERRUN_SHIFT = 30;
static const int FL_DROPPED_SHIFT = 29;
- static const int FL_END_OF_BURST_SHIFT = 28;
- static const int FL_START_OF_BURST_SHIFT = 27;
+ static const int FL_END_OF_BURST_SHIFT = 27;
+ static const int FL_START_OF_BURST_SHIFT = 28;
static const int RSSI_MASK = 0x3f;
static const int RSSI_SHIFT = 21;
@@ -66,6 +86,50 @@ public:
static const int PAYLOAD_LEN_MASK = 0x1ff;
static const int PAYLOAD_LEN_SHIFT = 0;
+ // Fixed size for opcode and length fields
+ static const int CS_FIXED_LEN = 2;
+
+ static const int CS_OPCODE_MASK = 0xff;
+ static const int CS_OPCODE_SHIFT = 24;
+
+ static const int CS_LEN_MASK = 0xff;
+ static const int CS_LEN_SHIFT = 16;
+
+ static const int CS_RID_MASK = 0x3f;
+ static const int CS_RID_SHIFT = 10;
+
+ static const int CS_PING_LEN = 2;
+ static const int CS_PINGVAL_MASK = 0x3ff;
+ static const int CS_PINGVAL_SHIFT = 0;
+
+ static const int CS_WRITEREG_LEN = 6;
+ static const int CS_WRITEREGMASKED_LEN = 10;
+ static const int CS_READREG_LEN = 2;
+ static const int CS_READREGREPLY_LEN = 6;
+ static const int CS_REGNUM_MASK = 0x3ff;
+ static const int CS_REGNUM_SHIFT = 0;
+
+ static const int CS_DELAY_LEN = 2;
+ static const int CS_DELAY_MASK = 0xffff;
+ static const int CS_DELAY_SHIFT = 0;
+
+ static const int CS_I2CADDR_MASK = 0x7f;
+ static const int CS_I2CADDR_SHIFT = 0;
+
+ static const int CS_I2CREAD_LEN = 3;
+ static const int CS_I2CREADBYTES_MASK = 0x7f;
+ static const int CS_I2CREADBYTES_SHIFT = 24;
+
+ static const int CS_SPIOPT_MASK = 0xffff;
+ static const int CS_SPIOPT_SHIFT = 0;
+ static const int CS_SPIFORMAT_MASK = 0xff;
+ static const int CS_SPIFORMAT_SHIFT = 16;
+ static const int CS_SPIENABLES_MASK = 0xff;
+ static const int CS_SPIENABLES_SHIFT = 24;
+ static const int CS_SPIREAD_LEN = 7;
+ static const int CS_SPINBYTES_MASK = 0xff;
+ static const int CS_SPINBYTES_SHIFT = 24;
+
public:
void set_timestamp(uint32_t timestamp){
@@ -77,7 +141,7 @@ public:
word0 |= 1<<FL_END_OF_BURST_SHIFT;
d_word0 = host_to_usrp_u32(word0);
}
-
+
void set_header(int flags, int chan, int tag, int payload_len){
uint32_t word0 = ((flags & FL_ALL_FLAGS)
| ((chan & CHAN_MASK) << CHAN_SHIFT)
@@ -144,6 +208,27 @@ public:
return MAX_PAYLOAD;
}
+ static int max_pkt_size() {
+ return USB_PKT_SIZE;
+ }
+
+ // C/S methods
+ bool align32();
+ bool cs_ping(long rid, long ping_val);
+ bool cs_ping_reply(long rid, long ping_val);
+ bool cs_write_reg(long reg_num, long val);
+ bool cs_write_reg_masked(long reg_num, long val, long mask);
+ bool cs_read_reg(long rid, long reg_num);
+ bool cs_read_reg_reply(long rid, long reg_num, long reg_val);
+ bool cs_delay(long ticks);
+ bool cs_i2c_write(long i2c_addr, uint8_t *i2c_data, size_t data_len);
+ bool cs_i2c_read(long rid, long i2c_addr, long n_bytes);
+ bool cs_i2c_read_reply(long rid, long i2c_addr, uint8_t *i2c_data, long i2c_data_len);
+ bool cs_spi_write(long enables, long format, long opt_header_bytes, uint8_t *spi_data, long spi_data_len);
+ bool cs_spi_read(long rid, long enables, long format, long opt_header_bytes, long n_bytes);
+ bool cs_spi_read_reply(long rid, uint8_t *spi_data, long spi_data_len);
+ int cs_len(int payload_offset);
+ pmt_t read_subpacket(int payload_offset);
};
#endif
diff --git a/usrp/host/lib/inband/usrp_interface.mbh b/usrp/host/lib/inband/usrp_interface.mbh
new file mode 100644
index 000000000..ad0f78b4e
--- /dev/null
+++ b/usrp/host/lib/inband/usrp_interface.mbh
@@ -0,0 +1,88 @@
+;; -*- 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++.
+;; ----------------------------------------------------------------
+
+;; ----------------------------------------------------------------
+;; usrp-interface-cs
+;;
+;; Handles interaction between the usrp_sever and the USB interface
+
+(define-protocol-class usrp-interface-cs
+
+ (:outgoing
+ (cmd-usrp-open invocation-handle which-usrp)
+ (cmd-usrp-close invocation-handle)
+ (cmd-usrp-ntx-chan invocation-handle)
+ (cmd-usrp-nrx-chan invocation-handle)
+ (cmd-usrp-write invocation-handle channel data)
+ (cmd-usrp-start-reading invocation-handle channel)
+ )
+
+ (:incoming
+ (response-usrp-open invocation-handle status)
+ (response-usrp-close invocation-handle status)
+ (response-usrp-ntx-chan invocation-handle ntx-chan)
+ (response-usrp-nrx-chan invocation-handle nrx-chan)
+ (response-usrp-write invocation-handle status channel)
+ (response-usrp-read invocation-handle status data)
+ )
+ )
+
+;; ----------------------------------------------------------------
+;; usrp-tx-cs
+;;
+;; Handles interaction between the USB interface and TX interface
+
+(define-protocol-class usrp-tx-cs
+
+ (:outgoing
+ (cmd-usrp-tx-write invocation-handle channel data tx-handle)
+ )
+
+ (:incoming
+ (response-usrp-tx-write invocation-handle status channel)
+ )
+ )
+
+;; ----------------------------------------------------------------
+;; usrp-rx-cs
+;;
+;; Handles interaction between the USB interface and RX interface
+
+(define-protocol-class usrp-rx-cs
+
+ (:outgoing
+ (cmd-usrp-rx-start-reading invocation-handle rx-handle)
+ (cmd-usrp-rx-stop-reading invocation-handle)
+ )
+
+ (:incoming
+ (response-usrp-rx-read invocation-handle status data)
+
+ ;; There is currently no response to a stop reading
+ )
+ )
diff --git a/usrp/host/lib/inband/usrp_rx.cc b/usrp/host/lib/inband/usrp_rx.cc
new file mode 100644
index 000000000..7344a6e89
--- /dev/null
+++ b/usrp/host/lib/inband/usrp_rx.cc
@@ -0,0 +1,142 @@
+/* -*- 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 <usrp_rx.h>
+
+#include <usrp_standard.h>
+#include <iostream>
+#include <vector>
+#include <usb.h>
+#include <mb_class_registry.h>
+#include <usrp_inband_usb_packet.h>
+#include <fpga_regs_common.h>
+#include <stdio.h>
+
+#include <symbols_usrp_rx_cs.h>
+
+typedef usrp_inband_usb_packet transport_pkt;
+
+static const bool verbose = false;
+
+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_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_cs_ofile.open("rx_cs.dat",std::ios::binary|std::ios::out);
+ }
+
+}
+
+usrp_rx::~usrp_rx()
+{
+ if(d_disk_write) {
+ d_ofile.close();
+ d_cs_ofile.close();
+ }
+}
+
+void
+usrp_rx::initial_transition()
+{
+
+}
+
+void
+usrp_rx::handle_message(mb_message_sptr msg)
+{
+ pmt_t event = msg->signal();
+ pmt_t port_id = msg->port_id();
+ pmt_t data = msg->data();
+
+ // 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_eqv(event, s_cmd_usrp_rx_start_reading))
+ read_and_respond(data);
+ }
+}
+
+void
+usrp_rx::read_and_respond(pmt_t data)
+{
+ size_t ignore;
+ bool underrun;
+ unsigned int n_read;
+ unsigned int pkt_size = sizeof(transport_pkt);
+
+ pmt_t invocation_handle = pmt_nth(0, data);
+
+ // Need the handle to the RX port to send responses, this is passed
+ // by the USRP interface m-block
+ d_urx =
+ boost::any_cast<usrp_standard_rx *>(pmt_any_ref(pmt_nth(1, data)));
+
+ if(verbose)
+ std::cout << "[usrp_rx] Waiting for packets..\n";
+
+ // Read by 512 which is packet size and send them back up
+ while(1) {
+
+ pmt_t v_pkt = pmt_make_u8vector(pkt_size, 0);
+ transport_pkt *pkt =
+ (transport_pkt *) pmt_u8vector_writeable_elements(v_pkt, ignore);
+
+ n_read = d_urx->read(pkt, pkt_size, &underrun);
+
+ if(n_read != pkt_size) {
+ std::cerr << "[usrp_rx] Error reading packet, shutting down\n";
+ d_cs->send(s_response_usrp_rx_read,
+ pmt_list3(PMT_NIL, PMT_F, PMT_NIL));
+ return;
+ }
+
+ if(underrun)
+ std::cout << "[usrp_rx] Underrun\n";
+
+ d_cs->send(s_response_usrp_rx_read,
+ pmt_list3(PMT_NIL, PMT_T, v_pkt));
+ if(verbose)
+ std::cout << "[usrp_rx] Read 1 packet\n";
+
+ if(d_disk_write) {
+ if(pkt->chan() == 0x1f)
+ d_cs_ofile.write((const char *)pkt, transport_pkt::max_pkt_size());
+ else
+ d_ofile.write((const char *)pkt, transport_pkt::max_pkt_size());
+
+ d_cs_ofile.flush();
+ d_ofile.flush();
+ }
+ }
+}
+
+REGISTER_MBLOCK_CLASS(usrp_rx);
diff --git a/usrp/host/lib/inband/usrp_rx.h b/usrp/host/lib/inband/usrp_rx.h
new file mode 100644
index 000000000..e1a90a781
--- /dev/null
+++ b/usrp/host/lib/inband/usrp_rx.h
@@ -0,0 +1,55 @@
+/* -*- 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_USRP_RX_H
+#define INCLUDED_USRP_RX_H
+
+#include <mb_mblock.h>
+#include <fstream>
+
+class usrp_standard_rx;
+
+/*!
+ * \brief Implements the low level usb interface to the USRP
+ */
+class usrp_rx : public mb_mblock
+{
+ mb_port_sptr d_cs;
+ usrp_standard_rx *d_urx;
+
+ bool d_disk_write;
+ std::ofstream d_ofile;
+ std::ofstream d_cs_ofile;
+
+ public:
+ usrp_rx(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg);
+ ~usrp_rx();
+ void initial_transition();
+ void handle_message(mb_message_sptr msg);
+
+ private:
+ void read_and_respond(pmt_t data);
+ void read_data();
+
+};
+
+
+#endif /* INCLUDED_USRP_RX_H */
+
diff --git a/usrp/host/lib/inband/usrp_rx_stub.cc b/usrp/host/lib/inband/usrp_rx_stub.cc
new file mode 100644
index 000000000..bf78ddf27
--- /dev/null
+++ b/usrp/host/lib/inband/usrp_rx_stub.cc
@@ -0,0 +1,183 @@
+/* -*- 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 <usrp_rx_stub.h>
+
+#include <iostream>
+#include <vector>
+#include <usb.h>
+#include <mb_class_registry.h>
+#include <usrp_inband_usb_packet.h>
+#include <fpga_regs_common.h>
+#include "usrp_standard.h"
+#include <stdio.h>
+#include "ui_nco.h"
+#include <fstream>
+
+#include <symbols_usrp_rx_cs.h>
+
+typedef usrp_inband_usb_packet transport_pkt;
+
+static const bool verbose = false;
+
+bool usrp_rx_stop;
+
+// 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.
+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_amplitude(16384),
+ d_disk_write(false)
+{
+ 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;
+ d_nco.set_freq(2*M_PI * freq/sample_rate);
+
+ //d_disk_write = true;
+
+ if(d_disk_write)
+ d_ofile.open("raw_rx.dat",std::ios::binary|std::ios::out);
+
+ usrp_rx_stop = false;
+}
+
+usrp_rx_stub::~usrp_rx_stub()
+{
+ if(d_disk_write)
+ d_ofile.close();
+}
+
+void
+usrp_rx_stub::initial_transition()
+{
+
+}
+
+void
+usrp_rx_stub::handle_message(mb_message_sptr msg)
+{
+ pmt_t event = msg->signal();
+ pmt_t port_id = msg->port_id();
+ pmt_t data = msg->data();
+
+ // 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(verbose)
+ std::cout << "[USRP_RX_STUB] Starting...\n";
+
+ if(pmt_eqv(event, s_cmd_usrp_rx_start_reading))
+ read_and_respond(data);
+ }
+}
+
+void
+usrp_rx_stub::read_and_respond(pmt_t data)
+{
+
+ while(!usrp_rx_stop) {
+
+ long nsamples_this_frame = d_samples_per_frame;
+
+ 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);
+
+ // 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();
+ }
+ }
+
+ 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));
+
+ // 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";
+ }
+
+ }
+
+ usrp_rx_stop = false;
+
+ if(verbose)
+ std::cout << "[USRP_RX_STUB] Got fake RX stop\n";
+
+}
+
+REGISTER_MBLOCK_CLASS(usrp_rx_stub);
diff --git a/usrp/host/lib/inband/usrp_rx_stub.h b/usrp/host/lib/inband/usrp_rx_stub.h
new file mode 100644
index 000000000..483af5b48
--- /dev/null
+++ b/usrp/host/lib/inband/usrp_rx_stub.h
@@ -0,0 +1,71 @@
+/* -*- 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_USRP_RX_STUB_H
+#define INCLUDED_USRP_RX_STUB_H
+
+#include <mb_mblock.h>
+#include <vector>
+#include "usrp_standard.h"
+#include "ui_nco.h"
+#include <fstream>
+#include <queue>
+#include <usrp_inband_usb_packet.h>
+
+typedef usrp_inband_usb_packet transport_pkt;
+
+extern bool usrp_rx_stop; // used to communicate a 'stop' to the RX stub
+extern std::queue<pmt_t> d_cs_queue;
+
+/*!
+ * \brief Implements the low level usb interface to the USRP
+ */
+class usrp_rx_stub : public mb_mblock
+{
+ public:
+
+ mb_port_sptr d_cs;
+ usrp_standard_rx* d_urx;
+
+ long d_samples_per_frame;
+
+ // for generating sine wave output
+ ui_nco<float,float> d_nco;
+ double d_amplitude;
+
+ bool d_disk_write;
+
+ std::ofstream d_ofile;
+
+ public:
+ usrp_rx_stub(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg);
+ ~usrp_rx_stub();
+ void initial_transition();
+ void handle_message(mb_message_sptr msg);
+
+ private:
+ void read_and_respond(pmt_t data);
+ void read_data();
+
+};
+
+
+#endif /* INCLUDED_USRP_RX_H */
+
diff --git a/usrp/host/lib/inband/usrp_server.cc b/usrp/host/lib/inband/usrp_server.cc
index 800bf0e15..760397dc7 100644
--- a/usrp/host/lib/inband/usrp_server.cc
+++ b/usrp/host/lib/inband/usrp_server.cc
@@ -27,39 +27,19 @@
#include <usrp_inband_usb_packet.h>
#include <mb_class_registry.h>
#include <vector>
+#include <usrp_usb_interface.h>
+
+#include <symbols_usrp_server_cs.h>
+#include <symbols_usrp_channel.h>
+#include <symbols_usrp_tx.h>
+#include <symbols_usrp_rx.h>
+#include <symbols_usrp_low_level_cs.h>
+#include <symbols_usrp_interface_cs.h>
+static pmt_t s_shutdown = pmt_intern("%shutdown");
typedef usrp_inband_usb_packet transport_pkt; // makes conversion to gigabit easy
-// FIXME We should machine generate these by a simple preprocessor run over this file
-//
-// These are all the messages that we expect to receive.
-//
-// We "intern" these here (make them into symbols) so that our
-// comparisions below are effectively pointer comparisons.
-
-static pmt_t s_cmd_allocate_channel = pmt_intern("cmd-allocate-channel");
-static pmt_t s_cmd_close = pmt_intern("cmd-close");
-static pmt_t s_cmd_deallocate_channel = pmt_intern("cmd-deallocate-channel");
-static pmt_t s_cmd_open = pmt_intern("cmd-open");
-static pmt_t s_cmd_start_recv_raw_samples = pmt_intern("cmd-start-recv-raw-samples");
-static pmt_t s_cmd_stop_recv_raw_samples = pmt_intern("cmd-stop-recv-raw-samples");
-static pmt_t s_cmd_to_control_channel = pmt_intern("cmd-to-control-channel");
-static pmt_t s_cmd_xmit_raw_frame = pmt_intern("cmd-xmit-raw-frame");
-static pmt_t s_cmd_max_capacity = pmt_intern("cmd-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_cmd_current_capacity_allocation = pmt_intern("cmd-current-capacity-allocation");
-static pmt_t s_response_allocate_channel = pmt_intern("response-allocate-channel");
-static pmt_t s_response_close = pmt_intern("response-close");
-static pmt_t s_response_deallocate_channel = pmt_intern("response-deallocate-channel");
-static pmt_t s_response_from_control_channel = pmt_intern("response-from-control-channel");
-static pmt_t s_response_open = pmt_intern("response-open");
-static pmt_t s_response_recv_raw_samples = pmt_intern("response-recv-raw-samples");
-static pmt_t s_response_xmit_raw_frame = pmt_intern("response-xmit-raw-frame");
-static pmt_t s_response_max_capacity = pmt_intern("response-max-capacity");
-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_response_current_capacity_allocation = pmt_intern("response-current-capacity-allocation");
+const static bool verbose = false;
static std::string
str(long x)
@@ -70,36 +50,75 @@ 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)
+ : mb_mblock(rt, instance_name, user_arg),
+ d_fake_rx(false)
{
- // define our ports
+ // Dictionary for arguments to all of the components
+ pmt_t usrp_dict = user_arg;
+
// control & status port
d_cs = define_port("cs", "usrp-server-cs", true, mb_port::EXTERNAL);
+ d_cs_usrp = define_port("cs_usrp", "usrp-interface-cs", false, mb_port::INTERNAL);
// ports
//
// (if/when we do replicated ports, these will be replaced by a
// single replicated port)
for(int port=0; port < N_PORTS; port++) {
- d_tx.push_back(define_port("tx"+str(port), "usrp-tx", true, mb_port::EXTERNAL));
- d_rx.push_back(define_port("rx"+str(port), "usrp-rx", true, mb_port::EXTERNAL));
+
+ d_tx.push_back(define_port("tx"+str(port),
+ "usrp-tx",
+ true,
+ mb_port::EXTERNAL));
+
+ d_rx.push_back(define_port("rx"+str(port),
+ "usrp-rx",
+ true,
+ mb_port::EXTERNAL));
}
- // FIXME ... initializing to 2 channels on each for now, eventually we should
- // query the FPGA to get these values
- d_ntx_chan = 2;
+ define_component("usrp", "usrp_usb_interface", usrp_dict);
+ connect("self", "cs_usrp", "usrp", "cs");
+
+ d_defer=false;
+ d_opened=false;
+
+ // FIXME: needs to be returned from open, if we want to use this
d_nrx_chan = 2;
+ d_ntx_chan = 2;
// Initialize capacity on each channel to 0 and to no owner
+ // Also initialize the USRP standard tx/rx pointers to NULL
+ for(int chan=0; chan < d_ntx_chan; chan++)
+ d_chaninfo_tx.push_back(channel_info());
+
+ for(int chan=0; chan < d_nrx_chan; chan++)
+ d_chaninfo_rx.push_back(channel_info());
+
+ d_rx_chan_mask = 0;
+
+ for(int i=0; i < D_MAX_RID; i++)
+ d_rids.push_back(rid_info());
+
+ //d_fake_rx=true;
+}
+
+void
+usrp_server::reset_channels()
+{
+
for(int chan=0; chan < d_ntx_chan; chan++) {
d_chaninfo_tx[chan].assigned_capacity = 0;
d_chaninfo_tx[chan].owner = PMT_NIL;
}
+
for(int chan=0; chan < d_nrx_chan; chan++) {
d_chaninfo_rx[chan].assigned_capacity = 0;
d_chaninfo_rx[chan].owner = PMT_NIL;
}
+
+ d_rx_chan_mask = 0;
}
usrp_server::~usrp_server()
@@ -119,78 +138,328 @@ usrp_server::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 invocation_handle;
- pmt_t reply_data;
+ pmt_t metadata = msg->metadata();
pmt_t status;
- if (1){
+ long port;
+
+ if (pmt_eq(event, s_shutdown)) // ignore (for now)
+ return;
+
+ invocation_handle = pmt_nth(0, data);
+
+ if (0){
std::cout << "[USRP_SERVER] event: " << event << std::endl;
std::cout << "[USRP_SERVER] port_id: " << port_id << std::endl;
}
- // It would be nice if this were all table driven, and we could
- // compute our state transition as f(current_state, port_id, signal)
+ // It would be nice if this were all table driven, and we could compute our
+ // state transition as f(current_state, port_id, signal)
+
+ // A message from the USRP CS, which should *only* be responses
+ //
+ // It is important that this set come before checking messages of any other
+ // components. This is since we always want to listen to the low level USRP
+ // server, even if we aren't initialized we are waiting for responses to
+ // become initialized. Likewise, after the usrp_server is "closed", we still
+ // want to pass responses back from the low level.
- if (pmt_eq(port_id, d_cs->port_symbol())){ // message came in on our control/status port
+ //---------------- USRP RESPONSE ---------------//
+ if (pmt_eq(port_id, d_cs_usrp->port_symbol())) {
+
+ //-------------- USRP OPEN ------------------//
+ if(pmt_eq(event, s_response_usrp_open)) {
+ // pass the response back over the regular CS port
+ pmt_t status = pmt_nth(1, data);
+ d_cs->send(s_response_open, pmt_list2(invocation_handle, status));
- if (pmt_eq(event, s_cmd_open)){
- // extract args from data
- invocation_handle = pmt_nth(0, data);
- long which_usrp = pmt_to_long(pmt_nth(1, data)); // integer usrp id, usually 0
+ if(pmt_eqv(status,PMT_T)) {
+ d_opened = true;
+ d_defer = false;
+ recall_defer_queue();
+ }
+
+ return;
+ }
+ //------------- USRP CLOSE -------------------//
+ else if (pmt_eq(event, s_response_usrp_close)) {
+ pmt_t status = pmt_nth(1, data);
+ d_cs->send(s_response_close, pmt_list2(invocation_handle, status));
+
+ if(pmt_eqv(status,PMT_T)) {
+ d_opened = false;
+ d_defer = false;
+ reset_channels();
+ recall_defer_queue();
+ }
- // Do the right thing....
- // build a reply
- (void) which_usrp; // avoid unused warning
+ return;
+ }
+ //--------------- USRP WRITE --------------//
+ else if (pmt_eq(event, s_response_usrp_write)) {
+
+ pmt_t status = pmt_nth(1, data);
+ long channel = pmt_to_long(pmt_nth(2, data));
+ long port;
+
+ // Do not report back responses if they were generated from a
+ // command packet
+ if(channel == 0x1f)
+ return;
+
+ // Find the port through the owner of the channel
+ if((port = tx_port_index(d_chaninfo_tx[channel].owner)) !=-1 )
+ d_tx[port]->send(s_response_xmit_raw_frame,
+ pmt_list2(invocation_handle, status));
+ return;
+ }
+ //--------------- USRP READ ---------------//
+ else if (pmt_eq(event, s_response_usrp_read)) {
+
+ pmt_t status = pmt_nth(1, data);
+
+ if(!pmt_eqv(status, PMT_T)) {
+ std::cerr << "[USRP_SERVER] Error receiving packet\n";
+ return;
+ }
+ else {
+ handle_response_usrp_read(data);
+ return;
+ }
+ }
+
+ goto unhandled;
+ }
+
+ // Checking for defer on all other messages
+ if(d_defer) {
+ if (verbose)
+ std::cout << "[USRP_SERVER] Received msg while deferring ("
+ << msg->signal() << ")\n";
+ d_defer_queue.push(msg);
+ return;
+ }
+
+ //--------- CONTROL / STATUS ------------//
+ if (pmt_eq(port_id, d_cs->port_symbol())){
+
+ //----------- OPEN -----------//
+ if (pmt_eq(event, s_cmd_open)){
- // if everything OK
- status = PMT_T;
- reply_data = pmt_list2(invocation_handle, status);
+ // Reject if already open
+ if(d_opened) {
+ d_cs->send(s_response_open, pmt_list2(invocation_handle, s_err_usrp_already_opened));
+ return;
+ }
- // ...and send it
- d_cs->send(s_response_open, reply_data);
+ // the parameters are the same to the low level interface, so we just pass 'data' along
+ d_cs_usrp->send(s_cmd_usrp_open, data);
+
+ d_defer = true;
+
return;
}
+ //---------- CLOSE -----------//
else if (pmt_eq(event, s_cmd_close)){
- // ...
+
+ if(!d_opened) {
+ d_cs->send(s_response_close, pmt_list2(invocation_handle, s_err_usrp_already_closed));
+ return;
+ }
+
+ d_defer = true;
+ d_cs_usrp->send(s_cmd_usrp_close, pmt_list1(invocation_handle));
+
+ return;
}
+ //---------- MAX CAPACITY ----------//
else if (pmt_eq(event, s_cmd_max_capacity)) {
- invocation_handle = pmt_nth(0, data);
- reply_data = pmt_list2(invocation_handle, pmt_from_long(max_capacity()));
- d_cs->send(s_response_max_capacity, reply_data);
+
+ if(!d_opened) {
+ d_cs->send(s_response_max_capacity,
+ pmt_list3(invocation_handle, s_err_usrp_not_opened, pmt_from_long(0)));
+ return;
+ }
+
+ d_cs->send(s_response_max_capacity,
+ pmt_list3(invocation_handle,
+ PMT_T,
+ pmt_from_long(max_capacity())));
return;
}
+ //---------- NTX CHAN --------------//
else if (pmt_eq(event, s_cmd_ntx_chan)) {
- invocation_handle = pmt_nth(0, data);
- reply_data = pmt_list2(invocation_handle, pmt_from_long(d_ntx_chan));
- d_cs->send(s_response_ntx_chan, reply_data);
+
+ if(!d_opened) {
+ d_cs->send(s_response_ntx_chan,
+ pmt_list3(invocation_handle, s_err_usrp_not_opened, pmt_from_long(0)));
+ return;
+ }
+
+ d_cs->send(s_response_ntx_chan,
+ pmt_list3(invocation_handle,
+ PMT_T,
+ pmt_from_long(d_ntx_chan)));
+ return;
}
+ //---------- NRX CHAN -----------//
else if (pmt_eq(event, s_cmd_nrx_chan)) {
- invocation_handle = pmt_nth(0, data);
- reply_data = pmt_list2(invocation_handle, pmt_from_long(d_nrx_chan));
- d_cs->send(s_response_nrx_chan, reply_data);
- }
+
+ if(!d_opened) {
+ d_cs->send(s_response_nrx_chan,
+ pmt_list3(invocation_handle, s_err_usrp_not_opened, pmt_from_long(0)));
+ return;
+ }
+
+ d_cs->send(s_response_nrx_chan,
+ pmt_list3(invocation_handle,
+ PMT_T,
+ pmt_from_long(d_nrx_chan)));
+ return;
+ }
+ //--------- ALLOCATION? -----------//
else if (pmt_eq(event, s_cmd_current_capacity_allocation)) {
- invocation_handle = pmt_nth(0, data);
- reply_data = pmt_list2(invocation_handle, pmt_from_long(current_capacity_allocation()));
- d_cs->send(s_response_current_capacity_allocation, reply_data);
+
+ if(!d_opened) {
+ d_cs->send(s_response_current_capacity_allocation,
+ pmt_list3(invocation_handle,
+ s_err_usrp_not_opened,
+ pmt_from_long(0)));
+ return;
+ }
+
+ d_cs->send(s_response_current_capacity_allocation,
+ pmt_list3(invocation_handle,
+ PMT_T,
+ pmt_from_long(current_capacity_allocation())));
+ return;
}
goto unhandled;
}
+
+ //-------------- TX ---------------//
+ if ((port = tx_port_index(port_id)) != -1) {
+
+ //------------ ALLOCATE (TX) ----------------//
+ if (pmt_eq(event, s_cmd_allocate_channel)){
+
+ if(!d_opened) {
+ d_tx[port]->send(s_response_allocate_channel,
+ pmt_list3(invocation_handle,
+ s_err_usrp_not_opened,
+ pmt_from_long(0)));
+ return;
+ }
+
+ handle_cmd_allocate_channel(d_tx[port], d_chaninfo_tx, data);
+ return;
+ }
+
+ //----------- DEALLOCATE (TX) ---------------//
+ if (pmt_eq(event, s_cmd_deallocate_channel)) {
+
+ if(!d_opened) {
+ d_tx[port]->send(s_response_deallocate_channel,
+ pmt_list3(invocation_handle,
+ s_err_usrp_not_opened,
+ pmt_from_long(0)));
+ return;
+ }
- if (pmt_eq(event, s_cmd_allocate_channel)){
- handle_cmd_allocate_channel(port_id, data);
- return;
- }
+ handle_cmd_deallocate_channel(d_tx[port], d_chaninfo_tx, data);
+ return;
+ }
+
+ //-------------- XMIT RAW FRAME -----------------/
+ if (pmt_eq(event, s_cmd_xmit_raw_frame)){
- if (pmt_eq(event, s_cmd_deallocate_channel)) {
- handle_cmd_deallocate_channel(port_id, data);
- return;
+ if(!d_opened) {
+ d_tx[port]->send(s_response_xmit_raw_frame,
+ pmt_list2(invocation_handle, s_err_usrp_not_opened));
+ return;
+ }
+
+ handle_cmd_xmit_raw_frame(d_tx[port], d_chaninfo_tx, data);
+ return;
+ }
+
+ //-------------- CONTROL PACKET -----------------/
+ if (pmt_eq(event, s_cmd_to_control_channel)) {
+
+ if(!d_opened) {
+ d_tx[port]->send(s_response_xmit_raw_frame,
+ pmt_list2(invocation_handle, s_err_usrp_not_opened));
+ return;
+ }
+
+ handle_cmd_to_control_channel(d_tx[port], d_chaninfo_tx, data);
+ return;
+
+ }
+
+ goto unhandled;
}
+
+ //-------------- RX ---------------//
+ if ((port = rx_port_index(port_id)) != -1) {
- if (pmt_eq(event, s_cmd_xmit_raw_frame)){
- handle_cmd_xmit_raw_frame(data);
- return;
+ //------------ ALLOCATE (RX) ----------------//
+ if (pmt_eq(event, s_cmd_allocate_channel)) {
+
+ if(!d_opened) {
+ d_rx[port]->send(s_response_allocate_channel,
+ pmt_list3(invocation_handle,
+ s_err_usrp_not_opened,
+ pmt_from_long(0)));
+ return;
+ }
+
+ handle_cmd_allocate_channel(d_rx[port], d_chaninfo_rx, data);
+ return;
+ }
+
+ //----------- DEALLOCATE (RX) ---------------//
+ if (pmt_eq(event, s_cmd_deallocate_channel)) {
+
+ if(!d_opened) {
+ d_rx[port]->send(s_response_deallocate_channel,
+ pmt_list3(invocation_handle,
+ s_err_usrp_not_opened,
+ pmt_from_long(0)));
+ return;
+ }
+
+ handle_cmd_deallocate_channel(d_rx[port], d_chaninfo_rx, data);
+ return;
+ }
+
+ //-------------- START RECV ----------------//
+ if (pmt_eq(event, s_cmd_start_recv_raw_samples)) {
+
+ if(!d_opened) {
+ d_rx[port]->send(s_response_recv_raw_samples,
+ pmt_list2(invocation_handle, s_err_usrp_not_opened));
+ return;
+ }
+
+ handle_cmd_start_recv_raw_samples(d_rx[port], d_chaninfo_rx, data);
+ return;
+ }
+
+ //-------------- STOP RECV ----------------//
+ if (pmt_eq(event, s_cmd_stop_recv_raw_samples)) {
+
+ if(!d_opened)
+ return;
+
+ // FIX ME : no response for stopping? even if error? (permissions)
+ handle_cmd_stop_recv_raw_samples(d_rx[port], d_chaninfo_rx, data);
+
+ return;
+ }
+
+ goto unhandled;
}
unhandled:
@@ -231,128 +500,94 @@ long usrp_server::current_capacity_allocation() {
return capacity;
}
-void usrp_server::handle_cmd_allocate_channel(pmt_t port_id, pmt_t data) {
-
+void
+usrp_server::handle_cmd_allocate_channel(
+ mb_port_sptr port,
+ std::vector<struct channel_info> &chan_info,
+ pmt_t data)
+{
pmt_t invocation_handle = pmt_nth(0, data);
long rqstd_capacity = pmt_to_long(pmt_nth(1, data));
- long chan, port;
- pmt_t reply_data;
+ long chan;
- // If it's a TX port, allocate on a free channel, else check if it's a RX port
- // and allocate.
- if((port = tx_port_index(port_id)) != -1) {
+ // Check capacity exists
+ if((D_USB_CAPACITY - current_capacity_allocation()) < rqstd_capacity) {
- // Check capacity exists
- if((D_USB_CAPACITY - current_capacity_allocation()) < rqstd_capacity) {
- reply_data = pmt_list3(invocation_handle, pmt_from_long(RQSTD_CAPACITY_UNAVAIL), PMT_NIL); // no capacity available
- d_tx[port]->send(s_response_allocate_channel, reply_data);
- return;
- }
+ // no capacity available
+ port->send(s_response_allocate_channel,
+ pmt_list3(invocation_handle,
+ s_err_requested_capacity_unavailable,
+ PMT_NIL));
+ return;
+ }
- // Find a free channel, assign the capacity and respond
- for(chan=0; chan < d_ntx_chan; chan++) {
- if(d_chaninfo_tx[chan].owner == PMT_NIL) {
- d_chaninfo_tx[chan].owner = port_id;
- d_chaninfo_tx[chan].assigned_capacity = rqstd_capacity;
- reply_data = pmt_list3(invocation_handle, PMT_T, pmt_from_long(chan));
- d_tx[port]->send(s_response_allocate_channel, reply_data);
- return;
- }
- }
+ // Find a free channel, assign the capacity and respond
+ for(chan=0; chan < (long)chan_info.size(); chan++) {
- std::cout << "[USRP_SERVER] Couldnt find a TX chan\n";
+ if(verbose)
+ std::cout << "[USRP_SERVER] Checking chan: " << chan
+ << " owner " << chan_info[chan].owner
+ << " size " << chan_info.size()
+ << std::endl;
- reply_data = pmt_list3(invocation_handle, pmt_from_long(CHANNEL_UNAVAIL), PMT_NIL); // no free TX chan found
- d_tx[port]->send(s_response_allocate_channel, reply_data);
- return;
- }
+ if(chan_info[chan].owner == PMT_NIL) {
- // Repeat the same process on the RX side if the port was not determined to be TX
- if((port = rx_port_index(port_id)) != -1) {
-
- if((D_USB_CAPACITY - current_capacity_allocation()) < rqstd_capacity) {
- reply_data = pmt_list3(invocation_handle, pmt_from_long(RQSTD_CAPACITY_UNAVAIL), PMT_NIL); // no capacity available
- d_rx[port]->send(s_response_allocate_channel, reply_data);
+ chan_info[chan].owner = port->port_symbol();
+ chan_info[chan].assigned_capacity = rqstd_capacity;
+
+ port->send(s_response_allocate_channel,
+ pmt_list3(invocation_handle,
+ PMT_T,
+ pmt_from_long(chan)));
+
+ if(verbose)
+ std::cout << "[USRP_SERVER] Assigning channel: " << chan
+ << " to " << chan_info[chan].owner
+ << std::endl;
return;
}
+
+ }
- for(chan=0; chan < d_nrx_chan; chan++) {
- if(d_chaninfo_rx[chan].owner == PMT_NIL) {
- d_chaninfo_rx[chan].owner = port_id;
- d_chaninfo_rx[chan].assigned_capacity = rqstd_capacity;
- reply_data = pmt_list3(invocation_handle, PMT_T, pmt_from_long(chan));
- d_rx[port]->send(s_response_allocate_channel, reply_data);
- return;
- }
- }
+ if (verbose)
+ std::cout << "[USRP_SERVER] Couldnt find a TX chan\n";
- std::cout << "[USRP_SERVER] Couldnt find a RX chan\n";
- reply_data = pmt_list3(invocation_handle, pmt_from_long(CHANNEL_UNAVAIL), PMT_NIL); // no free RX chan found
- d_rx[port]->send(s_response_allocate_channel, reply_data);
- return;
- }
+ // no free TX chan found
+ port->send(s_response_allocate_channel,
+ pmt_list3(invocation_handle,
+ s_err_channel_unavailable,
+ PMT_NIL));
+ 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.
-void usrp_server::handle_cmd_deallocate_channel(pmt_t port_id, pmt_t data) {
+// that the owner of the method invocation is the owner of the port and that the
+// channel number is valid.
+void
+usrp_server::handle_cmd_deallocate_channel(
+ 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));
- long port;
- pmt_t reply_data;
-
- // Check that the channel number is valid, and that the calling port is the owner
- // of the channel, and if so remove the assigned capacity.
- if((port = tx_port_index(port_id)) != -1) {
-
- if(channel >= d_ntx_chan) {
- reply_data = pmt_list2(invocation_handle, pmt_from_long(CHANNEL_INVALID)); // not a legit channel number
- d_tx[port]->send(s_response_deallocate_channel, reply_data);
- return;
- }
- if(d_chaninfo_tx[channel].owner != port_id) {
- reply_data = pmt_list2(invocation_handle, pmt_from_long(PERMISSION_DENIED)); // not the owner of the port
- d_tx[port]->send(s_response_deallocate_channel, reply_data);
- return;
- }
-
- d_chaninfo_tx[channel].assigned_capacity = 0;
- d_chaninfo_tx[channel].owner = PMT_NIL;
-
- reply_data = pmt_list2(invocation_handle, PMT_T);
- d_tx[port]->send(s_response_deallocate_channel, reply_data);
+ // Ensure the channel is valid and the caller owns the port
+ if(!check_valid(port, channel, chan_info,
+ pmt_list2(s_response_deallocate_channel, invocation_handle)))
return;
- }
-
- // Repeated process on the RX side
- if((port = rx_port_index(port_id)) != -1) {
- if(channel >= d_nrx_chan) {
- reply_data = pmt_list2(invocation_handle, pmt_from_long(CHANNEL_INVALID)); // not a legit channel number
- d_rx[port]->send(s_response_deallocate_channel, reply_data);
- return;
- }
-
- if(d_chaninfo_rx[channel].owner != port_id) {
- reply_data = pmt_list2(invocation_handle, pmt_from_long(PERMISSION_DENIED)); // not the owner of the port
- d_rx[port]->send(s_response_deallocate_channel, reply_data);
- return;
- }
-
- d_chaninfo_rx[channel].assigned_capacity = 0;
- d_chaninfo_rx[channel].owner = PMT_NIL;
-
- reply_data = pmt_list2(invocation_handle, PMT_T);
- d_rx[port]->send(s_response_deallocate_channel, reply_data);
- return;
- }
+ chan_info[channel].assigned_capacity = 0;
+ chan_info[channel].owner = PMT_NIL;
+ port->send(s_response_deallocate_channel,
+ pmt_list2(invocation_handle,
+ PMT_T));
+ return;
}
-void usrp_server::handle_cmd_xmit_raw_frame(pmt_t data) {
+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();
@@ -361,10 +596,18 @@ void usrp_server::handle_cmd_xmit_raw_frame(pmt_t data) {
long channel = pmt_to_long(pmt_nth(1, data));
const void *samples = pmt_uniform_vector_elements(pmt_nth(2, data), n_bytes);
long timestamp = pmt_to_long(pmt_nth(3, data));
+
+ // Ensure the channel is valid and the caller owns the port
+ if(!check_valid(port, channel, chan_info,
+ pmt_list2(s_response_xmit_raw_frame, invocation_handle)))
+ return;
+
+ // Determine the number of packets to allocate contiguous memory for
+ // bursting over the USB and get a pointer to the memory to be used in
+ // building the packets
+ long n_packets =
+ static_cast<long>(std::ceil(n_bytes / (double)max_payload_len));
- // Determine the number of packets to allocate contiguous memory for bursting over the
- // USB and get a pointer to the memory to be used in building the packets
- long n_packets = static_cast<long>(std::ceil(n_bytes / (double)max_payload_len));
pmt_t v_packets = pmt_make_u8vector(sizeof(transport_pkt) * n_packets, 0);
transport_pkt *pkts =
@@ -372,7 +615,8 @@ void usrp_server::handle_cmd_xmit_raw_frame(pmt_t data) {
for(int n=0; n < n_packets; n++) {
- long payload_len = std::min((long)(n_bytes-(n*max_payload_len)), (long)max_payload_len);
+ long payload_len =
+ std::min((long)(n_bytes-(n*max_payload_len)), (long)max_payload_len);
if(n == 0) { // first packet gets start of burst flag and timestamp
pkts[n].set_header(pkts[n].FL_START_OF_BURST, channel, 0, payload_len);
@@ -382,14 +626,740 @@ void usrp_server::handle_cmd_xmit_raw_frame(pmt_t data) {
pkts[n].set_timestamp(0xffffffff);
}
- memcpy(pkts[n].payload(), (uint8_t *)samples+(max_payload_len * n), payload_len);
+ memcpy(pkts[n].payload(),
+ (uint8_t *)samples+(max_payload_len * n),
+ payload_len);
+
+ }
+
+
+ pkts[n_packets-1].set_end_of_burst(); // set the last packet's end of burst
+
+ if (verbose)
+ std::cout << "[USRP_SERVER] Received raw frame invocation: "
+ << invocation_handle << std::endl;
+
+ // The actual response to the write will be generated by a
+ // s_response_usrp_write
+ d_cs_usrp->send(s_cmd_usrp_write,
+ pmt_list3(invocation_handle,
+ pmt_from_long(channel),
+ v_packets));
+
+ return;
+}
+
+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);
+ pmt_t subpackets = pmt_nth(1, data);
+
+ long n_subpkts = pmt_length(subpackets);
+ long curr_subpkt = 0;
+
+ size_t psize;
+ long payload_len = 0;
+ long channel = 0x1f;
+
+ // The design of the following code is optimized for simplicity, not
+ // performance. To performance optimize this code, the total size in bytes
+ // needed for all of the CS packets is needed to allocate contiguous memory
+ // which contains the USB packets for bursting over the bus. However to do
+ // this the packets subpackets would need to be parsed twice and their sizes
+ // would need to be determined.
+ //
+ // The approach taken is to keep parsing the subpackets and putting them in to
+ // USB packets. Once the USB packet is full, a write is sent for it and
+ // another packet is created.
+ //
+ // The subpacket creation methods will return false if the subpacket will not
+ // fit in to the current USB packet. In these cases a new USB packet is
+ // created and the old is sent.
+
+ new_packet:
+ // This code needs to become "smart" and only make a new packet when full
+ pmt_t v_packet = pmt_make_u8vector(sizeof(transport_pkt), 0);
+ transport_pkt *pkt = (transport_pkt *) pmt_u8vector_writeable_elements(v_packet, psize);
+ payload_len = 0;
+
+ pkt->set_header(0, channel, 0, payload_len);
+ pkt->set_timestamp(0xffffffff);
+
+ while(curr_subpkt < n_subpkts) {
+
+ pmt_t subp = pmt_nth(curr_subpkt, subpackets);
+ pmt_t subp_cmd = pmt_nth(0, subp);
+ pmt_t subp_data = pmt_nth(1, subp);
+
+ //--------- PING FIXED --------------//
+ if(pmt_eq(subp_cmd, s_op_ping_fixed)) {
+
+ long urid = pmt_to_long(pmt_nth(0, subp_data));
+ long pingval = pmt_to_long(pmt_nth(1, subp_data));
+
+ // USRP server sets request ID's to keep track of which application gets
+ // what response back. To allow a full 6-bits for an RID to the user, we
+ // keep a mapping and replace the RID's as the packets go in and out. If
+ // there are no RID's available, the command is thrown away silently.
+ long srid;
+ if((srid = next_rid()) == -1)
+ goto subpkt_bail;
+
+ // We use a vector to store the owner of the ping request and will use it
+ // to send the request on any RX port they own.
+ d_rids[srid].owner = port->port_symbol();
+ d_rids[srid].user_rid = urid;
+
+ // Adds a ping after the previous command in the pkt
+ if(!pkt->cs_ping(srid, pingval))
+ {
+ d_cs_usrp->send(s_cmd_usrp_write,
+ pmt_list3(invocation_handle,
+ pmt_from_long(channel),
+ v_packet));
+
+ // Return the RID
+ d_rids[srid].owner = PMT_NIL;
+
+ goto new_packet;
+ }
+
+ if(verbose)
+ std::cout << "[USRP_SERVER] Received ping command request"
+ << " assigning RID " << srid << std::endl;
+
+ }
+
+ //----------- WRITE REG ---------------//
+ if(pmt_eq(subp_cmd, s_op_write_reg)) {
+
+ long reg_num = pmt_to_long(pmt_nth(0, subp_data));
+ long val = pmt_to_long(pmt_nth(1, subp_data));
+
+ if(!pkt->cs_write_reg(reg_num, val))
+ {
+ d_cs_usrp->send(s_cmd_usrp_write,
+ pmt_list3(invocation_handle,
+ pmt_from_long(channel),
+ v_packet));
+
+ goto new_packet;
+ }
+
+ if(verbose)
+ std::cout << "[USRP_SERVER] Received write register request "
+ << "("
+ << "Reg: " << reg_num << ", "
+ << "Val: " << val
+ << ")\n";
+ }
+
+ //------- WRITE REG MASKED ----------//
+ if(pmt_eq(subp_cmd, s_op_write_reg_masked)) {
+
+ long reg_num = pmt_to_long(pmt_nth(0, subp_data));
+ long val = pmt_to_long(pmt_nth(1, subp_data));
+ long mask = pmt_to_long(pmt_nth(2, subp_data));
+
+ if(!pkt->cs_write_reg_masked(reg_num, val, mask))
+ {
+ d_cs_usrp->send(s_cmd_usrp_write,
+ pmt_list3(invocation_handle,
+ pmt_from_long(channel),
+ v_packet));
+
+ goto new_packet;
+ }
+
+ if(verbose)
+ std::cout << "[USRP_SERVER] Received write register masked request\n";
+ }
+
+ //------------ READ REG --------------//
+ if(pmt_eq(subp_cmd, s_op_read_reg)) {
+
+ long urid = pmt_to_long(pmt_nth(0, subp_data));
+ long reg_num = pmt_to_long(pmt_nth(1, subp_data));
+
+ long srid;
+ if((srid = next_rid()) == -1)
+ goto subpkt_bail;
+
+ d_rids[srid].owner = port->port_symbol();
+ d_rids[srid].user_rid = urid;
+
+ if(!pkt->cs_read_reg(srid, reg_num))
+ {
+ d_cs_usrp->send(s_cmd_usrp_write,
+ pmt_list3(invocation_handle,
+ pmt_from_long(channel),
+ v_packet));
+
+ // Return the rid
+ d_rids[srid].owner = PMT_NIL;
+
+ goto new_packet;
+ }
+
+ if(verbose)
+ std::cout << "[USRP_SERVER] Received read register request"
+ << " assigning RID " << srid << std::endl;
+ }
+
+ //------------ DELAY --------------//
+ if(pmt_eq(subp_cmd, s_op_delay)) {
+
+ long ticks = pmt_to_long(pmt_nth(0, subp_data));
+
+ if(!pkt->cs_delay(ticks))
+ {
+ d_cs_usrp->send(s_cmd_usrp_write,
+ pmt_list3(invocation_handle,
+ pmt_from_long(channel),
+ v_packet));
+
+ goto new_packet;
+ }
+
+ if(verbose)
+ std::cout << "[USRP_SERVER] Received delay request of "
+ << ticks << " ticks\n";
+ }
+
+ //--------- I2C WRITE -----------//
+ // FIXME: could check that byte count does not exceed 2^8 which
+ // is the max length in the subpacket for # of bytes to read.
+ if(pmt_eq(subp_cmd, s_op_i2c_write)) {
+
+ long i2c_addr = pmt_to_long(pmt_nth(0, subp_data));
+ pmt_t data = pmt_nth(1, subp_data);
+
+ // Get a readable address to the data which also gives us the length
+ size_t data_len;
+ uint8_t *i2c_data = (uint8_t *) pmt_u8vector_writeable_elements(data, data_len);
+
+ // Make the USB packet
+ if(!pkt->cs_i2c_write(i2c_addr, i2c_data, data_len))
+ {
+ d_cs_usrp->send(s_cmd_usrp_write,
+ pmt_list3(invocation_handle,
+ pmt_from_long(channel),
+ v_packet));
+
+ goto new_packet;
+ }
+
+ if(verbose)
+ std::cout << "[USRP_SERVER] Received I2C write\n";
+ }
+
+ //----------- I2C Read -------------//
+ if(pmt_eq(subp_cmd, s_op_i2c_read)) {
+
+ long urid = pmt_to_long(pmt_nth(0, subp_data));
+ long i2c_addr = pmt_to_long(pmt_nth(1, subp_data));
+ long i2c_bytes = pmt_to_long(pmt_nth(2, subp_data));
+
+ long srid;
+ if((srid = next_rid()) == -1)
+ goto subpkt_bail;
+
+ d_rids[srid].owner = port->port_symbol();
+ d_rids[srid].user_rid = urid;
+
+ if(!pkt->cs_i2c_read(srid, i2c_addr, i2c_bytes))
+ {
+
+ d_cs_usrp->send(s_cmd_usrp_write,
+ pmt_list3(invocation_handle,
+ pmt_from_long(channel),
+ v_packet));
+
+ d_rids[srid].owner = PMT_NIL;
+
+ goto new_packet;
+ }
+
+ if(verbose)
+ std::cout << "[USRP_SERVER] Received I2C read\n";
+ }
+
+ //--------- SPI WRITE -----------//
+ if(pmt_eq(subp_cmd, s_op_spi_write)) {
+
+ long enables = pmt_to_long(pmt_nth(0, subp_data));
+ long format = pmt_to_long(pmt_nth(1, subp_data));
+ long opt = pmt_to_long(pmt_nth(2, subp_data));
+ pmt_t data = pmt_nth(3, subp_data);
+
+ // Get a readable address to the data which also gives us the length
+ size_t data_len;
+ uint8_t *spi_data = (uint8_t *) pmt_u8vector_writeable_elements(data, data_len);
+
+ // Make the USB packet
+ if(!pkt->cs_spi_write(enables, format, opt, spi_data, data_len))
+ {
+ d_cs_usrp->send(s_cmd_usrp_write,
+ pmt_list3(invocation_handle,
+ pmt_from_long(channel),
+ v_packet));
+
+ goto new_packet;
+ }
+
+ if(verbose)
+ std::cout << "[USRP_SERVER] Received SPI write\n";
+ }
+
+ //--------- SPI READ -----------//
+ if(pmt_eq(subp_cmd, s_op_spi_read)) {
+
+ long urid = pmt_to_long(pmt_nth(0, subp_data));
+ long enables = pmt_to_long(pmt_nth(1, subp_data));
+ long format = pmt_to_long(pmt_nth(2, subp_data));
+ long opt = pmt_to_long(pmt_nth(3, subp_data));
+ long n_bytes = pmt_to_long(pmt_nth(4, subp_data));
+
+ long srid;
+ if((srid = next_rid()) == -1)
+ goto subpkt_bail;
+
+ d_rids[srid].owner = port->port_symbol();
+ d_rids[srid].user_rid = urid;
+
+ // Make the USB packet
+ if(!pkt->cs_spi_read(srid, enables, format, opt, n_bytes))
+ {
+ d_cs_usrp->send(s_cmd_usrp_write,
+ pmt_list3(invocation_handle,
+ pmt_from_long(channel),
+ v_packet));
+
+ // Return the rid
+ d_rids[srid].owner = PMT_NIL;
+
+ goto new_packet;
+ }
+
+ if(verbose)
+ std::cout << "[USRP_SERVER] Received SPI read\n";
+ }
+
+ subpkt_bail:
+ curr_subpkt++;
+
+ }
+
+
+ // If the current packets length is > 0, we know there are subpackets that
+ // need to be sent out still.
+ if(pkt->payload_len() > 0)
+ d_cs_usrp->send(s_cmd_usrp_write,
+ pmt_list3(invocation_handle,
+ pmt_from_long(channel),
+ v_packet));
+
+ return;
+}
+
+void
+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));
+
+ // Ensure the channel is valid and the caller owns the port
+ if(!check_valid(port, channel, chan_info,
+ pmt_list2(s_response_xmit_raw_frame, invocation_handle)))
+ return;
+
+ // Already started receiving samples? (another start before a stop)
+ // Check the RX channel bitmask.
+ if(d_rx_chan_mask & (1 << channel)) {
+ port->send(s_response_recv_raw_samples,
+ pmt_list5(invocation_handle,
+ s_err_already_receiving,
+ PMT_NIL,
+ PMT_NIL,
+ PMT_NIL));
+ return;
+ }
+
+ // We only need to generate a 'start reading' command down to the
+ // low level interface if no other channel is already reading
+ //
+ // We carry this over the CS interface because the lower level
+ // interface does not care about the channel, we only demux it
+ // at the usrp_server on responses.
+ if(d_rx_chan_mask == 0) {
+
+ if(verbose)
+ std::cout << "[USRP_SERVER] Sending read request down to start recv\n";
+
+ d_cs_usrp->send(s_cmd_usrp_start_reading, pmt_list1(invocation_handle));
+ }
+
+ d_rx_chan_mask |= 1<<channel;
+
+ return;
+}
+
+void
+usrp_server::handle_cmd_stop_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));
+
+ // FIX ME : we have no responses to send an error...
+ // Ensure the channel is valid and the caller owns the port
+ //if(!check_valid(port, channel, chan_info,
+ // pmt_list2(s_response_xmit_raw_frame, invocation_handle)))
+ // return;
+
+ // Remove this hosts bit from the receiver mask
+ d_rx_chan_mask &= ~(1<<channel);
+
+ // We only need to generate a 'start reading' command down to the
+ // low level interface if no other channel is already reading
+ //
+ // We carry this over the CS interface because the lower level
+ // interface does not care about the channel, we only demux it
+ // at the usrp_server on responses.
+ if(d_rx_chan_mask == 0) {
+
+ if(verbose)
+ std::cout << "[USRP_SERVER] Sending stop reading request down\n";
+
+ d_cs_usrp->send(s_cmd_usrp_stop_reading, pmt_list1(invocation_handle));
+ }
+
+ return;
+}
+
+// Read the packet header, determine the port by the channel owner
+void
+usrp_server::handle_response_usrp_read(pmt_t data)
+{
+
+ pmt_t invocation_handle = pmt_nth(0, data);
+ pmt_t status = pmt_nth(1, data);
+ pmt_t v_pkt = pmt_nth(2, data);
+
+ size_t n_bytes;
+ size_t ignore;
+
+ if (d_fake_rx) {
+
+ pmt_t pkt = pmt_nth(2, data);
+
+ d_rx[0]->send(s_response_recv_raw_samples,
+ pmt_list5(PMT_F,
+ PMT_T,
+ pkt,
+ pmt_from_long(0xffff),
+ PMT_NIL));
+
+ return;
+ }
+
+ // Extract the packet and return appropriately
+ transport_pkt *pkt = (transport_pkt *) pmt_u8vector_writeable_elements(v_pkt, n_bytes);
+
+ // The channel is used to find the port to pass the samples on
+ long channel = pkt->chan();
+ long payload_len = pkt->payload_len();
+ long port;
+
+ // Ignore packets which seem to have incorrect size or size 0
+ if(payload_len > pkt->max_payload() || payload_len == 0)
+ return;
+
+ // If the packet is a C/S packet, parse it separately
+ if(channel == 0x1f) {
+ parse_control_pkt(invocation_handle, pkt);
+ return;
+ }
+
+ if((port = rx_port_index(d_chaninfo_rx[channel].owner)) == -1)
+ return; // Don't know where to send the sample... possibility on abrupt close
+
+ pmt_t v_samples = pmt_make_u8vector(payload_len, 0);
+ uint8_t *samples = pmt_u8vector_writeable_elements(v_samples, ignore);
+
+ memcpy(samples, pkt->payload(), payload_len);
+
+ // Build a properties dictionary to store things such as the RSSI
+ pmt_t properties = pmt_make_dict();
+
+ pmt_dict_set(properties,
+ pmt_intern("rssi"),
+ pmt_from_long(pkt->rssi()));
+
+ if(pkt->overrun())
+ pmt_dict_set(properties,
+ pmt_intern("overrun"),
+ PMT_T);
+
+ if(pkt->underrun())
+ pmt_dict_set(properties,
+ pmt_intern("underrun"),
+ PMT_T);
+
+ d_rx[port]->send(s_response_recv_raw_samples,
+ pmt_list5(invocation_handle,
+ status,
+ v_samples,
+ pmt_from_long(pkt->timestamp()),
+ properties));
+ return;
+}
+
+void
+usrp_server::parse_control_pkt(pmt_t invocation_handle, transport_pkt *pkt)
+{
+
+ long payload_len = pkt->payload_len();
+ long curr_payload = 0;
+ long port;
+
+ // We dispatch based on the control packet type, however we can extract the
+ // opcode and the length immediately which is consistent in all responses.
+ //
+ // Since each control packet can have multiple responses, we keep reading the
+ // lengths of each subpacket until we reach the payload length.
+ while(curr_payload < payload_len) {
+
+ pmt_t sub_packet = pkt->read_subpacket(curr_payload);
+ pmt_t op_symbol = pmt_nth(0, sub_packet);
+
+ int len = pkt->cs_len(curr_payload);
+
+ if(verbose)
+ std::cout << "[USRP_SERVER] Parsing subpacket "
+ << op_symbol << " ... length " << len << std::endl;
+
+ //----------------- PING RESPONSE ------------------//
+ if(pmt_eq(op_symbol, s_op_ping_fixed_reply)) {
+
+ long srid = pmt_to_long(pmt_nth(1, sub_packet));
+ pmt_t pingval = pmt_nth(2, sub_packet);
+
+ long urid = d_rids[srid].user_rid;
+
+ if(verbose)
+ std::cout << "[USRP_SERVER] Found ping response "
+ << "("
+ << "URID: " << urid << ", "
+ << "SRID: " << srid << ", "
+ << "VAL: " << pingval
+ << ")\n";
+
+ // Do some bounds checking incase of bogus/corrupt responses
+ if(srid > D_MAX_RID)
+ return;
+
+ pmt_t owner = d_rids[srid].owner;
+
+ // FIXME: should be 1 response for all subpackets here ?
+ if((port = tx_port_index(owner)) != -1)
+ d_tx[port]->send(s_response_from_control_channel,
+ pmt_list4(invocation_handle,
+ PMT_T,
+ pmt_list2(s_op_ping_fixed_reply, // subp
+ pmt_list2(pmt_from_long(urid),
+ pingval)),
+ pmt_from_long(pkt->timestamp())));
+ }
+
+ //----------------- READ REG RESPONSE ------------------//
+ else if(pmt_eq(op_symbol, s_op_read_reg_reply)) {
+
+ long srid = pmt_to_long(pmt_nth(1, sub_packet));
+ pmt_t reg_num = pmt_nth(2, sub_packet);
+ pmt_t reg_val = pmt_nth(3, sub_packet);
+
+ long urid = d_rids[srid].user_rid;
+
+ if(verbose)
+ std::cout << "[USRP_SERVER] Found read register response "
+ << "("
+ << "URID: " << urid << ", "
+ << "SRID: " << srid << ", "
+ << "REG: " << reg_num << ", "
+ << "VAL: " << reg_val
+ << ")\n";
+
+ // Do some bounds checking to avoid seg faults
+ if(srid > D_MAX_RID)
+ return;
+
+ pmt_t owner = d_rids[srid].owner;
+
+ // FIXME: should be 1 response for all subpackets here ?
+ if((port = tx_port_index(owner)) != -1)
+ d_tx[port]->send(s_response_from_control_channel,
+ pmt_list4(invocation_handle,
+ PMT_T,
+ pmt_list2(s_op_read_reg_reply, // subp
+ pmt_list3(pmt_from_long(urid),
+ reg_num,
+ reg_val)),
+ pmt_from_long(pkt->timestamp())));
+ }
+
+ //------------------ I2C READ REPLY -------------------//
+ else if(pmt_eq(op_symbol, s_op_i2c_read_reply)) {
+
+ long srid = pmt_to_long(pmt_nth(1, sub_packet));
+ pmt_t i2c_addr = pmt_nth(2, sub_packet);
+ pmt_t i2c_data = pmt_nth(3, sub_packet);
+
+ long urid = d_rids[srid].user_rid;
+
+ if(verbose)
+ std::cout << "[USRP_SERVER] Found i2c read reply "
+ << "("
+ << "URID: " << urid << ", "
+ << "SRID: " << srid << ", "
+ << "Addr: " << i2c_addr << ", "
+ << "Data: " << i2c_data
+ << ")\n";
+
+ // Do some bounds checking to avoid seg faults
+ if(srid > D_MAX_RID)
+ return;
+
+ pmt_t owner = d_rids[srid].owner;
+
+ if((port = tx_port_index(owner)) != -1)
+ d_tx[port]->send(s_response_from_control_channel,
+ pmt_list4(invocation_handle,
+ PMT_T,
+ pmt_list2(s_op_i2c_read_reply,
+ pmt_list3(pmt_from_long(urid),
+ i2c_addr,
+ i2c_data)),
+ pmt_from_long(pkt->timestamp())));
+ }
+
+ //------------------ SPI READ REPLY -------------------//
+ else if(pmt_eq(op_symbol, s_op_spi_read_reply)) {
+
+ long srid = pmt_to_long(pmt_nth(1, sub_packet));
+ pmt_t spi_data = pmt_nth(2, sub_packet);
+
+ long urid = d_rids[srid].user_rid;
+
+ if(verbose)
+ std::cout << "[USRP_SERVER] Found SPI read reply "
+ << "("
+ << "URID: " << urid << ", "
+ << "SRID: " << srid << ", "
+ << "Data: " << spi_data
+ << ")\n";
+
+ // Bounds check the RID
+ if(srid > D_MAX_RID)
+ return;
+
+ pmt_t owner = d_rids[srid].owner;
+
+ if((port = tx_port_index(owner)) != -1)
+ d_tx[port]->send(s_response_from_control_channel,
+ pmt_list4(invocation_handle,
+ PMT_T,
+ pmt_list2(s_op_spi_read_reply,
+ pmt_list2(pmt_from_long(urid),
+ spi_data)),
+ pmt_from_long(pkt->timestamp())));
+ }
+
+ // Each subpacket has an unaccounted for 2 bytes which is the opcode
+ // and the length field
+ curr_payload += len + 2;
+
+ // All subpackets are 32-bit aligned
+ int align_offset = 4 - (curr_payload % 4);
+
+ if(align_offset != 4)
+ curr_payload += align_offset;
+ }
+}
+
+void
+usrp_server::recall_defer_queue()
+{
+
+ std::vector<mb_message_sptr> recall;
+
+ while(!d_defer_queue.empty()) {
+ recall.push_back(d_defer_queue.front());
+ d_defer_queue.pop();
}
- pkts[n_packets-1].set_end_of_burst(); // set the last packet's end of burst
+ // Parse the messages that were queued while waiting for an open response
+ for(int i=0; i < (int)recall.size(); i++)
+ handle_message(recall[i]);
+
+ return;
+}
+
+bool
+usrp_server::check_valid(mb_port_sptr port,
+ long channel,
+ std::vector<struct channel_info> &chan_info,
+ pmt_t signal_info)
+{
- // interface with the USRP to send the USB packet, since the memory is
- // contiguous, this should be a serious of memory copies to the bus, each being
- // USB_PKT_SIZE * MAX_PACKET_BURST bytes worth of data (given a full burst)
+ pmt_t response_signal = pmt_nth(0, signal_info);
+ pmt_t invocation_handle = pmt_nth(1, signal_info);
+
+ // not a valid channel number?
+ if(channel >= (long)chan_info.size() && channel != 0x1f) {
+ port->send(response_signal,
+ pmt_list2(invocation_handle,
+ s_err_channel_invalid));
+
+ if(verbose)
+ std::cout << "[USRP_SERVER] Invalid channel number for event "
+ << response_signal << std::endl;
+ return false;
+ }
+
+ // not the owner of the port?
+ if(chan_info[channel].owner != port->port_symbol()) {
+ port->send(response_signal,
+ pmt_list2(invocation_handle,
+ s_err_channel_permission_denied));
+
+ if(verbose)
+ std::cout << "[USRP_SERVER] Invalid permissions"
+ << " for " << response_signal
+ << " from " << port->port_symbol()
+ << " proper owner is " << chan_info[channel].owner
+ << " on channel " << channel
+ << " invocation " << invocation_handle
+ << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
+// Goes through the vector of RIDs and retreieves an
+// available one for use
+long
+usrp_server::next_rid()
+{
+ for(int i = 0; i < D_MAX_RID; i++)
+ if(pmt_eqv(d_rids[i].owner, PMT_NIL))
+ return i;
+
+ return -1;
}
REGISTER_MBLOCK_CLASS(usrp_server);
diff --git a/usrp/host/lib/inband/usrp_server.h b/usrp/host/lib/inband/usrp_server.h
index d2819cd66..81dceb1f4 100644
--- a/usrp/host/lib/inband/usrp_server.h
+++ b/usrp/host/lib/inband/usrp_server.h
@@ -23,21 +23,19 @@
#include <mb_mblock.h>
#include <vector>
+#include <queue>
+#include <fstream>
+#include <usrp_inband_usb_packet.h>
+
+typedef usrp_inband_usb_packet transport_pkt; // makes conversion to gigabit easy
/*!
- * \brief Implements the lowest-level mblock interface to the USRP
+ * \brief Implements the lowest-level mblock usb_interface to the USRP
*/
class usrp_server : public mb_mblock
{
public:
- enum error_codes {
- RQSTD_CAPACITY_UNAVAIL = 0,
- CHANNEL_UNAVAIL = 1,
- CHANNEL_INVALID = 2,
- PERMISSION_DENIED = 3
- };
-
// our ports
enum port_types {
RX_PORT = 0,
@@ -46,19 +44,49 @@ public:
static const int N_PORTS = 4;
std::vector<mb_port_sptr> d_tx, d_rx;
mb_port_sptr d_cs;
+ mb_port_sptr d_cs_usrp;
static const int D_USB_CAPACITY = 32 * 1024 * 1024;
static const int D_MAX_CHANNELS = 16;
long d_ntx_chan;
long d_nrx_chan;
+ // Keep track of the request IDs
+ struct rid_info {
+ pmt_t owner;
+ long user_rid;
+
+ rid_info() {
+ owner = PMT_NIL;
+ user_rid = 0;
+ }
+ };
+
+ static const long D_MAX_RID = 64;
+ std::vector<rid_info> d_rids;
+
struct channel_info {
- long assigned_capacity; // the capacity currently assignedby the channel
+ long assigned_capacity; // the capacity currently assignedby the channel
pmt_t owner; // port ID of the owner of the channel
+
+ channel_info() {
+ assigned_capacity = 0;
+ owner = PMT_NIL;
+ }
};
- struct channel_info d_chaninfo_tx[D_MAX_CHANNELS];
- struct channel_info d_chaninfo_rx[D_MAX_CHANNELS];
+ long d_rx_chan_mask; // A bitmask representing the channels in the
+ // receiving state
+
+ std::vector<struct channel_info> d_chaninfo_tx;
+ std::vector<struct channel_info> d_chaninfo_rx;
+
+ std::queue<mb_message_sptr> d_defer_queue;
+
+ bool d_defer;
+ bool d_opened;
+
+ bool d_fake_rx;
public:
usrp_server(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg);
@@ -71,12 +99,21 @@ protected:
static int max_capacity() { return D_USB_CAPACITY; }
private:
- void handle_cmd_allocate_channel(pmt_t port_id, pmt_t data);
- void handle_cmd_deallocate_channel(pmt_t port_id, pmt_t data);
- void handle_cmd_xmit_raw_frame(pmt_t data);
+ void handle_cmd_allocate_channel(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data);
+ void handle_cmd_deallocate_channel(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data);
+ void handle_cmd_xmit_raw_frame(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data);
+ void handle_cmd_to_control_channel(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data);
+ void handle_cmd_start_recv_raw_samples(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data);
+ void handle_cmd_stop_recv_raw_samples(mb_port_sptr port, std::vector<struct channel_info> &chan_info, pmt_t data);
int rx_port_index(pmt_t port_id);
int tx_port_index(pmt_t port_id);
long current_capacity_allocation();
+ void recall_defer_queue();
+ void reset_channels();
+ void handle_response_usrp_read(pmt_t data);
+ 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();
};
#endif /* INCLUDED_USRP_SERVER_H */
diff --git a/usrp/host/lib/inband/usrp_server.mbh b/usrp/host/lib/inband/usrp_server.mbh
index e96c3f1ac..06ec4b996 100644
--- a/usrp/host/lib/inband/usrp_server.mbh
+++ b/usrp/host/lib/inband/usrp_server.mbh
@@ -40,9 +40,8 @@
;; mechanism to match asynchronous responses with the commands that
;; generated them.
;;
-;; status is either #t, indicating success, or a pair containing
-;; (status-code . message), where status-code is a symbol and message
-;; is a string.
+;; status is either #t, indicating success, or a symbol indicating an error.
+;; All symbol's names shall begin with %error-
;; ----------------------------------------------------------------
@@ -128,7 +127,7 @@
(:incoming
- (response-from-control-channel invocation-handle status list-of-subpackets)
+ (response-from-control-channel invocation-handle status list-of-subpackets timestamp)
)
)
@@ -248,9 +247,9 @@
(:incoming
(response-open invocation-handle status)
(response-close invocation-handle status)
- (response-max-capacity invocation-handle capacity)
- (response-ntx-chan invocation-handle ntx-chan)
- (response-nrx-chan invocation-handle nrx-chan)
- (response-current-capacity-allocation invocation-handle capacity)
+ (response-max-capacity invocation-handle status capacity)
+ (response-ntx-chan invocation-handle status ntx-chan)
+ (response-nrx-chan invocation-handle status nrx-chan)
+ (response-current-capacity-allocation invocation-handle status capacity)
)
)
diff --git a/usrp/host/lib/inband/usrp_tx.cc b/usrp/host/lib/inband/usrp_tx.cc
new file mode 100644
index 000000000..a7a5e4a89
--- /dev/null
+++ b/usrp/host/lib/inband/usrp_tx.cc
@@ -0,0 +1,138 @@
+/* -*- 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 <usrp_tx.h>
+#include <iostream>
+#include <usb.h>
+#include <mb_class_registry.h>
+#include <usrp_inband_usb_packet.h>
+#include <fpga_regs_common.h>
+#include <usrp_standard.h>
+#include <stdio.h>
+
+#include <symbols_usrp_tx_cs.h>
+
+typedef usrp_inband_usb_packet transport_pkt;
+
+static const bool verbose = false;
+
+usrp_tx::usrp_tx(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg)
+ : mb_mblock(rt, instance_name, user_arg),
+ d_disk_write(false)
+{
+ d_cs = define_port("cs", "usrp-tx-cs", true, mb_port::EXTERNAL);
+
+ //d_disk_write=true;
+
+ if(d_disk_write) {
+ d_ofile.open("tx_data.dat",std::ios::binary|std::ios::out);
+ d_cs_ofile.open("tx_cs.dat",std::ios::binary|std::ios::out);
+ }
+}
+
+usrp_tx::~usrp_tx()
+{
+ if(d_disk_write) {
+ d_ofile.close();
+ d_cs_ofile.close();
+ }
+}
+
+void
+usrp_tx::initial_transition()
+{
+
+}
+
+void
+usrp_tx::handle_message(mb_message_sptr msg)
+{
+ pmt_t event = msg->signal();
+ pmt_t port_id = msg->port_id();
+ pmt_t data = msg->data();
+
+ // 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_eqv(event, s_cmd_usrp_tx_write))
+ write(data);
+ }
+}
+
+void
+usrp_tx::write(pmt_t data)
+{
+ pmt_t invocation_handle = pmt_nth(0, data);
+ pmt_t channel = pmt_nth(1, data);
+ pmt_t v_packets = pmt_nth(2, data);
+ d_utx = boost::any_cast<usrp_standard_tx *>(pmt_any_ref(pmt_nth(3, data)));
+
+ size_t n_bytes;
+ bool underrun; // this will need to go, as it is taken care of in the packet headers
+
+ transport_pkt *pkts = (transport_pkt *) pmt_u8vector_writeable_elements(v_packets, n_bytes);
+
+ int ret = d_utx->write (pkts, n_bytes, &underrun);
+
+ if (0 && underrun)
+ fprintf(stderr, "uU");
+
+ if (ret == (int) n_bytes) {
+ if (verbose)
+ std::cout << "[usrp_server] Write of " << n_bytes << " successful\n";
+ // need to respond with the channel so the USRP server knows who to forward the result of
+ // the write to by looking up the owner of the channel
+ d_cs->send(s_response_usrp_tx_write,
+ pmt_list3(invocation_handle, PMT_T, channel));
+ }
+ else {
+ if (verbose)
+ std::cout << "[usrp_server] Error writing " << n_bytes << " bytes to USB bus\n";
+ d_cs->send(s_response_usrp_tx_write,
+ pmt_list3(invocation_handle, PMT_F, channel));
+ }
+
+ long n_packets =
+ static_cast<long>(std::ceil(n_bytes / (double)transport_pkt::max_pkt_size()));
+
+ for(int i=0; i < n_packets; i++) {
+
+ if(d_disk_write) {
+ if(pkts[i].chan() == 0x1f)
+ 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());
+
+ d_cs_ofile.flush();
+ d_ofile.flush();
+ }
+ }
+
+
+ return;
+}
+
+REGISTER_MBLOCK_CLASS(usrp_tx);
diff --git a/usrp/host/lib/inband/usrp_tx.h b/usrp/host/lib/inband/usrp_tx.h
new file mode 100644
index 000000000..546a26afc
--- /dev/null
+++ b/usrp/host/lib/inband/usrp_tx.h
@@ -0,0 +1,53 @@
+/* -*- 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_USRP_TX_H
+#define INCLUDED_USRP_TX_H
+
+#include <mb_mblock.h>
+#include <fstream>
+
+class usrp_standard_tx;
+
+/*!
+ * \brief Implements the low level usb interface to the USRP
+ */
+class usrp_tx : public mb_mblock
+{
+ mb_port_sptr d_cs;
+ usrp_standard_tx *d_utx;
+
+ bool d_disk_write;
+ std::ofstream d_ofile;
+ std::ofstream d_cs_ofile;
+
+ public:
+ usrp_tx(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg);
+ ~usrp_tx();
+ void initial_transition();
+ void handle_message(mb_message_sptr msg);
+
+ private:
+ void write(pmt_t data);
+};
+
+
+#endif /* INCLUDED_USRP_TX_H */
+
diff --git a/usrp/host/lib/inband/usrp_tx_stub.cc b/usrp/host/lib/inband/usrp_tx_stub.cc
new file mode 100644
index 000000000..7a9876322
--- /dev/null
+++ b/usrp/host/lib/inband/usrp_tx_stub.cc
@@ -0,0 +1,344 @@
+/* -*- 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 <iostream>
+#include <vector>
+#include <usb.h>
+#include <mb_class_registry.h>
+#include <usrp_tx_stub.h>
+#include <usrp_inband_usb_packet.h>
+#include <fpga_regs_common.h>
+#include "usrp_standard.h"
+#include <stdio.h>
+#include <fstream>
+#include <usrp_rx_stub.h>
+
+#include <symbols_usrp_tx_cs.h>
+
+typedef usrp_inband_usb_packet transport_pkt;
+
+static const bool verbose = false;
+
+usrp_tx_stub::usrp_tx_stub(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg)
+ : mb_mblock(rt, instance_name, user_arg),
+ d_disk_write(false)
+{
+ d_cs = define_port("cs", "usrp-tx-cs", true, mb_port::EXTERNAL);
+
+ //d_disk_write=true;
+
+ if(d_disk_write) {
+ d_ofile.open("tx_stub_data.dat",std::ios::binary|std::ios::out);
+ d_cs_ofile.open("tx_stub_cs.dat",std::ios::binary|std::ios::out);
+ }
+}
+
+usrp_tx_stub::~usrp_tx_stub()
+{
+ if(d_disk_write) {
+ d_ofile.close();
+ d_cs_ofile.close();
+ }
+}
+
+void
+usrp_tx_stub::initial_transition()
+{
+
+}
+
+void
+usrp_tx_stub::handle_message(mb_message_sptr msg)
+{
+ pmt_t event = msg->signal();
+ pmt_t port_id = msg->port_id();
+ pmt_t data = msg->data();
+
+ // 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_eqv(event, s_cmd_usrp_tx_write))
+ write(data);
+ }
+}
+
+void
+usrp_tx_stub::write(pmt_t data)
+{
+ pmt_t invocation_handle = pmt_nth(0, data);
+ pmt_t channel = pmt_nth(1, data);
+ pmt_t v_packets = pmt_nth(2, data);
+ d_utx = boost::any_cast<usrp_standard_tx *>(pmt_any_ref(pmt_nth(3, data)));
+
+ size_t n_bytes;
+
+ transport_pkt *pkts = (transport_pkt *) pmt_u8vector_writeable_elements(v_packets, n_bytes);
+ long n_packets = static_cast<long>(std::ceil(n_bytes / (double)transport_pkt::max_pkt_size()));
+
+ // Parse the packets looking for C/S packets and dump them to a disk if
+ // necessary
+ for(long i=0; i<n_packets; i++) {
+
+ if(d_disk_write) {
+ if(pkts[i].chan() == 0x1f)
+ 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());
+
+ d_cs_ofile.flush();
+ d_ofile.flush();
+ }
+
+ if(pkts[i].chan() == 0x1f)
+ parse_cs(invocation_handle, pkts[i]);
+ }
+
+ d_cs->send(s_response_usrp_tx_write,
+ pmt_list3(invocation_handle, PMT_T, channel));
+
+ return;
+}
+
+void
+usrp_tx_stub::parse_cs(pmt_t invocation_handle, transport_pkt pkt)
+{
+
+ long payload_len = pkt.payload_len();
+ long curr_payload = 0;
+
+ size_t ignore;
+
+ // There is the possibility that the responses for a single USB packet full of
+ // CS packets will not fit back in a single USB packet, considering some
+ // responses are greater than their commands (read registers).
+ new_packet:
+ pmt_t v_pkt = pmt_make_u8vector(sizeof(transport_pkt), 0);
+
+ transport_pkt *q_pkt =
+ (transport_pkt *) pmt_u8vector_writeable_elements(v_pkt, ignore);
+
+ q_pkt->set_header(0, 0x1f, 0, 0);
+ q_pkt->set_timestamp(0xffffffff);
+
+ // We dispatch based on the control packet type, however we can extract the
+ // opcode and the length immediately which is consistent in all responses.
+ //
+ // Since each control packet can have multiple responses, we keep reading the
+ // lengths of each subpacket until we reach the payload length.
+ while(curr_payload < payload_len) {
+
+ pmt_t sub_packet = pkt.read_subpacket(curr_payload);
+ pmt_t op_symbol = pmt_nth(0, sub_packet);
+
+ int len = pkt.cs_len(curr_payload);
+
+ if(verbose)
+ std::cout << "[USRP_TX_STUB] Parsing subpacket "
+ << op_symbol << " ... length " << len << std::endl;
+
+ //----------------- PING FIXED ------------------//
+ if(pmt_eq(op_symbol, s_op_ping_fixed)) {
+
+ long rid = pmt_to_long(pmt_nth(1, sub_packet));
+ long pingval = pmt_to_long(pmt_nth(2, sub_packet));
+
+ // Generate a reply and put it in the queue for the RX stub to read
+ if(!q_pkt->cs_ping_reply(rid, pingval))
+ goto new_packet;
+
+ if(verbose)
+ std::cout << "[USRP_TX_STUB] Generated ping response "
+ << "("
+ << "RID: " << rid << ", "
+ << "VAL: " << pingval
+ << ")\n";
+ }
+
+ //----------------- READ REG ------------------//
+ if(pmt_eq(op_symbol, s_op_read_reg)) {
+
+ long rid = pmt_to_long(pmt_nth(1, sub_packet));
+ long reg_num = pmt_to_long(pmt_nth(2, sub_packet));
+ long reg_val = 0xdeef;
+
+ // Generate a reply and put it in the queue for the RX stub to read
+ if(!q_pkt->cs_read_reg_reply(rid, reg_num, reg_val))
+ goto new_packet;
+
+ if(verbose)
+ std::cout << "[USRP_TX_STUB] Generated read register response "
+ << "("
+ << "RID: " << rid << ", "
+ << "REG: " << reg_num << ", "
+ << "VAL: " << reg_val
+ << ")\n";
+ }
+
+ //----------------- DELAY ------------------//
+ if(pmt_eq(op_symbol, s_op_delay)) {
+
+ long ticks = pmt_to_long(pmt_nth(1, sub_packet));
+
+ if(verbose)
+ std::cout << "[USRP_TX_STUB] Received delay command "
+ << "("
+ << "Ticks: " << ticks
+ << ")\n";
+ }
+
+ //----------------- WRITE REG ------------------//
+ if(pmt_eq(op_symbol, s_op_write_reg)) {
+
+ pmt_t reg_num = pmt_nth(1, sub_packet);
+ pmt_t reg_val = pmt_nth(2, sub_packet);
+
+ if(verbose)
+ std::cout << "[USRP_TX_STUB] Received write register command "
+ << "("
+ << "RegNum: " << reg_num << ", "
+ << "Val: " << reg_val
+ << ")\n";
+ }
+
+ //----------------- WRITE REG MASK ---------------//
+ if(pmt_eq(op_symbol, s_op_write_reg_masked)) {
+
+ pmt_t reg_num = pmt_nth(1, sub_packet);
+ pmt_t reg_val = pmt_nth(2, sub_packet);
+ pmt_t mask = pmt_nth(3, sub_packet);
+
+ if(verbose)
+ std::cout << "[USRP_TX_STUB] Received write register command "
+ << "("
+ << "RegNum: " << reg_num << ", "
+ << "Val: " << reg_val << ", "
+ << "Mask: " << mask
+ << ")\n";
+ }
+
+ //---------------- I2C WRITE ------------------//
+ if(pmt_eq(op_symbol, s_op_i2c_write)) {
+ pmt_t i2c_addr = pmt_nth(1, sub_packet);
+ pmt_t i2c_data = pmt_nth(2, sub_packet);
+
+ if(verbose)
+ std::cout << "[USRP_TX_STUB] Received i2c write command "
+ << "("
+ << "Addr: " << i2c_addr << ", "
+ << "Data: " << i2c_data
+ << ")\n";
+ }
+
+ //---------------- I2C READ ------------------//
+ if(pmt_eq(op_symbol, s_op_i2c_read)) {
+ long rid = pmt_to_long(pmt_nth(1, sub_packet));
+ long i2c_addr = pmt_to_long(pmt_nth(2, sub_packet));
+ long i2c_bytes = pmt_to_long(pmt_nth(3, sub_packet));
+
+ // Create data to place as a response, filled with 0xff
+ size_t ignore;
+ pmt_t i2c_data = pmt_make_u8vector(i2c_bytes, 0xff);
+ uint8_t *w_data = (uint8_t *) pmt_u8vector_writeable_elements(i2c_data, ignore);
+
+ // Generate a reply and put it in the queue for the RX stub to read
+ if(!q_pkt->cs_i2c_read_reply(rid, i2c_addr, w_data, i2c_bytes))
+ goto new_packet;
+
+ if(verbose)
+ std::cout << "[USRP_TX_STUB] Received i2c read "
+ << "("
+ << "RID: " << rid << ", "
+ << "Addr: " << i2c_addr << ", "
+ << "Bytes: " << i2c_bytes
+ << ")\n";
+ }
+
+ //---------------- SPI WRITE ------------------//
+ if(pmt_eq(op_symbol, s_op_spi_write)) {
+ long enables = pmt_to_long(pmt_nth(1, sub_packet));
+ long format = pmt_to_long(pmt_nth(2, sub_packet));
+ long opt = pmt_to_long(pmt_nth(3, sub_packet));
+ pmt_t data = pmt_nth(4, sub_packet);
+
+ if(verbose)
+ std::cout << "[USRP_TX_STUB] Received spi write command "
+ << "("
+ << "Enables: " << enables << ", "
+ << "Format: " << format << ", "
+ << "Options: " << opt << ", "
+ << "Data: " << data
+ << ")\n";
+ }
+
+ //---------------- SPI READ ------------------//
+ if(pmt_eq(op_symbol, s_op_spi_read)) {
+ long rid = pmt_to_long(pmt_nth(1, sub_packet));
+ long enables = pmt_to_long(pmt_nth(2, sub_packet));
+ long format = pmt_to_long(pmt_nth(3, sub_packet));
+ long opt = pmt_to_long(pmt_nth(4, sub_packet));
+ long n_bytes = pmt_to_long(pmt_nth(5, sub_packet));
+
+ // Create data to place as a fake response
+ size_t ignore;
+ pmt_t spi_data = pmt_make_u8vector(n_bytes, 0xff);
+ uint8_t *w_data = (uint8_t *) pmt_u8vector_writeable_elements(spi_data, ignore);
+
+ // Generate a reply and put it in the queue for the RX stub to read
+ if(!q_pkt->cs_spi_read_reply(rid, w_data, n_bytes))
+ goto new_packet;
+
+ if(verbose)
+ std::cout << "[USRP_TX_STUB] Received spi read command "
+ << "("
+ << "RID: " << rid << ", "
+ << "Enables: " << enables << ", "
+ << "Format: " << format << ", "
+ << "Options: " << opt << ", "
+ << "Bytes: " << n_bytes
+ << ")\n";
+
+ }
+
+ // Each subpacket has an unaccounted for 2 bytes which is the opcode
+ // and the length field
+ curr_payload += len + 2;
+
+ // All subpackets are 32-bit aligned
+ int align_offset = 4 - (curr_payload % 4);
+
+ if(align_offset != 4)
+ curr_payload += align_offset;
+
+ }
+
+ // If the packet has data in the payload, it needs queued
+ if(q_pkt->payload_len() > 0)
+ d_cs_queue.push(pmt_list2(invocation_handle, v_pkt));
+
+ return;
+}
+
+REGISTER_MBLOCK_CLASS(usrp_tx_stub);
diff --git a/usrp/host/lib/inband/usrp_tx_stub.h b/usrp/host/lib/inband/usrp_tx_stub.h
new file mode 100644
index 000000000..52294beec
--- /dev/null
+++ b/usrp/host/lib/inband/usrp_tx_stub.h
@@ -0,0 +1,61 @@
+/* -*- 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_USRP_TX_STUB_H
+#define INCLUDED_USRP_TX_STUB_H
+
+#include <mb_mblock.h>
+#include <vector>
+#include "usrp_standard.h"
+#include <fstream>
+#include <usrp_inband_usb_packet.h>
+
+typedef usrp_inband_usb_packet transport_pkt;
+
+/*!
+ * \brief Implements the low level usb interface to the USRP
+ */
+class usrp_tx_stub : public mb_mblock
+{
+ public:
+
+ mb_port_sptr d_cs;
+ usrp_standard_tx* d_utx;
+
+ std::ofstream d_ofile;
+ std::ofstream d_cs_ofile;
+
+ bool d_disk_write;
+
+ public:
+ usrp_tx_stub(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg);
+ ~usrp_tx_stub();
+ void initial_transition();
+ void handle_message(mb_message_sptr msg);
+
+ private:
+ void write(pmt_t data);
+ void parse_cs(pmt_t invocation_handle, transport_pkt pkt);
+
+};
+
+
+#endif /* INCLUDED_USRP_TX_STUB_H */
+
diff --git a/usrp/host/lib/inband/usrp_usb_interface.cc b/usrp/host/lib/inband/usrp_usb_interface.cc
new file mode 100644
index 000000000..b2ccba81b
--- /dev/null
+++ b/usrp/host/lib/inband/usrp_usb_interface.cc
@@ -0,0 +1,431 @@
+/* -*- 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 <usrp_usb_interface.h>
+
+#include <iostream>
+#include <vector>
+#include <usb.h>
+#include <mb_class_registry.h>
+#include <usrp_inband_usb_packet.h>
+#include <fpga_regs_common.h>
+#include "usrp_rx.h"
+#include <usrp_rx_stub.h>
+#include "usrp_tx.h"
+#include "usrp_standard.h"
+#include <stdio.h>
+
+typedef usrp_inband_usb_packet transport_pkt;
+
+#include <symbols_usrp_interface_cs.h>
+#include <symbols_usrp_tx_cs.h>
+#include <symbols_usrp_rx_cs.h>
+static pmt_t s_shutdown = pmt_intern("%shutdown");
+
+static const bool verbose = false;
+
+
+
+// need to take number of TX and RX channels as parameter
+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_interp_tx(16),
+ d_interp_rx(16),
+ d_rf_freq(10e6),
+ d_rbf("inband_tx_rx.rbf")
+{
+ // Dictionary for arguments to all of the components
+ pmt_t usrp_dict = user_arg;
+
+ // Default TX/RX interface
+ std::string tx_interface = "usrp_tx";
+ std::string rx_interface = "usrp_rx";
+
+ if (pmt_is_dict(usrp_dict)) {
+
+ // The 'fake-usrp' key enables the TX and RX stubs if PMT_T
+ if(pmt_t fake_usrp = pmt_dict_ref(usrp_dict,
+ pmt_intern("fake-usrp"),
+ PMT_NIL)) {
+ if(pmt_eqv(fake_usrp, PMT_T)) {
+ tx_interface = "usrp_tx_stub";
+ rx_interface = "usrp_rx_stub";
+ d_fake_usrp=true;
+ }
+ }
+
+ // Read the TX interpolations
+ if(pmt_t interp_tx = pmt_dict_ref(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 interpolations
+ if(pmt_t interp_rx = pmt_dict_ref(usrp_dict,
+ pmt_intern("interp-rx"),
+ PMT_NIL)) {
+ if(!pmt_eqv(interp_rx, PMT_NIL))
+ d_interp_rx = pmt_to_long(interp_rx);
+ }
+
+ // Read the RBF
+ if(pmt_t rbf = pmt_dict_ref(usrp_dict,
+ pmt_intern("rbf"),
+ PMT_NIL)) {
+ if(!pmt_eqv(rbf, PMT_NIL))
+ d_rbf = pmt_symbol_to_string(rbf);
+ }
+
+ // The RF center frequency
+ if(pmt_t rf_freq = pmt_dict_ref(usrp_dict,
+ pmt_intern("rf-freq"),
+ PMT_NIL)) {
+ if(!pmt_eqv(rf_freq, PMT_NIL))
+ d_rf_freq = pmt_to_long(rf_freq);
+ }
+ }
+
+ if (verbose) {
+ std::cout << "[USRP_USB_INTERFACE] Setting USRP RBF to "
+ << d_rbf << std::endl;
+
+ std::cout << "[USRP_USB_INTERFACE] Setting TX interpolation to "
+ << d_interp_tx << std::endl;
+
+ std::cout << "[USRP_USB_INTERFACE] Setting RX interpolation to "
+ << d_interp_rx << std::endl;
+
+ std::cout << "[USRP_USB_INTERFACE] Using TX interface: "
+ << tx_interface << "\n";
+
+ std::cout << "[USRP_USB_INTERFACE] Using RX interface: "
+ << rx_interface << "\n";
+
+ }
+
+ d_cs = define_port("cs", "usrp-interface-cs", true, mb_port::EXTERNAL);
+ d_rx_cs = define_port("rx_cs", "usrp-rx-cs", false, mb_port::INTERNAL);
+ 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);
+ connect("self", "rx_cs", "rx", "cs");
+ connect("self", "tx_cs", "tx", "cs");
+
+ // FIX ME: the code should query the FPGA to retrieve the number of channels and such
+ d_ntx_chan = 2;
+ d_nrx_chan = 2;
+
+ 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()
+{
+
+}
+
+void
+usrp_usb_interface::initial_transition()
+{
+
+}
+
+void
+usrp_usb_interface::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 invocation_handle;
+
+ if (pmt_eq(event, s_shutdown)) // ignore (for now)
+ return;
+
+ //------------- CONTROL / STATUS -------------//
+ if (pmt_eq(port_id, d_cs->port_symbol())) {
+
+ //------------ OPEN --------------//
+ if (pmt_eq(event, s_cmd_usrp_open)){
+ handle_cmd_open(data);
+ return;
+ }
+ //----------- CLOSE -------------//
+ else if (pmt_eq(event, s_cmd_usrp_close)) {
+ handle_cmd_close(data);
+ return;
+ }
+ //---------- NTX CHAN ----------//
+ else if (pmt_eq(event, s_cmd_usrp_ntx_chan)) {
+ invocation_handle = pmt_nth(0, data);
+ d_cs->send(s_response_usrp_ntx_chan,
+ pmt_list2(invocation_handle,
+ pmt_from_long(d_ntx_chan)));
+ return;
+ }
+ //---------- NRX CHAN ----------//
+ else if (pmt_eq(event, s_cmd_usrp_nrx_chan)) {
+ invocation_handle = pmt_nth(0, data);
+ d_cs->send(s_response_usrp_nrx_chan,
+ pmt_list2(invocation_handle,
+ pmt_from_long(d_nrx_chan)));
+ return;
+ }
+ //------------ WRITE -----------//
+ else if(pmt_eq(event, s_cmd_usrp_write)) {
+ handle_cmd_write(data);
+ return;
+ }
+ //-------- START READING --------//
+ else if(pmt_eq(event, s_cmd_usrp_start_reading)) {
+ handle_cmd_start_reading(data);
+ return;
+ }
+ //-------- STOP READING --------//
+ else if(pmt_eq(event, s_cmd_usrp_stop_reading)) {
+ handle_cmd_stop_reading(data);
+ return;
+ }
+
+ goto unhandled;
+ }
+
+ //---------------- RX ------------------//
+ if (pmt_eq(port_id, d_rx_cs->port_symbol())) {
+
+ // Relay reads back up
+ if(pmt_eq(event, s_response_usrp_rx_read)) {
+ d_cs->send(s_response_usrp_read, data);
+ return;
+ }
+
+ goto unhandled;
+ }
+
+ //---------------- TX ------------------//
+ if (pmt_eq(port_id, d_tx_cs->port_symbol())) {
+
+ if(pmt_eq(event, s_response_usrp_tx_write)) {
+
+ pmt_t invocation_handle = pmt_nth(0, data);
+ pmt_t status = pmt_nth(1, data);
+ pmt_t channel = pmt_nth(2, data);
+
+ d_cs->send(s_response_usrp_write,
+ pmt_list3(invocation_handle,
+ status,
+ channel));
+
+ return;
+ }
+
+ goto unhandled;
+ }
+
+ unhandled:
+ std::cout << "[USRP_USB_INTERFACE] unhandled msg: " << msg << std::endl;
+}
+
+void
+usrp_usb_interface::handle_cmd_open(pmt_t data)
+{
+ pmt_t invocation_handle = pmt_nth(0, data);
+ long which_usrp = pmt_to_long(pmt_nth(1, data));
+ pmt_t reply_data;
+
+ if(d_fake_usrp) {
+ d_cs->send(s_response_usrp_open, pmt_list2(invocation_handle, PMT_T));
+ return;
+ }
+
+ if (verbose)
+ std::cout << "[USRP_USB_INTERFACE] Handling open request for USRP " << which_usrp << "\n";
+
+ // Open up a standard RX and TX for communication with the USRP
+
+ d_utx = usrp_standard_tx::make(which_usrp,
+ d_interp_tx,
+ 1, // 1 channel
+ -1, // mux
+ 4096, // USB block size
+ 16, // nblocks for async transfers
+ d_rbf
+ );
+
+ if(d_utx==0) {
+ if (verbose)
+ std::cout << "[USRP_USB_INTERFACE] Failed to open TX\n";
+ reply_data = pmt_list2(invocation_handle, PMT_F);
+ d_cs->send(s_response_usrp_open, reply_data);
+ return;
+ }
+
+ if(!d_utx->set_tx_freq (0,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);
+ d_cs->send(s_response_usrp_open, reply_data);
+ return;
+ }
+
+ d_utx->start();
+
+ if (verbose)
+ std::cout << "[USRP_USB_INTERFACE] Setup TX channel\n";
+
+ d_urx =
+ usrp_standard_rx::make (which_usrp,
+ d_interp_rx,
+ 1, // nchan
+ -1, // mux
+ 0, // set blank mode to start
+ 4096, // USB block size
+ 16, // number of blocks for async transfers
+ d_rbf);
+
+ if(!d_urx) {
+ if (verbose)
+ std::cout << "[usrp_server] Failed to open RX\n";
+ reply_data = pmt_list2(invocation_handle, PMT_F);
+ d_cs->send(s_response_usrp_open, reply_data);
+ return;
+ }
+
+ if(!d_urx->set_rx_freq (0, 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);
+// }
+ }
+
+ if (verbose)
+ std::cout << "[USRP_USB_INTERFACE] Setup RX channel\n";
+
+ d_cs->send(s_response_usrp_open, pmt_list2(invocation_handle, PMT_T));
+}
+
+void
+usrp_usb_interface::handle_cmd_write(pmt_t data)
+{
+ pmt_t invocation_handle = pmt_nth(0, data);
+ pmt_t channel = pmt_nth(1, data);
+ pmt_t pkts = pmt_nth(2, data);
+
+ pmt_t tx_handle = pmt_make_any(d_utx);
+
+ d_tx_cs->send(s_cmd_usrp_tx_write,
+ pmt_list4(invocation_handle,
+ channel,
+ pkts,
+ tx_handle));
+
+ return;
+}
+
+void
+usrp_usb_interface::handle_cmd_start_reading(pmt_t data)
+{
+ pmt_t invocation_handle = pmt_nth(0, data);
+
+ if(verbose)
+ std::cout << "[USRP_USB_INTERFACE] Starting RX...\n";
+
+ if(!d_fake_usrp)
+ d_urx->start();
+
+ pmt_t rx_handle = pmt_make_any(d_urx);
+
+ d_rx_cs->send(s_cmd_usrp_rx_start_reading, pmt_list2(PMT_NIL, rx_handle));
+
+ return;
+}
+
+void
+usrp_usb_interface::handle_cmd_stop_reading(pmt_t data)
+{
+ pmt_t invocation_handle = pmt_nth(0, data);
+
+ if(!d_fake_usrp) {
+ if(verbose)
+ std::cout << "[USRP_USB_INTERFACE] Stopping RX...\n";
+ 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
+ }
+
+ return;
+}
+
+void
+usrp_usb_interface::handle_cmd_close(pmt_t data)
+{
+ pmt_t invocation_handle = pmt_nth(0, data);
+
+ if(d_fake_usrp) {
+ d_cs->send(s_response_usrp_close, pmt_list2(invocation_handle, PMT_T));
+ return;
+ }
+
+ if (verbose)
+ std::cout << "[USRP_USB_INTERFACE] Handling close request for USRP\n";
+
+ delete d_utx;
+ d_utx = 0;
+
+ delete d_urx;
+ d_urx = 0;
+
+ d_cs->send(s_response_usrp_close, pmt_list2(invocation_handle, PMT_T));
+
+ shutdown_all(PMT_T);
+}
+
+
+REGISTER_MBLOCK_CLASS(usrp_usb_interface);
diff --git a/usrp/host/lib/inband/usrp_usb_interface.h b/usrp/host/lib/inband/usrp_usb_interface.h
new file mode 100644
index 000000000..42cda7af1
--- /dev/null
+++ b/usrp/host/lib/inband/usrp_usb_interface.h
@@ -0,0 +1,72 @@
+/* -*- 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_USRP_USB_INTERFACE_H
+#define INCLUDED_USRP_USB_INTERFACE_H
+
+#include <mb_mblock.h>
+#include <vector>
+#include "usrp_standard.h"
+
+/*!
+ * \brief Implements the low level usb interface to the USRP
+ */
+class usrp_usb_interface : public mb_mblock
+{
+ public:
+
+ usrp_standard_tx* d_utx;
+ usrp_standard_rx* d_urx;
+
+ mb_port_sptr d_cs;
+ mb_port_sptr d_rx_cs;
+ mb_port_sptr d_tx_cs;
+
+ long d_ntx_chan;
+ long d_nrx_chan;
+
+ long d_fpga_debug;
+
+ bool d_fake_usrp;
+
+ long d_interp_tx;
+ long d_interp_rx;
+
+ long d_rf_freq;
+
+ std::string d_rbf;
+
+ public:
+ usrp_usb_interface(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg);
+ ~usrp_usb_interface();
+ void initial_transition();
+ void handle_message(mb_message_sptr msg);
+
+ private:
+ void handle_cmd_open(pmt_t data);
+ void handle_cmd_close(pmt_t data);
+ void handle_cmd_write(pmt_t data);
+ void handle_cmd_start_reading(pmt_t data);
+ void handle_cmd_stop_reading(pmt_t data);
+
+};
+
+
+#endif /* INCLUDED_USRP_USB_INTERFACE_H */