~ubuntu-branches/ubuntu/trusty/gnuradio/trusty

« back to all changes in this revision

Viewing changes to usrp2/firmware/apps/txrx.c

  • Committer: Bazaar Package Importer
  • Author(s): Kamal Mostafa
  • Date: 2010-03-13 07:46:01 UTC
  • mfrom: (2.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20100313074601-zjsa893a87bozyh7
Tags: 3.2.2.dfsg-1ubuntu1
* Fix build for Ubuntu lucid (LP: #260406)
  - add binary package dep for libusrp0, libusrp2-0: adduser
  - debian/rules clean: remove pre-built Qt moc files

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2007,2008 Free Software Foundation, Inc.
 
3
 *
 
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.
 
8
 *
 
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.
 
13
 *
 
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/>.
 
16
 */
 
17
 
 
18
#ifdef HAVE_CONFIG_H
 
19
#include "config.h"
 
20
#endif
 
21
 
 
22
#include "u2_init.h"
 
23
#include "memory_map.h"
 
24
#include "spi.h"
 
25
#include "hal_io.h"
 
26
#include "buffer_pool.h"
 
27
#include "pic.h"
 
28
#include "bool.h"
 
29
#include "ethernet.h"
 
30
#include "nonstdio.h"
 
31
#include "usrp2_eth_packet.h"
 
32
#include "dbsm.h"
 
33
#include "app_common_v2.h"
 
34
#include "memcpy_wa.h"
 
35
#include <stddef.h>
 
36
#include <stdlib.h>
 
37
#include <string.h>
 
38
#include "clocks.h"
 
39
 
 
40
#define FW_SETS_SEQNO   1       // define to 0 or 1 (FIXME must be 1 for now)
 
41
 
 
42
#if (FW_SETS_SEQNO)
 
43
static int fw_seqno;    // used when f/w is filling in sequence numbers
 
44
#endif
 
45
 
 
46
 
 
47
/*
 
48
 * Full duplex Tx and Rx between ethernet and DSP pipelines
 
49
 *
 
50
 * Buffer 1 is used by the cpu to send frames to the host.
 
51
 * Buffers 2 and 3 are used to double-buffer the DSP Rx to eth flow
 
52
 * Buffers 4 and 5 are used to double-buffer the eth to DSP Tx  eth flow
 
53
 */
 
54
//#define CPU_RX_BUF    0       // eth -> cpu
 
55
 
 
56
#define DSP_RX_BUF_0    2       // dsp rx -> eth (double buffer)
 
57
#define DSP_RX_BUF_1    3       // dsp rx -> eth
 
58
#define DSP_TX_BUF_0    4       // eth -> dsp tx (double buffer)
 
59
#define DSP_TX_BUF_1    5       // eth -> dsp tx
 
60
 
 
61
/*
 
62
 * ================================================================
 
63
 *   configure DSP TX double buffering state machine (eth -> dsp)
 
64
 * ================================================================
 
65
 */
 
66
 
 
67
// 4 lines of ethernet hdr + 1 line transport hdr + 2 lines (word0 + timestamp)
 
68
// DSP Tx reads word0 (flags) + timestamp followed by samples
 
69
 
 
70
#define DSP_TX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4)
 
71
 
 
72
// Receive from ethernet
 
73
buf_cmd_args_t dsp_tx_recv_args = {
 
74
  PORT_ETH,
 
75
  0,
 
76
  BP_LAST_LINE
 
77
};
 
78
 
 
79
// send to DSP Tx
 
80
buf_cmd_args_t dsp_tx_send_args = {
 
81
  PORT_DSP,
 
82
  DSP_TX_FIRST_LINE,    // starts just past transport header
 
83
  0                     // filled in from last_line register
 
84
};
 
85
 
 
86
dbsm_t dsp_tx_sm;       // the state machine
 
87
 
 
88
/*
 
89
 * ================================================================
 
90
 *   configure DSP RX double buffering state machine (dsp -> eth)
 
91
 * ================================================================
 
92
 */
 
93
 
 
94
// 4 lines of ethernet hdr + 1 line transport hdr + 1 line (word0)
 
95
// DSP Rx writes timestamp followed by nlines_per_frame of samples
 
96
#define DSP_RX_FIRST_LINE ((sizeof(u2_eth_hdr_t) + sizeof(u2_transport_hdr_t))/4 + 1)
 
97
 
 
98
// receive from DSP
 
99
buf_cmd_args_t dsp_rx_recv_args = {
 
100
  PORT_DSP,
 
101
  DSP_RX_FIRST_LINE,
 
102
  BP_LAST_LINE
 
103
};
 
104
 
 
105
// send to ETH
 
106
buf_cmd_args_t dsp_rx_send_args = {
 
107
  PORT_ETH,
 
108
  0,            // starts with ethernet header in line 0
 
109
  0,            // filled in from list_line register
 
110
};
 
111
 
 
112
dbsm_t dsp_rx_sm;       // the state machine
 
113
 
 
114
 
 
115
// The mac address of the host we're sending to.
 
116
u2_mac_addr_t host_mac_addr;
 
117
 
 
118
 
 
119
// variables for streaming mode
 
120
 
 
121
static bool         streaming_p = false;
 
122
static unsigned int streaming_items_per_frame = 0;
 
123
static int          streaming_frame_count = 0;
 
124
#define FRAMES_PER_CMD  1000
 
125
 
 
126
bool is_streaming(void){ return streaming_p; }
 
127
 
 
128
 
 
129
// ----------------------------------------------------------------
 
130
 
 
131
 
 
132
void
 
133
restart_streaming(void)
 
134
{
 
135
  // setup RX DSP regs
 
136
  dsp_rx_regs->clear_state = 1;                 // reset
 
137
 
 
138
  streaming_p = true;
 
139
  streaming_frame_count = FRAMES_PER_CMD;
 
140
 
 
141
  dsp_rx_regs->rx_command =
 
142
    MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame,
 
143
              streaming_items_per_frame,
 
144
              1, 1);                    // set "chain" bit
 
145
 
 
146
  // kick off the state machine
 
147
  dbsm_start(&dsp_rx_sm);
 
148
 
 
149
  dsp_rx_regs->rx_time = 0;             // enqueue first of two commands
 
150
 
 
151
  // make sure this one and the rest have the "now" and "chain" bits set.
 
152
  dsp_rx_regs->rx_command =
 
153
    MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame,
 
154
              streaming_items_per_frame,
 
155
              1, 1);                            
 
156
 
 
157
  dsp_rx_regs->rx_time = 0;             // enqueue second command
 
158
}
 
159
 
 
160
void
 
161
start_rx_streaming_cmd(const u2_mac_addr_t *host, op_start_rx_streaming_t *p)
 
162
{
 
163
  host_mac_addr = *host;        // remember who we're sending to
 
164
 
 
165
  /*
 
166
   * Construct  ethernet header and word0 and preload into two buffers
 
167
   */
 
168
  u2_eth_packet_t       pkt;
 
169
  memset(&pkt, 0, sizeof(pkt));
 
170
  pkt.ehdr.dst = *host;
 
171
  pkt.ehdr.ethertype = U2_ETHERTYPE;
 
172
  u2p_set_word0(&pkt.fixed, 0, 0);
 
173
  // DSP RX will fill in timestamp
 
174
 
 
175
  memcpy_wa(buffer_ram(DSP_RX_BUF_0), &pkt, sizeof(pkt));
 
176
  memcpy_wa(buffer_ram(DSP_RX_BUF_1), &pkt, sizeof(pkt));
 
177
 
 
178
 
 
179
  if (FW_SETS_SEQNO)
 
180
    fw_seqno = 0;
 
181
 
 
182
  streaming_items_per_frame = p->items_per_frame;
 
183
  restart_streaming();
 
184
}
 
185
 
 
186
 
 
187
void
 
188
stop_rx_cmd(void)
 
189
{
 
190
  streaming_p = false;
 
191
  dsp_rx_regs->clear_state = 1; // flush cmd queue
 
192
  bp_clear_buf(DSP_RX_BUF_0);
 
193
  bp_clear_buf(DSP_RX_BUF_1);
 
194
}
 
195
 
 
196
 
 
197
static void
 
198
setup_tx()
 
199
{
 
200
  dsp_tx_regs->clear_state = 1;
 
201
  bp_clear_buf(DSP_TX_BUF_0);
 
202
  bp_clear_buf(DSP_TX_BUF_1);
 
203
 
 
204
  int tx_scale = 256;
 
205
  int interp = 32;
 
206
 
 
207
  // setup some defaults
 
208
 
 
209
  dsp_tx_regs->freq = 0;
 
210
  dsp_tx_regs->scale_iq = (tx_scale << 16) | tx_scale;
 
211
  dsp_tx_regs->interp_rate = interp;
 
212
}
 
213
 
 
214
 
 
215
#if (FW_SETS_SEQNO)
 
216
/*
 
217
 * Debugging ONLY.  This will be handled by the tx_protocol_engine.
 
218
 *
 
219
 * This is called when the DSP Rx chain has filled in a packet.
 
220
 * We set and increment the seqno, then return false, indicating
 
221
 * that we didn't handle the packet.  A bit of a kludge
 
222
 * but it should work.
 
223
 */
 
224
bool 
 
225
fw_sets_seqno_inspector(dbsm_t *sm, int buf_this)       // returns false
 
226
{
 
227
  uint32_t *p = buffer_ram(buf_this);
 
228
  uint32_t seqno = fw_seqno++;
 
229
 
 
230
  // KLUDGE all kinds of nasty magic numbers and embedded knowledge
 
231
  uint32_t t = p[4];
 
232
  t = (t & 0xffff00ff) | ((seqno & 0xff) << 8);
 
233
  p[4] = t;
 
234
 
 
235
  // queue up another rx command when required
 
236
  if (streaming_p && --streaming_frame_count == 0){
 
237
    streaming_frame_count = FRAMES_PER_CMD;
 
238
    dsp_rx_regs->rx_time = 0;
 
239
  }
 
240
 
 
241
  return false;         // we didn't handle the packet
 
242
}
 
243
#endif
 
244
 
 
245
 
 
246
inline static void
 
247
buffer_irq_handler(unsigned irq)
 
248
{
 
249
  uint32_t  status = buffer_pool_status->status;
 
250
 
 
251
  dbsm_process_status(&dsp_tx_sm, status);
 
252
  dbsm_process_status(&dsp_rx_sm, status);
 
253
}
 
254
 
 
255
int
 
256
main(void)
 
257
{
 
258
  u2_init();
 
259
 
 
260
  putstr("\nTxRx\n");
 
261
  print_mac_addr(ethernet_mac_addr()->addr);
 
262
  newline();
 
263
 
 
264
  ethernet_register_link_changed_callback(link_changed_callback);
 
265
  ethernet_init();
 
266
 
 
267
 
 
268
#if 0
 
269
  // make bit 15 of Tx gpio's be a s/w output
 
270
  hal_gpio_set_sel(GPIO_TX_BANK, 15, 's');
 
271
  hal_gpio_set_ddr(GPIO_TX_BANK, 0x8000, 0x8000);
 
272
#endif
 
273
 
 
274
  output_regs->debug_mux_ctrl = 1;
 
275
#if 0
 
276
  hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111");
 
277
  hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111");
 
278
  hal_gpio_set_ddr(GPIO_TX_BANK, 0xffff, 0xffff);
 
279
  hal_gpio_set_ddr(GPIO_RX_BANK, 0xffff, 0xffff);
 
280
#endif
 
281
 
 
282
 
 
283
  // initialize double buffering state machine for ethernet -> DSP Tx
 
284
 
 
285
  dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0,
 
286
            &dsp_tx_recv_args, &dsp_tx_send_args,
 
287
            eth_pkt_inspector);
 
288
 
 
289
 
 
290
  // initialize double buffering state machine for DSP RX -> Ethernet
 
291
 
 
292
  if (FW_SETS_SEQNO){
 
293
    dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
 
294
              &dsp_rx_recv_args, &dsp_rx_send_args,
 
295
              fw_sets_seqno_inspector);
 
296
  }
 
297
  else {
 
298
    dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
 
299
              &dsp_rx_recv_args, &dsp_rx_send_args,
 
300
              dbsm_nop_inspector);
 
301
  }
 
302
 
 
303
  // tell app_common that this dbsm could be sending to the ethernet
 
304
  ac_could_be_sending_to_eth = &dsp_rx_sm;
 
305
 
 
306
 
 
307
  // program tx registers
 
308
  setup_tx();
 
309
 
 
310
  // kick off the state machine
 
311
  dbsm_start(&dsp_tx_sm);
 
312
 
 
313
  //int which = 0;
 
314
 
 
315
  while(1){
 
316
    // hal_gpio_write(GPIO_TX_BANK, which, 0x8000);
 
317
    // which ^= 0x8000;
 
318
 
 
319
    buffer_irq_handler(0);
 
320
 
 
321
    int pending = pic_regs->pending;            // poll for under or overrun
 
322
 
 
323
    if (pending & PIC_UNDERRUN_INT){
 
324
      dbsm_handle_tx_underrun(&dsp_tx_sm);
 
325
      pic_regs->pending = PIC_UNDERRUN_INT;     // clear interrupt
 
326
      putchar('U');
 
327
    }
 
328
 
 
329
    if (pending & PIC_OVERRUN_INT){
 
330
      dbsm_handle_rx_overrun(&dsp_rx_sm);
 
331
      pic_regs->pending = PIC_OVERRUN_INT;      // clear pending interrupt
 
332
 
 
333
      // FIXME Figure out how to handle this robustly.
 
334
      // Any buffers that are emptying should be allowed to drain...
 
335
 
 
336
      if (streaming_p){
 
337
        // restart_streaming();
 
338
        // FIXME report error
 
339
      }
 
340
      else {
 
341
        // FIXME report error
 
342
      }
 
343
      putchar('O');
 
344
    }
 
345
  }
 
346
}