Statistics
| Branch: | Tag: | Revision:

root / firmware / fx2 / src / usrp1 / usrp_main.c @ b3a09205

History | View | Annotate | Download (8.1 kB)

1
/* 
2
 * USRP - Universal Software Radio Peripheral
3
 *
4
 * Copyright (C) 2003,2004 Free Software Foundation, Inc.
5
 *
6
 * This program is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Boston, MA  02110-1301  USA
19
 */
20

    
21
#include "usrp_common.h"
22
#include "usrp_commands.h"
23
#include "fpga.h"
24
#include "usrp_gpif_inline.h"
25
#include "timer.h"
26
#include "i2c.h"
27
#include "isr.h"
28
#include "usb_common.h"
29
#include "fx2utils.h"
30
#include "usrp_globals.h"
31
#include "usrp_i2c_addr.h"
32
#include <string.h>
33
#include "spi.h"
34
#include "eeprom_io.h"
35
#include "usb_descriptors.h"
36

    
37
/*
38
 * offsets into boot eeprom for configuration values
39
 */
40
#define        HW_REV_OFFSET                  5
41
#define SERIAL_NO_OFFSET        248
42
#define SERIAL_NO_LEN                  8
43

    
44

    
45
#define        bRequestType        SETUPDAT[0]
46
#define        bRequest        SETUPDAT[1]
47
#define        wValueL                SETUPDAT[2]
48
#define        wValueH                SETUPDAT[3]
49
#define        wIndexL                SETUPDAT[4]
50
#define        wIndexH                SETUPDAT[5]
51
#define        wLengthL        SETUPDAT[6]
52
#define        wLengthH        SETUPDAT[7]
53

    
54

    
55
unsigned char g_tx_enable = 0;
56
unsigned char g_rx_enable = 0;
57
unsigned char g_rx_overrun = 0;
58
unsigned char g_tx_underrun = 0;
59

    
60
/*
61
 * the host side fpga loader code pushes an MD5 hash of the bitstream
62
 * into hash1.
63
 */
64
#define          USRP_HASH_SIZE      16
65
xdata at USRP_HASH_SLOT_1_ADDR unsigned char hash1[USRP_HASH_SIZE];
66

    
67
static void
68
get_ep0_data (void)
69
{
70
  EP0BCL = 0;                        // arm EP0 for OUT xfer.  This sets the busy bit
71

    
72
  while (EP0CS & bmEPBUSY)        // wait for busy to clear
73
    ;
74
}
75

    
76
/*
77
 * Handle our "Vendor Extension" commands on endpoint 0.
78
 * If we handle this one, return non-zero.
79
 */
80
unsigned char
81
app_vendor_cmd (void)
82
{
83
  if (bRequestType == VRT_VENDOR_IN){
84

    
85
    /////////////////////////////////
86
    //    handle the IN requests
87
    /////////////////////////////////
88

    
89
    switch (bRequest){
90

    
91
    case VRQ_GET_STATUS:
92
      switch (wIndexL){
93

    
94
      case GS_TX_UNDERRUN:
95
        EP0BUF[0] = g_tx_underrun;
96
        g_tx_underrun = 0;
97
        EP0BCH = 0;
98
        EP0BCL = 1;
99
        break;
100

    
101
      case GS_RX_OVERRUN:
102
        EP0BUF[0] = g_rx_overrun;
103
        g_rx_overrun = 0;
104
        EP0BCH = 0;
105
        EP0BCL = 1;
106
        break;
107

    
108
      default:
109
        return 0;
110
      }
111
      break;
112

    
113
    case VRQ_I2C_READ:
114
      if (!i2c_read (wValueL, EP0BUF, wLengthL))
115
        return 0;
116

    
117
      EP0BCH = 0;
118
      EP0BCL = wLengthL;
119
      break;
120

    
121
    case VRQ_SPI_READ:
122
      if (!spi_read (wValueH, wValueL, wIndexH, wIndexL, EP0BUF, wLengthL))
123
        return 0;
124

    
125
      EP0BCH = 0;
126
      EP0BCL = wLengthL;
127
      break;
128

    
129
    case VRQ_SPI_TRANSACT:
130
      if (!spi_transact (wValueH, wValueL, wIndexH, wIndexL, wLengthH, EP0BUF, wLengthL))
131
        return 0;
132

    
133
      EP0BCH = 0;
134
      EP0BCL = wLengthL;
135
      break;
136

    
137
    default:
138
      return 0;
139
    }
140
  }
141

    
142
  else if (bRequestType == VRT_VENDOR_OUT){
143

    
144
    /////////////////////////////////
145
    //    handle the OUT requests
146
    /////////////////////////////////
147

    
148
    switch (bRequest){
149

    
150
    case VRQ_SET_LED:
151
      switch (wIndexL){
152
      case 0:
153
        set_led_0 (wValueL);
154
        break;
155
        
156
      case 1:
157
        set_led_1 (wValueL);
158
        break;
159
        
160
      default:
161
        return 0;
162
      }
163
      break;
164
      
165
    case VRQ_FPGA_LOAD:
166
      switch (wIndexL){                        // sub-command
167
      case FL_BEGIN:
168
        return fpga_load_begin ();
169
        
170
      case FL_XFER:
171
        get_ep0_data ();
172
        return fpga_load_xfer (EP0BUF, EP0BCL);
173
        
174
      case FL_END:
175
        return fpga_load_end ();
176
        
177
      default:
178
        return 0;
179
      }
180
      break;
181
      
182

    
183
    case VRQ_FPGA_SET_RESET:
184
      fpga_set_reset (wValueL);
185
      break;
186
      
187
    case VRQ_FPGA_SET_TX_ENABLE:
188
      fpga_set_tx_enable (wValueL);
189
      break;
190
      
191
    case VRQ_FPGA_SET_RX_ENABLE:
192
      fpga_set_rx_enable (wValueL);
193
      break;
194

    
195
    case VRQ_FPGA_SET_TX_RESET:
196
      fpga_set_tx_reset (wValueL);
197
      break;
198
      
199
    case VRQ_FPGA_SET_RX_RESET:
200
      fpga_set_rx_reset (wValueL);
201
      break;
202

    
203
    case VRQ_I2C_WRITE:
204
      get_ep0_data ();
205
      if (!i2c_write (wValueL, EP0BUF, EP0BCL))
206
        return 0;
207
      break;
208

    
209
    case VRQ_SPI_WRITE:
210
      get_ep0_data ();
211
      if (!spi_write (wValueH, wValueL, wIndexH, wIndexL, EP0BUF, EP0BCL))
212
        return 0;
213
      break;
214

    
215
    default:
216
      return 0;
217
    }
218

    
219
  }
220
  else
221
    return 0;    // invalid bRequestType
222

    
223
  return 1;
224
}
225

    
226

    
227

    
228
static void
229
main_loop (void)
230
{
231
  setup_flowstate_common ();
232

    
233
  while (1){
234

    
235
    if (usb_setup_packet_avail ())
236
      usb_handle_setup_packet ();
237
    
238
  
239
    if (GPIFTRIG & bmGPIF_IDLE){
240

    
241
      // OK, GPIF is idle.  Let's try to give it some work.
242

    
243
      // First check for underruns and overruns
244

    
245
      if (UC_BOARD_HAS_FPGA && (USRP_PA & (bmPA_TX_UNDERRUN | bmPA_RX_OVERRUN))){
246
      
247
        // record the under/over run
248
        if (USRP_PA & bmPA_TX_UNDERRUN)
249
          g_tx_underrun = 1;
250

    
251
        if (USRP_PA & bmPA_RX_OVERRUN)
252
          g_rx_overrun = 1;
253

    
254
        // tell the FPGA to clear the flags
255
        fpga_clear_flags ();
256
      }
257

    
258
      // Next see if there are any "OUT" packets waiting for our attention,
259
      // and if so, if there's room in the FPGA's FIFO for them.
260

    
261
      if (g_tx_enable && !(EP24FIFOFLGS & 0x02)){  // USB end point fifo is not empty...
262

    
263
        if (fpga_has_room_for_packet ()){           // ... and FPGA has room for packet
264

    
265
          GPIFTCB1 = 0x01;        SYNCDELAY;
266
          GPIFTCB0 = 0x00;        SYNCDELAY;
267

    
268
          setup_flowstate_write ();
269

    
270
          SYNCDELAY;
271
          GPIFTRIG = bmGPIF_EP2_START | bmGPIF_WRITE;         // start the xfer
272
          SYNCDELAY;
273

    
274
          while (!(GPIFTRIG & bmGPIF_IDLE)){
275
            // wait for the transaction to complete
276
          }
277
        }
278
      }
279

    
280
      // See if there are any requests for "IN" packets, and if so
281
      // whether the FPGA's got any packets for us.
282

    
283
      if (g_rx_enable && !(EP6CS & bmEPFULL)){        // USB end point fifo is not full...
284

    
285
        if (fpga_has_packet_avail ()){                // ... and FPGA has packet available
286

    
287
          GPIFTCB1 = 0x01;        SYNCDELAY;
288
          GPIFTCB0 = 0x00;        SYNCDELAY;
289

    
290
          setup_flowstate_read ();
291

    
292
          SYNCDELAY;
293
          GPIFTRIG = bmGPIF_EP6_START | bmGPIF_READ;         // start the xfer
294
          SYNCDELAY;
295

    
296
          while (!(GPIFTRIG & bmGPIF_IDLE)){
297
            // wait for the transaction to complete
298
          }
299

    
300
          SYNCDELAY;
301
          INPKTEND = 6;        // tell USB we filled buffer (6 is our endpoint num)
302
        }
303
      }
304
    }
305
  }
306
}
307

    
308

    
309
/*
310
 * called at 100 Hz from timer2 interrupt
311
 *
312
 * Toggle led 0
313
 */
314
void
315
isr_tick (void) interrupt
316
{
317
  static unsigned char        count = 1;
318
  
319
  if (--count == 0){
320
    count = 50;
321
    USRP_LED_REG ^= bmLED0;
322
  }
323

    
324
  clear_timer_irq ();
325
}
326

    
327
/*
328
 * Read h/w rev code and serial number out of boot eeprom and
329
 * patch the usb descriptors with the values.
330
 */
331
void
332
patch_usb_descriptors(void)
333
{
334
  static xdata unsigned char hw_rev;
335
  static xdata unsigned char serial_no[8];
336
  unsigned char i;
337

    
338
  eeprom_read(I2C_ADDR_BOOT, HW_REV_OFFSET, &hw_rev, 1);        // LSB of device id
339
  usb_desc_hw_rev_binary_patch_location_0[0] = hw_rev;
340
  usb_desc_hw_rev_binary_patch_location_1[0] = hw_rev;
341
  usb_desc_hw_rev_ascii_patch_location_0[0] = hw_rev + '0';     // FIXME if we get > 9
342

    
343
  eeprom_read(I2C_ADDR_BOOT, SERIAL_NO_OFFSET, serial_no, SERIAL_NO_LEN);
344

    
345
  for (i = 0; i < SERIAL_NO_LEN; i++){
346
    unsigned char ch = serial_no[i];
347
    if (ch == 0xff)        // make unprogrammed EEPROM default to '0'
348
      ch = '0';
349
    usb_desc_serial_number_ascii[i << 1] = ch;
350
  }
351
}
352

    
353
void
354
main (void)
355
{
356
#if 0
357
  g_rx_enable = 0;        // FIXME (work around initialization bug)
358
  g_tx_enable = 0;
359
  g_rx_overrun = 0;
360
  g_tx_underrun = 0;
361
#endif
362

    
363
  memset (hash1, 0, USRP_HASH_SIZE);        // zero fpga bitstream hash.  This forces reload
364
  
365
  init_usrp ();
366
  init_gpif ();
367
  
368
  // if (UC_START_WITH_GSTATE_OUTPUT_ENABLED)
369
  IFCONFIG |= bmGSTATE;                        // no conflict, start with it on
370

    
371
  set_led_0 (0);
372
  set_led_1 (0);
373
  
374
  EA = 0;                // disable all interrupts
375

    
376
  patch_usb_descriptors();
377

    
378
  setup_autovectors ();
379
  usb_install_handlers ();
380
  hook_timer_tick ((unsigned short) isr_tick);
381

    
382
  EIEX4 = 1;                // disable INT4 FIXME
383
  EA = 1;                // global interrupt enable
384

    
385
  fx2_renumerate ();        // simulates disconnect / reconnect
386

    
387
  main_loop ();
388
}