2 * Copyright 2007,2008 Free Software Foundation, Inc.
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "memory_map.h"
26 #include "buffer_pool.h"
31 #include "usrp2_eth_packet.h"
33 #include "app_common.h"
34 #include "print_rmon_regs.h"
41 * Like tx_only.c, but we discard data packets instead of sending them to the
45 int total_rx_pkts = 0;
46 int total_rx_bytes = 0;
49 static int timer_delta = MASTER_CLK_RATE/1000; // tick at 1kHz
52 * This program can respond to queries from the host
53 * and stream rx samples.
55 * Buffer 1 is used by the cpu to send frames to the host.
56 * Buffers 2 and 3 are used to double-buffer the DSP Rx to eth flow
57 * Buffers 4 and 5 are used to double-buffer the eth to DSP Tx eth flow
59 //#define CPU_RX_BUF 0 // eth -> cpu
60 //#define CPU_TX_BUF 1 // cpu -> eth
62 #define DSP_RX_BUF_0 2 // dsp rx -> eth (double buffer)
63 #define DSP_RX_BUF_1 3 // dsp rx -> eth
64 #define DSP_TX_BUF_0 4 // eth -> dsp tx (double buffer)
65 #define DSP_TX_BUF_1 5 // eth -> dsp tx
69 * ================================================================
70 * configure DSP TX double buffering state machine
71 * ================================================================
74 // 4 lines of ethernet hdr + 2 lines (word0 + timestamp)
75 // DSP Tx reads word0 (flags) + timestamp followed by samples
77 #define DSP_TX_FIRST_LINE 4
78 #define DSP_TX_SAMPLES_PER_FRAME 250 // not used except w/ debugging
79 #define DSP_TX_EXTRA_LINES 2 // reads word0 + timestamp
81 // Receive from ethernet
82 buf_cmd_args_t dsp_tx_recv_args = {
89 buf_cmd_args_t dsp_tx_send_args = {
91 DSP_TX_FIRST_LINE, // starts just past ethernet header
92 0 // filled in from last_line register
95 dbsm_t dsp_tx_sm; // the state machine
98 // ----------------------------------------------------------------
101 // The mac address of the host we're sending to.
102 u2_mac_addr_t host_mac_addr;
106 timer_irq_handler(unsigned irq)
108 hal_set_timeout(timer_delta); // schedule next timeout
113 underrun_irq_handler(unsigned irq)
117 dbsm_stop(&dsp_tx_sm);
118 dsp_tx_regs->clear_state = 1;
119 dbsm_start(&dsp_tx_sm); // restart sm so we're listening to ethernet again
121 // putstr("\nirq: underrun\n");
126 start_rx_cmd(const u2_mac_addr_t *host, op_start_rx_t *p)
138 dsp_tx_regs->clear_state = 1;
139 bp_clear_buf(DSP_TX_BUF_0);
140 bp_clear_buf(DSP_TX_BUF_1);
145 op_config_tx_t def_config;
146 memset(&def_config, 0, sizeof(def_config));
147 def_config.phase_inc = 408021893; // 9.5 MHz [2**32 * fc/fsample]
148 def_config.scale_iq = (tx_scale << 16) | tx_scale;
149 def_config.interp = interp;
152 config_tx_cmd(&def_config);
157 buffer_irq_handler(unsigned irq)
159 uint32_t status = buffer_pool_status->status;
161 if (status & BPS_ERROR_ALL){
162 // FIXME rare path, handle error conditions
163 putstr("Errors! status = ");
166 printf("total_rx_pkts = %d\n", total_rx_pkts);
167 printf("total_rx_bytes = %d\n", total_rx_bytes);
171 if (status & (BPS_ERROR(DSP_TX_BUF_0) | BPS_ERROR(DSP_TX_BUF_1))){
172 dbsm_stop(&dsp_tx_sm);
173 dsp_tx_regs->clear_state = 1; // try to restart
174 dbsm_start(&dsp_tx_sm);
179 dbsm_process_status(&dsp_tx_sm, status);
181 if (status & BPS_DONE(CPU_TX_BUF)){
182 bp_clear_buf(CPU_TX_BUF);
188 * Called when an ethernet packet is received.
190 * Claim that we handled all the packets,
191 * dropping those destined for the TX DSP chain
195 nop_eth_pkt_inspector(dbsm_t *sm, int bufno)
197 hal_toggle_leds(0x1);
199 u2_eth_packet_t *pkt = (u2_eth_packet_t *) buffer_ram(bufno);
200 size_t byte_len = (buffer_pool_status->last_line[bufno] - 1) * 4;
203 total_rx_bytes += byte_len;
205 // inspect rcvd frame and figure out what do do.
207 if (pkt->ehdr.ethertype != U2_ETHERTYPE)
208 return true; // ignore, probably bogus PAUSE frame from MAC
210 int chan = u2p_chan(&pkt->fixed);
214 handle_control_chan_frame(pkt, byte_len);
215 return true; // we handled the packet
220 return true; // We handled the data by dropping it :)
231 // setup tx gpio bits for GPIOM_FPGA_1 -- fpga debug output
232 hal_gpio_set_tx_mode(15, 0, GPIOM_FPGA_1);
233 hal_gpio_set_rx_mode(15, 0, GPIOM_FPGA_1);
235 putstr("\ntx_drop\n");
238 hal_set_leds(0x0, 0x3);
240 pic_register_handler(IRQ_UNDERRUN, underrun_irq_handler);
242 ethernet_register_link_changed_callback(link_changed_callback);
245 // initialize double buffering state machine for ethernet -> DSP Tx
247 dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0,
248 &dsp_tx_recv_args, &dsp_tx_send_args,
249 nop_eth_pkt_inspector);
251 // program tx registers
254 // kick off the state machine
255 dbsm_start(&dsp_tx_sm);
258 buffer_irq_handler(0);