mirror of https://gerrit.osmocom.org/libusrp
Merged features/inband -r4812:5218 into trunk. This group of changes
includes: * working stand-alone mblock code * work-in-progress on usrp inband signaling usrp now depends on mblock, and guile is a dependency. git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@5221 221aa14e-8319-0410-a670-987f0aec2ac5
This commit is contained in:
parent
071e2f6d1b
commit
87a72fff96
|
@ -18,241 +18,6 @@
|
|||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
|
||||
This is preliminary design document on the organization of the host
|
||||
component of the USRP inband signaling implementation over USB.
|
||||
|
||||
Assumptions: we'll have a single usrp_usb_daemon, implemented as an
|
||||
mblock, that will provide the high-level message based interface to
|
||||
the USRP. The daemon will handle all resource allocation, muxing and
|
||||
demuxing for the control and status messages from multiple clients.
|
||||
|
||||
The underlying cross-process IPC mechanism is not yet specified.
|
||||
All communication will be via messages.
|
||||
|
||||
The external interface to the usrp_usb_daemon will consist of two sets
|
||||
of replicated ports, one set for the transmit, and one set for
|
||||
receive.
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
// Protocol class usrp_usb_common
|
||||
// Defined from client's point-of-view
|
||||
//
|
||||
// This protocol class is shared by the usrp_usb_tx and usrp_usb_rx
|
||||
// protocol classes
|
||||
|
||||
// outgoing:
|
||||
|
||||
cmd_allocate_channel(invocation_handle, channel, capacity_reservation)
|
||||
|
||||
invocation_handle
|
||||
Type Handle
|
||||
Use The identifier provided by the client to tag the method invocation.
|
||||
The identifier will be returned with the response, to provide
|
||||
the client with a mechanism to match asynchronous responses with
|
||||
commands that generated them.
|
||||
|
||||
channel
|
||||
Type integer
|
||||
Use Specifies the Tx channel to allocate
|
||||
|
||||
capacity_reservation
|
||||
Type float, units are bytes/s
|
||||
Use Specifies the number of bytes/s of USB capacity to reserve for
|
||||
this channel.
|
||||
|
||||
|
||||
// incoming:
|
||||
|
||||
response_allocate_channel(invocation_handle, status)
|
||||
|
||||
Type Handle
|
||||
Use The identifier provided by the client in the prompting invocation.
|
||||
The identifier is returned with the response, so that the
|
||||
client has a mechanism to match asynchronous responses with
|
||||
commands that generated them. The value of the invocation_handle
|
||||
is opaque to the server, and is not required by the server to be unique.
|
||||
|
||||
Type Status
|
||||
Use Contains the status code for the operation, per FIXME, and
|
||||
an optional message.
|
||||
|
||||
Preconditions:
|
||||
a) None
|
||||
|
||||
Postconditions:
|
||||
a) If successful, the requested channel and USB capacity are
|
||||
allocated for the client's exclusive use.
|
||||
|
||||
|
||||
// outgoing:
|
||||
|
||||
cmd_deallocate_channel(invocation_handle, channel)
|
||||
|
||||
invocation_handle
|
||||
Type Handle
|
||||
Use The identifier provided by the client to tag the method invocation.
|
||||
The identifier will be returned with the response, to provide
|
||||
the client with a mechanism to match asynchronous responses with
|
||||
commands that generated them.
|
||||
|
||||
channel
|
||||
Type integer
|
||||
Use Specifies the Tx channel to deallocate
|
||||
|
||||
|
||||
// incoming:
|
||||
|
||||
response_deallocate_channel(invocation_handle, status)
|
||||
|
||||
Type Handle
|
||||
Use The identifier provided by the client in the prompting invocation.
|
||||
The identifier is returned with the response, so that the
|
||||
client has a mechanism to match asynchronous responses with
|
||||
commands that generated them. The value of the invocation_handle
|
||||
is opaque to the server, and is not required by the server to be unique.
|
||||
|
||||
Type Status
|
||||
Use Contains the status code for the operation, per FIXME, and
|
||||
an optional message.
|
||||
|
||||
Preconditions:
|
||||
a) None
|
||||
|
||||
Postconditions:
|
||||
a) If successful, the requested channel and associated USB capacity
|
||||
are deallocated, and return to the pool of available resources.
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
// Protocol class usrp_usb_tx inherits from usrp_usb_common
|
||||
// Defined from client's point-of-view
|
||||
|
||||
// outgoing:
|
||||
|
||||
cmd_xmit_raw_frame(invocation_handle, channel, samples, timestamp)
|
||||
|
||||
invocation_handle
|
||||
Type Handle
|
||||
Use The identifier provided by the client to tag the method invocation.
|
||||
The identifier will be returned with the response, to provide
|
||||
the client with a mechanism to match asynchronous responses with
|
||||
commands that generated them.
|
||||
|
||||
channel
|
||||
Type integer
|
||||
Use Specifies the channel that the frame of samples shall be transmitted on.
|
||||
|
||||
samples
|
||||
Type homogenous vector of unsigned char
|
||||
Use These samples must already be in the appropriate format for parsing
|
||||
by the USRP FPGA. The required format depends on the
|
||||
configuration associated with this channel. No conversion of
|
||||
the samples takes place in this method. Samples will be split
|
||||
into multiple USB data packets as required for transport
|
||||
across the USB.
|
||||
|
||||
timestamp
|
||||
Type 32-bit integer
|
||||
Use Specifies the time at which the first sample in samples
|
||||
shall be sent to the D/A converter. The format and
|
||||
interpretation of time is as specified in
|
||||
inband-signaling-usb.
|
||||
|
||||
|
||||
// incoming:
|
||||
|
||||
response_xmit_raw_frame(invocation_handle, status)
|
||||
|
||||
Type Handle
|
||||
Use The identifier provided by the client in the prompting invocation.
|
||||
The identifier is returned with the response, so that the
|
||||
client has a mechanism to match asynchronous responses with
|
||||
commands that generated them. The value of the invocation_handle
|
||||
is opaque to the server, and is not required by the server to be unique.
|
||||
|
||||
Type Status
|
||||
Use Contains the status code for the operation, per FIXME, and
|
||||
an optional message.
|
||||
|
||||
Preconditions:
|
||||
a) The specified channel is allocated to this client
|
||||
|
||||
Postconditions:
|
||||
a) If successful, the samples of the frame have been queued for
|
||||
transmission to the USRP.
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
// Protocol class usrp_usb_rx inherits from usrp_usb_common
|
||||
// Defined from client's point-of-view
|
||||
|
||||
|
||||
// outgoing:
|
||||
|
||||
cmd_recv_raw_samples(invocation_handle, channel)
|
||||
|
||||
invocation_handle
|
||||
Type Handle
|
||||
Use The identifier provided by the client to tag the method invocation.
|
||||
The identifier will be returned with the response, to provide
|
||||
the client with a mechanism to match asynchronous responses with
|
||||
commands that generated them.
|
||||
|
||||
channel
|
||||
Type integer
|
||||
Use Specifies the channel that the samples shall be received from.
|
||||
|
||||
The client may issue multiple cmd_recv_raw_samples commands to ensure
|
||||
an uninterrupted flow of samples. The appropriate number of
|
||||
outstanding cmds to issue is TBD, but is at least 2.
|
||||
|
||||
[Discussion: I'm not sure if this is really the interface we want.
|
||||
We may want to provide an enable/disable method, and then just begin
|
||||
streaming samples. Or, we may wan to implement packet boundary
|
||||
detection in the FPGA, and then return a frame's worth of samples
|
||||
(potentially in multiple pieces).
|
||||
|
||||
It may be that we need to different modes, one for packet based
|
||||
reception and one for continuous streaming.]
|
||||
|
||||
|
||||
// incoming:
|
||||
|
||||
response_recv_raw_samples(invocation_handle, samples, timestamp, properties)
|
||||
|
||||
Type Handle
|
||||
Use The identifier provided by the client in the prompting invocation.
|
||||
The identifier is returned with the response, so that the
|
||||
client has a mechanism to match asynchronous responses with
|
||||
commands that generated them. The value of the invocation_handle
|
||||
is opaque to the server, and is not required by the server to be unique.
|
||||
|
||||
samples
|
||||
Type homogenous vector of unsigned char
|
||||
Use Samples as returned by the USRP FPGA. The format of the
|
||||
returned samples depends on the configuration associated with
|
||||
this channel. No conversion or unpacking of samples takes place in
|
||||
this method.
|
||||
|
||||
timestamp
|
||||
Type 32-bit integer
|
||||
Use Specifies the time at which the first sample in samples
|
||||
was received from the A/D converter. The format and
|
||||
interpretation of time is as specified in
|
||||
inband-signaling-usb.
|
||||
|
||||
properties
|
||||
Type Map
|
||||
Use Returns additional (key, value) pairs associated with the
|
||||
reception of these samples. In particular, the map may contain
|
||||
the Received Strength Signal Indication (RSSI) reported by the
|
||||
front end at the time the first sample was received from the A/D.
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
To do: control and configuration messages...
|
||||
See usrp/host/lib/inband/usrp_server.mbh for interface
|
||||
|
||||
|
|
|
@ -0,0 +1,197 @@
|
|||
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) ;
|
||||
|
||||
// Should not be needed if adc clock rate < tx clock rate
|
||||
`define JITTER 5
|
||||
|
||||
//Samples format
|
||||
// 16 bits interleaved complex samples
|
||||
`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
|
||||
|
||||
// State registers
|
||||
reg[3:0] reader_state;
|
||||
reg[3:0] reader_next_state;
|
||||
|
||||
//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)
|
||||
begin
|
||||
reader_state <= `IDLE;
|
||||
reader_next_state <= `IDLE;
|
||||
rdreq <= 0;
|
||||
skip <= 0;
|
||||
overrun <= 0;
|
||||
underrun <= 0;
|
||||
burst <= 0;
|
||||
qsample <= 1;
|
||||
end
|
||||
else
|
||||
begin
|
||||
reader_state = reader_next_state;
|
||||
case (reader_state)
|
||||
`IDLE:
|
||||
begin
|
||||
if (pkt_waiting == 1)
|
||||
begin
|
||||
reader_next_state <= `READ;
|
||||
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
|
||||
|
||||
// Read payload length
|
||||
`HEADER2:
|
||||
begin
|
||||
payload_len <= (fifodata & 16'h1FF);
|
||||
read_len <= 9'd0;
|
||||
reader_next_state <= `TIMESTAMP1;
|
||||
end
|
||||
|
||||
`TIMESTAMP1:
|
||||
begin
|
||||
timestamp <= {fifodata, 16'b0};
|
||||
rdreq <= 0;
|
||||
reader_next_state <= `TIMESTAMP2;
|
||||
end
|
||||
|
||||
`TIMESTAMP2:
|
||||
begin
|
||||
timestamp <= timestamp + fifodata;
|
||||
reader_next_state <= `WAIT;
|
||||
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;
|
||||
// Let's send it
|
||||
else if ((timestamp < adc_clock + `JITTER
|
||||
&& timestamp > adc_clock)
|
||||
|| timestamp == 32'hFFFFFFFF)
|
||||
begin
|
||||
reader_next_state <= `WAITSTROBE;
|
||||
end
|
||||
// Outdated
|
||||
else if (timestamp < adc_clock)
|
||||
begin
|
||||
reader_next_state <= `DISCARD;
|
||||
skip <= 1;
|
||||
end
|
||||
end
|
||||
|
||||
// Wait for the transmit chain to be ready
|
||||
`WAITSTROBE:
|
||||
begin
|
||||
// If end of payload...
|
||||
if (read_len == payload_len)
|
||||
begin
|
||||
reader_next_state <= `DISCARD;
|
||||
skip <= (payload_len < 508);
|
||||
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
|
||||
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
|
||||
|
||||
default:
|
||||
begin
|
||||
$display ("Error unknown state");
|
||||
reader_state <= `IDLE;
|
||||
reader_next_state <= `IDLE;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
|
@ -0,0 +1,128 @@
|
|||
module data_packet_fifo
|
||||
( input reset,
|
||||
input clock,
|
||||
input [15:0]ram_data_in,
|
||||
input write_enable,
|
||||
output reg have_space,
|
||||
output reg [15:0]ram_data_out,
|
||||
output reg pkt_waiting,
|
||||
input read_enable,
|
||||
input pkt_complete,
|
||||
input skip_packet) ;
|
||||
|
||||
/* Some parameters for usage later on */
|
||||
parameter DATA_WIDTH = 16 ;
|
||||
parameter NUM_PACKETS = 4 ;
|
||||
|
||||
/* Create the RAM here */
|
||||
reg [DATA_WIDTH-1:0] usb_ram [256*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 ;
|
||||
|
||||
wire [7-2+NUM_PACKETS:0] usb_ram_aout ;
|
||||
wire [7-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)
|
||||
begin
|
||||
if (reset)
|
||||
pkt_waiting <= 0;
|
||||
else if (usb_ram_ain >= usb_ram_aout)
|
||||
pkt_waiting <= usb_ram_ain - usb_ram_aout >= 256;
|
||||
else
|
||||
pkt_waiting <= (usb_ram_ain + 10'b1111111111 - usb_ram_aout) >= 256;
|
||||
end
|
||||
|
||||
// Check if there is room
|
||||
always @(usb_ram_ain, usb_ram_aout)
|
||||
begin
|
||||
if (reset)
|
||||
have_space <= 1;
|
||||
else 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);
|
||||
else
|
||||
have_space <= (usb_ram_aout - usb_ram_ain) >= 256;
|
||||
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 */
|
||||
always @(posedge clock)
|
||||
begin
|
||||
if( write_enable )
|
||||
begin
|
||||
usb_ram[usb_ram_ain] <= ram_data_in ;
|
||||
end
|
||||
end
|
||||
|
||||
/* RAM Read Address process */
|
||||
always @(posedge clock)
|
||||
begin
|
||||
if( reset )
|
||||
begin
|
||||
usb_ram_packet_out <= 0 ;
|
||||
usb_ram_offset_out <= 0 ;
|
||||
isfull <= 0;
|
||||
end
|
||||
else
|
||||
if( skip_packet )
|
||||
begin
|
||||
usb_ram_packet_out <= usb_ram_packet_out + 1 ;
|
||||
usb_ram_offset_out <= 0 ;
|
||||
end
|
||||
else if(read_enable) begin
|
||||
if( usb_ram_offset_out == 8'b11111111 )
|
||||
begin
|
||||
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
|
||||
|
||||
endmodule
|
|
@ -0,0 +1,183 @@
|
|||
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
|
||||
);
|
||||
|
||||
wire [15:0] tx_data_bus;
|
||||
|
||||
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;
|
||||
|
||||
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)
|
||||
);
|
||||
|
||||
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)
|
||||
);
|
||||
|
||||
|
||||
//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)
|
||||
);
|
||||
|
||||
endmodule // tx_buffer
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
module usb_fifo_reader (tx_clock, fifodata, pkt_waiting, reset,
|
||||
rdreq, skip, done_chan, WR_chan, tx_data_bus);
|
||||
|
||||
/* Module parameters */
|
||||
parameter NUM_CHAN = 2 ;
|
||||
parameter WIDTH = 32 ;
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
module usb_packet_fifo
|
||||
( input reset,
|
||||
input clock_in,
|
||||
input clock_out,
|
||||
input [15:0]ram_data_in,
|
||||
input write_enable,
|
||||
output reg [15:0]ram_data_out,
|
||||
output reg pkt_waiting,
|
||||
output reg have_space,
|
||||
input read_enable,
|
||||
input skip_packet ) ;
|
||||
|
||||
/* Some parameters for usage later on */
|
||||
parameter DATA_WIDTH = 16 ;
|
||||
parameter NUM_PACKETS = 4 ;
|
||||
|
||||
/* Create the RAM here */
|
||||
reg [DATA_WIDTH-1:0] usb_ram [256*NUM_PACKETS-1:0] ;
|
||||
|
||||
/* Create the address signals */
|
||||
reg [7-2+NUM_PACKETS:0] usb_ram_ain ;
|
||||
reg [7:0] usb_ram_offset ;
|
||||
reg [1:0] usb_ram_packet ;
|
||||
|
||||
wire [7-2+NUM_PACKETS:0] usb_ram_aout ;
|
||||
reg isfull;
|
||||
|
||||
assign usb_ram_aout = {usb_ram_packet,usb_ram_offset} ;
|
||||
|
||||
// Check if there is one full packet to process
|
||||
always @(usb_ram_ain, usb_ram_aout)
|
||||
begin
|
||||
if (reset)
|
||||
pkt_waiting <= 0;
|
||||
else 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) >= 256;
|
||||
else
|
||||
pkt_waiting <= (usb_ram_ain + 10'b1111111111 - usb_ram_aout) >= 256;
|
||||
end
|
||||
|
||||
// Check if there is room
|
||||
always @(usb_ram_ain, usb_ram_aout)
|
||||
begin
|
||||
if (reset)
|
||||
have_space <= 1;
|
||||
else 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);
|
||||
else
|
||||
have_space <= (usb_ram_aout - usb_ram_ain) >= 256;
|
||||
end
|
||||
|
||||
/* RAM Write Address process */
|
||||
always @(posedge clock_in)
|
||||
begin
|
||||
if( reset )
|
||||
usb_ram_ain <= 0 ;
|
||||
else
|
||||
if( write_enable )
|
||||
begin
|
||||
usb_ram_ain <= usb_ram_ain + 1 ;
|
||||
if (usb_ram_ain + 1 == usb_ram_aout)
|
||||
isfull <= 1;
|
||||
end
|
||||
end
|
||||
|
||||
/* RAM Writing process */
|
||||
always @(posedge clock_in)
|
||||
begin
|
||||
if( write_enable )
|
||||
begin
|
||||
usb_ram[usb_ram_ain] <= ram_data_in ;
|
||||
end
|
||||
end
|
||||
|
||||
/* RAM Read Address process */
|
||||
always @(posedge clock_out)
|
||||
begin
|
||||
if( reset )
|
||||
begin
|
||||
usb_ram_packet <= 0 ;
|
||||
usb_ram_offset <= 0 ;
|
||||
isfull <= 0;
|
||||
end
|
||||
else
|
||||
if( skip_packet )
|
||||
begin
|
||||
usb_ram_packet <= usb_ram_packet + 1 ;
|
||||
usb_ram_offset <= 0 ;
|
||||
end
|
||||
else if(read_enable)
|
||||
if( usb_ram_offset == 8'b11111111 )
|
||||
begin
|
||||
usb_ram_offset <= 0 ;
|
||||
usb_ram_packet <= usb_ram_packet + 1 ;
|
||||
end
|
||||
else
|
||||
usb_ram_offset <= usb_ram_offset + 1 ;
|
||||
if (usb_ram_ain == usb_ram_aout)
|
||||
isfull <= 0;
|
||||
end
|
||||
|
||||
/* RAM Reading Process */
|
||||
always @(posedge clock_out)
|
||||
begin
|
||||
ram_data_out <= usb_ram[usb_ram_aout] ;
|
||||
end
|
||||
|
||||
endmodule
|
|
@ -0,0 +1,119 @@
|
|||
`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
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
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))
|
||||
)
|
||||
)
|
|
@ -0,0 +1,31 @@
|
|||
--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_512
|
||||
PORT
|
||||
(
|
||||
aclr : IN STD_LOGIC := '0';
|
||||
data : IN STD_LOGIC_VECTOR (31 DOWNTO 0);
|
||||
rdclk : IN STD_LOGIC ;
|
||||
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
|
||||
);
|
||||
end component;
|
|
@ -0,0 +1,32 @@
|
|||
--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_512
|
||||
(
|
||||
aclr,
|
||||
data[31..0],
|
||||
rdclk,
|
||||
rdreq,
|
||||
wrclk,
|
||||
wrreq
|
||||
)
|
||||
|
||||
RETURNS (
|
||||
q[31..0],
|
||||
rdempty,
|
||||
rdfull,
|
||||
wrempty,
|
||||
wrfull
|
||||
);
|
|
@ -0,0 +1,180 @@
|
|||
// megafunction wizard: %LPM_FIFO+%
|
||||
// GENERATION: STANDARD
|
||||
// VERSION: WM1.0
|
||||
// MODULE: dcfifo
|
||||
|
||||
// ============================================================
|
||||
// File Name: fifo_512.v
|
||||
// Megafunction Name(s):
|
||||
// dcfifo
|
||||
// ============================================================
|
||||
// ************************************************************
|
||||
// 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_512 (
|
||||
aclr,
|
||||
data,
|
||||
rdclk,
|
||||
rdreq,
|
||||
wrclk,
|
||||
wrreq,
|
||||
q,
|
||||
rdempty,
|
||||
rdfull,
|
||||
wrempty,
|
||||
wrfull);
|
||||
|
||||
input aclr;
|
||||
input [31:0] data;
|
||||
input rdclk;
|
||||
input rdreq;
|
||||
input wrclk;
|
||||
input wrreq;
|
||||
output [31:0] q;
|
||||
output rdempty;
|
||||
output rdfull;
|
||||
output wrempty;
|
||||
output wrfull;
|
||||
|
||||
wire sub_wire0;
|
||||
wire sub_wire1;
|
||||
wire 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];
|
||||
|
||||
dcfifo dcfifo_component (
|
||||
.wrclk (wrclk),
|
||||
.rdreq (rdreq),
|
||||
.aclr (aclr),
|
||||
.rdclk (rdclk),
|
||||
.wrreq (wrreq),
|
||||
.data (data),
|
||||
.rdfull (sub_wire0),
|
||||
.rdempty (sub_wire1),
|
||||
.wrfull (sub_wire2),
|
||||
.wrempty (sub_wire3),
|
||||
.q (sub_wire4)
|
||||
// synopsys translate_off
|
||||
,
|
||||
.rdusedw (),
|
||||
.wrusedw ()
|
||||
// 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";
|
||||
|
||||
|
||||
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 "4"
|
||||
// Retrieval info: PRIVATE: Depth NUMERIC "128"
|
||||
// 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 "32"
|
||||
// Retrieval info: PRIVATE: dc_aclr NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: rsEmpty NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: rsFull NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: rsUsedW NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: sc_aclr NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: sc_sclr NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: wsEmpty NUMERIC "1"
|
||||
// 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_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: 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: 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: 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: @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: @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
|
|
@ -0,0 +1,131 @@
|
|||
// megafunction wizard: %LPM_FIFO+%VBB%
|
||||
// GENERATION: STANDARD
|
||||
// VERSION: WM1.0
|
||||
// MODULE: dcfifo
|
||||
|
||||
// ============================================================
|
||||
// File Name: fifo_512.v
|
||||
// Megafunction Name(s):
|
||||
// dcfifo
|
||||
// ============================================================
|
||||
// ************************************************************
|
||||
// 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_512 (
|
||||
aclr,
|
||||
data,
|
||||
rdclk,
|
||||
rdreq,
|
||||
wrclk,
|
||||
wrreq,
|
||||
q,
|
||||
rdempty,
|
||||
rdfull,
|
||||
wrempty,
|
||||
wrfull);
|
||||
|
||||
input aclr;
|
||||
input [31:0] data;
|
||||
input rdclk;
|
||||
input rdreq;
|
||||
input wrclk;
|
||||
input wrreq;
|
||||
output [31:0] q;
|
||||
output rdempty;
|
||||
output rdfull;
|
||||
output wrempty;
|
||||
output wrfull;
|
||||
|
||||
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 "4"
|
||||
// Retrieval info: PRIVATE: Depth NUMERIC "128"
|
||||
// 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 "32"
|
||||
// Retrieval info: PRIVATE: dc_aclr NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: rsEmpty NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: rsFull NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: rsUsedW NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: sc_aclr NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: sc_sclr NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: wsEmpty NUMERIC "1"
|
||||
// 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_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: 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: 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: 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: @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: @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
|
|
@ -27,7 +27,7 @@
|
|||
# ========================
|
||||
set_global_assignment -name ORIGINAL_QUARTUS_VERSION 3.0
|
||||
set_global_assignment -name PROJECT_CREATION_TIME_DATE "00:14:04 JULY 13, 2003"
|
||||
set_global_assignment -name LAST_QUARTUS_VERSION 6.1
|
||||
set_global_assignment -name LAST_QUARTUS_VERSION "5.1 SP1"
|
||||
|
||||
# Pin & Location Assignments
|
||||
# ==========================
|
||||
|
@ -371,6 +371,13 @@ 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/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
|
||||
set_global_assignment -name VERILOG_FILE ../../megacells/fifo_4k.v
|
||||
|
@ -405,5 +412,4 @@ 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
|
||||
set_global_assignment -name FITTER_AUTO_EFFORT_DESIRED_SLACK_MARGIN "100 ps"
|
||||
set_global_assignment -name VERILOG_FILE ../../sdr_lib/sign_extend.v
|
|
@ -19,6 +19,7 @@
|
|||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Boston, MA 02110-1301 USA
|
||||
//
|
||||
`define IN_BAND
|
||||
|
||||
`include "config.vh"
|
||||
`include "../../../firmware/include/fpga_regs_common.v"
|
||||
|
@ -122,6 +123,20 @@ module usrp_inband_usb
|
|||
assign bb_tx_i1 = ch2tx;
|
||||
assign bb_tx_q1 = ch3tx;
|
||||
|
||||
`ifdef 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),
|
||||
.channels({tx_numchan,1'b0}),
|
||||
.tx_i_0(ch0tx),.tx_q_0(ch1tx),
|
||||
.tx_i_1(ch2tx),.tx_q_1(ch3tx),
|
||||
.tx_i_2(),.tx_q_2(),
|
||||
.tx_i_3(),.tx_q_3(),
|
||||
.txclk(clk64),.txstrobe(strobe_interp),
|
||||
.clear_status(clear_status),
|
||||
.tx_empty(tx_empty),
|
||||
.debugbus(tx_debugbus) );
|
||||
`else
|
||||
tx_buffer 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),
|
||||
|
@ -134,6 +149,7 @@ module usrp_inband_usb
|
|||
.clear_status(clear_status),
|
||||
.tx_empty(tx_empty),
|
||||
.debugbus(tx_debugbus) );
|
||||
`endif
|
||||
|
||||
`ifdef TX_EN_0
|
||||
tx_chain tx_chain_0
|
||||
|
|
|
@ -23,8 +23,6 @@ include $(top_srcdir)/Makefile.common
|
|||
|
||||
INCLUDES = $(USRP_INCLUDES) $(BOOST_CFLAGS)
|
||||
|
||||
USRP_LIB = $(top_builddir)/usrp/host/lib/libusrp.la
|
||||
|
||||
bin_PROGRAMS = \
|
||||
usrper \
|
||||
usrp_cal_dc_offset
|
||||
|
@ -45,13 +43,13 @@ noinst_PYTHON = \
|
|||
check_order_quickly_SOURCES = check_order_quickly.cc
|
||||
|
||||
test_usrp_standard_rx_SOURCES = test_usrp_standard_rx.cc time_stuff.c
|
||||
test_usrp_standard_rx_LDADD = $(USRP_LIB)
|
||||
test_usrp_standard_rx_LDADD = $(USRP_LA)
|
||||
|
||||
test_usrp_standard_tx_SOURCES = test_usrp_standard_tx.cc time_stuff.c
|
||||
test_usrp_standard_tx_LDADD = $(USRP_LIB)
|
||||
test_usrp_standard_tx_LDADD = $(USRP_LA)
|
||||
|
||||
usrper_SOURCES = usrper.cc
|
||||
usrper_LDADD = $(USRP_LIB)
|
||||
usrper_LDADD = $(USRP_LA)
|
||||
|
||||
usrp_cal_dc_offset_SOURCES = usrp_cal_dc_offset.cc
|
||||
usrp_cal_dc_offset_LDADD = $(USRP_LIB)
|
||||
usrp_cal_dc_offset_LDADD = $(USRP_LA)
|
||||
|
|
|
@ -20,133 +20,5 @@
|
|||
|
||||
include $(top_srcdir)/Makefile.common
|
||||
|
||||
INCLUDES = $(USRP_INCLUDES)
|
||||
SUBDIRS = legacy inband
|
||||
|
||||
lib_LTLIBRARIES = libusrp.la
|
||||
|
||||
|
||||
EXTRA_DIST = \
|
||||
std_paths.h.in \
|
||||
usrp_dbid.dat
|
||||
|
||||
|
||||
BUILT_SOURCES = \
|
||||
usrp_dbid.h \
|
||||
usrp_dbid.cc \
|
||||
usrp_dbid.py
|
||||
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# FUSB_TECH is set at configure time by way of
|
||||
# usrp/config/usrp_fusb_tech.m4.
|
||||
# It indicates which fast usb strategy we should be building.
|
||||
# We currently implement "generic", "darwin", "win32" and "linux"
|
||||
|
||||
|
||||
generic_CODE = \
|
||||
fusb_generic.cc \
|
||||
fusb_sysconfig_generic.cc
|
||||
|
||||
darwin_CODE = \
|
||||
fusb_darwin.cc \
|
||||
fusb_sysconfig_darwin.cc \
|
||||
README_OSX \
|
||||
circular_buffer.h \
|
||||
circular_linked_list.h \
|
||||
darwin_libusb.h \
|
||||
mld_threads.h
|
||||
|
||||
win32_CODE = \
|
||||
fusb_win32.cc \
|
||||
fusb_sysconfig_win32.cc
|
||||
|
||||
linux_CODE = \
|
||||
fusb_linux.cc \
|
||||
fusb_sysconfig_linux.cc
|
||||
|
||||
ra_wb_CODE = \
|
||||
fusb_ra_wb.cc \
|
||||
fusb_sysconfig_ra_wb.cc
|
||||
|
||||
|
||||
#
|
||||
# include each <foo>_CODE entry here...
|
||||
#
|
||||
EXTRA_libusrp_la_SOURCES = \
|
||||
$(generic_CODE) \
|
||||
$(darwin_CODE) \
|
||||
$(win32_CODE) \
|
||||
$(linux_CODE) \
|
||||
$(ra_wb_CODE)
|
||||
|
||||
|
||||
# work around automake deficiency
|
||||
libusrp_la_common_SOURCES = \
|
||||
fusb.cc \
|
||||
md5.c \
|
||||
usrp_basic.cc \
|
||||
usrp_config.cc \
|
||||
usrp_dbid.cc \
|
||||
usrp_local_sighandler.cc \
|
||||
usrp_prims.cc \
|
||||
usrp_standard.cc
|
||||
|
||||
|
||||
if FUSB_TECH_generic
|
||||
libusrp_la_SOURCES = $(libusrp_la_common_SOURCES) $(generic_CODE)
|
||||
endif
|
||||
|
||||
if FUSB_TECH_darwin
|
||||
libusrp_la_SOURCES = $(libusrp_la_common_SOURCES) $(darwin_CODE)
|
||||
endif
|
||||
|
||||
if FUSB_TECH_win32
|
||||
libusrp_la_SOURCES = $(libusrp_la_common_SOURCES) $(win32_CODE)
|
||||
endif
|
||||
|
||||
if FUSB_TECH_linux
|
||||
libusrp_la_SOURCES = $(libusrp_la_common_SOURCES) $(linux_CODE)
|
||||
endif
|
||||
|
||||
if FUSB_TECH_ra_wb
|
||||
libusrp_la_SOURCES = $(libusrp_la_common_SOURCES) $(ra_wb_CODE)
|
||||
endif
|
||||
|
||||
|
||||
libusrp_la_LDFLAGS = $(NO_UNDEFINED) -version-info 0:0:0
|
||||
libusrp_la_LIBADD = $(USB_LIBS) ../misc/libmisc.la
|
||||
|
||||
include_HEADERS = \
|
||||
usrp_basic.h \
|
||||
usrp_bytesex.h \
|
||||
usrp_config.h \
|
||||
usrp_dbid.h \
|
||||
usrp_prims.h \
|
||||
usrp_slots.h \
|
||||
usrp_standard.h
|
||||
|
||||
noinst_HEADERS = \
|
||||
ad9862.h \
|
||||
fusb.h \
|
||||
fusb_darwin.h \
|
||||
fusb_win32.h \
|
||||
fusb_generic.h \
|
||||
fusb_linux.h \
|
||||
fusb_ra_wb.h \
|
||||
md5.h \
|
||||
rate_to_regval.h \
|
||||
usrp_local_sighandler.h
|
||||
|
||||
usrppython_PYTHON = \
|
||||
usrp_dbid.py
|
||||
|
||||
noinst_PYTHON = \
|
||||
gen_usrp_dbid.py \
|
||||
check_data.py \
|
||||
dump_data.py
|
||||
|
||||
usrp_dbid.py usrp_dbid.h usrp_dbid.cc: gen_usrp_dbid.py usrp_dbid.dat
|
||||
PYTHONPATH=$(top_srcdir)/usrp/src srcdir=$(srcdir) $(PYTHON) $(srcdir)/gen_usrp_dbid.py $(srcdir)/usrp_dbid.dat
|
||||
|
||||
MOSTLYCLEANFILES = \
|
||||
$(BUILT_SOURCES) *~ *.pyc
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,92 @@
|
|||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
include $(top_srcdir)/Makefile.common
|
||||
|
||||
INCLUDES = \
|
||||
$(DEFINES) $(OMNITHREAD_INCLUDES) $(PMT_INCLUDES) $(MBLOCK_INCLUDES) \
|
||||
$(USRP_INCLUDES) $(BOOST_CFLAGS) $(CPPUNIT_INCLUDES)
|
||||
|
||||
TESTS = test_inband
|
||||
|
||||
EXTRA_DIST =
|
||||
|
||||
lib_LTLIBRARIES = \
|
||||
libusrp_inband.la \
|
||||
libusrp_inband-qa.la
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------
|
||||
# Build the inband library
|
||||
|
||||
BUILT_SOURCES = \
|
||||
usrp_server_mbh.cc
|
||||
|
||||
usrp_server_mbh.cc : usrp_server.mbh
|
||||
$(COMPILE_MBH) usrp_server.mbh usrp_server_mbh.cc
|
||||
|
||||
libusrp_inband_la_SOURCES = \
|
||||
$(BUILT_SOURCES) \
|
||||
usrp_server.cc
|
||||
|
||||
libusrp_inband_la_LDFLAGS = $(NO_UNDEFINED) -version-info 0:0:0
|
||||
|
||||
libusrp_inband_la_LIBADD = \
|
||||
$(MBLOCK_LA) \
|
||||
-lstdc++
|
||||
|
||||
|
||||
include_HEADERS = \
|
||||
usrp_server.h
|
||||
|
||||
noinst_HEADERS = \
|
||||
qa_inband.h \
|
||||
qa_inband_packet_prims.h \
|
||||
qa_inband_usrp_server.h
|
||||
|
||||
# ------------------------------------------------------------------------
|
||||
# Build the qa code in its own library
|
||||
|
||||
libusrp_inband_qa_la_SOURCES = \
|
||||
qa_inband.cc \
|
||||
qa_inband_packet_prims.cc \
|
||||
qa_inband_usrp_server.cc
|
||||
|
||||
# magic flags
|
||||
libusrp_inband_qa_la_LDFLAGS = $(NO_UNDEFINED) -avoid-version
|
||||
|
||||
# link against c++ standard library
|
||||
libusrp_inband_qa_la_LIBADD = \
|
||||
libusrp_inband.la \
|
||||
$(CPPUNIT_LIBS) \
|
||||
-lstdc++
|
||||
|
||||
# ------------------------------------------------------------------------
|
||||
|
||||
noinst_PROGRAMS = \
|
||||
test_inband
|
||||
|
||||
test_inband_SOURCES = test_inband.cc
|
||||
test_inband_LDADD = libusrp_inband-qa.la
|
||||
|
||||
|
||||
MOSTLYCLEANFILES = \
|
||||
$(BUILT_SOURCES) *~ *.pyc
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
import sys
|
||||
import struct
|
||||
from optparse import OptionParser
|
||||
|
||||
from usb_packet import *
|
||||
|
||||
def dump_packet(raw_pkt, outfile, dump_payload):
|
||||
pkt = usb_packet(raw_pkt)
|
||||
outfile.write(pkt.decoded_flags())
|
||||
outfile.write(' chan= %2d len= %3d timestamp= 0x%08x rssi= % 2d tag= %2d\n' % (
|
||||
pkt.chan(), pkt.payload_len(), pkt.timestamp(), pkt.rssi(), pkt.tag()))
|
||||
if dump_payload:
|
||||
assert pkt.payload_len() % 4 == 0
|
||||
shorts = struct.unpack('<%dh' % (pkt.payload_len() // 2), pkt.payload())
|
||||
for i in range(0, len(shorts), 2):
|
||||
outfile.write(' %6d, %6d\n' % (shorts[i], shorts[i+1]))
|
||||
|
||||
|
||||
def dump_packets(infile, outfile, dump_payload):
|
||||
raw_pkt = infile.read(512)
|
||||
while raw_pkt:
|
||||
if len(raw_pkt) != 512:
|
||||
sys.stderr.write("File length is not a multiple of 512 bytes")
|
||||
raise SystemExit, 1
|
||||
|
||||
dump_packet(raw_pkt, outfile, dump_payload)
|
||||
raw_pkt = infile.read(512)
|
||||
|
||||
|
||||
def main():
|
||||
parser = OptionParser()
|
||||
parser.add_option('-p', '--dump-payload', action='store_true', default=False,
|
||||
help='dump payload in decimal and hex')
|
||||
|
||||
(options, files) = parser.parse_args()
|
||||
if len(files) == 0:
|
||||
dump_packets(sys.stdin, sys.stdout, options.dump_payload)
|
||||
else:
|
||||
for f in files:
|
||||
dump_packets(open(f, "r"), sys.stdout, options.dump_payload)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -0,0 +1,87 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import random
|
||||
import struct
|
||||
from pprint import pprint
|
||||
from usb_packet import *
|
||||
|
||||
MAX_PAYLOAD = 504
|
||||
TIME_NOW = 0xffffffff
|
||||
|
||||
|
||||
class sequence_generator(object):
|
||||
def __init__(self):
|
||||
self.i = 0
|
||||
|
||||
def __call__(self):
|
||||
t = self.i
|
||||
self.i += 1
|
||||
return t
|
||||
|
||||
def gen_shuffled_lengths():
|
||||
valid_lengths = range(0, MAX_PAYLOAD+1, 4) # [0, 4, 8, ... 504]
|
||||
random.shuffle(valid_lengths)
|
||||
return valid_lengths
|
||||
|
||||
|
||||
class packet_sequence_generator(object):
|
||||
def __init__(self, channel, lengths):
|
||||
self.next = sequence_generator()
|
||||
self.channel = channel
|
||||
self.lengths = lengths
|
||||
|
||||
def __call__(self, output_file):
|
||||
gen_packet(output_file, self.channel, self.next, self.lengths[0])
|
||||
del self.lengths[0]
|
||||
|
||||
|
||||
def gen_packet(output_file, channel, content_generator, payload_len):
|
||||
assert (payload_len % 4) == 0
|
||||
payload = []
|
||||
n_iq = payload_len // 4
|
||||
for n in range(n_iq):
|
||||
payload.append(content_generator()) # I
|
||||
payload.append(content_generator()) # Q
|
||||
for n in range(MAX_PAYLOAD // 4 - n_iq):
|
||||
payload.append(0x0000)
|
||||
payload.append(0xffff)
|
||||
|
||||
assert (len(payload) == MAX_PAYLOAD // 2)
|
||||
|
||||
#print "\npayload_len =", payload_len
|
||||
#pprint(payload)
|
||||
|
||||
output_file.write(make_header(FL_START_OF_BURST|FL_END_OF_BURST,
|
||||
channel, payload_len, TIME_NOW))
|
||||
output_file.write(struct.pack('<252h', *payload))
|
||||
|
||||
|
||||
def gen_all_valid_packet_lengths_1_channel(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)
|
||||
for i in range(npkts):
|
||||
pkt_gen_0(output_file)
|
||||
|
||||
assert pkt_gen_0.next() == 16002 # 2*sum(1, 2, ..., 126) == 126 * 127
|
||||
|
||||
|
||||
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 = (pkt_gen_0, pkt_gen_1)
|
||||
|
||||
which_gen = (npkts * [0]) + (npkts * [1])
|
||||
random.shuffle(which_gen)
|
||||
|
||||
for i in which_gen:
|
||||
pkt_gen[i](output_file)
|
||||
|
||||
assert pkt_gen_0.next() == 16002 # 2*sum(1, 2, ..., 126) == 126 * 127
|
||||
assert pkt_gen_1.next() == 16002 # 2*sum(1, 2, ..., 126) == 126 * 127
|
||||
|
||||
if __name__ == '__main__':
|
||||
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"))
|
|
@ -0,0 +1,35 @@
|
|||
/* -*- 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 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.
|
||||
*/
|
||||
|
||||
#include <qa_inband.h>
|
||||
#include <qa_inband_packet_prims.h>
|
||||
#include <qa_inband_usrp_server.h>
|
||||
|
||||
CppUnit::TestSuite *
|
||||
qa_inband::suite()
|
||||
{
|
||||
CppUnit::TestSuite *s = new CppUnit::TestSuite("inband");
|
||||
|
||||
s->addTest (qa_inband_packet_prims::suite());
|
||||
s->addTest (qa_inband_usrp_server::suite());
|
||||
|
||||
return s;
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/* -*- 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 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.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_QA_INBAND_H
|
||||
#define INCLUDED_QA_INBAND_H
|
||||
|
||||
#include <cppunit/TestSuite.h>
|
||||
|
||||
//! collect all the tests for the user server
|
||||
|
||||
class qa_inband {
|
||||
public:
|
||||
//! return suite of tests for all of usrp server
|
||||
static CppUnit::TestSuite *suite();
|
||||
};
|
||||
|
||||
#endif /* INCLUDED_QA_INBAND_H */
|
|
@ -0,0 +1,161 @@
|
|||
/* -*- 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 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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <qa_inband_packet_prims.h>
|
||||
#include <cppunit/TestAssert.h>
|
||||
#include <stdio.h>
|
||||
#include <usrp_inband_usb_packet.h> // will change on gigabit crossover
|
||||
|
||||
typedef usrp_inband_usb_packet transport_pkt;
|
||||
|
||||
void
|
||||
qa_inband_packet_prims::test_flags()
|
||||
{
|
||||
transport_pkt pkt;
|
||||
|
||||
// Test each one of the flags while ensuring no other fields become set in the process
|
||||
pkt.set_header(pkt.FL_START_OF_BURST,0,0,0);
|
||||
CPPUNIT_ASSERT_EQUAL(1, pkt.start_of_burst());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.end_of_burst());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.overrun());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.underrun());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.dropped());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
|
||||
|
||||
pkt.set_header(pkt.FL_END_OF_BURST,0,0,0);
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.start_of_burst());
|
||||
CPPUNIT_ASSERT_EQUAL(1, pkt.end_of_burst());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.overrun());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.underrun());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.dropped());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
|
||||
|
||||
pkt.set_header(pkt.FL_OVERRUN,0,0,0);
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.start_of_burst());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.end_of_burst());
|
||||
CPPUNIT_ASSERT_EQUAL(1, pkt.overrun());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.underrun());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.dropped());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
|
||||
|
||||
pkt.set_header(pkt.FL_UNDERRUN,0,0,0);
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.start_of_burst());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.end_of_burst());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.overrun());
|
||||
CPPUNIT_ASSERT_EQUAL(1, pkt.underrun());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.dropped());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
|
||||
|
||||
pkt.set_header(pkt.FL_DROPPED,0,0,0);
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.start_of_burst());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.end_of_burst());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.overrun());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.underrun());
|
||||
CPPUNIT_ASSERT_EQUAL(1, pkt.dropped());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
|
||||
|
||||
// test of all fields set
|
||||
pkt.set_header(
|
||||
pkt.FL_START_OF_BURST |
|
||||
pkt.FL_END_OF_BURST |
|
||||
pkt.FL_UNDERRUN |
|
||||
pkt.FL_OVERRUN |
|
||||
pkt.FL_DROPPED
|
||||
,0,0,0);
|
||||
CPPUNIT_ASSERT_EQUAL(1, pkt.start_of_burst());
|
||||
CPPUNIT_ASSERT_EQUAL(1, pkt.end_of_burst());
|
||||
CPPUNIT_ASSERT_EQUAL(1, pkt.overrun());
|
||||
CPPUNIT_ASSERT_EQUAL(1, pkt.underrun());
|
||||
CPPUNIT_ASSERT_EQUAL(1, pkt.dropped());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
|
||||
|
||||
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
qa_inband_packet_prims::test_fields()
|
||||
{
|
||||
transport_pkt pkt;
|
||||
void * payload;
|
||||
|
||||
// test word0 field exclusiveness
|
||||
//
|
||||
// I want to test max values of each field to ensure field boundaries
|
||||
// but these max values could change based on technology? The
|
||||
// max payload is returned by a private method so the code is not
|
||||
// technology dependent
|
||||
pkt.set_header(0,16,0,0);
|
||||
CPPUNIT_ASSERT_EQUAL(16, pkt.chan());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
|
||||
|
||||
pkt.set_header(0,0,8,0);
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
|
||||
CPPUNIT_ASSERT_EQUAL(8, pkt.tag());
|
||||
CPPUNIT_ASSERT_EQUAL(0,pkt.payload_len());
|
||||
|
||||
pkt.set_header(0,0,0,pkt.max_payload());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
|
||||
CPPUNIT_ASSERT_EQUAL(pkt.max_payload(), pkt.payload_len());
|
||||
|
||||
// test timestamp, shouldn't have to test other fields since
|
||||
// setting the timestamp only has the ability to affect one word
|
||||
pkt.set_timestamp(54);
|
||||
CPPUNIT_ASSERT_EQUAL(uint32_t(54), pkt.timestamp());
|
||||
|
||||
// test the payload, ensure no other fields overwritten
|
||||
//
|
||||
// is there a better test for this?
|
||||
pkt.set_header(0,0,0,0);
|
||||
payload = malloc(pkt.payload_len());
|
||||
memset(payload, 'f', pkt.payload_len());
|
||||
memcpy(pkt.payload(), payload, pkt.payload_len());
|
||||
CPPUNIT_ASSERT_EQUAL(0, memcmp(pkt.payload(), payload, pkt.payload_len()));
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.start_of_burst());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.end_of_burst());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.overrun());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.underrun());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.dropped());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.chan());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.tag());
|
||||
CPPUNIT_ASSERT_EQUAL(0, pkt.payload_len());
|
||||
free(payload);
|
||||
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,41 @@
|
|||
/* -*- 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 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.
|
||||
*/
|
||||
|
||||
#ifndef QA_INBAND_PACKET_PRIMS_H
|
||||
#define QA_INBAND_PACKET_PRIMS_H
|
||||
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
#include <cppunit/TestCase.h>
|
||||
|
||||
class qa_inband_packet_prims : public CppUnit::TestCase {
|
||||
|
||||
CPPUNIT_TEST_SUITE(qa_inband_packet_prims);
|
||||
CPPUNIT_TEST(test_flags);
|
||||
CPPUNIT_TEST(test_fields);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
private:
|
||||
void test_flags();
|
||||
void test_fields();
|
||||
|
||||
};
|
||||
|
||||
#endif /* INCLUDED_QA_INBAND_PACKET_PRIMS_H */
|
|
@ -0,0 +1,455 @@
|
|||
/* -*- 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 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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <qa_inband_usrp_server.h>
|
||||
#include <cppunit/TestAssert.h>
|
||||
#include <stdio.h>
|
||||
#include <usrp_server.h>
|
||||
#include <mb_mblock.h>
|
||||
#include <mb_runtime.h>
|
||||
#include <mb_protocol_class.h>
|
||||
#include <mb_class_registry.h>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
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");
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
|
||||
class qa_alloc_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_alloc_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
|
||||
~qa_alloc_top();
|
||||
void initial_transition();
|
||||
void handle_message(mb_message_sptr msg);
|
||||
|
||||
protected:
|
||||
void check_message(mb_message_sptr msg);
|
||||
void run_tests();
|
||||
};
|
||||
|
||||
qa_alloc_top::qa_alloc_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 = 7;
|
||||
d_nstatus=0;
|
||||
d_nstatus_to_recv = 3;
|
||||
|
||||
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);
|
||||
|
||||
// Test the TX side
|
||||
define_component("server", "usrp_server", PMT_F);
|
||||
connect("self", "tx0", "server", "tx0");
|
||||
connect("self", "rx0", "server", "rx0");
|
||||
connect("self", "cs", "server", "cs");
|
||||
|
||||
}
|
||||
|
||||
qa_alloc_top::~qa_alloc_top(){}
|
||||
|
||||
void
|
||||
qa_alloc_top::initial_transition()
|
||||
{
|
||||
// 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));
|
||||
}
|
||||
|
||||
void
|
||||
qa_alloc_top::run_tests()
|
||||
{
|
||||
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)));
|
||||
|
||||
// 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)));
|
||||
|
||||
// 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++) {
|
||||
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)));
|
||||
|
||||
// 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)));
|
||||
|
||||
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)));
|
||||
}
|
||||
|
||||
void
|
||||
qa_alloc_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_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";
|
||||
}
|
||||
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";
|
||||
}
|
||||
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";
|
||||
}
|
||||
else if(pmt_eq(msg->signal(), s_response_current_capacity_allocation)) {
|
||||
check_message(msg);
|
||||
}
|
||||
|
||||
d_nstatus++;
|
||||
|
||||
if(d_nstatus==d_nstatus_to_recv)
|
||||
run_tests();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
qa_alloc_top::check_message(mb_message_sptr msg)
|
||||
{
|
||||
pmt_t data = msg->data();
|
||||
|
||||
pmt_t expected_result = pmt_nth(0, data);
|
||||
pmt_t result = pmt_nth(1, data);
|
||||
|
||||
d_nrecvd++;
|
||||
|
||||
|
||||
if(!pmt_eqv(expected_result, result)) {
|
||||
std::cout << "Got: " << result << " Expected: " << expected_result << "\n";
|
||||
shutdown_all(PMT_F);
|
||||
} else {
|
||||
std::cout << "[qa_alloc_top] Received expected response for message " << d_nrecvd << "\n";
|
||||
}
|
||||
|
||||
if(d_nrecvd == d_nmsgs_to_recv)
|
||||
shutdown_all(PMT_T);
|
||||
}
|
||||
|
||||
REGISTER_MBLOCK_CLASS(qa_alloc_top);
|
||||
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
|
||||
class qa_dealloc_top : public mb_mblock
|
||||
{
|
||||
mb_port_sptr d_tx;
|
||||
mb_port_sptr d_rx;
|
||||
mb_port_sptr d_cs;
|
||||
|
||||
long d_max_capacity;
|
||||
long d_ntx_chan, d_nrx_chan;
|
||||
|
||||
long d_nstatus;
|
||||
long d_nstatus_to_recv;
|
||||
|
||||
long d_nalloc_to_recv;
|
||||
long d_nalloc_recvd;
|
||||
|
||||
long d_ndealloc_to_recv;
|
||||
long d_ndealloc_recvd;
|
||||
|
||||
std::vector<long> d_tx_chans;
|
||||
std::vector<long> d_rx_chans;
|
||||
|
||||
public:
|
||||
qa_dealloc_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
|
||||
~qa_dealloc_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 allocate_max();
|
||||
void deallocate_all();
|
||||
};
|
||||
|
||||
qa_dealloc_top::qa_dealloc_top(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
|
||||
: mb_mblock(runtime, instance_name, user_arg)
|
||||
{
|
||||
d_ndealloc_recvd=0;
|
||||
d_ndealloc_to_recv = 0;
|
||||
d_nalloc_recvd=0;
|
||||
d_nalloc_to_recv = 0;
|
||||
d_nstatus=0;
|
||||
d_nstatus_to_recv = 3;
|
||||
|
||||
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);
|
||||
|
||||
// Test the TX side
|
||||
define_component("server", "usrp_server", PMT_F);
|
||||
connect("self", "tx0", "server", "tx0");
|
||||
connect("self", "rx0", "server", "rx0");
|
||||
connect("self", "cs", "server", "cs");
|
||||
}
|
||||
|
||||
qa_dealloc_top::~qa_dealloc_top(){}
|
||||
|
||||
void
|
||||
qa_dealloc_top::initial_transition()
|
||||
{
|
||||
// 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));
|
||||
}
|
||||
|
||||
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_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_nalloc_to_recv++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
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])));
|
||||
d_ndealloc_to_recv++;
|
||||
}
|
||||
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])));
|
||||
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
|
||||
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_ndealloc_to_recv++;
|
||||
}
|
||||
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_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
|
||||
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)));
|
||||
|
||||
|
||||
// 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)));
|
||||
}
|
||||
|
||||
void
|
||||
qa_dealloc_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())) {
|
||||
|
||||
if(pmt_eq(msg->signal(), s_response_allocate_channel)) {
|
||||
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";
|
||||
}
|
||||
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";
|
||||
}
|
||||
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";
|
||||
}
|
||||
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);
|
||||
|
||||
if(pmt_eqv(expected_result, result))
|
||||
shutdown_all(PMT_T);
|
||||
else
|
||||
shutdown_all(PMT_F);
|
||||
}
|
||||
|
||||
d_nstatus++;
|
||||
|
||||
if(d_nstatus==d_nstatus_to_recv)
|
||||
allocate_max();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
qa_dealloc_top::check_deallocation(mb_message_sptr msg)
|
||||
{
|
||||
pmt_t data = msg->data();
|
||||
|
||||
pmt_t expected_result = pmt_nth(0, data);
|
||||
pmt_t result = pmt_nth(1, data);
|
||||
|
||||
d_ndealloc_recvd++;
|
||||
|
||||
if(!pmt_eqv(expected_result, result)) {
|
||||
std::cout << "Got: " << result << " Expected: " << expected_result << "\n";
|
||||
shutdown_all(PMT_F);
|
||||
} else {
|
||||
std::cout << "[qa_dealloc_top] Received expected deallocation response for message " << d_ndealloc_recvd << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
qa_dealloc_top::check_allocation(mb_message_sptr msg)
|
||||
{
|
||||
pmt_t data = msg->data();
|
||||
|
||||
pmt_t invocation_handle = pmt_nth(0, data);
|
||||
pmt_t status = pmt_nth(1, data);
|
||||
pmt_t channel = pmt_nth(2, data);
|
||||
|
||||
d_nalloc_recvd++;
|
||||
|
||||
if(pmt_eqv(status, PMT_F)) {
|
||||
std::cout << "[qa_dealloc_top] Unexpected error response when allocating channels\n";
|
||||
shutdown_all(PMT_F);
|
||||
} else {
|
||||
// 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) {
|
||||
|
||||
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);
|
||||
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
|
||||
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);
|
||||
|
||||
CPPUNIT_ASSERT(pmt_equal(PMT_T, result));
|
||||
}
|
||||
|
||||
void
|
||||
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);
|
||||
|
||||
CPPUNIT_ASSERT(pmt_equal(PMT_T, result));
|
||||
}
|
||||
|
||||
void
|
||||
qa_inband_usrp_server::test_fragmentation()
|
||||
{
|
||||
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/* -*- 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 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.
|
||||
*/
|
||||
|
||||
#ifndef QA_INBAND_USRP_SERVER_H
|
||||
#define QA_INBAND_USRP_SERVER_H
|
||||
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
#include <cppunit/TestCase.h>
|
||||
|
||||
class qa_inband_usrp_server : public CppUnit::TestCase {
|
||||
|
||||
CPPUNIT_TEST_SUITE(qa_inband_usrp_server);
|
||||
CPPUNIT_TEST(test_chan_allocation);
|
||||
CPPUNIT_TEST(test_chan_deallocation);
|
||||
CPPUNIT_TEST(test_fragmentation);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
private:
|
||||
void test_chan_allocation();
|
||||
void test_chan_deallocation();
|
||||
void test_fragmentation();
|
||||
};
|
||||
|
||||
#endif /* INCLUDED_QA_INBAND_USRP_SERVER_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 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.
|
||||
*/
|
||||
|
||||
#include <cppunit/TextTestRunner.h>
|
||||
#include <qa_inband.h>
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
|
||||
CppUnit::TextTestRunner runner;
|
||||
|
||||
runner.addTest(qa_inband::suite ());
|
||||
|
||||
bool was_successful = runner.run("", false);
|
||||
|
||||
return was_successful ? 0 : 1;
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
import struct
|
||||
|
||||
|
||||
FL_OVERRUN = 0x80000000
|
||||
FL_UNDERRUN = 0x40000000
|
||||
FL_DROPPED = 0x20000000
|
||||
FL_END_OF_BURST = 0x10000000
|
||||
FL_START_OF_BURST = 0x08000000
|
||||
|
||||
FL_ALL_FLAGS = 0xf8000000
|
||||
|
||||
FL_OVERRUN_SHIFT = 31
|
||||
FL_UNDERRUN_SHIFT = 30
|
||||
FL_DROPPED_SHIFT = 29
|
||||
FL_END_OF_BURST_SHIFT = 28
|
||||
FL_START_OF_BURST_SHIFT = 27
|
||||
|
||||
RSSI_MASK = 0x3f
|
||||
RSSI_SHIFT = 21
|
||||
|
||||
CHAN_MASK = 0x1f
|
||||
CHAN_SHIFT = 16
|
||||
|
||||
TAG_MASK = 0xf
|
||||
TAG_SHIFT = 9
|
||||
|
||||
PAYLOAD_LEN_MASK = 0x1ff
|
||||
PAYLOAD_LEN_SHIFT = 0
|
||||
|
||||
def make_header(flags, chan, payload_len, timestamp, rssi=0, tag=0):
|
||||
word0 = ((flags & FL_ALL_FLAGS)
|
||||
| ((rssi & RSSI_MASK) << RSSI_SHIFT)
|
||||
| ((chan & CHAN_MASK) << CHAN_SHIFT)
|
||||
| ((tag & TAG_MASK) << TAG_SHIFT)
|
||||
| ((payload_len & PAYLOAD_LEN_MASK) << PAYLOAD_LEN_SHIFT))
|
||||
word1 = timestamp
|
||||
return struct.pack('<2I', word0, word1)
|
||||
|
||||
|
||||
def _decode(pred, indicator):
|
||||
if pred:
|
||||
return indicator
|
||||
else:
|
||||
return '-'
|
||||
|
||||
|
||||
class usb_packet(object):
|
||||
def __init__(self, raw_pkt):
|
||||
assert isinstance(raw_pkt, str) and len(raw_pkt) == 512
|
||||
self._raw_pkt = raw_pkt;
|
||||
(self._word0, self._word1) = struct.unpack('<2I', self._raw_pkt[0:8])
|
||||
|
||||
def timestamp(self):
|
||||
return self._word1
|
||||
|
||||
def rssi(self):
|
||||
return (self._word0 >> RSSI_SHIFT) & RSSI_MASK
|
||||
|
||||
def chan(self):
|
||||
return (self._word0 >> CHAN_SHIFT) & CHAN_MASK
|
||||
|
||||
def tag(self):
|
||||
return (self._word0 >> TAG_SHIFT) & TAG_MASK
|
||||
|
||||
def payload_len(self):
|
||||
return (self._word0 >> PAYLOAD_LEN_SHIFT) & PAYLOAD_LEN_MASK
|
||||
|
||||
def flags(self):
|
||||
return self._word0 & FL_ALL_FLAGS
|
||||
|
||||
def overrun(self):
|
||||
return (self._word0 >> FL_OVERRUN_SHIFT) & 0x1
|
||||
|
||||
def underrun(self):
|
||||
return (self._word0 >> FL_UNDERRUN_SHIFT) & 0x1
|
||||
|
||||
def start_of_burst(self):
|
||||
return (self._word0 >> FL_START_OF_BURST_SHIFT) & 0x1
|
||||
|
||||
def end_of_burst(self):
|
||||
return (self._word0 >> FL_END_OF_BURST_SHIFT) & 0x1
|
||||
|
||||
def dropped(self):
|
||||
return (self._word0 >> FL_DROPPED_SHIFT) & 0x1
|
||||
|
||||
def payload(self):
|
||||
return self._raw_pkt[8:8+self.payload_len()]
|
||||
|
||||
def decoded_flags(self):
|
||||
s = (_decode(self.overrun(), 'O')
|
||||
+ _decode(self.underrun(), 'U')
|
||||
+ _decode(self.dropped(), 'D')
|
||||
+ _decode(self.end_of_burst(), 'E')
|
||||
+ _decode(self.start_of_burst(), 'S'))
|
||||
return s
|
|
@ -0,0 +1,149 @@
|
|||
/* -*- 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 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.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_USRP_INBAND_USB_PACKET_H_
|
||||
#define INCLUDED_USRP_INBAND_USB_PACKET_H_
|
||||
|
||||
#include <usrp_bytesex.h>
|
||||
#include <mb_mblock.h>
|
||||
|
||||
static const int USB_PKT_SIZE = 512; // bytes
|
||||
static const int MAX_PAYLOAD = USB_PKT_SIZE-2*sizeof(uint32_t);
|
||||
|
||||
class usrp_inband_usb_packet {
|
||||
//
|
||||
// keep raw packet in USRP-endian order
|
||||
//
|
||||
uint32_t d_word0;
|
||||
uint32_t d_timestamp;
|
||||
unsigned char d_payload[MAX_PAYLOAD];
|
||||
|
||||
public:
|
||||
|
||||
enum flags {
|
||||
FL_OVERRUN = 0x80000000,
|
||||
FL_UNDERRUN = 0x40000000,
|
||||
FL_DROPPED = 0x20000000,
|
||||
FL_END_OF_BURST = 0x10000000,
|
||||
FL_START_OF_BURST = 0x08000000,
|
||||
|
||||
FL_ALL_FLAGS = 0xf8000000
|
||||
};
|
||||
|
||||
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 RSSI_MASK = 0x3f;
|
||||
static const int RSSI_SHIFT = 21;
|
||||
|
||||
static const int CHAN_MASK = 0x1f;
|
||||
static const int CHAN_SHIFT = 16;
|
||||
|
||||
static const int TAG_MASK = 0xf;
|
||||
static const int TAG_SHIFT = 9;
|
||||
|
||||
static const int PAYLOAD_LEN_MASK = 0x1ff;
|
||||
static const int PAYLOAD_LEN_SHIFT = 0;
|
||||
|
||||
public:
|
||||
|
||||
void set_timestamp(uint32_t timestamp){
|
||||
d_timestamp = host_to_usrp_u32(timestamp);
|
||||
}
|
||||
|
||||
void set_end_of_burst() {
|
||||
uint32_t word0 = usrp_to_host_u32(d_word0);
|
||||
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)
|
||||
| ((tag & TAG_MASK) << TAG_SHIFT)
|
||||
| ((payload_len & PAYLOAD_LEN_MASK) << PAYLOAD_LEN_SHIFT));
|
||||
d_word0 = host_to_usrp_u32(word0);
|
||||
}
|
||||
|
||||
uint32_t timestamp() const {
|
||||
return usrp_to_host_u32(d_timestamp);
|
||||
}
|
||||
|
||||
int rssi() const {
|
||||
uint32_t word0 = usrp_to_host_u32(d_word0);
|
||||
return (word0 >> RSSI_SHIFT) & RSSI_MASK;
|
||||
}
|
||||
|
||||
int chan() const {
|
||||
uint32_t word0 = usrp_to_host_u32(d_word0);
|
||||
return (word0 >> CHAN_SHIFT) & CHAN_MASK;
|
||||
}
|
||||
|
||||
int tag() const {
|
||||
uint32_t word0 = usrp_to_host_u32(d_word0);
|
||||
return (word0 >> TAG_SHIFT) & TAG_MASK;
|
||||
}
|
||||
|
||||
int payload_len() const {
|
||||
uint32_t word0 = usrp_to_host_u32(d_word0);
|
||||
return (word0 >> PAYLOAD_LEN_SHIFT) & PAYLOAD_LEN_MASK;
|
||||
}
|
||||
|
||||
int flags() const {
|
||||
return usrp_to_host_u32(d_word0) & FL_ALL_FLAGS;
|
||||
}
|
||||
|
||||
int overrun() const {
|
||||
return (usrp_to_host_u32(d_word0) & FL_OVERRUN) >> FL_OVERRUN_SHIFT;
|
||||
}
|
||||
|
||||
|
||||
int underrun() const {
|
||||
return (usrp_to_host_u32(d_word0) & FL_UNDERRUN) >> FL_UNDERRUN_SHIFT;
|
||||
}
|
||||
|
||||
|
||||
int start_of_burst() const {
|
||||
return (usrp_to_host_u32(d_word0) & FL_START_OF_BURST) >> FL_START_OF_BURST_SHIFT;
|
||||
}
|
||||
|
||||
int end_of_burst() const {
|
||||
return (usrp_to_host_u32(d_word0) & FL_END_OF_BURST) >> FL_END_OF_BURST_SHIFT;
|
||||
}
|
||||
|
||||
int dropped() const {
|
||||
return (usrp_to_host_u32(d_word0) & FL_DROPPED) >> FL_DROPPED_SHIFT;
|
||||
}
|
||||
|
||||
unsigned char *payload() {
|
||||
return d_payload;
|
||||
}
|
||||
|
||||
static int max_payload() {
|
||||
return MAX_PAYLOAD;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,394 @@
|
|||
/* -*- 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 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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include <usrp_server.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
|
||||
|
||||
// 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");
|
||||
|
||||
static std::string
|
||||
str(long x)
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << x;
|
||||
return s.str();
|
||||
}
|
||||
|
||||
usrp_server::usrp_server(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg)
|
||||
: mb_mblock(rt, instance_name, user_arg)
|
||||
{
|
||||
// define our ports
|
||||
|
||||
// control & status port
|
||||
d_cs = define_port("cs", "usrp-server-cs", true, mb_port::EXTERNAL);
|
||||
|
||||
// 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));
|
||||
}
|
||||
|
||||
// FIXME ... initializing to 2 channels on each for now, eventually we should
|
||||
// query the FPGA to get these values
|
||||
d_ntx_chan = 2;
|
||||
d_nrx_chan = 2;
|
||||
|
||||
// Initialize capacity on each channel to 0 and to no owner
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
usrp_server::~usrp_server()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
usrp_server::initial_transition()
|
||||
{
|
||||
// the initial transition
|
||||
}
|
||||
|
||||
void
|
||||
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 status;
|
||||
|
||||
if (1){
|
||||
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)
|
||||
|
||||
if (pmt_eq(port_id, d_cs->port_symbol())){ // message came in on our control/status port
|
||||
|
||||
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
|
||||
|
||||
// Do the right thing....
|
||||
// build a reply
|
||||
|
||||
// if everything OK
|
||||
status = PMT_T;
|
||||
reply_data = pmt_list2(invocation_handle, status);
|
||||
|
||||
// ...and send it
|
||||
d_cs->send(s_response_open, reply_data);
|
||||
return;
|
||||
}
|
||||
else if (pmt_eq(event, s_cmd_close)){
|
||||
// ...
|
||||
}
|
||||
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);
|
||||
return;
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
goto unhandled;
|
||||
}
|
||||
|
||||
if (pmt_eq(event, s_cmd_allocate_channel)){
|
||||
handle_cmd_allocate_channel(port_id, data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pmt_eq(event, s_cmd_deallocate_channel)) {
|
||||
handle_cmd_deallocate_channel(port_id, data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pmt_eq(event, s_cmd_xmit_raw_frame)){
|
||||
handle_cmd_xmit_raw_frame(data);
|
||||
return;
|
||||
}
|
||||
|
||||
unhandled:
|
||||
std::cout << "[USRP_SERVER] unhandled msg: " << msg << std::endl;
|
||||
}
|
||||
|
||||
// Return -1 if it is not an RX port, or an index
|
||||
int usrp_server::tx_port_index(pmt_t port_id) {
|
||||
|
||||
for(int i=0; i < (int) d_tx.size(); i++)
|
||||
if(pmt_eq(d_tx[i]->port_symbol(), port_id))
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Return -1 if it is not an RX port, or an index
|
||||
int usrp_server::rx_port_index(pmt_t port_id) {
|
||||
|
||||
for(int i=0; i < (int) d_rx.size(); i++)
|
||||
if(pmt_eq(d_rx[i]->port_symbol(), port_id))
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Go through all TX and RX channels, sum up the assigned capacity
|
||||
// and return it
|
||||
long usrp_server::current_capacity_allocation() {
|
||||
long capacity = 0;
|
||||
|
||||
for(int chan=0; chan < d_ntx_chan; chan++)
|
||||
capacity += d_chaninfo_tx[chan].assigned_capacity;
|
||||
|
||||
for(int chan=0; chan < d_nrx_chan; chan++)
|
||||
capacity += d_chaninfo_rx[chan].assigned_capacity;
|
||||
|
||||
return capacity;
|
||||
}
|
||||
|
||||
void usrp_server::handle_cmd_allocate_channel(pmt_t port_id, 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;
|
||||
|
||||
// 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) {
|
||||
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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "[USRP_SERVER] Couldnt find a TX chan\n";
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// 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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void usrp_server::handle_cmd_xmit_raw_frame(pmt_t data) {
|
||||
|
||||
size_t n_bytes, psize;
|
||||
long max_payload_len = transport_pkt::max_payload();
|
||||
|
||||
pmt_t invocation_handle = pmt_nth(0, 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));
|
||||
|
||||
// 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 =
|
||||
(transport_pkt *) pmt_u8vector_writeable_elements(v_packets, psize);
|
||||
|
||||
for(int n=0; n < n_packets; n++) {
|
||||
|
||||
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);
|
||||
pkts[n].set_timestamp(timestamp);
|
||||
} else {
|
||||
pkts[n].set_header(0, channel, 0, payload_len);
|
||||
pkts[n].set_timestamp(0xffffffff);
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
REGISTER_MBLOCK_CLASS(usrp_server);
|
|
@ -0,0 +1,82 @@
|
|||
/* -*- 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 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.
|
||||
*/
|
||||
#ifndef INCLUDED_USRP_SERVER_H
|
||||
#define INCLUDED_USRP_SERVER_H
|
||||
|
||||
#include <mb_mblock.h>
|
||||
#include <vector>
|
||||
|
||||
/*!
|
||||
* \brief Implements the lowest-level mblock 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,
|
||||
TX_PORT = 1
|
||||
};
|
||||
static const int N_PORTS = 4;
|
||||
std::vector<mb_port_sptr> d_tx, d_rx;
|
||||
mb_port_sptr d_cs;
|
||||
|
||||
static const int D_USB_CAPACITY = 32 * 1024 * 1024;
|
||||
static const int D_MAX_CHANNELS = 16;
|
||||
long d_ntx_chan;
|
||||
long d_nrx_chan;
|
||||
|
||||
struct channel_info {
|
||||
long assigned_capacity; // the capacity currently assignedby the channel
|
||||
pmt_t owner; // port ID of the owner of the channel
|
||||
};
|
||||
|
||||
struct channel_info d_chaninfo_tx[D_MAX_CHANNELS];
|
||||
struct channel_info d_chaninfo_rx[D_MAX_CHANNELS];
|
||||
|
||||
public:
|
||||
usrp_server(mb_runtime *rt, const std::string &instance_name, pmt_t user_arg);
|
||||
~usrp_server();
|
||||
|
||||
void initial_transition();
|
||||
void handle_message(mb_message_sptr msg);
|
||||
|
||||
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);
|
||||
int rx_port_index(pmt_t port_id);
|
||||
int tx_port_index(pmt_t port_id);
|
||||
long current_capacity_allocation();
|
||||
};
|
||||
|
||||
#endif /* INCLUDED_USRP_SERVER_H */
|
|
@ -0,0 +1,256 @@
|
|||
;; -*- scheme -*- ; not really, but tells emacs how to format this
|
||||
;;
|
||||
;; Copyright 2007 Free Software Foundation, Inc.
|
||||
;;
|
||||
;; This file is part of GNU Radio
|
||||
;;
|
||||
;; GNU Radio is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation; either version 2, or (at your option)
|
||||
;; any later version.
|
||||
;;
|
||||
;; GNU Radio is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
;;
|
||||
;; You should have received a copy of the GNU General Public License along
|
||||
;; with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
;; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
;;
|
||||
|
||||
;; ----------------------------------------------------------------
|
||||
;; This is an mblock header file
|
||||
;;
|
||||
;; The format is very much a work-in-progress.
|
||||
;; It'll be compiled to C++.
|
||||
;; ----------------------------------------------------------------
|
||||
|
||||
;; In the outgoing messages described below, invocation-handle is an
|
||||
;; identifier provided by the client to tag the method invocation.
|
||||
;; The identifier will be returned with the response, to provide the
|
||||
;; client with a mechanism to match asynchronous responses with the
|
||||
;; commands that generate them. The value of the invocation-handle is
|
||||
;; opaque the the server, and is not required by the server to be
|
||||
;; unique.
|
||||
;;
|
||||
;; In the incoming messages described below, invocation-handle is the
|
||||
;; identifier provided by the client in the prompting invocation. The
|
||||
;; identifier is returned with the response, so that the client has a
|
||||
;; mechanism to match asynchronous responses with the commands that
|
||||
;; generated them.
|
||||
;;
|
||||
;; status is either #t, indicating success, or a pair containing
|
||||
;; (status-code . message), where status-code is a symbol and message
|
||||
;; is a string.
|
||||
|
||||
|
||||
;; ----------------------------------------------------------------
|
||||
;; usrp-channel
|
||||
;;
|
||||
;; The protocol class is defined from the client's point-of-view.
|
||||
;; (The client port is unconjugated, the server port is conjugated.)
|
||||
|
||||
(define-protocol-class usrp-channel
|
||||
|
||||
(:outgoing
|
||||
|
||||
(cmd-allocate-channel invocation-handle capacity-reservation)
|
||||
|
||||
;; The cmd-allocate-channel message requests that the server
|
||||
;; allocates a logical channel in the FPGA for use.
|
||||
;; capacity-reservation specifies the number of bytes/s of
|
||||
;; interconnect capacity (USB or ethernet) to reserve for this
|
||||
;; channel. (The reservation is just a sanity check, no OS
|
||||
;; specific mechanism is used.)
|
||||
|
||||
(cmd-deallocate-channel invocation-handle channel)
|
||||
|
||||
;; The integer channel specifies the channel to deallocate.
|
||||
|
||||
)
|
||||
|
||||
(:incoming
|
||||
|
||||
|
||||
(response-allocate-channel invocation-handle status channel)
|
||||
|
||||
;; If successful, a channel the specified capacity was allocated.
|
||||
;; channel, an integer, indicates which channel was allocated.
|
||||
|
||||
(response-deallocate-channel invocation-handle status)
|
||||
|
||||
;; If successful, the specified channel and associated interconnect
|
||||
;; capacity were deallocated.
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
;; ----------------------------------------------------------------
|
||||
;; usrp-low-level-cs
|
||||
;;
|
||||
;; The protocol class is defined from the client's point-of-view.
|
||||
;; (The client port is unconjugated, the server port is conjugated.)
|
||||
;;
|
||||
;; This defines a low level control and status interface to the usrp.
|
||||
;; This will probably be replaced (or at least augmented) with a
|
||||
;; higher level interface. For now, this will allow us to get on
|
||||
;; the air.
|
||||
;;
|
||||
;; The subpackets are lists containing the relevant parameters. The
|
||||
;; server will marshall them appropriately. Below is a list of
|
||||
;; subpackets. See inband-signaling-usb for details. The opcodes are
|
||||
;; symbols; unless otherwise indicated the remaining parameters are
|
||||
;; integers. rid values are limited to 3-bits.
|
||||
;;
|
||||
;; (op-ping-fixed rid ping-value)
|
||||
;; (op-ping-fixed-reply rid ping-value)
|
||||
;; (op-write-reg reg-number reg-value)
|
||||
;; (op-write-reg-masked reg-number reg-value mask-value)
|
||||
;; (op-read-reg rid reg-number reg-value)
|
||||
;; (op-read-reg-reply rid reg-number reg-value)
|
||||
;; (op-i2c-write i2c-addr u8-vec)
|
||||
;; (op-i2c-read rid i2c-addr nbytes)
|
||||
;; (op-i2c-read-reply rid i2c-addr u8-vec)
|
||||
;; (op-spi-write enables format opt-header-bytes u8-vec)
|
||||
;; (op-spi-read rid enables format opt-header-bytes nbytes)
|
||||
;; (op-spi-read-reply rid u8-vec)
|
||||
;; (op-delay ticks)
|
||||
|
||||
|
||||
(define-protocol-class usrp-low-level-cs
|
||||
|
||||
(:outgoing
|
||||
|
||||
(cmd-to-control-channel invocation-handle list-of-subpackets)
|
||||
|
||||
)
|
||||
|
||||
(:incoming
|
||||
|
||||
(response-from-control-channel invocation-handle status list-of-subpackets)
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
;; ----------------------------------------------------------------
|
||||
;; usrp-tx
|
||||
;;
|
||||
;; The protocol class is defined from the client's point-of-view.
|
||||
;; (The client port is unconjugated, the server port is conjugated.)
|
||||
|
||||
(define-protocol-class usrp-tx
|
||||
(:include usrp-channel)
|
||||
(:include usrp-low-level-cs)
|
||||
|
||||
(:outgoing
|
||||
|
||||
(cmd-xmit-raw-frame invocation-handle channel samples timestamp)
|
||||
|
||||
;; The argument channel must be an integer. It specifies the
|
||||
;; channel on which the frame of samples will be be sent.
|
||||
;;
|
||||
;; samples must be a uniform numeric vector. The contents of the
|
||||
;; sample vector is treated as opaque and is passed on to the FPGA
|
||||
;; unmodified. It is the responsibility of the sender to ensure
|
||||
;; that the binary format is sensible for the current FPGA
|
||||
;; configuration.
|
||||
;;
|
||||
;; timestamp is a 32-bit integer that specifies the time at which
|
||||
;; the first sample in samples shall be sent to the D/A converter.
|
||||
;; The format and interpration of time is specified in the file
|
||||
;; inband-signaling-usb
|
||||
)
|
||||
|
||||
(:incoming
|
||||
|
||||
(response-xmit-raw-frame invocation-handle status)
|
||||
|
||||
;; If successful, the samples of the associated frame have been
|
||||
;; transmitted to the USRP. This message may be used to implement
|
||||
;; Tx flow control. The client could for example implement a
|
||||
;; policy of never having more than 4 unacknowledged
|
||||
;; cmd-xmit-raw-frame's outstanding.
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
;; ----------------------------------------------------------------
|
||||
;; usrp-rx
|
||||
;;
|
||||
;; The protocol class is defined from the client's point-of-view.
|
||||
;; (The client port is unconjugated, the server port is conjugated.)
|
||||
|
||||
(define-protocol-class usrp-rx
|
||||
(:include usrp-channel)
|
||||
(:include usrp-low-level-cs)
|
||||
|
||||
(:outgoing
|
||||
|
||||
(cmd-start-recv-raw-samples invocation-handle channel)
|
||||
|
||||
;; The argument channel must be an integer. It specifies the
|
||||
;; channel from which frames of samples will be be received. The
|
||||
;; server will return response-recv-raw-samples messages until a
|
||||
;; cmd-stop-recv-raw-samples message is received.
|
||||
|
||||
(cmd-stop-recv-raw-samples invocation-handle channel)
|
||||
|
||||
;; The argument channel must be an integer. There is no reply to
|
||||
;; this message.
|
||||
|
||||
)
|
||||
|
||||
(:incoming
|
||||
|
||||
(response-recv-raw-samples invocation-handle status samples timestamp properties)
|
||||
|
||||
;; samples is a uniform numeric vector. The contents of the sample
|
||||
;; vector is treated as opaque and is passed from the FPGA
|
||||
;; unmodified. It is the responsibility of the receiver to decode
|
||||
;; the binary format as appropriate for the current FPGA
|
||||
;; configuration.
|
||||
;;
|
||||
;; timestamp is a 32-bit integer that specifies the time at which
|
||||
;; the first sample in samples was received from the A/D converter.
|
||||
;; The format and interpretation of time is as specified in the
|
||||
;; file inband-signaling-usb.
|
||||
;;
|
||||
;; properties is a dictionary containing additional (key, value)
|
||||
;; pairs associated with the reception of these samples. In
|
||||
;; particular, the map may contain the Received Signal Strength
|
||||
;; Indication (RSSI) reported by the front end at the time the
|
||||
;; first sample was received from the A/D.
|
||||
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
;; ----------------------------------------------------------------
|
||||
;; usrp-server-cs
|
||||
;;
|
||||
;; Control and status port for usrp-server
|
||||
;;
|
||||
;; The protocol class is defined from the client's point-of-view.
|
||||
;; (The client port is unconjugated, the server port is conjugated.)
|
||||
|
||||
(define-protocol-class usrp-server-cs
|
||||
|
||||
(:outgoing
|
||||
(cmd-open invocation-handle which-usrp)
|
||||
(cmd-close invocation-handle)
|
||||
(cmd-max-capacity invocation-handle)
|
||||
(cmd-ntx-chan invocation-handle)
|
||||
(cmd-nrx-chan invocation-handle)
|
||||
(cmd-current-capacity-allocation invocation-handle)
|
||||
)
|
||||
|
||||
(: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)
|
||||
)
|
||||
)
|
|
@ -0,0 +1,153 @@
|
|||
#
|
||||
# USRP - Universal Software Radio Peripheral
|
||||
#
|
||||
# Copyright (C) 2003,2004,2006,2007 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program 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, Boston, MA 02110-1301 USA
|
||||
#
|
||||
|
||||
include $(top_srcdir)/Makefile.common
|
||||
|
||||
INCLUDES = $(USRP_INCLUDES)
|
||||
|
||||
lib_LTLIBRARIES = libusrp.la
|
||||
|
||||
libusrp_la_LDFLAGS = $(NO_UNDEFINED) -version-info 0:0:0
|
||||
|
||||
libusrp_la_LIBADD = \
|
||||
$(USB_LIBS) \
|
||||
../../misc/libmisc.la
|
||||
|
||||
EXTRA_DIST = \
|
||||
std_paths.h.in \
|
||||
usrp_dbid.dat
|
||||
|
||||
|
||||
BUILT_SOURCES = \
|
||||
usrp_dbid.h \
|
||||
usrp_dbid.cc \
|
||||
usrp_dbid.py
|
||||
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# FUSB_TECH is set at configure time by way of
|
||||
# usrp/config/usrp_fusb_tech.m4.
|
||||
# It indicates which fast usb strategy we should be building.
|
||||
# We currently implement "generic", "darwin", "win32" and "linux"
|
||||
|
||||
|
||||
generic_CODE = \
|
||||
fusb_generic.cc \
|
||||
fusb_sysconfig_generic.cc
|
||||
|
||||
darwin_CODE = \
|
||||
fusb_darwin.cc \
|
||||
fusb_sysconfig_darwin.cc \
|
||||
README_OSX \
|
||||
circular_buffer.h \
|
||||
circular_linked_list.h \
|
||||
darwin_libusb.h \
|
||||
mld_threads.h
|
||||
|
||||
win32_CODE = \
|
||||
fusb_win32.cc \
|
||||
fusb_sysconfig_win32.cc
|
||||
|
||||
linux_CODE = \
|
||||
fusb_linux.cc \
|
||||
fusb_sysconfig_linux.cc
|
||||
|
||||
ra_wb_CODE = \
|
||||
fusb_ra_wb.cc \
|
||||
fusb_sysconfig_ra_wb.cc
|
||||
|
||||
|
||||
#
|
||||
# include each <foo>_CODE entry here...
|
||||
#
|
||||
EXTRA_libusrp_la_SOURCES = \
|
||||
$(generic_CODE) \
|
||||
$(darwin_CODE) \
|
||||
$(win32_CODE) \
|
||||
$(linux_CODE) \
|
||||
$(ra_wb_CODE)
|
||||
|
||||
|
||||
# work around automake deficiency
|
||||
libusrp_la_common_SOURCES = \
|
||||
fusb.cc \
|
||||
md5.c \
|
||||
usrp_basic.cc \
|
||||
usrp_config.cc \
|
||||
usrp_dbid.cc \
|
||||
usrp_local_sighandler.cc \
|
||||
usrp_prims.cc \
|
||||
usrp_standard.cc
|
||||
|
||||
|
||||
if FUSB_TECH_generic
|
||||
libusrp_la_SOURCES = $(libusrp_la_common_SOURCES) $(generic_CODE)
|
||||
endif
|
||||
|
||||
if FUSB_TECH_darwin
|
||||
libusrp_la_SOURCES = $(libusrp_la_common_SOURCES) $(darwin_CODE)
|
||||
endif
|
||||
|
||||
if FUSB_TECH_win32
|
||||
libusrp_la_SOURCES = $(libusrp_la_common_SOURCES) $(win32_CODE)
|
||||
endif
|
||||
|
||||
if FUSB_TECH_linux
|
||||
libusrp_la_SOURCES = $(libusrp_la_common_SOURCES) $(linux_CODE)
|
||||
endif
|
||||
|
||||
if FUSB_TECH_ra_wb
|
||||
libusrp_la_SOURCES = $(libusrp_la_common_SOURCES) $(ra_wb_CODE)
|
||||
endif
|
||||
|
||||
include_HEADERS = \
|
||||
usrp_basic.h \
|
||||
usrp_bytesex.h \
|
||||
usrp_config.h \
|
||||
usrp_dbid.h \
|
||||
usrp_prims.h \
|
||||
usrp_slots.h \
|
||||
usrp_standard.h
|
||||
|
||||
noinst_HEADERS = \
|
||||
ad9862.h \
|
||||
fusb.h \
|
||||
fusb_darwin.h \
|
||||
fusb_win32.h \
|
||||
fusb_generic.h \
|
||||
fusb_linux.h \
|
||||
fusb_ra_wb.h \
|
||||
md5.h \
|
||||
rate_to_regval.h \
|
||||
usrp_local_sighandler.h
|
||||
|
||||
usrppython_PYTHON = \
|
||||
usrp_dbid.py
|
||||
|
||||
noinst_PYTHON = \
|
||||
gen_usrp_dbid.py \
|
||||
check_data.py \
|
||||
dump_data.py
|
||||
|
||||
usrp_dbid.py usrp_dbid.h usrp_dbid.cc: gen_usrp_dbid.py usrp_dbid.dat
|
||||
PYTHONPATH=$(top_srcdir)/usrp/src srcdir=$(srcdir) $(PYTHON) $(srcdir)/gen_usrp_dbid.py $(srcdir)/usrp_dbid.dat
|
||||
|
||||
MOSTLYCLEANFILES = \
|
||||
$(BUILT_SOURCES) *~ *.pyc
|
|
@ -923,8 +923,6 @@ usrp_basic_tx::usrp_basic_tx (int which_board, int fusb_block_size, int fusb_nbl
|
|||
_write_fpga_reg(FR_ATR_MASK_2, 0);
|
||||
_write_fpga_reg(FR_ATR_TXVAL_2, 0);
|
||||
_write_fpga_reg(FR_ATR_RXVAL_2, 0);
|
||||
_write_fpga_reg(FR_ATR_TX_DELAY, 0);
|
||||
_write_fpga_reg(FR_ATR_RX_DELAY, 0);
|
||||
}
|
||||
|
||||
|
|
@ -38,11 +38,30 @@ bswap_16 (unsigned short int x)
|
|||
{
|
||||
return ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8));
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
bswap32 (unsigned int x)
|
||||
{
|
||||
return ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) \
|
||||
| (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
|
||||
static inline unsigned int
|
||||
host_to_usrp_u32 (unsigned int x)
|
||||
{
|
||||
return bswap_32(x);
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
usrp_to_host_u32 (unsigned int x)
|
||||
{
|
||||
return bswap_32(x);
|
||||
}
|
||||
|
||||
static inline short int
|
||||
host_to_usrp_short (short int x)
|
||||
{
|
||||
|
@ -57,6 +76,18 @@ usrp_to_host_short (short int x)
|
|||
|
||||
#else
|
||||
|
||||
static inline unsigned int
|
||||
host_to_usrp_u32 (unsigned int x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
usrp_to_host_u32 (unsigned int x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline short int
|
||||
host_to_usrp_short (short int x)
|
||||
{
|
|
@ -64,7 +64,7 @@ _usrp_prims_la_SOURCES = \
|
|||
|
||||
noinst_HEADERS =
|
||||
|
||||
_usrp_prims_la_LIBADD = $(top_builddir)/usrp/host/lib/libusrp.la -lstdc++ $(PYTHON_LDFLAGS)
|
||||
_usrp_prims_la_LIBADD = $(USRP_LA) -lstdc++ $(PYTHON_LDFLAGS)
|
||||
_usrp_prims_la_LDFLAGS = $(NO_UNDEFINED) -module -avoid-version
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue