From 70eae1d242a9530cab4efa927bd1331b099fdd00 Mon Sep 17 00:00:00 2001 From: Thomas Tsou Date: Thu, 5 Aug 2010 11:48:41 -0700 Subject: usrp1: Add FX2 firmware files These firmware files for the usrp1 are imported from GNURadio. --- firmware/fx2/src/.gitignore | 17 + firmware/fx2/src/Makefile.am | 22 + firmware/fx2/src/common/.gitignore | 17 + firmware/fx2/src/common/Makefile.am | 50 +++ firmware/fx2/src/common/_startup.a51 | 80 ++++ firmware/fx2/src/common/_startup.a51.brittle | 78 ++++ firmware/fx2/src/common/blink_leds.c | 36 ++ firmware/fx2/src/common/build_eeprom.py | 182 +++++++++ firmware/fx2/src/common/check_mdelay.c | 37 ++ firmware/fx2/src/common/check_udelay.c | 37 ++ firmware/fx2/src/common/edit-gpif | 114 ++++++ firmware/fx2/src/common/fpga.h | 31 ++ firmware/fx2/src/common/fpga_load.c | 193 +++++++++ firmware/fx2/src/common/fpga_load.h | 28 ++ firmware/fx2/src/common/gpif.c | 292 ++++++++++++++ firmware/fx2/src/common/gpif.gpf | Bin 0 -> 5281 bytes firmware/fx2/src/common/init_gpif.c | 59 +++ firmware/fx2/src/common/usrp_common.c | 109 +++++ firmware/fx2/src/common/usrp_globals.h | 32 ++ firmware/fx2/src/common/vectors.a51 | 180 +++++++++ firmware/fx2/src/usrp1/.gitignore | 20 + firmware/fx2/src/usrp1/Makefile.am | 171 ++++++++ firmware/fx2/src/usrp1/_startup.a51 | 1 + firmware/fx2/src/usrp1/blink_leds.c | 1 + firmware/fx2/src/usrp1/board_specific.c | 113 ++++++ firmware/fx2/src/usrp1/check_mdelay.c | 1 + firmware/fx2/src/usrp1/check_udelay.c | 1 + firmware/fx2/src/usrp1/edit-gpif | 114 ++++++ firmware/fx2/src/usrp1/eeprom_boot.a51 | 573 +++++++++++++++++++++++++++ firmware/fx2/src/usrp1/eeprom_init.c | 116 ++++++ firmware/fx2/src/usrp1/eeprom_io.c | 65 +++ firmware/fx2/src/usrp1/eeprom_io.h | 38 ++ firmware/fx2/src/usrp1/fpga_load.c | 1 + firmware/fx2/src/usrp1/fpga_rev2.c | 122 ++++++ firmware/fx2/src/usrp1/fpga_rev2.h | 58 +++ firmware/fx2/src/usrp1/gpif.c | 292 ++++++++++++++ firmware/fx2/src/usrp1/gpif.gpf | Bin 0 -> 5341 bytes firmware/fx2/src/usrp1/init_gpif.c | 1 + firmware/fx2/src/usrp1/spi.c | 381 ++++++++++++++++++ firmware/fx2/src/usrp1/spi.h | 43 ++ firmware/fx2/src/usrp1/usb_descriptors.a51 | 404 +++++++++++++++++++ firmware/fx2/src/usrp1/usrp_common.c | 1 + firmware/fx2/src/usrp1/usrp_common.h | 77 ++++ firmware/fx2/src/usrp1/usrp_main.c | 380 ++++++++++++++++++ firmware/fx2/src/usrp1/usrp_rev2_regs.h | 163 ++++++++ firmware/fx2/src/usrp1/vectors.a51 | 1 + 46 files changed, 4732 insertions(+) create mode 100644 firmware/fx2/src/.gitignore create mode 100644 firmware/fx2/src/Makefile.am create mode 100644 firmware/fx2/src/common/.gitignore create mode 100644 firmware/fx2/src/common/Makefile.am create mode 100644 firmware/fx2/src/common/_startup.a51 create mode 100644 firmware/fx2/src/common/_startup.a51.brittle create mode 100644 firmware/fx2/src/common/blink_leds.c create mode 100755 firmware/fx2/src/common/build_eeprom.py create mode 100644 firmware/fx2/src/common/check_mdelay.c create mode 100644 firmware/fx2/src/common/check_udelay.c create mode 100755 firmware/fx2/src/common/edit-gpif create mode 100644 firmware/fx2/src/common/fpga.h create mode 100644 firmware/fx2/src/common/fpga_load.c create mode 100644 firmware/fx2/src/common/fpga_load.h create mode 100755 firmware/fx2/src/common/gpif.c create mode 100755 firmware/fx2/src/common/gpif.gpf create mode 100644 firmware/fx2/src/common/init_gpif.c create mode 100644 firmware/fx2/src/common/usrp_common.c create mode 100644 firmware/fx2/src/common/usrp_globals.h create mode 100644 firmware/fx2/src/common/vectors.a51 create mode 100644 firmware/fx2/src/usrp1/.gitignore create mode 100644 firmware/fx2/src/usrp1/Makefile.am create mode 100644 firmware/fx2/src/usrp1/_startup.a51 create mode 100644 firmware/fx2/src/usrp1/blink_leds.c create mode 100644 firmware/fx2/src/usrp1/board_specific.c create mode 100644 firmware/fx2/src/usrp1/check_mdelay.c create mode 100644 firmware/fx2/src/usrp1/check_udelay.c create mode 100755 firmware/fx2/src/usrp1/edit-gpif create mode 100644 firmware/fx2/src/usrp1/eeprom_boot.a51 create mode 100644 firmware/fx2/src/usrp1/eeprom_init.c create mode 100644 firmware/fx2/src/usrp1/eeprom_io.c create mode 100644 firmware/fx2/src/usrp1/eeprom_io.h create mode 100644 firmware/fx2/src/usrp1/fpga_load.c create mode 100644 firmware/fx2/src/usrp1/fpga_rev2.c create mode 100644 firmware/fx2/src/usrp1/fpga_rev2.h create mode 100644 firmware/fx2/src/usrp1/gpif.c create mode 100755 firmware/fx2/src/usrp1/gpif.gpf create mode 100644 firmware/fx2/src/usrp1/init_gpif.c create mode 100644 firmware/fx2/src/usrp1/spi.c create mode 100644 firmware/fx2/src/usrp1/spi.h create mode 100644 firmware/fx2/src/usrp1/usb_descriptors.a51 create mode 100644 firmware/fx2/src/usrp1/usrp_common.c create mode 100644 firmware/fx2/src/usrp1/usrp_common.h create mode 100644 firmware/fx2/src/usrp1/usrp_main.c create mode 100644 firmware/fx2/src/usrp1/usrp_rev2_regs.h create mode 100644 firmware/fx2/src/usrp1/vectors.a51 (limited to 'firmware/fx2/src') diff --git a/firmware/fx2/src/.gitignore b/firmware/fx2/src/.gitignore new file mode 100644 index 000000000..d46c52c00 --- /dev/null +++ b/firmware/fx2/src/.gitignore @@ -0,0 +1,17 @@ +/*.ihx +/*.lnk +/*.lst +/*.map +/*.mem +/*.rel +/*.rst +/*.sym +/blink_leds.asm +/usrp_common.asm +/command_loop.asm +/fpga.asm +/*.asm +/usrp_gpif.c +/usrp_gpif_inline.h +/Makefile +/Makefile.in diff --git a/firmware/fx2/src/Makefile.am b/firmware/fx2/src/Makefile.am new file mode 100644 index 000000000..5dcff2c85 --- /dev/null +++ b/firmware/fx2/src/Makefile.am @@ -0,0 +1,22 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +SUBDIRS = common usrp1 diff --git a/firmware/fx2/src/common/.gitignore b/firmware/fx2/src/common/.gitignore new file mode 100644 index 000000000..d46c52c00 --- /dev/null +++ b/firmware/fx2/src/common/.gitignore @@ -0,0 +1,17 @@ +/*.ihx +/*.lnk +/*.lst +/*.map +/*.mem +/*.rel +/*.rst +/*.sym +/blink_leds.asm +/usrp_common.asm +/command_loop.asm +/fpga.asm +/*.asm +/usrp_gpif.c +/usrp_gpif_inline.h +/Makefile +/Makefile.in diff --git a/firmware/fx2/src/common/Makefile.am b/firmware/fx2/src/common/Makefile.am new file mode 100644 index 000000000..95232324d --- /dev/null +++ b/firmware/fx2/src/common/Makefile.am @@ -0,0 +1,50 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +EXTRA_DIST = \ + _startup.a51 \ + blink_leds.c \ + check_mdelay.c \ + check_udelay.c \ + edit-gpif \ + fpga.h \ + fpga_load.h \ + fpga_load.c \ + gpif.c \ + gpif.gpf \ + init_gpif.c \ + usrp_common.c \ + usrp_globals.h \ + vectors.a51 \ + build_eeprom.py + +all: usrp_gpif.c + +usrp_gpif.c usrp_gpif_inline.h : gpif.c + srcdir=$(srcdir) $(PYTHON) $(srcdir)/edit-gpif $(srcdir)/gpif.c usrp_gpif.c usrp_gpif_inline.h + +CLEANFILES = \ + *.ihx *.lnk *.lst *.map *.mem *.rel *.rst *.sym *.asm *.lib \ + usrp_gpif.c usrp_gpif_inline.h + +DISTCLEANFILES = \ + *.ihx *.lnk *.lst *.map *.mem *.rel *.rst *.sym *.asm *.lib \ + usrp_gpif.c usrp_gpif_inline.h diff --git a/firmware/fx2/src/common/_startup.a51 b/firmware/fx2/src/common/_startup.a51 new file mode 100644 index 000000000..30a907857 --- /dev/null +++ b/firmware/fx2/src/common/_startup.a51 @@ -0,0 +1,80 @@ +;;; -*- asm -*- +;;; +;;; Copyright 2003,2004 Free Software Foundation, Inc. +;;; +;;; This file is part of GNU Radio +;;; +;;; GNU Radio is free software; you can redistribute it and/or modify +;;; it under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3, or (at your option) +;;; any later version. +;;; +;;; GNU Radio is distributed in the hope that it will be useful, +;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Radio; see the file COPYING. If not, write to +;;; the Free Software Foundation, Inc., 51 Franklin Street, +;;; Boston, MA 02110-1301, USA. + + +;;; The default external memory initialization provided by sdcc is not +;;; appropriate to the FX2. This is derived from the sdcc code, but uses +;;; the FX2 specific _MPAGE sfr. + + + ;; .area XISEG (XDATA) ; the initialized external data area + ;; .area XINIT (CODE) ; the code space consts to init XISEG + .area XSEG (XDATA) ; zero initialized xdata + .area USBDESCSEG (XDATA) ; usb descriptors + + + .area CSEG (CODE) + + ;; sfr that sets upper address byte of MOVX using @r0 or @r1 + _MPAGE = 0x0092 + +__sdcc_external_startup:: + ;; This system is now compiled with the --no-xinit-opt + ;; which means that any initialized XDATA is handled + ;; inline by code in the GSINIT segs emitted for each file. + ;; + ;; We zero XSEG and all of the internal ram to ensure + ;; a known good state for uninitialized variables. + +; _mcs51_genRAMCLEAR() start + mov r0,#l_XSEG + mov a,r0 + orl a,#(l_XSEG >> 8) + jz 00002$ + mov r1,#((l_XSEG + 255) >> 8) + mov dptr,#s_XSEG + clr a + +00001$: movx @dptr,a + inc dptr + djnz r0,00001$ + djnz r1,00001$ + + ;; We're about to clear internal memory. This will overwrite + ;; the stack which contains our return address. + ;; Pop our return address into DPH, DPL +00002$: pop dph + pop dpl + + ;; R0 and A contain 0. This loop will execute 256 times. + ;; + ;; FWIW the first iteration writes direct address 0x00, + ;; which is the location of r0. We get lucky, we're + ;; writing the correct value (0) + +00003$: mov @r0,a + djnz r0,00003$ + + push dpl ; restore our return address + push dph + + mov dpl,#0 ; indicate that data init is still required + ret diff --git a/firmware/fx2/src/common/_startup.a51.brittle b/firmware/fx2/src/common/_startup.a51.brittle new file mode 100644 index 000000000..2996275cf --- /dev/null +++ b/firmware/fx2/src/common/_startup.a51.brittle @@ -0,0 +1,78 @@ +;;; -*- asm -*- +;;; +;;; Copyright 2003 Free Software Foundation, Inc. +;;; +;;; This file is part of GNU Radio +;;; +;;; GNU Radio is free software; you can redistribute it and/or modify +;;; it under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3, or (at your option) +;;; any later version. +;;; +;;; GNU Radio is distributed in the hope that it will be useful, +;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Radio; see the file COPYING. If not, write to +;;; the Free Software Foundation, Inc., 51 Franklin Street, +;;; Boston, MA 02110-1301, USA. + + +;;; The default external memory initialization provided by sdcc is not +;;; appropriate to the FX2. This is derived from the sdcc code, but uses +;;; the FX2 specific _MPAGE sfr. + + + .area XISEG (XDATA) ; the initialized external data area + .area XINIT (CODE) ; the code space consts to init XISEG + .area XSEG (XDATA) ; zero initialized xdata + .area USBDESCSEG (XDATA); usb descriptors + + + ;; BIG TIME KLUDGE! + ;; Look at usrp_main.rst and count the bytes from our + ;; "normal return location" to the first instruction following + ;; the comment: "_mcs51_getRAMCLEAR () start" + + INSTRUCTION_BYTES_TO_SKIP = 0x29 ; valid for sdcc 2.4.0 + + + .area CSEG (CODE) + + ;; sfr that sets upper address byte of MOVX using @r0 or @r1 + _MPAGE = 0x0092 + +__sdcc_external_startup:: +; _mcs51_genXINIT() start + mov r1,#l_XINIT + mov a,r1 + orl a,#(l_XINIT >> 8) + jz 00003$ + mov r2,#((l_XINIT+255) >> 8) + mov dptr,#s_XINIT + mov r0,#s_XISEG + mov _MPAGE,#(s_XISEG >> 8) +00001$: clr a + movc a,@a+dptr + movx @r0,a + inc dptr + inc r0 + cjne r0,#0,00002$ + inc _MPAGE +00002$: djnz r1,00001$ + djnz r2,00001$ + mov _MPAGE,#0xFF +00003$: + + ;; Danger! Total KLUDGE! + ;; We pop the return address, add a magic number to it + ;; then jump to that address. Believe it or not, this + ;; looks like the least kludgy way to handle this, + ;; short of patching the compiler... + + pop dph + pop dpl + mov a,#INSTRUCTION_BYTES_TO_SKIP + jmp @a+dptr diff --git a/firmware/fx2/src/common/blink_leds.c b/firmware/fx2/src/common/blink_leds.c new file mode 100644 index 000000000..255c69733 --- /dev/null +++ b/firmware/fx2/src/common/blink_leds.c @@ -0,0 +1,36 @@ +/* + * USRP - Universal Software Radio Peripheral + * + * Copyright (C) 2003 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 3 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 "usrp_common.h" + +void +main (void) +{ + unsigned short counter = 0; + + init_usrp (); + + while (1){ + unsigned char counter_high = counter >> 8; + set_led_0 (counter_high & 0x40); + set_led_1 (counter_high & 0x80); + counter++; + } +} diff --git a/firmware/fx2/src/common/build_eeprom.py b/firmware/fx2/src/common/build_eeprom.py new file mode 100755 index 000000000..023c4b3f5 --- /dev/null +++ b/firmware/fx2/src/common/build_eeprom.py @@ -0,0 +1,182 @@ +#!/usr/bin/env python +# +# Copyright 2004,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +import re +import sys +import os, os.path +from optparse import OptionParser + +# USB Vendor and Product ID's + +VID = 0xfffe # Free Software Folks +PID = 0x0002 # Universal Software Radio Peripheral + + +def hex_to_bytes (s): + if len (s) & 0x1: + raise ValueError, "Length must be even" + r = [] + for i in range (0, len(s), 2): + r.append (int (s[i:i+2], 16)) + return r + +def msb (x): + return (x >> 8) & 0xff + +def lsb (x): + return x & 0xff + +class ihx_rec (object): + def __init__ (self, addr, type, data): + self.addr = addr + self.type = type + self.data = data + +class ihx_file (object): + def __init__ (self): + self.pat = re.compile (r':[0-9A-F]{10,}') + def read (self, file): + r = [] + for line in file: + line = line.strip().upper () + if not self.pat.match (line): + raise ValueError, "Invalid hex record format" + bytes = hex_to_bytes (line[1:]) + sum = reduce (lambda x, y: x + y, bytes, 0) % 256 + if sum != 0: + raise ValueError, "Bad hex checksum" + lenx = bytes[0] + addr = (bytes[1] << 8) + bytes[2] + type = bytes[3] + data = bytes[4:-1] + if lenx != len (data): + raise ValueError, "Invalid hex record (bad length)" + if type != 0: + break; + r.append (ihx_rec (addr, type, data)) + + return r + +def get_code (filename): + """Read the intel hex format file FILENAME and return a tuple + of the code starting address and a list of bytes to load there. + """ + f = open (filename, 'r') + ifx = ihx_file () + r = ifx.read (f) + r.sort (lambda a,b: a.addr - b.addr) + code_start = r[0].addr + code_end = r[-1].addr + len (r[-1].data) + code_len = code_end - code_start + code = [0] * code_len + for x in r: + a = x.addr + l = len (x.data) + code[a-code_start:a-code_start+l] = x.data + return (code_start, code) + + +def build_eeprom_image (filename, rev): + """Build a ``C2 Load'' EEPROM image. + + For details on this format, see section 3.4.3 of + the EZ-USB FX2 Technical Reference Manual + """ + # get the code we want to run + (start_addr, bytes) = get_code (filename) + + devid = rev + + rom_header = [ + 0xC2, # boot from EEPROM + lsb (VID), + msb (VID), + lsb (PID), + msb (PID), + lsb (devid), + msb (devid), + 0 # configuration byte + ] + + # 4 byte header that indicates where to load + # the immediately follow code bytes. + code_header = [ + msb (len (bytes)), + lsb (len (bytes)), + msb (start_addr), + lsb (start_addr) + ] + + # writes 0 to CPUCS reg (brings FX2 out of reset) + trailer = [ + 0x80, + 0x01, + 0xe6, + 0x00, + 0x00 + ] + + image = rom_header + code_header + bytes + trailer + + assert (len (image) <= 256) + return image + +def build_shell_script (out, ihx_filename, rev): + + image = build_eeprom_image (ihx_filename, rev) + + out.write ('#!/bin/sh\n') + out.write ('usrper -x load_firmware /usr/local/share/usrp/rev%d/std.ihx\n' % rev) + out.write ('sleep 1\n') + + # print "len(image) =", len(image) + + i2c_addr = 0x50 + rom_addr = 0x00 + + hex_image = map (lambda x : "%02x" % (x,), image) + + while (len (hex_image) > 0): + l = min (len (hex_image), 16) + out.write ('usrper i2c_write 0x%02x %02x%s\n' % + (i2c_addr, rom_addr, ''.join (hex_image[0:l]))) + hex_image = hex_image[l:] + rom_addr = rom_addr + l + out.write ('sleep 1\n') + +if __name__ == '__main__': + usage = "usage: %prog -r REV [options] bootfile.ihx" + parser = OptionParser (usage=usage) + parser.add_option ("-r", "--rev", type="int", default=-1, + help="Specify USRP revision number REV (2 or 4)") + (options, args) = parser.parse_args () + if len (args) != 1: + parser.print_help () + sys.exit (1) + if options.rev < 0: + sys.stderr.write ( + "You must specify the USRP revision number (2 or 4) with -r REV\n") + sys.exit (1) + + ihx_filename = args[0] + + build_shell_script (sys.stdout, ihx_filename, options.rev) diff --git a/firmware/fx2/src/common/check_mdelay.c b/firmware/fx2/src/common/check_mdelay.c new file mode 100644 index 000000000..de1af47f6 --- /dev/null +++ b/firmware/fx2/src/common/check_mdelay.c @@ -0,0 +1,37 @@ +/* + * USRP - Universal Software Radio Peripheral + * + * Copyright (C) 2003 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 3 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 "usrp_common.h" +#include "delay.h" + +void +main (void) +{ + init_usrp (); + + // CPUCS = 0; // 12 MHz + // CPUCS = bmCLKSPD0; // 24 MHz + CPUCS = bmCLKSPD1; // 48 MHz + + while (1){ + USRP_LED_REG ^= bmLED0; + mdelay (10); + } +} diff --git a/firmware/fx2/src/common/check_udelay.c b/firmware/fx2/src/common/check_udelay.c new file mode 100644 index 000000000..46885a067 --- /dev/null +++ b/firmware/fx2/src/common/check_udelay.c @@ -0,0 +1,37 @@ +/* + * USRP - Universal Software Radio Peripheral + * + * Copyright (C) 2003 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 3 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 "usrp_common.h" +#include "delay.h" + +void +main (void) +{ + init_usrp (); + + // CPUCS = 0; // 12 MHz + // CPUCS = bmCLKSPD0; // 24 MHz + CPUCS = bmCLKSPD1; // 48 MHz + + while (1){ + USRP_LED_REG ^= bmLED0; + udelay (250); + } +} diff --git a/firmware/fx2/src/common/edit-gpif b/firmware/fx2/src/common/edit-gpif new file mode 100755 index 000000000..5367b75a5 --- /dev/null +++ b/firmware/fx2/src/common/edit-gpif @@ -0,0 +1,114 @@ +#!/usr/bin/env python +# -*- Python -*- +# +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + + +# Edit the gpif.c file generated by the Cypress GPIF Designer Tool and +# produce usrp_gpif.c, and usrp_gpif_inline.h, files suitable for our +# uses. + +import re +import string +import sys + +def check_flow_state (line, flow_state_dict): + mo = re.match (r'/\* Wave (\d) FlowStates \*/ (.*),', line) + if mo: + wave = int (mo.group (1)) + data = mo.group (2) + split = data.split (',', 8) + v = map (lambda x : int (x, 16), split) + # print "%s, %s" % (wave, data) + # print "split: ", split + # print "v : ", v + flow_state_dict[wave] = v + + +def delta (xseq, yseq): + # set subtraction + z = [] + for x in xseq: + if x not in yseq: + z.append (x) + return z + + +def write_define (output, name, pairs): + output.write ('#define %s()\t\\\n' % name) + output.write ('do {\t\t\t\t\t\\\n') + for reg, val in pairs: + output.write ('%14s = 0x%02x;\t\t\t\\\n' % (reg, val)) + output.write ('} while (0)\n\n') + +def write_inlines (output, dict): + regs = ['FLOWSTATE', 'FLOWLOGIC', 'FLOWEQ0CTL', 'FLOWEQ1CTL', 'FLOWHOLDOFF', + 'FLOWSTB', 'FLOWSTBEDGE', 'FLOWSTBHPERIOD', 'GPIFHOLDAMOUNT'] + + READ_FLOW_STATE = 2 + WRITE_FLOW_STATE = 3 + + read_info = zip (regs, dict[READ_FLOW_STATE]) + write_info = zip (regs, dict[WRITE_FLOW_STATE]) + + output.write ('''/* + * Machine generated by "edit-gpif". Do not edit by hand. + */ + +''') + write_define (output, 'setup_flowstate_common', read_info) + write_define (output, 'setup_flowstate_read', delta (read_info, write_info)) + write_define (output, 'setup_flowstate_write', delta (write_info, read_info)) + + +def edit_gpif (input_name, output_name, inline_name): + input = open (input_name, 'r') + output = open (output_name, 'w') + inline = open (inline_name, 'w') + flow_state_dict = {} + + output.write ('''/* + * Machine generated by "edit-gpif". Do not edit by hand. + */ + +''') + + while 1: + line = input.readline () + line = string.replace (line, '\r','') + line = re.sub (r' *$', r'', line) + + check_flow_state (line, flow_state_dict) + + line = re.sub (r'#include', r'// #include', line) + line = re.sub (r'xdata ', r'', line) + if re.search (r'GpifInit', line): + break + + output.write (line) + + output.close () + write_inlines (inline, flow_state_dict) + inline.close () + + +# gpif.c usrp_gpif.c usrp_gpif_inline.h +edit_gpif (sys.argv[1], sys.argv[2], sys.argv[3]) diff --git a/firmware/fx2/src/common/fpga.h b/firmware/fx2/src/common/fpga.h new file mode 100644 index 000000000..6cd5de8e2 --- /dev/null +++ b/firmware/fx2/src/common/fpga.h @@ -0,0 +1,31 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ +#ifndef INCLUDED_FPGA_H +#define INCLUDED_FPGA_H + +#include "fpga_load.h" + +#if defined(HAVE_USRP2) +#include "fpga_rev2.h" +#endif + +#endif /* INCLUDED_FPGA_H */ diff --git a/firmware/fx2/src/common/fpga_load.c b/firmware/fx2/src/common/fpga_load.c new file mode 100644 index 000000000..c3ae9e707 --- /dev/null +++ b/firmware/fx2/src/common/fpga_load.c @@ -0,0 +1,193 @@ +/* + * USRP - Universal Software Radio Peripheral + * + * Copyright (C) 2003 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 3 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 "usrp_common.h" +#include "fpga_load.h" +#include "delay.h" + +/* + * setup altera FPGA serial load (PS). + * + * On entry: + * don't care + * + * On exit: + * ALTERA_DCLK = 0 + * ALTERA_NCONFIG = 1 + * ALTERA_NSTATUS = 1 (input) + */ +unsigned char +fpga_load_begin (void) +{ + USRP_ALTERA_CONFIG &= ~bmALTERA_BITS; // clear all bits (NCONFIG low) + udelay (40); // wait 40 us + USRP_ALTERA_CONFIG |= bmALTERA_NCONFIG; // set NCONFIG high + + if (UC_BOARD_HAS_FPGA){ + // FIXME should really cap this loop with a counter so we + // don't hang forever on a hardware failure. + while ((USRP_ALTERA_CONFIG & bmALTERA_NSTATUS) == 0) // wait for NSTATUS to go high + ; + } + + // ready to xfer now + + return 1; +} + +/* + * clock out the low bit of bits. + * + * On entry: + * ALTERA_DCLK = 0 + * ALTERA_NCONFIG = 1 + * ALTERA_NSTATUS = 1 (input) + * + * On exit: + * ALTERA_DCLK = 0 + * ALTERA_NCONFIG = 1 + * ALTERA_NSTATUS = 1 (input) + */ + + +#if 0 + +static void +clock_out_config_byte (unsigned char bits) +{ + unsigned char i; + + // clock out configuration byte, least significant bit first + + for (i = 0; i < 8; i++){ + + USRP_ALTERA_CONFIG = ((USRP_ALTERA_CONFIG & ~bmALTERA_DATA0) | ((bits & 1) ? bmALTERA_DATA0 : 0)); + USRP_ALTERA_CONFIG |= bmALTERA_DCLK; /* set DCLK to 1 */ + USRP_ALTERA_CONFIG &= ~bmALTERA_DCLK; /* set DCLK to 0 */ + + bits = bits >> 1; + } +} + +#else + +static void +clock_out_config_byte (unsigned char bits) _naked +{ + _asm + mov a, dpl + + rrc a + mov _bitALTERA_DATA0,c + setb _bitALTERA_DCLK + clr _bitALTERA_DCLK + + rrc a + mov _bitALTERA_DATA0,c + setb _bitALTERA_DCLK + clr _bitALTERA_DCLK + + rrc a + mov _bitALTERA_DATA0,c + setb _bitALTERA_DCLK + clr _bitALTERA_DCLK + + rrc a + mov _bitALTERA_DATA0,c + setb _bitALTERA_DCLK + clr _bitALTERA_DCLK + + rrc a + mov _bitALTERA_DATA0,c + setb _bitALTERA_DCLK + clr _bitALTERA_DCLK + + rrc a + mov _bitALTERA_DATA0,c + setb _bitALTERA_DCLK + clr _bitALTERA_DCLK + + rrc a + mov _bitALTERA_DATA0,c + setb _bitALTERA_DCLK + clr _bitALTERA_DCLK + + rrc a + mov _bitALTERA_DATA0,c + setb _bitALTERA_DCLK + clr _bitALTERA_DCLK + + ret + + _endasm; +} + +#endif + +static void +clock_out_bytes (unsigned char bytecount, + unsigned char xdata *p) +{ + while (bytecount-- > 0) + clock_out_config_byte (*p++); +} + +/* + * Transfer block of bytes from packet to FPGA serial configuration port + * + * On entry: + * ALTERA_DCLK = 0 + * ALTERA_NCONFIG = 1 + * ALTERA_NSTATUS = 1 (input) + * + * On exit: + * ALTERA_DCLK = 0 + * ALTERA_NCONFIG = 1 + * ALTERA_NSTATUS = 1 (input) + */ +unsigned char +fpga_load_xfer (xdata unsigned char *p, unsigned char bytecount) +{ + clock_out_bytes (bytecount, p); + return 1; +} + +/* + * check for successful load... + */ +unsigned char +fpga_load_end (void) +{ + unsigned char status = USRP_ALTERA_CONFIG; + + if (!UC_BOARD_HAS_FPGA) // always true if we don't have FPGA + return 1; + + if ((status & bmALTERA_NSTATUS) == 0) // failed to program + return 0; + + if ((status & bmALTERA_CONF_DONE) == bmALTERA_CONF_DONE) + return 1; // everything's cool + + // I don't think this should happen. It indicates that + // programming is still in progress. + + return 0; +} diff --git a/firmware/fx2/src/common/fpga_load.h b/firmware/fx2/src/common/fpga_load.h new file mode 100644 index 000000000..7c36a04c8 --- /dev/null +++ b/firmware/fx2/src/common/fpga_load.h @@ -0,0 +1,28 @@ +/* + * USRP - Universal Software Radio Peripheral + * + * Copyright (C) 2003 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 3 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 + */ + +#ifndef INCLUDED_FPGA_LOAD_H +#define INCLUDED_FPGA_LOAD_H + +unsigned char fpga_load_begin (void); +unsigned char fpga_load_xfer (xdata unsigned char *p, unsigned char len); +unsigned char fpga_load_end (void); + +#endif /* INCLUDED_FPGA_LOAD_H */ diff --git a/firmware/fx2/src/common/gpif.c b/firmware/fx2/src/common/gpif.c new file mode 100755 index 000000000..489e6e81a --- /dev/null +++ b/firmware/fx2/src/common/gpif.c @@ -0,0 +1,292 @@ +// This program configures the General Programmable Interface (GPIF) for FX2. +// Please do not modify sections of text which are marked as "DO NOT EDIT ...". +// +// DO NOT EDIT ... +// GPIF Initialization +// Interface Timing Async +// Internal Ready Init IntRdy=1 +// CTL Out Tristate-able Binary +// SingleWrite WF Select 1 +// SingleRead WF Select 0 +// FifoWrite WF Select 3 +// FifoRead WF Select 2 +// Data Bus Idle Drive Tristate +// END DO NOT EDIT + +// DO NOT EDIT ... +// GPIF Wave Names +// Wave 0 = singlerd +// Wave 1 = singlewr +// Wave 2 = FIFORd +// Wave 3 = FIFOWr + +// GPIF Ctrl Outputs Level +// CTL 0 = WEN# CMOS +// CTL 1 = REN# CMOS +// CTL 2 = OE# CMOS +// CTL 3 = CLRST CMOS +// CTL 4 = unused CMOS +// CTL 5 = BOGUS CMOS + +// GPIF Rdy Inputs +// RDY0 = EF# +// RDY1 = FF# +// RDY2 = unused +// RDY3 = unused +// RDY4 = unused +// RDY5 = TCXpire +// FIFOFlag = FIFOFlag +// IntReady = IntReady +// END DO NOT EDIT +// DO NOT EDIT ... +// +// GPIF Waveform 0: singlerd +// +// Interval 0 1 2 3 4 5 6 Idle (7) +// _________ _________ _________ _________ _________ _________ _________ _________ +// +// AddrMode Same Val Same Val Same Val Same Val Same Val Same Val Same Val +// DataMode NO Data NO Data NO Data NO Data NO Data NO Data NO Data +// NextData SameData SameData SameData SameData SameData SameData SameData +// Int Trig No Int No Int No Int No Int No Int No Int No Int +// IF/Wait Wait 1 Wait 1 Wait 1 Wait 1 Wait 1 Wait 1 Wait 1 +// Term A +// LFunc +// Term B +// Branch1 +// Branch0 +// Re-Exec +// Sngl/CRC Default Default Default Default Default Default Default +// WEN# 0 0 0 0 0 0 0 0 +// REN# 0 0 0 0 0 0 0 0 +// OE# 0 0 0 0 0 0 0 0 +// CLRST 0 0 0 0 0 0 0 0 +// unused 0 0 0 0 0 0 0 0 +// BOGUS 0 0 0 0 0 0 0 0 +// +// END DO NOT EDIT +// DO NOT EDIT ... +// +// GPIF Waveform 1: singlewr +// +// Interval 0 1 2 3 4 5 6 Idle (7) +// _________ _________ _________ _________ _________ _________ _________ _________ +// +// AddrMode Same Val Same Val Same Val Same Val Same Val Same Val Same Val +// DataMode Activate Activate Activate Activate Activate Activate Activate +// NextData SameData SameData SameData SameData SameData SameData SameData +// Int Trig No Int No Int No Int No Int No Int No Int No Int +// IF/Wait Wait 1 IF Wait 1 Wait 1 Wait 1 Wait 1 Wait 1 +// Term A EF# +// LFunc AND +// Term B EF# +// Branch1 ThenIdle +// Branch0 ElseIdle +// Re-Exec No +// Sngl/CRC Default Default Default Default Default Default Default +// WEN# 0 1 1 1 1 1 1 0 +// REN# 0 0 0 0 0 0 0 0 +// OE# 0 0 0 0 0 0 0 0 +// CLRST 0 0 0 0 0 0 0 0 +// unused 0 0 0 0 0 0 0 0 +// BOGUS 0 0 0 0 0 0 0 0 +// +// END DO NOT EDIT +// DO NOT EDIT ... +// +// GPIF Waveform 2: FIFORd +// +// Interval 0 1 2 3 4 5 6 Idle (7) +// _________ _________ _________ _________ _________ _________ _________ _________ +// +// AddrMode Same Val Same Val Same Val Same Val Same Val Same Val Same Val +// DataMode NO Data Activate NO Data NO Data NO Data NO Data NO Data +// NextData SameData SameData SameData SameData SameData SameData SameData +// Int Trig No Int No Int No Int No Int No Int No Int No Int +// IF/Wait Wait 1 IF Wait 1 IF Wait 1 Wait 1 Wait 1 +// Term A TCXpire TCXpire +// LFunc AND AND +// Term B TCXpire TCXpire +// Branch1 Then 2 ThenIdle +// Branch0 Else 1 ElseIdle +// Re-Exec No No +// Sngl/CRC Default Default Default Default Default Default Default +// WEN# 0 0 0 0 0 0 0 0 +// REN# 0 0 0 0 0 0 0 0 +// OE# 1 1 1 0 0 0 0 0 +// CLRST 0 0 0 0 0 0 0 0 +// unused 0 0 0 0 0 0 0 0 +// BOGUS 0 0 0 0 0 0 0 0 +// +// END DO NOT EDIT +// DO NOT EDIT ... +// +// GPIF Waveform 3: FIFOWr +// +// Interval 0 1 2 3 4 5 6 Idle (7) +// _________ _________ _________ _________ _________ _________ _________ _________ +// +// AddrMode Same Val Same Val Same Val Same Val Same Val Same Val Same Val +// DataMode NO Data Activate Activate Activate Activate Activate Activate +// NextData SameData SameData SameData SameData SameData SameData SameData +// Int Trig No Int No Int No Int No Int No Int No Int No Int +// IF/Wait Wait 1 IF Wait 1 Wait 1 Wait 1 Wait 1 Wait 1 +// Term A TCXpire +// LFunc AND +// Term B TCXpire +// Branch1 ThenIdle +// Branch0 Else 1 +// Re-Exec No +// Sngl/CRC Default Default Default Default Default Default Default +// WEN# 0 0 0 0 0 0 0 0 +// REN# 0 0 0 0 0 0 0 0 +// OE# 0 0 0 0 0 0 0 0 +// CLRST 0 0 0 0 0 0 0 0 +// unused 0 0 0 0 0 0 0 0 +// BOGUS 0 0 0 0 0 0 0 0 +// +// END DO NOT EDIT + +// GPIF Program Code + +// DO NOT EDIT ... +#include "fx2.h" +#include "fx2regs.h" +#include "fx2sdly.h" // SYNCDELAY macro +// END DO NOT EDIT + +// DO NOT EDIT ... +const char xdata WaveData[128] = +{ +// Wave 0 +/* LenBr */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, +/* Opcode*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* Output*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* LFun */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, +// Wave 1 +/* LenBr */ 0x01, 0x3F, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, +/* Opcode*/ 0x22, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, +/* Output*/ 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, +/* LFun */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, +// Wave 2 +/* LenBr */ 0x01, 0x11, 0x01, 0x3F, 0x01, 0x01, 0x01, 0x07, +/* Opcode*/ 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, +/* Output*/ 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, +/* LFun */ 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x3F, +// Wave 3 +/* LenBr */ 0x01, 0x39, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, +/* Opcode*/ 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, +/* Output*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* LFun */ 0x00, 0x2D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, +}; +// END DO NOT EDIT + +// DO NOT EDIT ... +const char xdata FlowStates[36] = +{ +/* Wave 0 FlowStates */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* Wave 1 FlowStates */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* Wave 2 FlowStates */ 0x81,0x2D,0x26,0x00,0x04,0x04,0x03,0x02,0x00, +/* Wave 3 FlowStates */ 0x81,0x2D,0x21,0x00,0x04,0x04,0x03,0x02,0x00, +}; +// END DO NOT EDIT + +// DO NOT EDIT ... +const char xdata InitData[7] = +{ +/* Regs */ 0xA0,0x00,0x00,0x00,0xEE,0x4E,0x00 +}; +// END DO NOT EDIT + +// TO DO: You may add additional code below. + +void GpifInit( void ) +{ + BYTE i; + + // Registers which require a synchronization delay, see section 15.14 + // FIFORESET FIFOPINPOLAR + // INPKTEND OUTPKTEND + // EPxBCH:L REVCTL + // GPIFTCB3 GPIFTCB2 + // GPIFTCB1 GPIFTCB0 + // EPxFIFOPFH:L EPxAUTOINLENH:L + // EPxFIFOCFG EPxGPIFFLGSEL + // PINFLAGSxx EPxFIFOIRQ + // EPxFIFOIE GPIFIRQ + // GPIFIE GPIFADRH:L + // UDMACRCH:L EPxGPIFTRIG + // GPIFTRIG + + // Note: The pre-REVE EPxGPIFTCH/L register are affected, as well... + // ...these have been replaced by GPIFTC[B3:B0] registers + + // 8051 doesn't have access to waveform memories 'til + // the part is in GPIF mode. + + IFCONFIG = 0xEE; + // IFCLKSRC=1 , FIFOs executes on internal clk source + // xMHz=1 , 48MHz internal clk rate + // IFCLKOE=0 , Don't drive IFCLK pin signal at 48MHz + // IFCLKPOL=0 , Don't invert IFCLK pin signal from internal clk + // ASYNC=1 , master samples asynchronous + // GSTATE=1 , Drive GPIF states out on PORTE[2:0], debug WF + // IFCFG[1:0]=10, FX2 in GPIF master mode + + GPIFABORT = 0xFF; // abort any waveforms pending + + GPIFREADYCFG = InitData[ 0 ]; + GPIFCTLCFG = InitData[ 1 ]; + GPIFIDLECS = InitData[ 2 ]; + GPIFIDLECTL = InitData[ 3 ]; + GPIFWFSELECT = InitData[ 5 ]; + GPIFREADYSTAT = InitData[ 6 ]; + + // use dual autopointer feature... + AUTOPTRSETUP = 0x07; // inc both pointers, + // ...warning: this introduces pdata hole(s) + // ...at E67B (XAUTODAT1) and E67C (XAUTODAT2) + + // source + AUTOPTRH1 = MSB( &WaveData ); + AUTOPTRL1 = LSB( &WaveData ); + + // destination + AUTOPTRH2 = 0xE4; + AUTOPTRL2 = 0x00; + + // transfer + for ( i = 0x00; i < 128; i++ ) + { + EXTAUTODAT2 = EXTAUTODAT1; + } + +// Configure GPIF Address pins, output initial value, + PORTCCFG = 0xFF; // [7:0] as alt. func. GPIFADR[7:0] + OEC = 0xFF; // and as outputs + PORTECFG |= 0x80; // [8] as alt. func. GPIFADR[8] + OEE |= 0x80; // and as output + +// ...OR... tri-state GPIFADR[8:0] pins +// PORTCCFG = 0x00; // [7:0] as port I/O +// OEC = 0x00; // and as inputs +// PORTECFG &= 0x7F; // [8] as port I/O +// OEE &= 0x7F; // and as input + +// GPIF address pins update when GPIFADRH/L written + SYNCDELAY; // + GPIFADRH = 0x00; // bits[7:1] always 0 + SYNCDELAY; // + GPIFADRL = 0x00; // point to PERIPHERAL address 0x0000 + +// Configure GPIF FlowStates registers for Wave 0 of WaveData + FLOWSTATE = FlowStates[ 0 ]; + FLOWLOGIC = FlowStates[ 1 ]; + FLOWEQ0CTL = FlowStates[ 2 ]; + FLOWEQ1CTL = FlowStates[ 3 ]; + FLOWHOLDOFF = FlowStates[ 4 ]; + FLOWSTB = FlowStates[ 5 ]; + FLOWSTBEDGE = FlowStates[ 6 ]; + FLOWSTBHPERIOD = FlowStates[ 7 ]; +} + diff --git a/firmware/fx2/src/common/gpif.gpf b/firmware/fx2/src/common/gpif.gpf new file mode 100755 index 000000000..a954ac193 Binary files /dev/null and b/firmware/fx2/src/common/gpif.gpf differ diff --git a/firmware/fx2/src/common/init_gpif.c b/firmware/fx2/src/common/init_gpif.c new file mode 100644 index 000000000..edde919be --- /dev/null +++ b/firmware/fx2/src/common/init_gpif.c @@ -0,0 +1,59 @@ +/* + * USRP - Universal Software Radio Peripheral + * + * Copyright (C) 2003 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 3 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 "usrp_common.h" + +// These are the tables generated by the Cypress GPIF Designer + +extern const char WaveData[128]; +extern const char FlowStates[36]; +extern const char InitData[7]; + +// The tool is kind of screwed up, in that it doesn't configure some +// of the ports correctly. We just use their tables and handle the +// initialization ourselves. They also declare that their static +// initialized data is in xdata, which screws us too. + +void +init_gpif (void) +{ + // we've already setup IFCONFIG before calling this... + + GPIFABORT = 0xFF; // abort any waveforms pending + SYNCDELAY; + + GPIFREADYCFG = InitData[ 0 ]; + GPIFCTLCFG = InitData[ 1 ]; + GPIFIDLECS = InitData[ 2 ]; + GPIFIDLECTL = InitData[ 3 ]; + // Hmmm, what's InitData[ 4 ] ... + GPIFWFSELECT = InitData[ 5 ]; + // GPIFREADYSTAT = InitData[ 6 ]; // I think this register is read only... + + { + BYTE i; + + for (i = 0; i < 128; i++){ + GPIF_WAVE_DATA[i] = WaveData[i]; + } + } + + FLOWSTATE = 0; /* ensure it's off */ +} diff --git a/firmware/fx2/src/common/usrp_common.c b/firmware/fx2/src/common/usrp_common.c new file mode 100644 index 000000000..0998653c2 --- /dev/null +++ b/firmware/fx2/src/common/usrp_common.c @@ -0,0 +1,109 @@ +/* + * USRP - Universal Software Radio Peripheral + * + * Copyright (C) 2003 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 3 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 + */ + +/* + * common code for USRP + */ + +#include "usrp_common.h" + +void init_board (void); + +void +init_usrp (void) +{ + CPUCS = bmCLKSPD1; // CPU runs @ 48 MHz + CKCON = 0; // MOVX takes 2 cycles + + // IFCLK is generated internally and runs at 48 MHz; GPIF "master mode" + + IFCONFIG = bmIFCLKSRC | bm3048MHZ | bmIFCLKOE | bmIFCLKPOL | bmIFGPIF; + SYNCDELAY; + + // configure IO ports (B and D are used by GPIF) + + IOA = bmPORT_A_INITIAL; // Port A initial state + OEA = bmPORT_A_OUTPUTS; // Port A direction register + + IOC = bmPORT_C_INITIAL; // Port C initial state + OEC = bmPORT_C_OUTPUTS; // Port C direction register + + IOE = bmPORT_E_INITIAL; // Port E initial state + OEE = bmPORT_E_OUTPUTS; // Port E direction register + + + // REVCTL = bmDYN_OUT | bmENH_PKT; // highly recommended by docs + // SYNCDELAY; + + // configure end points + + EP1OUTCFG = bmVALID | bmBULK; SYNCDELAY; + EP1INCFG = bmVALID | bmBULK | bmIN; SYNCDELAY; + + EP2CFG = bmVALID | bmBULK | bmQUADBUF; SYNCDELAY; // 512 quad bulk OUT + EP4CFG = 0; SYNCDELAY; // disabled + EP6CFG = bmVALID | bmBULK | bmQUADBUF | bmIN; SYNCDELAY; // 512 quad bulk IN + EP8CFG = 0; SYNCDELAY; // disabled + + // reset FIFOs + + FIFORESET = bmNAKALL; SYNCDELAY; + FIFORESET = 2; SYNCDELAY; + // FIFORESET = 4; SYNCDELAY; + FIFORESET = 6; SYNCDELAY; + // FIFORESET = 8; SYNCDELAY; + FIFORESET = 0; SYNCDELAY; + + // configure end point FIFOs + + // let core see 0 to 1 transistion of autoout bit + + EP2FIFOCFG = bmWORDWIDE; SYNCDELAY; + EP2FIFOCFG = bmAUTOOUT | bmWORDWIDE; SYNCDELAY; + EP6FIFOCFG = bmAUTOIN | bmWORDWIDE; SYNCDELAY; + + + // prime the pump + +#if 0 + EP2BCL = 0x80; SYNCDELAY; + EP2BCL = 0x80; SYNCDELAY; + EP2BCL = 0x80; SYNCDELAY; + EP2BCL = 0x80; SYNCDELAY; +#endif + + EP0BCH = 0; SYNCDELAY; + + // arm EP1OUT so we can receive "out" packets (TRM pg 8-8) + + EP1OUTBC = 0; SYNCDELAY; + + EP2GPIFFLGSEL = 0x01; SYNCDELAY; // For EP2OUT, GPIF uses EF flag + EP6GPIFFLGSEL = 0x02; SYNCDELAY; // For EP6IN, GPIF uses FF flag + + // set autoin length for EP6 + // FIXME should be f(enumeration) + + EP6AUTOINLENH = (512) >> 8; SYNCDELAY; // this is the length for high speed + EP6AUTOINLENL = (512) & 0xff; SYNCDELAY; + + init_board (); +} + diff --git a/firmware/fx2/src/common/usrp_globals.h b/firmware/fx2/src/common/usrp_globals.h new file mode 100644 index 000000000..445e9e6b4 --- /dev/null +++ b/firmware/fx2/src/common/usrp_globals.h @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ +#ifndef _USRP_GLOBALS_H_ +#define _USRP_GLOBALS_H_ + +extern unsigned char g_tx_enable; +extern unsigned char g_rx_enable; +extern unsigned char g_fpga_reset; +extern unsigned char g_rx_overrun; +extern unsigned char g_tx_underrun; + + +#endif /* _USRP_GLOBALS_H_ */ diff --git a/firmware/fx2/src/common/vectors.a51 b/firmware/fx2/src/common/vectors.a51 new file mode 100644 index 000000000..e9382ab84 --- /dev/null +++ b/firmware/fx2/src/common/vectors.a51 @@ -0,0 +1,180 @@ +;;; -*- asm -*- +;;; +;;; Copyright 2003 Free Software Foundation, Inc. +;;; +;;; This file is part of GNU Radio +;;; +;;; GNU Radio is free software; you can redistribute it and/or modify +;;; it under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3, or (at your option) +;;; any later version. +;;; +;;; GNU Radio is distributed in the hope that it will be useful, +;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Radio; see the file COPYING. If not, write to +;;; the Free Software Foundation, Inc., 51 Franklin Street, +;;; Boston, MA 02110-1301, USA. +;;; + +;;; Interrupt vectors. + +;;; N.B. This object module must come first in the list of modules + + .module vectors + +;;; ---------------------------------------------------------------- +;;; standard FX2 interrupt vectors +;;; ---------------------------------------------------------------- + + .area CSEG (CODE) + .area GSINIT (CODE) + .area CSEG (CODE) +__standard_interrupt_vector:: +__reset_vector:: + ljmp s_GSINIT + + ;; 13 8-byte entries. We point them all at __isr_nop + ljmp __isr_nop ; 3 bytes + .ds 5 ; + 5 = 8 bytes for vector slot + ljmp __isr_nop + .ds 5 + ljmp __isr_nop + .ds 5 + ljmp __isr_nop + .ds 5 + ljmp __isr_nop + .ds 5 + ljmp __isr_nop + .ds 5 + ljmp __isr_nop + .ds 5 + ljmp __isr_nop + .ds 5 + ljmp __isr_nop + .ds 5 + ljmp __isr_nop + .ds 5 + ljmp __isr_nop + .ds 5 + ljmp __isr_nop + .ds 5 + ljmp __isr_nop + .ds 5 + +__isr_nop:: + reti + +;;; ---------------------------------------------------------------- +;;; the FIFO/GPIF autovector. 14 4-byte entries. +;;; must start on a 128 byte boundary. +;;; ---------------------------------------------------------------- + + . = __reset_vector + 0x0080 + +__fifo_gpif_autovector:: + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + + +;;; ---------------------------------------------------------------- +;;; the USB autovector. 32 4-byte entries. +;;; must start on a 256 byte boundary. +;;; ---------------------------------------------------------------- + + . = __reset_vector + 0x0100 + +__usb_autovector:: + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop + ljmp __isr_nop + nop diff --git a/firmware/fx2/src/usrp1/.gitignore b/firmware/fx2/src/usrp1/.gitignore new file mode 100644 index 000000000..54a9e9415 --- /dev/null +++ b/firmware/fx2/src/usrp1/.gitignore @@ -0,0 +1,20 @@ +/*.ihx +/*.lnk +/*.lst +/*.map +/*.mem +/*.rel +/*.rst +/*.sym +/blink_leds.asm +/usrp_common.asm +/command_loop.asm +/fpga.asm +/*.asm +/Makefile +/Makefile.in +/usrp_gpif.c +/usrp_gpif_inline.h +/Makefile.in +/burn-usrp2-eeprom +/burn-usrp4-eeprom diff --git a/firmware/fx2/src/usrp1/Makefile.am b/firmware/fx2/src/usrp1/Makefile.am new file mode 100644 index 000000000..5586e83a3 --- /dev/null +++ b/firmware/fx2/src/usrp1/Makefile.am @@ -0,0 +1,171 @@ +# +# Copyright 2003,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +firmware2dir = $(prefix)/share/usrp/rev2 +firmware2_DATA = std.ihx + +# we put the same stuff in the rev4 directory +firmware4dir = $(prefix)/share/usrp/rev4 +firmware4_DATA = std.ihx + +EXTRA_DIST = \ + edit-gpif \ + _startup.a51 \ + blink_leds.c \ + board_specific.c \ + check_mdelay.c \ + check_udelay.c \ + eeprom_boot.a51 \ + eeprom_init.c \ + eeprom_io.c \ + eeprom_io.h \ + fpga_load.c \ + fpga_rev2.c \ + fpga_rev2.h \ + gpif.c \ + init_gpif.c \ + spi.c \ + spi.h \ + usb_descriptors.a51 \ + usrp_common.c \ + usrp_common.h \ + usrp_gpif.c \ + usrp_main.c \ + usrp_rev2_regs.h \ + vectors.a51 + + +DEFINES=-DHAVE_USRP2 +FW_INCLUDES=-I$(top_srcdir)/include \ + -I$(top_srcdir)/src/usrp1 \ + -I$(top_srcdir)/src/common \ + -I$(top_builddir)/src/common + +# with EA = 0, the FX2 implements a portion of the 8051 "external memory" +# on chip. This memory is mapped like this: +# +# The bottom 8K of memory (0x0000 - 0x1fff) is used for both data and +# code accesses. There's also 512 bytes for data only from 0xe000 - 0xe1ff. +# +# We tell the linker to start the xdata segment at 0x1800, 6K up from +# the bottom. + +MEMOPTS = --code-loc 0x0000 --code-size 0x1800 --xram-loc 0x1800 --xram-size 0x0800 \ + -Wl '-b USBDESCSEG = 0xE000' + +LIBOPTS = -L ../../lib libfx2.lib +LIBDEP = ../../lib/libfx2.lib + +LINKOPTS = $(MEMOPTS) $(LIBOPTS) + +EXECUTABLES = \ + std.ihx \ + blink_leds.ihx \ + check_mdelay.ihx \ + check_udelay.ihx \ + eeprom_boot.ihx + +STARTUP = _startup.rel + +noinst_SCRIPTS = \ + burn-usrp2-eeprom \ + burn-usrp4-eeprom + + +.c.rel: + $(XCC) $(FW_INCLUDES) $(DEFINES) \ + -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< + +.a51.rel: + test -f `basename '$<'` || $(LN_S) '$<' . + test -f ../common/`basename '$<'` -o \ + \! -f `dirname '$<'`/../common/`basename '$<'` \ + || $(LN_S) `dirname '$<'`/../common/`basename '$<'` ../common/`basename '$<'` + $(XAS) `basename '$<'` + + +EEPROM_BOOT_OBJS = eeprom_boot.rel eeprom_init.rel $(STARTUP) + +eeprom_boot.ihx: $(EEPROM_BOOT_OBJS) $(LIBDEP) + $(XCC) $(LINKOPTS) -o $@ $(EEPROM_BOOT_OBJS) + +burn-usrp2-eeprom: eeprom_boot.ihx + $(PYTHON) $(srcdir)/../common/build_eeprom.py -r2 eeprom_boot.ihx > $@ + chmod +x $@ + +burn-usrp4-eeprom: eeprom_boot.ihx + $(PYTHON) $(srcdir)/../common/build_eeprom.py -r4 eeprom_boot.ihx > $@ + chmod +x $@ + + +BLINK_LEDS_OBJS = blink_leds.rel usrp_common.rel board_specific.rel spi.rel $(STARTUP) + +blink_leds.ihx: $(BLINK_LEDS_OBJS) $(LIBDEP) + $(XCC) $(LINKOPTS) -o $@ $(BLINK_LEDS_OBJS) + + +CHECK_MDELAY_OBJS = check_mdelay.rel usrp_common.rel board_specific.rel spi.rel $(STARTUP) + +check_mdelay.ihx: $(CHECK_MDELAY_OBJS) $(LIBDEP) + $(XCC) $(LINKOPTS) -o $@ $(CHECK_MDELAY_OBJS) + + + +CHECK_UDELAY_OBJS = check_udelay.rel usrp_common.rel board_specific.rel spi.rel $(STARTUP) + +check_udelay.ihx: $(CHECK_UDELAY_OBJS) $(LIBDEP) + $(XCC) $(LINKOPTS) -o $@ $(CHECK_UDELAY_OBJS) + + + +USRP_OBJS = \ + vectors.rel \ + usrp_main.rel usrp_common.rel board_specific.rel \ + fpga_load.rel fpga_rev2.rel init_gpif.rel usrp_gpif.rel \ + usb_descriptors.rel spi.rel eeprom_io.rel $(STARTUP) + +std.ihx: $(USRP_OBJS) $(LIBDEP) + $(XCC) $(LINKOPTS) -o $@ $(USRP_OBJS) + +CLEANFILES = \ + *.ihx *.lnk *.lst *.map *.mem *.rel *.rst *.sym *.asm *.lib \ + usrp_gpif.c usrp_gpif_inline.h \ + burn-usrp2-eeprom \ + burn-usrp4-eeprom + +DISTCLEANFILES = \ + *.ihx *.lnk *.lst *.map *.mem *.rel *.rst *.sym *.asm *.lib + +# build gpif stuff + +all: usrp_gpif.c + +usrp_gpif.c usrp_gpif_inline.h : gpif.c + srcdir=$(srcdir) $(PYTHON) $(srcdir)/edit-gpif $(srcdir)/gpif.c usrp_gpif.c usrp_gpif_inline.h + + +# dependencies + +usrp_main.rel: usrp_gpif_inline.h +#usrp_main.rel: fpga.h usrp_common.h ../../include/usrp_commands.h usrp_gpif_inline.h ../../include/usrp_config.h usrp_rev2_regs.h ../../include/fx2regs.h +#usrp_common.rel: usrp_common.h ../../include/usrp_commands.h ../../include/usrp_config.h usrp_rev2_regs.h ../../include/fx2regs.h +#fpga.rel: usrp_common.h ../../include/usrp_commands.h fpga.h ../../include/usrp_config.h usrp_rev2_regs.h ../../include/fx2regs.h +#init_gpif.rel: usrp_common.h ../../include/usrp_config.h usrp_rev2_regs.h ../../include/fx2regs.h diff --git a/firmware/fx2/src/usrp1/_startup.a51 b/firmware/fx2/src/usrp1/_startup.a51 new file mode 100644 index 000000000..4f5309922 --- /dev/null +++ b/firmware/fx2/src/usrp1/_startup.a51 @@ -0,0 +1 @@ + .include "../common/_startup.a51" diff --git a/firmware/fx2/src/usrp1/blink_leds.c b/firmware/fx2/src/usrp1/blink_leds.c new file mode 100644 index 000000000..c633d5d48 --- /dev/null +++ b/firmware/fx2/src/usrp1/blink_leds.c @@ -0,0 +1 @@ +#include "../common/blink_leds.c" diff --git a/firmware/fx2/src/usrp1/board_specific.c b/firmware/fx2/src/usrp1/board_specific.c new file mode 100644 index 000000000..ef0081d84 --- /dev/null +++ b/firmware/fx2/src/usrp1/board_specific.c @@ -0,0 +1,113 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "usrp_common.h" +#include "spi.h" + +void +set_led_0 (unsigned char on) +{ + if (!on) // active low + USRP_PC |= bmPC_LED0; + else + USRP_PC &= ~bmPC_LED0; +} + +void +set_led_1 (unsigned char on) +{ + if (!on) // active low + USRP_PC |= bmPC_LED1; + else + USRP_PC &= ~bmPC_LED1; +} + +void +toggle_led_0 (void) +{ + USRP_PC ^= bmPC_LED0; +} + +void +toggle_led_1 (void) +{ + USRP_PC ^= bmPC_LED1; +} + +void +la_trace_init (void) +{ +} + +void +set_sleep_bits (unsigned char bits, unsigned char mask) +{ + // NOP on usrp1 +} + +static xdata unsigned char xbuf[1]; + +void +write_9862 (unsigned char which, unsigned char regno, unsigned char value) +{ + xbuf[0] = value; + + spi_write (0, regno & 0x3f, + which == 0 ? SPI_ENABLE_CODEC_A : SPI_ENABLE_CODEC_B, + SPI_FMT_MSB | SPI_FMT_HDR_1, + xbuf, 1); +} + +void +write_both_9862s (unsigned char regno, unsigned char value) +{ + xbuf[0] = value; + + spi_write (0, regno & 0x3f, + SPI_ENABLE_CODEC_A | SPI_ENABLE_CODEC_B, + SPI_FMT_MSB | SPI_FMT_HDR_1, + xbuf, 1); +} + +#define REG_RX_PWR_DN 1 +#define REG_TX_PWR_DN 8 +#define REG_TX_MODULATOR 20 + +static void +power_down_9862s (void) +{ + write_both_9862s (REG_RX_PWR_DN, 0x01); + write_both_9862s (REG_TX_PWR_DN, 0x0f); // pwr dn digital and analog_both + write_both_9862s (REG_TX_MODULATOR, 0x00); // coarse & fine modulators disabled +} + +void +init_board (void) +{ + la_trace_init (); + init_spi (); + + USRP_PC &= ~bmPC_nRESET; // active low reset + USRP_PC |= bmPC_nRESET; + + power_down_9862s (); +} diff --git a/firmware/fx2/src/usrp1/check_mdelay.c b/firmware/fx2/src/usrp1/check_mdelay.c new file mode 100644 index 000000000..ea4ccdb14 --- /dev/null +++ b/firmware/fx2/src/usrp1/check_mdelay.c @@ -0,0 +1 @@ +#include "../common/check_mdelay.c" diff --git a/firmware/fx2/src/usrp1/check_udelay.c b/firmware/fx2/src/usrp1/check_udelay.c new file mode 100644 index 000000000..d01622e5e --- /dev/null +++ b/firmware/fx2/src/usrp1/check_udelay.c @@ -0,0 +1 @@ +#include "../common/check_udelay.c" diff --git a/firmware/fx2/src/usrp1/edit-gpif b/firmware/fx2/src/usrp1/edit-gpif new file mode 100755 index 000000000..5367b75a5 --- /dev/null +++ b/firmware/fx2/src/usrp1/edit-gpif @@ -0,0 +1,114 @@ +#!/usr/bin/env python +# -*- Python -*- +# +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + + +# Edit the gpif.c file generated by the Cypress GPIF Designer Tool and +# produce usrp_gpif.c, and usrp_gpif_inline.h, files suitable for our +# uses. + +import re +import string +import sys + +def check_flow_state (line, flow_state_dict): + mo = re.match (r'/\* Wave (\d) FlowStates \*/ (.*),', line) + if mo: + wave = int (mo.group (1)) + data = mo.group (2) + split = data.split (',', 8) + v = map (lambda x : int (x, 16), split) + # print "%s, %s" % (wave, data) + # print "split: ", split + # print "v : ", v + flow_state_dict[wave] = v + + +def delta (xseq, yseq): + # set subtraction + z = [] + for x in xseq: + if x not in yseq: + z.append (x) + return z + + +def write_define (output, name, pairs): + output.write ('#define %s()\t\\\n' % name) + output.write ('do {\t\t\t\t\t\\\n') + for reg, val in pairs: + output.write ('%14s = 0x%02x;\t\t\t\\\n' % (reg, val)) + output.write ('} while (0)\n\n') + +def write_inlines (output, dict): + regs = ['FLOWSTATE', 'FLOWLOGIC', 'FLOWEQ0CTL', 'FLOWEQ1CTL', 'FLOWHOLDOFF', + 'FLOWSTB', 'FLOWSTBEDGE', 'FLOWSTBHPERIOD', 'GPIFHOLDAMOUNT'] + + READ_FLOW_STATE = 2 + WRITE_FLOW_STATE = 3 + + read_info = zip (regs, dict[READ_FLOW_STATE]) + write_info = zip (regs, dict[WRITE_FLOW_STATE]) + + output.write ('''/* + * Machine generated by "edit-gpif". Do not edit by hand. + */ + +''') + write_define (output, 'setup_flowstate_common', read_info) + write_define (output, 'setup_flowstate_read', delta (read_info, write_info)) + write_define (output, 'setup_flowstate_write', delta (write_info, read_info)) + + +def edit_gpif (input_name, output_name, inline_name): + input = open (input_name, 'r') + output = open (output_name, 'w') + inline = open (inline_name, 'w') + flow_state_dict = {} + + output.write ('''/* + * Machine generated by "edit-gpif". Do not edit by hand. + */ + +''') + + while 1: + line = input.readline () + line = string.replace (line, '\r','') + line = re.sub (r' *$', r'', line) + + check_flow_state (line, flow_state_dict) + + line = re.sub (r'#include', r'// #include', line) + line = re.sub (r'xdata ', r'', line) + if re.search (r'GpifInit', line): + break + + output.write (line) + + output.close () + write_inlines (inline, flow_state_dict) + inline.close () + + +# gpif.c usrp_gpif.c usrp_gpif_inline.h +edit_gpif (sys.argv[1], sys.argv[2], sys.argv[3]) diff --git a/firmware/fx2/src/usrp1/eeprom_boot.a51 b/firmware/fx2/src/usrp1/eeprom_boot.a51 new file mode 100644 index 000000000..65e452668 --- /dev/null +++ b/firmware/fx2/src/usrp1/eeprom_boot.a51 @@ -0,0 +1,573 @@ +;-------------------------------------------------------- +; Hand tweaked minimal eeprom boot code +;-------------------------------------------------------- + .module eeprom_boot + .optsdcc -mmcs51 --model-small + +;-------------------------------------------------------- +; Public variables in this module +;-------------------------------------------------------- + .globl _eeprom_init + .globl _EP8FIFOBUF + .globl _EP6FIFOBUF + .globl _EP4FIFOBUF + .globl _EP2FIFOBUF + .globl _EP1INBUF + .globl _EP1OUTBUF + .globl _EP0BUF + .globl _CT4 + .globl _CT3 + .globl _CT2 + .globl _CT1 + .globl _USBTEST + .globl _TESTCFG + .globl _DBUG + .globl _UDMACRCQUAL + .globl _UDMACRCL + .globl _UDMACRCH + .globl _GPIFHOLDAMOUNT + .globl _FLOWSTBHPERIOD + .globl _FLOWSTBEDGE + .globl _FLOWSTB + .globl _FLOWHOLDOFF + .globl _FLOWEQ1CTL + .globl _FLOWEQ0CTL + .globl _FLOWLOGIC + .globl _FLOWSTATE + .globl _GPIFABORT + .globl _GPIFREADYSTAT + .globl _GPIFREADYCFG + .globl _XGPIFSGLDATLNOX + .globl _XGPIFSGLDATLX + .globl _XGPIFSGLDATH + .globl _EP8GPIFTRIG + .globl _EP8GPIFPFSTOP + .globl _EP8GPIFFLGSEL + .globl _EP6GPIFTRIG + .globl _EP6GPIFPFSTOP + .globl _EP6GPIFFLGSEL + .globl _EP4GPIFTRIG + .globl _EP4GPIFPFSTOP + .globl _EP4GPIFFLGSEL + .globl _EP2GPIFTRIG + .globl _EP2GPIFPFSTOP + .globl _EP2GPIFFLGSEL + .globl _GPIFTCB0 + .globl _GPIFTCB1 + .globl _GPIFTCB2 + .globl _GPIFTCB3 + .globl _GPIFADRL + .globl _GPIFADRH + .globl _GPIFCTLCFG + .globl _GPIFIDLECTL + .globl _GPIFIDLECS + .globl _GPIFWFSELECT + .globl _SETUPDAT + .globl _SUDPTRCTL + .globl _SUDPTRL + .globl _SUDPTRH + .globl _EP8FIFOBCL + .globl _EP8FIFOBCH + .globl _EP6FIFOBCL + .globl _EP6FIFOBCH + .globl _EP4FIFOBCL + .globl _EP4FIFOBCH + .globl _EP2FIFOBCL + .globl _EP2FIFOBCH + .globl _EP8FIFOFLGS + .globl _EP6FIFOFLGS + .globl _EP4FIFOFLGS + .globl _EP2FIFOFLGS + .globl _EP8CS + .globl _EP6CS + .globl _EP4CS + .globl _EP2CS + .globl _EP1INCS + .globl _EP1OUTCS + .globl _EP0CS + .globl _EP8BCL + .globl _EP8BCH + .globl _EP6BCL + .globl _EP6BCH + .globl _EP4BCL + .globl _EP4BCH + .globl _EP2BCL + .globl _EP2BCH + .globl _EP1INBC + .globl _EP1OUTBC + .globl _EP0BCL + .globl _EP0BCH + .globl _FNADDR + .globl _MICROFRAME + .globl _USBFRAMEL + .globl _USBFRAMEH + .globl _TOGCTL + .globl _WAKEUPCS + .globl _SUSPEND + .globl _USBCS + .globl _XAUTODAT2 + .globl _XAUTODAT1 + .globl _I2CTL + .globl _I2DAT + .globl _I2CS + .globl _PORTECFG + .globl _PORTCCFG + .globl _PORTACFG + .globl _INTSETUP + .globl _INT4IVEC + .globl _INT2IVEC + .globl _CLRERRCNT + .globl _ERRCNTLIM + .globl _USBERRIRQ + .globl _USBERRIE + .globl _GPIFIRQ + .globl _GPIFIE + .globl _EPIRQ + .globl _EPIE + .globl _USBIRQ + .globl _USBIE + .globl _NAKIRQ + .globl _NAKIE + .globl _IBNIRQ + .globl _IBNIE + .globl _EP8FIFOIRQ + .globl _EP8FIFOIE + .globl _EP6FIFOIRQ + .globl _EP6FIFOIE + .globl _EP4FIFOIRQ + .globl _EP4FIFOIE + .globl _EP2FIFOIRQ + .globl _EP2FIFOIE + .globl _OUTPKTEND + .globl _INPKTEND + .globl _EP8ISOINPKTS + .globl _EP6ISOINPKTS + .globl _EP4ISOINPKTS + .globl _EP2ISOINPKTS + .globl _EP8FIFOPFL + .globl _EP8FIFOPFH + .globl _EP6FIFOPFL + .globl _EP6FIFOPFH + .globl _EP4FIFOPFL + .globl _EP4FIFOPFH + .globl _EP2FIFOPFL + .globl _EP2FIFOPFH + .globl _EP8AUTOINLENL + .globl _EP8AUTOINLENH + .globl _EP6AUTOINLENL + .globl _EP6AUTOINLENH + .globl _EP4AUTOINLENL + .globl _EP4AUTOINLENH + .globl _EP2AUTOINLENL + .globl _EP2AUTOINLENH + .globl _EP8FIFOCFG + .globl _EP6FIFOCFG + .globl _EP4FIFOCFG + .globl _EP2FIFOCFG + .globl _EP8CFG + .globl _EP6CFG + .globl _EP4CFG + .globl _EP2CFG + .globl _EP1INCFG + .globl _EP1OUTCFG + .globl _REVCTL + .globl _REVID + .globl _FIFOPINPOLAR + .globl _UART230 + .globl _BPADDRL + .globl _BPADDRH + .globl _BREAKPT + .globl _FIFORESET + .globl _PINFLAGSCD + .globl _PINFLAGSAB + .globl _IFCONFIG + .globl _CPUCS + .globl _RES_WAVEDATA_END + .globl _GPIF_WAVE_DATA +;-------------------------------------------------------- +; special function registers +;-------------------------------------------------------- +_IOA = 0x0080 +_SP = 0x0081 +_DPL = 0x0082 +_DPH = 0x0083 +_DPL1 = 0x0084 +_DPH1 = 0x0085 +_DPS = 0x0086 +_PCON = 0x0087 +_TCON = 0x0088 +_TMOD = 0x0089 +_TL0 = 0x008a +_TL1 = 0x008b +_TH0 = 0x008c +_TH1 = 0x008d +_CKCON = 0x008e +_IOB = 0x0090 +_EXIF = 0x0091 +_MPAGE = 0x0092 +_SCON0 = 0x0098 +_SBUF0 = 0x0099 +_APTR1H = 0x009a +_APTR1L = 0x009b +_AUTODAT1 = 0x009c +_AUTOPTRH2 = 0x009d +_AUTOPTRL2 = 0x009e +_AUTODAT2 = 0x009f +_IOC = 0x00a0 +_INT2CLR = 0x00a1 +_INT4CLR = 0x00a2 +_IE = 0x00a8 +_EP2468STAT = 0x00aa +_EP24FIFOFLGS = 0x00ab +_EP68FIFOFLGS = 0x00ac +_AUTOPTRSETUP = 0x00af +_IOD = 0x00b0 +_IOE = 0x00b1 +_OEA = 0x00b2 +_OEB = 0x00b3 +_OEC = 0x00b4 +_OED = 0x00b5 +_OEE = 0x00b6 +_IP = 0x00b8 +_EP01STAT = 0x00ba +_GPIFTRIG = 0x00bb +_GPIFSGLDATH = 0x00bd +_GPIFSGLDATLX = 0x00be +_GPIFSGLDATLNOX = 0x00bf +_SCON1 = 0x00c0 +_SBUF1 = 0x00c1 +_T2CON = 0x00c8 +_RCAP2L = 0x00ca +_RCAP2H = 0x00cb +_TL2 = 0x00cc +_TH2 = 0x00cd +_PSW = 0x00d0 +_EICON = 0x00d8 +_ACC = 0x00e0 +_EIE = 0x00e8 +_B = 0x00f0 +_EIP = 0x00f8 +;-------------------------------------------------------- +; special function bits +;-------------------------------------------------------- +_SEL = 0x0086 +_IT0 = 0x0088 +_IE0 = 0x0089 +_IT1 = 0x008a +_IE1 = 0x008b +_TR0 = 0x008c +_TF0 = 0x008d +_TR1 = 0x008e +_TF1 = 0x008f +_RI = 0x0098 +_TI = 0x0099 +_RB8 = 0x009a +_TB8 = 0x009b +_REN = 0x009c +_SM2 = 0x009d +_SM1 = 0x009e +_SM0 = 0x009f +_EX0 = 0x00a8 +_ET0 = 0x00a9 +_EX1 = 0x00aa +_ET1 = 0x00ab +_ES0 = 0x00ac +_ET2 = 0x00ad +_ES1 = 0x00ae +_EA = 0x00af +_PX0 = 0x00b8 +_PT0 = 0x00b9 +_PX1 = 0x00ba +_PT1 = 0x00bb +_PS0 = 0x00bc +_PT2 = 0x00bd +_PS1 = 0x00be +_RI1 = 0x00c0 +_TI1 = 0x00c1 +_RB81 = 0x00c2 +_TB81 = 0x00c3 +_REN1 = 0x00c4 +_SM21 = 0x00c5 +_SM11 = 0x00c6 +_SM01 = 0x00c7 +_CP_RL2 = 0x00c8 +_C_T2 = 0x00c9 +_TR2 = 0x00ca +_EXEN2 = 0x00cb +_TCLK = 0x00cc +_RCLK = 0x00cd +_EXF2 = 0x00ce +_TF2 = 0x00cf +_P = 0x00d0 +_FL = 0x00d1 +_OV = 0x00d2 +_RS0 = 0x00d3 +_RS1 = 0x00d4 +_F0 = 0x00d5 +_AC = 0x00d6 +_CY = 0x00d7 +_INT6 = 0x00db +_RESI = 0x00dc +_ERESI = 0x00dd +_SMOD1 = 0x00df +_EIUSB = 0x00e8 +_EI2C = 0x00e9 +_EIEX4 = 0x00ea +_EIEX5 = 0x00eb +_EIEX6 = 0x00ec +_PUSB = 0x00f8 +_PI2C = 0x00f9 +_EIPX4 = 0x00fa +_EIPX5 = 0x00fb +_EIPX6 = 0x00fc +_bitS_CLK = 0x0080 +_bitS_OUT = 0x0081 +_bitS_IN = 0x0082 +_bitALTERA_DATA0 = 0x00a1 +_bitALTERA_DCLK = 0x00a3 +;-------------------------------------------------------- +; overlayable register banks +;-------------------------------------------------------- + .area REG_BANK_0 (REL,OVR,DATA) + .ds 8 +;-------------------------------------------------------- +; internal ram data +;-------------------------------------------------------- + .area DSEG (DATA) +;-------------------------------------------------------- +; overlayable items in internal ram +;-------------------------------------------------------- + .area OSEG (OVR,DATA) +;-------------------------------------------------------- +; Stack segment in internal ram +;-------------------------------------------------------- + .area SSEG (DATA) +__start__stack: + .ds 1 + +;-------------------------------------------------------- +; indirectly addressable internal ram data +;-------------------------------------------------------- + .area ISEG (DATA) +;-------------------------------------------------------- +; bit data +;-------------------------------------------------------- + .area BSEG (BIT) +;-------------------------------------------------------- +; external ram data +;-------------------------------------------------------- + .area XSEG (XDATA) +_GPIF_WAVE_DATA = 0xe400 +_RES_WAVEDATA_END = 0xe480 +_CPUCS = 0xe600 +_IFCONFIG = 0xe601 +_PINFLAGSAB = 0xe602 +_PINFLAGSCD = 0xe603 +_FIFORESET = 0xe604 +_BREAKPT = 0xe605 +_BPADDRH = 0xe606 +_BPADDRL = 0xe607 +_UART230 = 0xe608 +_FIFOPINPOLAR = 0xe609 +_REVID = 0xe60a +_REVCTL = 0xe60b +_EP1OUTCFG = 0xe610 +_EP1INCFG = 0xe611 +_EP2CFG = 0xe612 +_EP4CFG = 0xe613 +_EP6CFG = 0xe614 +_EP8CFG = 0xe615 +_EP2FIFOCFG = 0xe618 +_EP4FIFOCFG = 0xe619 +_EP6FIFOCFG = 0xe61a +_EP8FIFOCFG = 0xe61b +_EP2AUTOINLENH = 0xe620 +_EP2AUTOINLENL = 0xe621 +_EP4AUTOINLENH = 0xe622 +_EP4AUTOINLENL = 0xe623 +_EP6AUTOINLENH = 0xe624 +_EP6AUTOINLENL = 0xe625 +_EP8AUTOINLENH = 0xe626 +_EP8AUTOINLENL = 0xe627 +_EP2FIFOPFH = 0xe630 +_EP2FIFOPFL = 0xe631 +_EP4FIFOPFH = 0xe632 +_EP4FIFOPFL = 0xe633 +_EP6FIFOPFH = 0xe634 +_EP6FIFOPFL = 0xe635 +_EP8FIFOPFH = 0xe636 +_EP8FIFOPFL = 0xe637 +_EP2ISOINPKTS = 0xe640 +_EP4ISOINPKTS = 0xe641 +_EP6ISOINPKTS = 0xe642 +_EP8ISOINPKTS = 0xe643 +_INPKTEND = 0xe648 +_OUTPKTEND = 0xe649 +_EP2FIFOIE = 0xe650 +_EP2FIFOIRQ = 0xe651 +_EP4FIFOIE = 0xe652 +_EP4FIFOIRQ = 0xe653 +_EP6FIFOIE = 0xe654 +_EP6FIFOIRQ = 0xe655 +_EP8FIFOIE = 0xe656 +_EP8FIFOIRQ = 0xe657 +_IBNIE = 0xe658 +_IBNIRQ = 0xe659 +_NAKIE = 0xe65a +_NAKIRQ = 0xe65b +_USBIE = 0xe65c +_USBIRQ = 0xe65d +_EPIE = 0xe65e +_EPIRQ = 0xe65f +_GPIFIE = 0xe660 +_GPIFIRQ = 0xe661 +_USBERRIE = 0xe662 +_USBERRIRQ = 0xe663 +_ERRCNTLIM = 0xe664 +_CLRERRCNT = 0xe665 +_INT2IVEC = 0xe666 +_INT4IVEC = 0xe667 +_INTSETUP = 0xe668 +_PORTACFG = 0xe670 +_PORTCCFG = 0xe671 +_PORTECFG = 0xe672 +_I2CS = 0xe678 +_I2DAT = 0xe679 +_I2CTL = 0xe67a +_XAUTODAT1 = 0xe67b +_XAUTODAT2 = 0xe67c +_USBCS = 0xe680 +_SUSPEND = 0xe681 +_WAKEUPCS = 0xe682 +_TOGCTL = 0xe683 +_USBFRAMEH = 0xe684 +_USBFRAMEL = 0xe685 +_MICROFRAME = 0xe686 +_FNADDR = 0xe687 +_EP0BCH = 0xe68a +_EP0BCL = 0xe68b +_EP1OUTBC = 0xe68d +_EP1INBC = 0xe68f +_EP2BCH = 0xe690 +_EP2BCL = 0xe691 +_EP4BCH = 0xe694 +_EP4BCL = 0xe695 +_EP6BCH = 0xe698 +_EP6BCL = 0xe699 +_EP8BCH = 0xe69c +_EP8BCL = 0xe69d +_EP0CS = 0xe6a0 +_EP1OUTCS = 0xe6a1 +_EP1INCS = 0xe6a2 +_EP2CS = 0xe6a3 +_EP4CS = 0xe6a4 +_EP6CS = 0xe6a5 +_EP8CS = 0xe6a6 +_EP2FIFOFLGS = 0xe6a7 +_EP4FIFOFLGS = 0xe6a8 +_EP6FIFOFLGS = 0xe6a9 +_EP8FIFOFLGS = 0xe6aa +_EP2FIFOBCH = 0xe6ab +_EP2FIFOBCL = 0xe6ac +_EP4FIFOBCH = 0xe6ad +_EP4FIFOBCL = 0xe6ae +_EP6FIFOBCH = 0xe6af +_EP6FIFOBCL = 0xe6b0 +_EP8FIFOBCH = 0xe6b1 +_EP8FIFOBCL = 0xe6b2 +_SUDPTRH = 0xe6b3 +_SUDPTRL = 0xe6b4 +_SUDPTRCTL = 0xe6b5 +_SETUPDAT = 0xe6b8 +_GPIFWFSELECT = 0xe6c0 +_GPIFIDLECS = 0xe6c1 +_GPIFIDLECTL = 0xe6c2 +_GPIFCTLCFG = 0xe6c3 +_GPIFADRH = 0xe6c4 +_GPIFADRL = 0xe6c5 +_GPIFTCB3 = 0xe6ce +_GPIFTCB2 = 0xe6cf +_GPIFTCB1 = 0xe6d0 +_GPIFTCB0 = 0xe6d1 +_EP2GPIFFLGSEL = 0xe6d2 +_EP2GPIFPFSTOP = 0xe6d3 +_EP2GPIFTRIG = 0xe6d4 +_EP4GPIFFLGSEL = 0xe6da +_EP4GPIFPFSTOP = 0xe6db +_EP4GPIFTRIG = 0xe6dc +_EP6GPIFFLGSEL = 0xe6e2 +_EP6GPIFPFSTOP = 0xe6e3 +_EP6GPIFTRIG = 0xe6e4 +_EP8GPIFFLGSEL = 0xe6ea +_EP8GPIFPFSTOP = 0xe6eb +_EP8GPIFTRIG = 0xe6ec +_XGPIFSGLDATH = 0xe6f0 +_XGPIFSGLDATLX = 0xe6f1 +_XGPIFSGLDATLNOX = 0xe6f2 +_GPIFREADYCFG = 0xe6f3 +_GPIFREADYSTAT = 0xe6f4 +_GPIFABORT = 0xe6f5 +_FLOWSTATE = 0xe6c6 +_FLOWLOGIC = 0xe6c7 +_FLOWEQ0CTL = 0xe6c8 +_FLOWEQ1CTL = 0xe6c9 +_FLOWHOLDOFF = 0xe6ca +_FLOWSTB = 0xe6cb +_FLOWSTBEDGE = 0xe6cc +_FLOWSTBHPERIOD = 0xe6cd +_GPIFHOLDAMOUNT = 0xe60c +_UDMACRCH = 0xe67d +_UDMACRCL = 0xe67e +_UDMACRCQUAL = 0xe67f +_DBUG = 0xe6f8 +_TESTCFG = 0xe6f9 +_USBTEST = 0xe6fa +_CT1 = 0xe6fb +_CT2 = 0xe6fc +_CT3 = 0xe6fd +_CT4 = 0xe6fe +_EP0BUF = 0xe740 +_EP1OUTBUF = 0xe780 +_EP1INBUF = 0xe7c0 +_EP2FIFOBUF = 0xf000 +_EP4FIFOBUF = 0xf400 +_EP6FIFOBUF = 0xf800 +_EP8FIFOBUF = 0xfc00 +;-------------------------------------------------------- +; external initialized ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; interrupt vector +;-------------------------------------------------------- + .area CSEG (CODE) +__interrupt_vect: + ljmp __sdcc_gsinit_startup +;-------------------------------------------------------- +; global & static initialisations +;-------------------------------------------------------- + .area GSINIT (CODE) + .area GSFINAL (CODE) + .area GSINIT (CODE) +__sdcc_gsinit_startup: + mov sp,#__start__stack - 1 + lcall __sdcc_external_startup + mov a,dpl + jz __sdcc_init_data + ljmp __sdcc_program_startup +__sdcc_init_data: + .area GSFINAL (CODE) + ljmp __sdcc_program_startup +;-------------------------------------------------------- +; Home +;-------------------------------------------------------- + .area HOME (CODE) + .area CSEG (CODE) +;-------------------------------------------------------- +; code +;-------------------------------------------------------- + .area CSEG (CODE) +__sdcc_program_startup: + lcall _eeprom_init +; return from _eeprom_init will spin here + sjmp . + .area CSEG (CODE) diff --git a/firmware/fx2/src/usrp1/eeprom_init.c b/firmware/fx2/src/usrp1/eeprom_init.c new file mode 100644 index 000000000..a6f6cbe2d --- /dev/null +++ b/firmware/fx2/src/usrp1/eeprom_init.c @@ -0,0 +1,116 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "usrp_common.h" +#include "usrp_commands.h" +#include "spi.h" + +/* + * the host side fpga loader code pushes an MD5 hash of the bitstream + * into hash1. + */ +#define USRP_HASH_SIZE 16 +xdata at USRP_HASH_SLOT_0_ADDR unsigned char hash0[USRP_HASH_SIZE]; + + +#define enable_codecs() USRP_PA &= ~(bmPA_SEN_CODEC_A | bmPA_SEN_CODEC_B) +#define disable_all() USRP_PA |= (bmPA_SEN_CODEC_A | bmPA_SEN_CODEC_B) + +static void +write_byte_msb (unsigned char v); + +void +write_both_9862s (unsigned char header_lo, unsigned char v) +{ + enable_codecs (); + + write_byte_msb (header_lo); + write_byte_msb (v); + + disable_all (); +} + +// ---------------------------------------------------------------- + +static void +write_byte_msb (unsigned char v) +{ + unsigned char n = 8; + do { + v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit) + bitS_OUT = v & 0x1; + bitS_CLK = 1; + bitS_CLK = 0; + } while (--n != 0); +} + +// ---------------------------------------------------------------- + +#define REG_RX_PWR_DN 1 +#define REG_TX_PWR_DN 8 +#define REG_TX_MODULATOR 20 + +void eeprom_init (void) +{ + unsigned short counter; + unsigned char i; + + // configure IO ports (B and D are used by GPIF) + + IOA = bmPORT_A_INITIAL; // Port A initial state + OEA = bmPORT_A_OUTPUTS; // Port A direction register + + IOC = bmPORT_C_INITIAL; // Port C initial state + OEC = bmPORT_C_OUTPUTS; // Port C direction register + + IOE = bmPORT_E_INITIAL; // Port E initial state + OEE = bmPORT_E_OUTPUTS; // Port E direction register + + EP0BCH = 0; SYNCDELAY; + + // USBCS &= ~bmRENUM; // chip firmware handles commands + USBCS = 0; // chip firmware handles commands + + USRP_PC &= ~bmPC_nRESET; // active low reset + USRP_PC |= bmPC_nRESET; + + // init_spi (); + bitS_OUT = 0; /* idle state has CLK = 0 */ + + write_both_9862s (REG_RX_PWR_DN, 0x01); + write_both_9862s (REG_TX_PWR_DN, 0x0f); // pwr dn digital and analog_both + write_both_9862s (REG_TX_MODULATOR, 0x00); // coarse & fine modulators disabled + + // zero firmware hash slot + i = 0; + do { + hash0[i] = 0; + i++; + } while (i != USRP_HASH_SIZE); + + counter = 0; + while (1){ + counter++; + if (counter & 0x8000) + IOC ^= bmPC_LED0; + } +} diff --git a/firmware/fx2/src/usrp1/eeprom_io.c b/firmware/fx2/src/usrp1/eeprom_io.c new file mode 100644 index 000000000..9eeb53636 --- /dev/null +++ b/firmware/fx2/src/usrp1/eeprom_io.c @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "eeprom_io.h" +#include "i2c.h" +#include "delay.h" + +// returns non-zero if successful, else 0 +unsigned char +eeprom_read (unsigned char i2c_addr, unsigned char eeprom_offset, + xdata unsigned char *buf, unsigned char len) +{ + // We setup a random read by first doing a "zero byte write". + // Writes carry an address. Reads use an implicit address. + + static xdata unsigned char cmd[1]; + cmd[0] = eeprom_offset; + if (!i2c_write(i2c_addr, cmd, 1)) + return 0; + + return i2c_read(i2c_addr, buf, len); +} + + +#if 0 + +// returns non-zero if successful, else 0 +unsigned char +eeprom_write (unsigned char i2c_addr, unsigned char eeprom_offset, + const xdata unsigned char *buf, unsigned char len) +{ + static xdata unsigned char cmd[2]; + unsigned char ok; + + while (len-- > 0){ + cmd[0] = eeprom_offset++; + cmd[1] = *buf++; + ok = i2c_write(i2c_addr, cmd, 2); + mdelay(10); // delay 10ms worst case write time + if (!ok) + return 0; + } + return 1; +} + +#endif diff --git a/firmware/fx2/src/usrp1/eeprom_io.h b/firmware/fx2/src/usrp1/eeprom_io.h new file mode 100644 index 000000000..558017b12 --- /dev/null +++ b/firmware/fx2/src/usrp1/eeprom_io.h @@ -0,0 +1,38 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_EEPROM_IO_H +#define INCLUDED_EEPROM_IO_H + + +// returns non-zero if successful, else 0 +unsigned char +eeprom_read (unsigned char i2c_addr, unsigned char eeprom_offset, + xdata unsigned char *buf, unsigned char len); + +// returns non-zero if successful, else 0 +unsigned char +eeprom_write (unsigned char i2c_addr, unsigned char eeprom_offset, + const xdata unsigned char *buf, unsigned char len); + + +#endif /* INCLUDED_EEPROM_IO_H */ diff --git a/firmware/fx2/src/usrp1/fpga_load.c b/firmware/fx2/src/usrp1/fpga_load.c new file mode 100644 index 000000000..b0256e925 --- /dev/null +++ b/firmware/fx2/src/usrp1/fpga_load.c @@ -0,0 +1 @@ +#include "../common/fpga_load.c" diff --git a/firmware/fx2/src/usrp1/fpga_rev2.c b/firmware/fx2/src/usrp1/fpga_rev2.c new file mode 100644 index 000000000..cca961dc4 --- /dev/null +++ b/firmware/fx2/src/usrp1/fpga_rev2.c @@ -0,0 +1,122 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "fpga.h" +#include "fpga_regs_common.h" +#include "usrp_common.h" +#include "usrp_globals.h" +#include "spi.h" + +unsigned char g_tx_reset = 0; +unsigned char g_rx_reset = 0; + +void +fpga_write_reg (unsigned char regno, const xdata unsigned char *regval) +{ + spi_write (0, 0x00 | (regno & 0x7f), + SPI_ENABLE_FPGA, + SPI_FMT_MSB | SPI_FMT_HDR_1, + regval, 4); +} + + +static xdata unsigned char regval[4] = {0, 0, 0, 0}; + +static void +write_fpga_master_ctrl (void) +{ + unsigned char v = 0; + if (g_tx_enable) + v |= bmFR_MC_ENABLE_TX; + if (g_rx_enable) + v |= bmFR_MC_ENABLE_RX; + if (g_tx_reset) + v |= bmFR_MC_RESET_TX; + if (g_rx_reset) + v |= bmFR_MC_RESET_RX; + regval[3] = v; + + fpga_write_reg (FR_MASTER_CTRL, regval); +} + +// Resets both AD9862's and the FPGA serial bus interface. + +void +fpga_set_reset (unsigned char on) +{ + on &= 0x1; + + if (on){ + USRP_PC &= ~bmPC_nRESET; // active low + g_tx_enable = 0; + g_rx_enable = 0; + g_tx_reset = 0; + g_rx_reset = 0; + } + else + USRP_PC |= bmPC_nRESET; +} + +void +fpga_set_tx_enable (unsigned char on) +{ + on &= 0x1; + g_tx_enable = on; + + write_fpga_master_ctrl (); + + if (on){ + g_tx_underrun = 0; + fpga_clear_flags (); + } +} + +void +fpga_set_rx_enable (unsigned char on) +{ + on &= 0x1; + g_rx_enable = on; + + write_fpga_master_ctrl (); + if (on){ + g_rx_overrun = 0; + fpga_clear_flags (); + } +} + +void +fpga_set_tx_reset (unsigned char on) +{ + on &= 0x1; + g_tx_reset = on; + + write_fpga_master_ctrl (); +} + +void +fpga_set_rx_reset (unsigned char on) +{ + on &= 0x1; + g_rx_reset = on; + + write_fpga_master_ctrl (); +} diff --git a/firmware/fx2/src/usrp1/fpga_rev2.h b/firmware/fx2/src/usrp1/fpga_rev2.h new file mode 100644 index 000000000..54ec3f9fa --- /dev/null +++ b/firmware/fx2/src/usrp1/fpga_rev2.h @@ -0,0 +1,58 @@ +/* + * USRP - Universal Software Radio Peripheral + * + * Copyright (C) 2003,2004 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 3 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 + */ + +#ifndef INCLUDED_FPGA_REV1_H +#define INCLUDED_FPGA_REV1_H + +void fpga_set_reset (unsigned char v); +void fpga_set_tx_enable (unsigned char v); +void fpga_set_rx_enable (unsigned char v); +void fpga_set_tx_reset (unsigned char v); +void fpga_set_rx_reset (unsigned char v); + +unsigned char fpga_has_room_for_packet (void); +unsigned char fpga_has_packet_avail (void); + +#if (UC_BOARD_HAS_FPGA) +/* + * return TRUE iff FPGA internal fifo has room for 512 bytes. + */ +#define fpga_has_room_for_packet() (GPIFREADYSTAT & bmFPGA_HAS_SPACE) + +/* + * return TRUE iff FPGA internal fifo has at least 512 bytes available. + */ +#define fpga_has_packet_avail() (GPIFREADYSTAT & bmFPGA_PKT_AVAIL) + +#else /* no FPGA on board. fake it. */ + +#define fpga_has_room_for_packet() TRUE +#define fpga_has_packet_avail() TRUE + +#endif + +#define fpga_clear_flags() \ + do { \ + USRP_PE |= bmPE_FPGA_CLR_STATUS; \ + USRP_PE &= ~bmPE_FPGA_CLR_STATUS; \ + } while (0) + + +#endif /* INCLUDED_FPGA_REV1_H */ diff --git a/firmware/fx2/src/usrp1/gpif.c b/firmware/fx2/src/usrp1/gpif.c new file mode 100644 index 000000000..f6745a43b --- /dev/null +++ b/firmware/fx2/src/usrp1/gpif.c @@ -0,0 +1,292 @@ +// This program configures the General Programmable Interface (GPIF) for FX2. +// Please do not modify sections of text which are marked as "DO NOT EDIT ...". +// +// DO NOT EDIT ... +// GPIF Initialization +// Interface Timing Async +// Internal Ready Init IntRdy=1 +// CTL Out Tristate-able Binary +// SingleWrite WF Select 1 +// SingleRead WF Select 0 +// FifoWrite WF Select 3 +// FifoRead WF Select 2 +// Data Bus Idle Drive Tristate +// END DO NOT EDIT + +// DO NOT EDIT ... +// GPIF Wave Names +// Wave 0 = singlerd +// Wave 1 = singlewr +// Wave 2 = FIFORd +// Wave 3 = FIFOWr + +// GPIF Ctrl Outputs Level +// CTL 0 = WEN# CMOS +// CTL 1 = REN# CMOS +// CTL 2 = OE# CMOS +// CTL 3 = CLRST CMOS +// CTL 4 = unused CMOS +// CTL 5 = BOGUS CMOS + +// GPIF Rdy Inputs +// RDY0 = EF# +// RDY1 = FF# +// RDY2 = unused +// RDY3 = unused +// RDY4 = unused +// RDY5 = TCXpire +// FIFOFlag = FIFOFlag +// IntReady = IntReady +// END DO NOT EDIT +// DO NOT EDIT ... +// +// GPIF Waveform 0: singlerd +// +// Interval 0 1 2 3 4 5 6 Idle (7) +// _________ _________ _________ _________ _________ _________ _________ _________ +// +// AddrMode Same Val Same Val Same Val Same Val Same Val Same Val Same Val +// DataMode NO Data NO Data NO Data NO Data NO Data NO Data NO Data +// NextData SameData SameData SameData SameData SameData SameData SameData +// Int Trig No Int No Int No Int No Int No Int No Int No Int +// IF/Wait Wait 1 Wait 1 Wait 1 Wait 1 Wait 1 Wait 1 Wait 1 +// Term A +// LFunc +// Term B +// Branch1 +// Branch0 +// Re-Exec +// Sngl/CRC Default Default Default Default Default Default Default +// WEN# 0 0 0 0 0 0 0 0 +// REN# 0 0 0 0 0 0 0 0 +// OE# 0 0 0 0 0 0 0 0 +// CLRST 0 0 0 0 0 0 0 0 +// unused 0 0 0 0 0 0 0 0 +// BOGUS 0 0 0 0 0 0 0 0 +// +// END DO NOT EDIT +// DO NOT EDIT ... +// +// GPIF Waveform 1: singlewr +// +// Interval 0 1 2 3 4 5 6 Idle (7) +// _________ _________ _________ _________ _________ _________ _________ _________ +// +// AddrMode Same Val Same Val Same Val Same Val Same Val Same Val Same Val +// DataMode Activate Activate Activate Activate Activate Activate Activate +// NextData SameData SameData SameData SameData SameData SameData SameData +// Int Trig No Int No Int No Int No Int No Int No Int No Int +// IF/Wait Wait 1 IF Wait 1 Wait 1 Wait 1 Wait 1 Wait 1 +// Term A EF# +// LFunc AND +// Term B EF# +// Branch1 ThenIdle +// Branch0 ElseIdle +// Re-Exec No +// Sngl/CRC Default Default Default Default Default Default Default +// WEN# 0 1 1 1 1 1 1 0 +// REN# 0 0 0 0 0 0 0 0 +// OE# 0 0 0 0 0 0 0 0 +// CLRST 0 0 0 0 0 0 0 0 +// unused 0 0 0 0 0 0 0 0 +// BOGUS 0 0 0 0 0 0 0 0 +// +// END DO NOT EDIT +// DO NOT EDIT ... +// +// GPIF Waveform 2: FIFORd +// +// Interval 0 1 2 3 4 5 6 Idle (7) +// _________ _________ _________ _________ _________ _________ _________ _________ +// +// AddrMode Same Val Same Val Same Val Same Val Same Val Same Val Same Val +// DataMode NO Data Activate NO Data NO Data NO Data NO Data NO Data +// NextData SameData SameData SameData SameData SameData SameData SameData +// Int Trig No Int No Int No Int No Int No Int No Int No Int +// IF/Wait Wait 1 IF Wait 1 IF Wait 1 Wait 1 Wait 1 +// Term A TCXpire TCXpire +// LFunc AND AND +// Term B TCXpire TCXpire +// Branch1 Then 2 ThenIdle +// Branch0 Else 1 ElseIdle +// Re-Exec No No +// Sngl/CRC Default Default Default Default Default Default Default +// WEN# 0 0 0 0 0 0 0 0 +// REN# 1 0 0 0 0 0 0 0 +// OE# 1 1 1 0 0 0 0 0 +// CLRST 0 0 0 0 0 0 0 0 +// unused 0 0 0 0 0 0 0 0 +// BOGUS 0 0 0 0 0 0 0 0 +// +// END DO NOT EDIT +// DO NOT EDIT ... +// +// GPIF Waveform 3: FIFOWr +// +// Interval 0 1 2 3 4 5 6 Idle (7) +// _________ _________ _________ _________ _________ _________ _________ _________ +// +// AddrMode Same Val Same Val Same Val Same Val Same Val Same Val Same Val +// DataMode NO Data Activate Activate Activate Activate Activate Activate +// NextData SameData SameData SameData SameData SameData SameData SameData +// Int Trig No Int No Int No Int No Int No Int No Int No Int +// IF/Wait Wait 1 IF Wait 1 Wait 1 Wait 1 Wait 1 Wait 1 +// Term A TCXpire +// LFunc AND +// Term B TCXpire +// Branch1 ThenIdle +// Branch0 Else 1 +// Re-Exec No +// Sngl/CRC Default Default Default Default Default Default Default +// WEN# 0 0 0 0 0 0 0 0 +// REN# 0 0 0 0 0 0 0 0 +// OE# 0 0 0 0 0 0 0 0 +// CLRST 0 0 0 0 0 0 0 0 +// unused 0 0 0 0 0 0 0 0 +// BOGUS 0 0 0 0 0 0 0 0 +// +// END DO NOT EDIT + +// GPIF Program Code + +// DO NOT EDIT ... +#include "fx2.h" +#include "fx2regs.h" +#include "fx2sdly.h" // SYNCDELAY macro +// END DO NOT EDIT + +// DO NOT EDIT ... +const char xdata WaveData[128] = +{ +// Wave 0 +/* LenBr */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, +/* Opcode*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* Output*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* LFun */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, +// Wave 1 +/* LenBr */ 0x01, 0x3F, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, +/* Opcode*/ 0x22, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, +/* Output*/ 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, +/* LFun */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, +// Wave 2 +/* LenBr */ 0x01, 0x11, 0x01, 0x3F, 0x01, 0x01, 0x01, 0x07, +/* Opcode*/ 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, +/* Output*/ 0x06, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, +/* LFun */ 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x3F, +// Wave 3 +/* LenBr */ 0x01, 0x39, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, +/* Opcode*/ 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, +/* Output*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* LFun */ 0x00, 0x2D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, +}; +// END DO NOT EDIT + +// DO NOT EDIT ... +const char xdata FlowStates[36] = +{ +/* Wave 0 FlowStates */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* Wave 1 FlowStates */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +/* Wave 2 FlowStates */ 0x81,0x2D,0x26,0x00,0x04,0x04,0x03,0x02,0x00, +/* Wave 3 FlowStates */ 0x81,0x2D,0x21,0x00,0x04,0x04,0x03,0x02,0x00, +}; +// END DO NOT EDIT + +// DO NOT EDIT ... +const char xdata InitData[7] = +{ +/* Regs */ 0xA0,0x00,0x00,0x00,0xEE,0x4E,0x00 +}; +// END DO NOT EDIT + +// TO DO: You may add additional code below. + +void GpifInit( void ) +{ + BYTE i; + + // Registers which require a synchronization delay, see section 15.14 + // FIFORESET FIFOPINPOLAR + // INPKTEND OUTPKTEND + // EPxBCH:L REVCTL + // GPIFTCB3 GPIFTCB2 + // GPIFTCB1 GPIFTCB0 + // EPxFIFOPFH:L EPxAUTOINLENH:L + // EPxFIFOCFG EPxGPIFFLGSEL + // PINFLAGSxx EPxFIFOIRQ + // EPxFIFOIE GPIFIRQ + // GPIFIE GPIFADRH:L + // UDMACRCH:L EPxGPIFTRIG + // GPIFTRIG + + // Note: The pre-REVE EPxGPIFTCH/L register are affected, as well... + // ...these have been replaced by GPIFTC[B3:B0] registers + + // 8051 doesn't have access to waveform memories 'til + // the part is in GPIF mode. + + IFCONFIG = 0xEE; + // IFCLKSRC=1 , FIFOs executes on internal clk source + // xMHz=1 , 48MHz internal clk rate + // IFCLKOE=0 , Don't drive IFCLK pin signal at 48MHz + // IFCLKPOL=0 , Don't invert IFCLK pin signal from internal clk + // ASYNC=1 , master samples asynchronous + // GSTATE=1 , Drive GPIF states out on PORTE[2:0], debug WF + // IFCFG[1:0]=10, FX2 in GPIF master mode + + GPIFABORT = 0xFF; // abort any waveforms pending + + GPIFREADYCFG = InitData[ 0 ]; + GPIFCTLCFG = InitData[ 1 ]; + GPIFIDLECS = InitData[ 2 ]; + GPIFIDLECTL = InitData[ 3 ]; + GPIFWFSELECT = InitData[ 5 ]; + GPIFREADYSTAT = InitData[ 6 ]; + + // use dual autopointer feature... + AUTOPTRSETUP = 0x07; // inc both pointers, + // ...warning: this introduces pdata hole(s) + // ...at E67B (XAUTODAT1) and E67C (XAUTODAT2) + + // source + AUTOPTRH1 = MSB( &WaveData ); + AUTOPTRL1 = LSB( &WaveData ); + + // destination + AUTOPTRH2 = 0xE4; + AUTOPTRL2 = 0x00; + + // transfer + for ( i = 0x00; i < 128; i++ ) + { + EXTAUTODAT2 = EXTAUTODAT1; + } + +// Configure GPIF Address pins, output initial value, + PORTCCFG = 0xFF; // [7:0] as alt. func. GPIFADR[7:0] + OEC = 0xFF; // and as outputs + PORTECFG |= 0x80; // [8] as alt. func. GPIFADR[8] + OEE |= 0x80; // and as output + +// ...OR... tri-state GPIFADR[8:0] pins +// PORTCCFG = 0x00; // [7:0] as port I/O +// OEC = 0x00; // and as inputs +// PORTECFG &= 0x7F; // [8] as port I/O +// OEE &= 0x7F; // and as input + +// GPIF address pins update when GPIFADRH/L written + SYNCDELAY; // + GPIFADRH = 0x00; // bits[7:1] always 0 + SYNCDELAY; // + GPIFADRL = 0x00; // point to PERIPHERAL address 0x0000 + +// Configure GPIF FlowStates registers for Wave 0 of WaveData + FLOWSTATE = FlowStates[ 0 ]; + FLOWLOGIC = FlowStates[ 1 ]; + FLOWEQ0CTL = FlowStates[ 2 ]; + FLOWEQ1CTL = FlowStates[ 3 ]; + FLOWHOLDOFF = FlowStates[ 4 ]; + FLOWSTB = FlowStates[ 5 ]; + FLOWSTBEDGE = FlowStates[ 6 ]; + FLOWSTBHPERIOD = FlowStates[ 7 ]; +} + diff --git a/firmware/fx2/src/usrp1/gpif.gpf b/firmware/fx2/src/usrp1/gpif.gpf new file mode 100755 index 000000000..854e25399 Binary files /dev/null and b/firmware/fx2/src/usrp1/gpif.gpf differ diff --git a/firmware/fx2/src/usrp1/init_gpif.c b/firmware/fx2/src/usrp1/init_gpif.c new file mode 100644 index 000000000..0f5944b3b --- /dev/null +++ b/firmware/fx2/src/usrp1/init_gpif.c @@ -0,0 +1 @@ +#include "../common/init_gpif.c" diff --git a/firmware/fx2/src/usrp1/spi.c b/firmware/fx2/src/usrp1/spi.c new file mode 100644 index 000000000..f5803c55b --- /dev/null +++ b/firmware/fx2/src/usrp1/spi.c @@ -0,0 +1,381 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "spi.h" +#include "usrp_rev2_regs.h" + +static void +setup_enables (unsigned char enables) +{ + // Software eanbles are active high. + // Hardware enables are active low. + + // Uhh, the CODECs are active low, but the FPGA is active high... + enables ^= SPI_ENABLE_FPGA; + + // KLUDGE: This code is fragile, but reasonably fast... + // low three bits of enables go into port A + USRP_PA = USRP_PA | (0x7 << 3); // disable FPGA, CODEC_A, CODEC_B + USRP_PA ^= (enables & 0x7) << 3; // enable specified devs + + // high four bits of enables go into port E + USRP_PE = USRP_PE | (0xf << 4); // disable TX_A, RX_A, TX_B, RX_B + USRP_PE ^= (enables & 0xf0); // enable specified devs +} + +#define disable_all() setup_enables (0) + +void +init_spi (void) +{ + disable_all (); /* disable all devs */ + bitS_OUT = 0; /* idle state has CLK = 0 */ +} + +#if 0 +static unsigned char +count_bits8 (unsigned char v) +{ + static unsigned char count4[16] = { + 0, // 0 + 1, // 1 + 1, // 2 + 2, // 3 + 1, // 4 + 2, // 5 + 2, // 6 + 3, // 7 + 1, // 8 + 2, // 9 + 2, // a + 3, // b + 2, // c + 3, // d + 3, // e + 4 // f + }; + return count4[v & 0xf] + count4[(v >> 4) & 0xf]; +} + +#else + +static unsigned char +count_bits8 (unsigned char v) +{ + unsigned char count = 0; + if (v & (1 << 0)) count++; + if (v & (1 << 1)) count++; + if (v & (1 << 2)) count++; + if (v & (1 << 3)) count++; + if (v & (1 << 4)) count++; + if (v & (1 << 5)) count++; + if (v & (1 << 6)) count++; + if (v & (1 << 7)) count++; + return count; +} +#endif + +static void +write_byte_msb (unsigned char v); + +static void +write_bytes_msb (const xdata unsigned char *buf, unsigned char len); + +static void +read_bytes_msb (xdata unsigned char *buf, unsigned char len); + + +// returns non-zero if successful, else 0 +unsigned char +spi_read (unsigned char header_hi, unsigned char header_lo, + unsigned char enables, unsigned char format, + xdata unsigned char *buf, unsigned char len) +{ + if (count_bits8 (enables) > 1) + return 0; // error, too many enables set + + setup_enables (enables); + + if (format & SPI_FMT_LSB){ // order: LSB +#if 1 + return 0; // error, not implemented +#else + switch (format & SPI_FMR_HDR_MASK){ + case SPI_FMT_HDR_0: + break; + case SPI_FMT_HDR_1: + write_byte_lsb (header_lo); + break; + case SPI_FMT_HDR_2: + write_byte_lsb (header_lo); + write_byte_lsb (header_hi); + break; + default: + return 0; // error + } + if (len != 0) + read_bytes_lsb (buf, len); +#endif + } + + else { // order: MSB + + switch (format & SPI_FMT_HDR_MASK){ + case SPI_FMT_HDR_0: + break; + case SPI_FMT_HDR_1: + write_byte_msb (header_lo); + break; + case SPI_FMT_HDR_2: + write_byte_msb (header_hi); + write_byte_msb (header_lo); + break; + default: + return 0; // error + } + if (len != 0) + read_bytes_msb (buf, len); + } + + disable_all (); + return 1; // success +} + + +// returns non-zero if successful, else 0 +unsigned char +spi_write (unsigned char header_hi, unsigned char header_lo, + unsigned char enables, unsigned char format, + const xdata unsigned char *buf, unsigned char len) +{ + setup_enables (enables); + + if (format & SPI_FMT_LSB){ // order: LSB +#if 1 + return 0; // error, not implemented +#else + switch (format & SPI_FMR_HDR_MASK){ + case SPI_FMT_HDR_0: + break; + case SPI_FMT_HDR_1: + write_byte_lsb (header_lo); + break; + case SPI_FMT_HDR_2: + write_byte_lsb (header_lo); + write_byte_lsb (header_hi); + break; + default: + return 0; // error + } + if (len != 0) + write_bytes_lsb (buf, len); +#endif + } + + else { // order: MSB + + switch (format & SPI_FMT_HDR_MASK){ + case SPI_FMT_HDR_0: + break; + case SPI_FMT_HDR_1: + write_byte_msb (header_lo); + break; + case SPI_FMT_HDR_2: + write_byte_msb (header_hi); + write_byte_msb (header_lo); + break; + default: + return 0; // error + } + if (len != 0) + write_bytes_msb (buf, len); + } + + disable_all (); + return 1; // success +} + +// ---------------------------------------------------------------- + +static void +write_byte_msb (unsigned char v) +{ + v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit) + bitS_OUT = v & 0x1; + bitS_CLK = 1; + bitS_CLK = 0; + + v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit) + bitS_OUT = v & 0x1; + bitS_CLK = 1; + bitS_CLK = 0; + + v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit) + bitS_OUT = v & 0x1; + bitS_CLK = 1; + bitS_CLK = 0; + + v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit) + bitS_OUT = v & 0x1; + bitS_CLK = 1; + bitS_CLK = 0; + + v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit) + bitS_OUT = v & 0x1; + bitS_CLK = 1; + bitS_CLK = 0; + + v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit) + bitS_OUT = v & 0x1; + bitS_CLK = 1; + bitS_CLK = 0; + + v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit) + bitS_OUT = v & 0x1; + bitS_CLK = 1; + bitS_CLK = 0; + + v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit) + bitS_OUT = v & 0x1; + bitS_CLK = 1; + bitS_CLK = 0; +} + +static void +write_bytes_msb (const xdata unsigned char *buf, unsigned char len) +{ + while (len-- != 0){ + write_byte_msb (*buf++); + } +} + +#if 0 +/* + * This is incorrectly compiled by SDCC 2.4.0 + */ +static unsigned char +read_byte_msb (void) +{ + unsigned char v = 0; + + bitS_CLK = 1; + v |= bitS_IN; + bitS_CLK = 0; + + v = v << 1; + bitS_CLK = 1; + v |= bitS_IN; + bitS_CLK = 0; + + v = v << 1; + bitS_CLK = 1; + v |= bitS_IN; + bitS_CLK = 0; + + v = v << 1; + bitS_CLK = 1; + v |= bitS_IN; + bitS_CLK = 0; + + v = v << 1; + bitS_CLK = 1; + v |= bitS_IN; + bitS_CLK = 0; + + v = v << 1; + bitS_CLK = 1; + v |= bitS_IN; + bitS_CLK = 0; + + v = v << 1; + bitS_CLK = 1; + v |= bitS_IN; + bitS_CLK = 0; + + v = v << 1; + bitS_CLK = 1; + v |= bitS_IN; + bitS_CLK = 0; + + return v; +} +#else +static unsigned char +read_byte_msb (void) _naked +{ + _asm + clr a + + setb _bitS_CLK + mov c, _bitS_IN + rlc a + clr _bitS_CLK + + setb _bitS_CLK + mov c, _bitS_IN + rlc a + clr _bitS_CLK + + setb _bitS_CLK + mov c, _bitS_IN + rlc a + clr _bitS_CLK + + setb _bitS_CLK + mov c, _bitS_IN + rlc a + clr _bitS_CLK + + setb _bitS_CLK + mov c, _bitS_IN + rlc a + clr _bitS_CLK + + setb _bitS_CLK + mov c, _bitS_IN + rlc a + clr _bitS_CLK + + setb _bitS_CLK + mov c, _bitS_IN + rlc a + clr _bitS_CLK + + setb _bitS_CLK + mov c, _bitS_IN + rlc a + clr _bitS_CLK + + mov dpl,a + ret + _endasm; +} +#endif + +static void +read_bytes_msb (xdata unsigned char *buf, unsigned char len) +{ + while (len-- != 0){ + *buf++ = read_byte_msb (); + } +} + diff --git a/firmware/fx2/src/usrp1/spi.h b/firmware/fx2/src/usrp1/spi.h new file mode 100644 index 000000000..12bc5e544 --- /dev/null +++ b/firmware/fx2/src/usrp1/spi.h @@ -0,0 +1,43 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_SPI_H +#define INCLUDED_SPI_H + +#include "usrp_spi_defs.h" + +void init_spi (void); // one time call to init + +// returns non-zero if successful, else 0 +unsigned char +spi_read (unsigned char header_hi, unsigned char header_lo, + unsigned char enables, unsigned char format, + xdata unsigned char *buf, unsigned char len); + +// returns non-zero if successful, else 0 +unsigned char +spi_write (unsigned char header_hi, unsigned char header_lo, + unsigned char enables, unsigned char format, + const xdata unsigned char *buf, unsigned char len); + + +#endif /* INCLUDED_SPI_H */ diff --git a/firmware/fx2/src/usrp1/usb_descriptors.a51 b/firmware/fx2/src/usrp1/usb_descriptors.a51 new file mode 100644 index 000000000..a60adbef8 --- /dev/null +++ b/firmware/fx2/src/usrp1/usb_descriptors.a51 @@ -0,0 +1,404 @@ +;;; -*- asm -*- +;;; +;;; Copyright 2003 Free Software Foundation, Inc. +;;; +;;; This file is part of GNU Radio +;;; +;;; GNU Radio is free software; you can redistribute it and/or modify +;;; it under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3, or (at your option) +;;; any later version. +;;; +;;; GNU Radio is distributed in the hope that it will be useful, +;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Radio; see the file COPYING. If not, write to +;;; the Free Software Foundation, Inc., 51 Franklin Street, +;;; Boston, MA 02110-1301, USA. +;;; + +;;; USB Descriptor table for the USRP +;;; +;;; We're a high-speed only device (480 Mb/sec) with 1 configuration +;;; and 3 interfaces. +;;; +;;; interface 0: command and status (ep0 COMMAND) +;;; interface 1: Transmit path (ep2 OUT BULK) +;;; interface 2: Receive path (ep6 IN BULK) + + .module usb_descriptors + + VID_FREE = 0xfffe ; Free Software Folks + PID_USRP = 0x0002 ; USRP + + ;; We distinguish configured from unconfigured USRPs using the Device ID. + ;; If the MSB of the DID is 0, the device is unconfigured. + ;; The LSB of the DID is reserved for hardware revs. + + DID_USRP = 0x0100 ; Device ID (bcd) + + + DSCR_DEVICE = 1 ; Descriptor type: Device + DSCR_CONFIG = 2 ; Descriptor type: Configuration + DSCR_STRING = 3 ; Descriptor type: String + DSCR_INTRFC = 4 ; Descriptor type: Interface + DSCR_ENDPNT = 5 ; Descriptor type: Endpoint + DSCR_DEVQUAL = 6 ; Descriptor type: Device Qualifier + + DSCR_DEVICE_LEN = 18 + DSCR_CONFIG_LEN = 9 + DSCR_INTRFC_LEN = 9 + DSCR_ENDPNT_LEN = 7 + DSCR_DEVQUAL_LEN = 10 + + ET_CONTROL = 0 ; Endpoint type: Control + ET_ISO = 1 ; Endpoint type: Isochronous + ET_BULK = 2 ; Endpoint type: Bulk + ET_INT = 3 ; Endpoint type: Interrupt + + + ;; configuration attributes + bmSELF_POWERED = 1 << 6 + +;;; -------------------------------------------------------- +;;; external ram data +;;;-------------------------------------------------------- + + .area USBDESCSEG (XDATA) + +;;; ---------------------------------------------------------------- +;;; descriptors used when operating at high speed (480Mb/sec) +;;; ---------------------------------------------------------------- + + .even ; descriptors must be 2-byte aligned for SUDPTR{H,L} to work + + ;; The .even directive isn't really honored by the linker. Bummer! + ;; (There's no way to specify an alignment requirement for a given area, + ;; hence when they're concatenated together, even doesn't work.) + ;; + ;; We work around this by telling the linker to put USBDESCSEG + ;; at 0xE000 absolute. This means that the maximimum length of this + ;; segment is 480 bytes, leaving room for the two hash slots + ;; at 0xE1EO to 0xE1FF. + ;; + ;; As of July 7, 2004, this segment is 326 bytes long + +_high_speed_device_descr:: + .db DSCR_DEVICE_LEN + .db DSCR_DEVICE + .db <0x0200 ; Specification version (LSB) + .db >0x0200 ; Specification version (MSB) + .db 0xff ; device class (vendor specific) + .db 0xff ; device subclass (vendor specific) + .db 0xff ; device protocol (vendor specific) + .db 64 ; bMaxPacketSize0 for endpoint 0 + .db VID_FREE ; idVendor + .db PID_USRP ; idProduct +_usb_desc_hw_rev_binary_patch_location_0:: + .db DID_USRP ; bcdDevice + .db SI_VENDOR ; iManufacturer (string index) + .db SI_PRODUCT ; iProduct (string index) + .db SI_SERIAL ; iSerial number (string index) + .db 1 ; bNumConfigurations + +;;; describes the other speed (12Mb/sec) + .even +_high_speed_devqual_descr:: + .db DSCR_DEVQUAL_LEN + .db DSCR_DEVQUAL + .db <0x0200 ; bcdUSB (LSB) + .db >0x0200 ; bcdUSB (MSB) + .db 0xff ; bDeviceClass + .db 0xff ; bDeviceSubClass + .db 0xff ; bDeviceProtocol + .db 64 ; bMaxPacketSize0 + .db 1 ; bNumConfigurations (one config at 12Mb/sec) + .db 0 ; bReserved + + .even +_high_speed_config_descr:: + .db DSCR_CONFIG_LEN + .db DSCR_CONFIG + .db <(_high_speed_config_descr_end - _high_speed_config_descr) ; LSB + .db >(_high_speed_config_descr_end - _high_speed_config_descr) ; MSB + .db 3 ; bNumInterfaces + .db 1 ; bConfigurationValue + .db 0 ; iConfiguration + .db 0x80 | bmSELF_POWERED ; bmAttributes + .db 0 ; bMaxPower + + ;; interface descriptor 0 (command & status, ep0 COMMAND) + + .db DSCR_INTRFC_LEN + .db DSCR_INTRFC + .db 0 ; bInterfaceNumber (zero based) + .db 0 ; bAlternateSetting + .db 0 ; bNumEndpoints + .db 0xff ; bInterfaceClass (vendor specific) + .db 0xff ; bInterfaceSubClass (vendor specific) + .db 0xff ; bInterfaceProtocol (vendor specific) + .db SI_COMMAND_AND_STATUS ; iInterface (description) + + ;; interface descriptor 1 (transmit path, ep2 OUT BULK) + + .db DSCR_INTRFC_LEN + .db DSCR_INTRFC + .db 1 ; bInterfaceNumber (zero based) + .db 0 ; bAlternateSetting + .db 1 ; bNumEndpoints + .db 0xff ; bInterfaceClass (vendor specific) + .db 0xff ; bInterfaceSubClass (vendor specific) + .db 0xff ; bInterfaceProtocol (vendor specific) + .db SI_TX_PATH ; iInterface (description) + + ;; interface 1's end point + + .db DSCR_ENDPNT_LEN + .db DSCR_ENDPNT + .db 0x02 ; bEndpointAddress (ep 2 OUT) + .db ET_BULK ; bmAttributes + .db <512 ; wMaxPacketSize (LSB) + .db >512 ; wMaxPacketSize (MSB) + .db 0 ; bInterval (iso only) + + ;; interface descriptor 2 (receive path, ep6 IN BULK) + + .db DSCR_INTRFC_LEN + .db DSCR_INTRFC + .db 2 ; bInterfaceNumber (zero based) + .db 0 ; bAlternateSetting + .db 1 ; bNumEndpoints + .db 0xff ; bInterfaceClass (vendor specific) + .db 0xff ; bInterfaceSubClass (vendor specific) + .db 0xff ; bInterfaceProtocol (vendor specific) + .db SI_RX_PATH ; iInterface (description) + + ;; interface 2's end point + + .db DSCR_ENDPNT_LEN + .db DSCR_ENDPNT + .db 0x86 ; bEndpointAddress (ep 6 IN) + .db ET_BULK ; bmAttributes + .db <512 ; wMaxPacketSize (LSB) + .db >512 ; wMaxPacketSize (MSB) + .db 0 ; bInterval (iso only) + +_high_speed_config_descr_end: + +;;; ---------------------------------------------------------------- +;;; descriptors used when operating at full speed (12Mb/sec) +;;; ---------------------------------------------------------------- + + .even +_full_speed_device_descr:: + .db DSCR_DEVICE_LEN + .db DSCR_DEVICE + .db <0x0200 ; Specification version (LSB) + .db >0x0200 ; Specification version (MSB) + .db 0xff ; device class (vendor specific) + .db 0xff ; device subclass (vendor specific) + .db 0xff ; device protocol (vendor specific) + .db 64 ; bMaxPacketSize0 for endpoint 0 + .db VID_FREE ; idVendor + .db PID_USRP ; idProduct +_usb_desc_hw_rev_binary_patch_location_1:: + .db DID_USRP ; bcdDevice + .db SI_VENDOR ; iManufacturer (string index) + .db SI_PRODUCT ; iProduct (string index) + .db SI_NONE ; iSerial number (None) + .db 1 ; bNumConfigurations + + +;;; describes the other speed (480Mb/sec) + .even +_full_speed_devqual_descr:: + .db DSCR_DEVQUAL_LEN + .db DSCR_DEVQUAL + .db <0x0200 ; bcdUSB + .db >0x0200 ; bcdUSB + .db 0xff ; bDeviceClass + .db 0xff ; bDeviceSubClass + .db 0xff ; bDeviceProtocol + .db 64 ; bMaxPacketSize0 + .db 1 ; bNumConfigurations (one config at 480Mb/sec) + .db 0 ; bReserved + + .even +_full_speed_config_descr:: + .db DSCR_CONFIG_LEN + .db DSCR_CONFIG + .db <(_full_speed_config_descr_end - _full_speed_config_descr) ; LSB + .db >(_full_speed_config_descr_end - _full_speed_config_descr) ; MSB + .db 1 ; bNumInterfaces + .db 1 ; bConfigurationValue + .db 0 ; iConfiguration + .db 0x80 | bmSELF_POWERED ; bmAttributes + .db 0 ; bMaxPower + + ;; interface descriptor 0 (command & status, ep0 COMMAND) + + .db DSCR_INTRFC_LEN + .db DSCR_INTRFC + .db 0 ; bInterfaceNumber (zero based) + .db 0 ; bAlternateSetting + .db 0 ; bNumEndpoints + .db 0xff ; bInterfaceClass (vendor specific) + .db 0xff ; bInterfaceSubClass (vendor specific) + .db 0xff ; bInterfaceProtocol (vendor specific) + .db SI_COMMAND_AND_STATUS ; iInterface (description) + +_full_speed_config_descr_end: + +;;; ---------------------------------------------------------------- +;;; string descriptors +;;; ---------------------------------------------------------------- + +_nstring_descriptors:: + .db (_string_descriptors_end - _string_descriptors) / 2 + +_string_descriptors:: + .db str0 + .db str1 + .db str2 + .db str3 + .db str4 + .db str5 + .db str6 +_string_descriptors_end: + + SI_NONE = 0 + ;; str0 contains the language ID's. + .even +str0: .db str0_end - str0 + .db DSCR_STRING + .db 0 + .db 0 + .db <0x0409 ; magic code for US English (LSB) + .db >0x0409 ; magic code for US English (MSB) +str0_end: + + SI_VENDOR = 1 + .even +str1: .db str1_end - str1 + .db DSCR_STRING + .db 'F, 0 ; 16-bit unicode + .db 'r, 0 + .db 'e, 0 + .db 'e, 0 + .db ' , 0 + .db 'S, 0 + .db 'o, 0 + .db 'f, 0 + .db 't, 0 + .db 'w, 0 + .db 'a, 0 + .db 'r, 0 + .db 'e, 0 + .db ' , 0 + .db 'F, 0 + .db 'o, 0 + .db 'l, 0 + .db 'k, 0 + .db 's, 0 +str1_end: + + SI_PRODUCT = 2 + .even +str2: .db str2_end - str2 + .db DSCR_STRING + .db 'U, 0 + .db 'S, 0 + .db 'R, 0 + .db 'P, 0 + .db ' , 0 + .db 'R, 0 + .db 'e, 0 + .db 'v, 0 + .db ' , 0 +_usb_desc_hw_rev_ascii_patch_location_0:: + .db '?, 0 +str2_end: + + SI_COMMAND_AND_STATUS = 3 + .even +str3: .db str3_end - str3 + .db DSCR_STRING + .db 'C, 0 + .db 'o, 0 + .db 'm, 0 + .db 'm, 0 + .db 'a, 0 + .db 'n, 0 + .db 'd, 0 + .db ' , 0 + .db '&, 0 + .db ' , 0 + .db 'S, 0 + .db 't, 0 + .db 'a, 0 + .db 't, 0 + .db 'u, 0 + .db 's, 0 +str3_end: + + SI_TX_PATH = 4 + .even +str4: .db str4_end - str4 + .db DSCR_STRING + .db 'T, 0 + .db 'r, 0 + .db 'a, 0 + .db 'n, 0 + .db 's, 0 + .db 'm, 0 + .db 'i, 0 + .db 't, 0 + .db ' , 0 + .db 'P, 0 + .db 'a, 0 + .db 't, 0 + .db 'h, 0 +str4_end: + + SI_RX_PATH = 5 + .even +str5: .db str5_end - str5 + .db DSCR_STRING + .db 'R, 0 + .db 'e, 0 + .db 'c, 0 + .db 'e, 0 + .db 'i, 0 + .db 'v, 0 + .db 'e, 0 + .db ' , 0 + .db 'P, 0 + .db 'a, 0 + .db 't, 0 + .db 'h, 0 +str5_end: + + SI_SERIAL = 6 + .even +str6: .db str6_end - str6 + .db DSCR_STRING +_usb_desc_serial_number_ascii:: + .db '3, 0 + .db '., 0 + .db '1, 0 + .db '4, 0 + .db '1, 0 + .db '5, 0 + .db '9, 0 + .db '3, 0 +str6_end: + diff --git a/firmware/fx2/src/usrp1/usrp_common.c b/firmware/fx2/src/usrp1/usrp_common.c new file mode 100644 index 000000000..f389d9253 --- /dev/null +++ b/firmware/fx2/src/usrp1/usrp_common.c @@ -0,0 +1 @@ +#include "../common/usrp_common.c" diff --git a/firmware/fx2/src/usrp1/usrp_common.h b/firmware/fx2/src/usrp1/usrp_common.h new file mode 100644 index 000000000..738ba6b37 --- /dev/null +++ b/firmware/fx2/src/usrp1/usrp_common.h @@ -0,0 +1,77 @@ +/* + * USRP - Universal Software Radio Peripheral + * + * Copyright (C) 2003,2006 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 3 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 + */ + +/* + * common defines and prototypes for USRP + * + * In comments below "TRM" refers to the EZ-USB FX2 Technical Reference Manual + */ + +#ifndef _USRPCOMMON_H_ +#define _USRPCOMMON_H_ + +#include +#include +#include + +/* + * From TRM page 15-105: + * + * Under certain conditions, some read and write access to the FX2 + * registers must be separated by a "synchronization delay". The + * delay is necessary only under the following conditions: + * + * - between a write to any register in the 0xE600 - 0xE6FF range + * and a write to one of the registers listed below. + * + * - between a write to one of the registers listed below and a read + * from any register in the 0xE600 - 0xE6FF range. + * + * Registers which require a synchronization delay: + * + * FIFORESET FIFOPINPOLAR + * INPKTEND EPxBCH:L + * EPxFIFOPFH:L EPxAUTOINLENH:L + * EPxFIFOCFG EPxGPIFFLGSEL + * PINFLAGSAB PINFLAGSCD + * EPxFIFOIE EPxFIFOIRQ + * GPIFIE GPIFIRQ + * UDMACRCH:L GPIFADRH:L + * GPIFTRIG EPxGPIFTRIG + * OUTPKTEND REVCTL + * GPIFTCB3 GPIFTCB2 + * GPIFTCB1 GPIFTCB0 + */ + +#define TRUE 1 +#define FALSE 0 + + +void init_usrp (void); +void init_gpif (void); + +void set_led_0 (unsigned char on); +void set_led_1 (unsigned char on); +void toggle_led_0 (void); +void toggle_led_1 (void); + +#define la_trace(v) + +#endif /* _USRPCOMMON_H_ */ diff --git a/firmware/fx2/src/usrp1/usrp_main.c b/firmware/fx2/src/usrp1/usrp_main.c new file mode 100644 index 000000000..c7c09f8c5 --- /dev/null +++ b/firmware/fx2/src/usrp1/usrp_main.c @@ -0,0 +1,380 @@ +/* + * USRP - Universal Software Radio Peripheral + * + * Copyright (C) 2003,2004 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 3 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 "usrp_common.h" +#include "usrp_commands.h" +#include "fpga.h" +#include "usrp_gpif_inline.h" +#include "timer.h" +#include "i2c.h" +#include "isr.h" +#include "usb_common.h" +#include "fx2utils.h" +#include "usrp_globals.h" +#include "usrp_i2c_addr.h" +#include +#include "spi.h" +#include "eeprom_io.h" +#include "usb_descriptors.h" + +/* + * offsets into boot eeprom for configuration values + */ +#define HW_REV_OFFSET 5 +#define SERIAL_NO_OFFSET 248 +#define SERIAL_NO_LEN 8 + + +#define bRequestType SETUPDAT[0] +#define bRequest SETUPDAT[1] +#define wValueL SETUPDAT[2] +#define wValueH SETUPDAT[3] +#define wIndexL SETUPDAT[4] +#define wIndexH SETUPDAT[5] +#define wLengthL SETUPDAT[6] +#define wLengthH SETUPDAT[7] + + +unsigned char g_tx_enable = 0; +unsigned char g_rx_enable = 0; +unsigned char g_rx_overrun = 0; +unsigned char g_tx_underrun = 0; + +/* + * the host side fpga loader code pushes an MD5 hash of the bitstream + * into hash1. + */ +#define USRP_HASH_SIZE 16 +xdata at USRP_HASH_SLOT_1_ADDR unsigned char hash1[USRP_HASH_SIZE]; + +static void +get_ep0_data (void) +{ + EP0BCL = 0; // arm EP0 for OUT xfer. This sets the busy bit + + while (EP0CS & bmEPBUSY) // wait for busy to clear + ; +} + +/* + * Handle our "Vendor Extension" commands on endpoint 0. + * If we handle this one, return non-zero. + */ +unsigned char +app_vendor_cmd (void) +{ + if (bRequestType == VRT_VENDOR_IN){ + + ///////////////////////////////// + // handle the IN requests + ///////////////////////////////// + + switch (bRequest){ + + case VRQ_GET_STATUS: + switch (wIndexL){ + + case GS_TX_UNDERRUN: + EP0BUF[0] = g_tx_underrun; + g_tx_underrun = 0; + EP0BCH = 0; + EP0BCL = 1; + break; + + case GS_RX_OVERRUN: + EP0BUF[0] = g_rx_overrun; + g_rx_overrun = 0; + EP0BCH = 0; + EP0BCL = 1; + break; + + default: + return 0; + } + break; + + case VRQ_I2C_READ: + if (!i2c_read (wValueL, EP0BUF, wLengthL)) + return 0; + + EP0BCH = 0; + EP0BCL = wLengthL; + break; + + case VRQ_SPI_READ: + if (!spi_read (wValueH, wValueL, wIndexH, wIndexL, EP0BUF, wLengthL)) + return 0; + + EP0BCH = 0; + EP0BCL = wLengthL; + break; + + default: + return 0; + } + } + + else if (bRequestType == VRT_VENDOR_OUT){ + + ///////////////////////////////// + // handle the OUT requests + ///////////////////////////////// + + switch (bRequest){ + + case VRQ_SET_LED: + switch (wIndexL){ + case 0: + set_led_0 (wValueL); + break; + + case 1: + set_led_1 (wValueL); + break; + + default: + return 0; + } + break; + + case VRQ_FPGA_LOAD: + switch (wIndexL){ // sub-command + case FL_BEGIN: + return fpga_load_begin (); + + case FL_XFER: + get_ep0_data (); + return fpga_load_xfer (EP0BUF, EP0BCL); + + case FL_END: + return fpga_load_end (); + + default: + return 0; + } + break; + + + case VRQ_FPGA_SET_RESET: + fpga_set_reset (wValueL); + break; + + case VRQ_FPGA_SET_TX_ENABLE: + fpga_set_tx_enable (wValueL); + break; + + case VRQ_FPGA_SET_RX_ENABLE: + fpga_set_rx_enable (wValueL); + break; + + case VRQ_FPGA_SET_TX_RESET: + fpga_set_tx_reset (wValueL); + break; + + case VRQ_FPGA_SET_RX_RESET: + fpga_set_rx_reset (wValueL); + break; + + case VRQ_I2C_WRITE: + get_ep0_data (); + if (!i2c_write (wValueL, EP0BUF, EP0BCL)) + return 0; + break; + + case VRQ_SPI_WRITE: + get_ep0_data (); + if (!spi_write (wValueH, wValueL, wIndexH, wIndexL, EP0BUF, EP0BCL)) + return 0; + break; + + default: + return 0; + } + + } + else + return 0; // invalid bRequestType + + return 1; +} + + + +static void +main_loop (void) +{ + setup_flowstate_common (); + + while (1){ + + if (usb_setup_packet_avail ()) + usb_handle_setup_packet (); + + + if (GPIFTRIG & bmGPIF_IDLE){ + + // OK, GPIF is idle. Let's try to give it some work. + + // First check for underruns and overruns + + if (UC_BOARD_HAS_FPGA && (USRP_PA & (bmPA_TX_UNDERRUN | bmPA_RX_OVERRUN))){ + + // record the under/over run + if (USRP_PA & bmPA_TX_UNDERRUN) + g_tx_underrun = 1; + + if (USRP_PA & bmPA_RX_OVERRUN) + g_rx_overrun = 1; + + // tell the FPGA to clear the flags + fpga_clear_flags (); + } + + // Next see if there are any "OUT" packets waiting for our attention, + // and if so, if there's room in the FPGA's FIFO for them. + + if (g_tx_enable && !(EP24FIFOFLGS & 0x02)){ // USB end point fifo is not empty... + + if (fpga_has_room_for_packet ()){ // ... and FPGA has room for packet + + GPIFTCB1 = 0x01; SYNCDELAY; + GPIFTCB0 = 0x00; SYNCDELAY; + + setup_flowstate_write (); + + SYNCDELAY; + GPIFTRIG = bmGPIF_EP2_START | bmGPIF_WRITE; // start the xfer + SYNCDELAY; + + while (!(GPIFTRIG & bmGPIF_IDLE)){ + // wait for the transaction to complete + } + } + } + + // See if there are any requests for "IN" packets, and if so + // whether the FPGA's got any packets for us. + + if (g_rx_enable && !(EP6CS & bmEPFULL)){ // USB end point fifo is not full... + + if (fpga_has_packet_avail ()){ // ... and FPGA has packet available + + GPIFTCB1 = 0x01; SYNCDELAY; + GPIFTCB0 = 0x00; SYNCDELAY; + + setup_flowstate_read (); + + SYNCDELAY; + GPIFTRIG = bmGPIF_EP6_START | bmGPIF_READ; // start the xfer + SYNCDELAY; + + while (!(GPIFTRIG & bmGPIF_IDLE)){ + // wait for the transaction to complete + } + + SYNCDELAY; + INPKTEND = 6; // tell USB we filled buffer (6 is our endpoint num) + } + } + } + } +} + + +/* + * called at 100 Hz from timer2 interrupt + * + * Toggle led 0 + */ +void +isr_tick (void) interrupt +{ + static unsigned char count = 1; + + if (--count == 0){ + count = 50; + USRP_LED_REG ^= bmLED0; + } + + clear_timer_irq (); +} + +/* + * Read h/w rev code and serial number out of boot eeprom and + * patch the usb descriptors with the values. + */ +void +patch_usb_descriptors(void) +{ + static xdata unsigned char hw_rev; + static xdata unsigned char serial_no[8]; + unsigned char i; + + eeprom_read(I2C_ADDR_BOOT, HW_REV_OFFSET, &hw_rev, 1); // LSB of device id + usb_desc_hw_rev_binary_patch_location_0[0] = hw_rev; + usb_desc_hw_rev_binary_patch_location_1[0] = hw_rev; + usb_desc_hw_rev_ascii_patch_location_0[0] = hw_rev + '0'; // FIXME if we get > 9 + + eeprom_read(I2C_ADDR_BOOT, SERIAL_NO_OFFSET, serial_no, SERIAL_NO_LEN); + + for (i = 0; i < SERIAL_NO_LEN; i++){ + unsigned char ch = serial_no[i]; + if (ch == 0xff) // make unprogrammed EEPROM default to '0' + ch = '0'; + usb_desc_serial_number_ascii[i << 1] = ch; + } +} + +void +main (void) +{ +#if 0 + g_rx_enable = 0; // FIXME (work around initialization bug) + g_tx_enable = 0; + g_rx_overrun = 0; + g_tx_underrun = 0; +#endif + + memset (hash1, 0, USRP_HASH_SIZE); // zero fpga bitstream hash. This forces reload + + init_usrp (); + init_gpif (); + + // if (UC_START_WITH_GSTATE_OUTPUT_ENABLED) + IFCONFIG |= bmGSTATE; // no conflict, start with it on + + set_led_0 (0); + set_led_1 (0); + + EA = 0; // disable all interrupts + + patch_usb_descriptors(); + + setup_autovectors (); + usb_install_handlers (); + hook_timer_tick ((unsigned short) isr_tick); + + EIEX4 = 1; // disable INT4 FIXME + EA = 1; // global interrupt enable + + fx2_renumerate (); // simulates disconnect / reconnect + + main_loop (); +} diff --git a/firmware/fx2/src/usrp1/usrp_rev2_regs.h b/firmware/fx2/src/usrp1/usrp_rev2_regs.h new file mode 100644 index 000000000..a4f1d9896 --- /dev/null +++ b/firmware/fx2/src/usrp1/usrp_rev2_regs.h @@ -0,0 +1,163 @@ +/* + * USRP - Universal Software Radio Peripheral + * + * Copyright (C) 2003 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 3 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 + */ + +/* + * These are the register definitions for the Rev 1 USRP prototype + * The Rev 1 is the version with the AD9862's and daughterboards + */ + +#ifndef _USRP_REV1_REGS_H_ +#define _USRP_REV1_REGS_H_ + +#include "fx2regs.h" + +/* + * Port A (bit addressable): + */ + +#define USRP_PA IOA // Port A +#define USRP_PA_OE OEA // Port A direction register + +#define bmPA_S_CLK bmBIT0 // SPI serial clock +#define bmPA_S_DATA_TO_PERIPH bmBIT1 // SPI SDI (peripheral rel name) +#define bmPA_S_DATA_FROM_PERIPH bmBIT2 // SPI SDO (peripheral rel name) +#define bmPA_SEN_FPGA bmBIT3 // serial enable for FPGA (active low) +#define bmPA_SEN_CODEC_A bmBIT4 // serial enable AD9862 A (active low) +#define bmPA_SEN_CODEC_B bmBIT5 // serial enable AD9862 B (active low) +//#define bmPA_FX2_2 bmBIT6 // misc pin to FPGA (overflow) +//#define bmPA_FX2_3 bmBIT7 // misc pin to FPGA (underflow) +#define bmPA_RX_OVERRUN bmBIT6 // misc pin to FPGA (overflow) +#define bmPA_TX_UNDERRUN bmBIT7 // misc pin to FPGA (underflow) + + +sbit at 0x80+0 bitS_CLK; // 0x80 is the bit address of PORT A +sbit at 0x80+1 bitS_OUT; // out from FX2 point of view +sbit at 0x80+2 bitS_IN; // in from FX2 point of view + + +/* all outputs except S_DATA_FROM_PERIPH, FX2_2, FX2_3 */ + +#define bmPORT_A_OUTPUTS (bmPA_S_CLK \ + | bmPA_S_DATA_TO_PERIPH \ + | bmPA_SEN_FPGA \ + | bmPA_SEN_CODEC_A \ + | bmPA_SEN_CODEC_B \ + ) + +#define bmPORT_A_INITIAL (bmPA_SEN_FPGA | bmPA_SEN_CODEC_A | bmPA_SEN_CODEC_B) + + +/* Port B: GPIF FD[7:0] */ + +/* + * Port C (bit addressable): + * 5:1 FPGA configuration + */ + +#define USRP_PC IOC // Port C +#define USRP_PC_OE OEC // Port C direction register + +#define USRP_ALTERA_CONFIG USRP_PC + +#define bmPC_nRESET bmBIT0 // reset line to codecs (active low) +#define bmALTERA_DATA0 bmBIT1 +#define bmALTERA_NCONFIG bmBIT2 +#define bmALTERA_DCLK bmBIT3 +#define bmALTERA_CONF_DONE bmBIT4 +#define bmALTERA_NSTATUS bmBIT5 +#define bmPC_LED0 bmBIT6 // active low +#define bmPC_LED1 bmBIT7 // active low + +sbit at 0xA0+1 bitALTERA_DATA0; // 0xA0 is the bit address of PORT C +sbit at 0xA0+3 bitALTERA_DCLK; + + +#define bmALTERA_BITS (bmALTERA_DATA0 \ + | bmALTERA_NCONFIG \ + | bmALTERA_DCLK \ + | bmALTERA_CONF_DONE \ + | bmALTERA_NSTATUS) + +#define bmPORT_C_OUTPUTS (bmPC_nRESET \ + | bmALTERA_DATA0 \ + | bmALTERA_NCONFIG \ + | bmALTERA_DCLK \ + | bmPC_LED0 \ + | bmPC_LED1 \ + ) + +#define bmPORT_C_INITIAL (bmPC_LED0 | bmPC_LED1) + + +#define USRP_LED_REG USRP_PC +#define bmLED0 bmPC_LED0 +#define bmLED1 bmPC_LED1 + + +/* Port D: GPIF FD[15:8] */ + +/* Port E: not bit addressible */ + +#define USRP_PE IOE // Port E +#define USRP_PE_OE OEE // Port E direction register + +#define bmPE_PE0 bmBIT0 // GPIF debug output +#define bmPE_PE1 bmBIT1 // GPIF debug output +#define bmPE_PE2 bmBIT2 // GPIF debug output +#define bmPE_FPGA_CLR_STATUS bmBIT3 // misc pin to FPGA (clear status) +#define bmPE_SEN_TX_A bmBIT4 // serial enable d'board TX A (active low) +#define bmPE_SEN_RX_A bmBIT5 // serial enable d'board RX A (active low) +#define bmPE_SEN_TX_B bmBIT6 // serial enable d'board TX B (active low) +#define bmPE_SEN_RX_B bmBIT7 // serial enable d'board RX B (active low) + + +#define bmPORT_E_OUTPUTS (bmPE_FPGA_CLR_STATUS \ + | bmPE_SEN_TX_A \ + | bmPE_SEN_RX_A \ + | bmPE_SEN_TX_B \ + | bmPE_SEN_RX_B \ + ) + + +#define bmPORT_E_INITIAL (bmPE_SEN_TX_A \ + | bmPE_SEN_RX_A \ + | bmPE_SEN_TX_B \ + | bmPE_SEN_RX_B \ + ) + +/* + * FPGA output lines that are tied to FX2 RDYx inputs. + * These are readable using GPIFREADYSTAT. + */ +#define bmFPGA_HAS_SPACE bmBIT0 // usbrdy[0] has room for 512 byte packet +#define bmFPGA_PKT_AVAIL bmBIT1 // usbrdy[1] has >= 512 bytes available +// #define bmTX_UNDERRUN bmBIT2 // usbrdy[2] D/A ran out of data +// #define bmRX_OVERRUN bmBIT3 // usbrdy[3] A/D ran out of buffer + +/* + * FPGA input lines that are tied to the FX2 CTLx outputs. + * + * These are controlled by the GPIF microprogram... + */ +// WR bmBIT0 // usbctl[0] +// RD bmBIT1 // usbctl[1] +// OE bmBIT2 // usbctl[2] + +#endif /* _USRP_REV1_REGS_H_ */ diff --git a/firmware/fx2/src/usrp1/vectors.a51 b/firmware/fx2/src/usrp1/vectors.a51 new file mode 100644 index 000000000..fa579ba8a --- /dev/null +++ b/firmware/fx2/src/usrp1/vectors.a51 @@ -0,0 +1 @@ + .include "../common/vectors.a51" -- cgit v1.2.3 From b3a092055abacb99b3e9d71edd26c2dd2059dd7f Mon Sep 17 00:00:00 2001 From: Thomas Tsou Date: Thu, 12 Aug 2010 16:22:04 -0700 Subject: usrp1: Add SPI transaction command to FX2 firmware The existing SPI read command is set for half-duplex 8-bit or 16-bit writes followed by an equivalent sized read. This patch adds a new command, VRQ_SPI_TRANSACT, which performs a full-duplex transaction up to 4-bytes. Since the data buffer of the USB control transfer is not available for outbound data on IN requests, the 4 bytes of write data are sent through the request parameters. Enables are sent in the previsouly unused high byte of the length parameter. The USB field mappings are shown below. Only rising edge and MSB operation is supported. Field (8-bit) Description ===== ===== bmRequestType 0x80 (USB Device IN request) bRequest 0x83 (VRQ_SPI_TRANSACT) wValueH OUT data(0) wValueL OUT data(1) wIndexH OUT data(2) wIndexL OUT data(3) wLengthH SPI enables wLengthL Number of bytes to transfer (1-4) EP0BUF IN data --- firmware/fx2/include/usrp_commands.h | 7 +++ firmware/fx2/src/usrp1/spi.c | 95 +++++++++++++++++++++++++++++++++++- firmware/fx2/src/usrp1/spi.h | 7 +++ firmware/fx2/src/usrp1/usrp_main.c | 10 +++- 4 files changed, 116 insertions(+), 3 deletions(-) (limited to 'firmware/fx2/src') diff --git a/firmware/fx2/include/usrp_commands.h b/firmware/fx2/include/usrp_commands.h index 20c28e264..02778c7e3 100644 --- a/firmware/fx2/include/usrp_commands.h +++ b/firmware/fx2/include/usrp_commands.h @@ -54,6 +54,13 @@ // wIndexL: format // len: how much to read +#define VRQ_SPI_TRANSACT 0x83 // wValueH: OUT byte 0 + // wValueL: OUT byte 1 + // wIndexH: OUT byte 2 + // wIndexL: OUT byte 3 + // wLengthH: enables + // wLengthL: transaction length + // OUT commands #define VRQ_SET_LED 0x01 // wValueL off/on {0,1}; wIndexL: which {0,1} diff --git a/firmware/fx2/src/usrp1/spi.c b/firmware/fx2/src/usrp1/spi.c index f5803c55b..0aaffea5d 100644 --- a/firmware/fx2/src/usrp1/spi.c +++ b/firmware/fx2/src/usrp1/spi.c @@ -97,13 +97,18 @@ count_bits8 (unsigned char v) static void write_byte_msb (unsigned char v); +unsigned char +transact_byte_msb (unsigned char v); + static void write_bytes_msb (const xdata unsigned char *buf, unsigned char len); static void read_bytes_msb (xdata unsigned char *buf, unsigned char len); - +static void +transact_bytes_msb (xdata unsigned char *buf, unsigned char len); + // returns non-zero if successful, else 0 unsigned char spi_read (unsigned char header_hi, unsigned char header_lo, @@ -214,7 +219,93 @@ spi_write (unsigned char header_hi, unsigned char header_lo, return 1; // success } -// ---------------------------------------------------------------- +unsigned char +spi_transact (unsigned char data0, unsigned char data1, + unsigned char data2, unsigned char data3, + unsigned char enables, xdata unsigned char *buf, + unsigned char len) +{ + if (count_bits8 (enables) > 1) + return 0; // error, too many enables set + + if (len > 4) + return 0; + + setup_enables (enables); + + buf[0] = data0; + buf[1] = data1; + buf[2] = data2; + buf[3] = data3; + + if (len != 0) + transact_bytes_msb(buf, len); + + disable_all (); + return 1; // success +} + +static unsigned char +transact_byte_msb (unsigned char v) +{ + v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit) + bitS_OUT = v & 0x1; + bitS_CLK = 1; + v |= bitS_IN; // read into bottom bit + bitS_CLK = 0; + + v = (v << 1) | (v >> 7); + bitS_OUT = v & 0x1; + bitS_CLK = 1; + v |= bitS_IN; + bitS_CLK = 0; + + v = (v << 1) | (v >> 7); + bitS_OUT = v & 0x1; + bitS_CLK = 1; + v |= bitS_IN; + bitS_CLK = 0; + + v = (v << 1) | (v >> 7); + bitS_OUT = v & 0x1; + bitS_CLK = 1; + v |= bitS_IN; + bitS_CLK = 0; + + v = (v << 1) | (v >> 7); + bitS_OUT = v & 0x1; + bitS_CLK = 1; + v |= bitS_IN; + bitS_CLK = 0; + + v = (v << 1) | (v >> 7); + bitS_OUT = v & 0x1; + bitS_CLK = 1; + v |= bitS_IN; + bitS_CLK = 0; + + v = (v << 1) | (v >> 7); + bitS_OUT = v & 0x1; + bitS_CLK = 1; + v |= bitS_IN; + bitS_CLK = 0; + + v = (v << 1) | (v >> 7); + bitS_OUT = v & 0x1; + bitS_CLK = 1; + v |= bitS_IN; + bitS_CLK = 0; + + return v; +} + +static void +transact_bytes_msb (xdata unsigned char *buf, unsigned char len) +{ + while (len-- != 0){ + *buf++ = transact_byte_msb (*buf); + } +} static void write_byte_msb (unsigned char v) diff --git a/firmware/fx2/src/usrp1/spi.h b/firmware/fx2/src/usrp1/spi.h index 12bc5e544..5342b82b8 100644 --- a/firmware/fx2/src/usrp1/spi.h +++ b/firmware/fx2/src/usrp1/spi.h @@ -39,5 +39,12 @@ spi_write (unsigned char header_hi, unsigned char header_lo, unsigned char enables, unsigned char format, const xdata unsigned char *buf, unsigned char len); +// returns non-zero if successful, else 0 +unsigned char +spi_transact (unsigned char data0, unsigned char data1, + unsigned char data2, unsigned char data3, + unsigned char enables, xdata unsigned char *buf, + unsigned char len); + #endif /* INCLUDED_SPI_H */ diff --git a/firmware/fx2/src/usrp1/usrp_main.c b/firmware/fx2/src/usrp1/usrp_main.c index c7c09f8c5..b8c2e98ec 100644 --- a/firmware/fx2/src/usrp1/usrp_main.c +++ b/firmware/fx2/src/usrp1/usrp_main.c @@ -117,7 +117,7 @@ app_vendor_cmd (void) EP0BCH = 0; EP0BCL = wLengthL; break; - + case VRQ_SPI_READ: if (!spi_read (wValueH, wValueL, wIndexH, wIndexL, EP0BUF, wLengthL)) return 0; @@ -126,6 +126,14 @@ app_vendor_cmd (void) EP0BCL = wLengthL; break; + case VRQ_SPI_TRANSACT: + if (!spi_transact (wValueH, wValueL, wIndexH, wIndexL, wLengthH, EP0BUF, wLengthL)) + return 0; + + EP0BCH = 0; + EP0BCL = wLengthL; + break; + default: return 0; } -- cgit v1.2.3 From b96088b692a5c44974919ee36e253b6ea8c51972 Mon Sep 17 00:00:00 2001 From: Nick Foster Date: Tue, 31 Aug 2010 16:44:30 -0700 Subject: EEPROM burning in UHD. Changed some USB device handle stuff. Added usrp_init_eeprom.cpp. Hacked up the firmware makefile to behave and to generate .bin EEPROM images instead of IHX. --- firmware/fx2/src/common/build_eeprom.py | 103 +++-------------------- firmware/fx2/src/usrp1/Makefile.am | 58 +++---------- host/include/uhd/transport/usb_device_handle.hpp | 4 +- host/lib/transport/libusb1_base.cpp | 52 ++---------- host/lib/transport/libusb1_base.hpp | 10 --- host/lib/transport/libusb1_device_handle.cpp | 18 ++-- host/lib/usrp/usrp1/mboard_impl.cpp | 11 +++ host/lib/usrp/usrp1/usrp1_ctrl.cpp | 63 +++++++++++++- host/lib/usrp/usrp1/usrp1_ctrl.hpp | 31 +++++++ host/lib/usrp/usrp1/usrp1_iface.cpp | 21 +++-- host/lib/usrp/usrp1/usrp1_impl.cpp | 34 ++++---- host/utils/CMakeLists.txt | 4 + host/utils/usrp_init_eeprom.cpp | 69 +++++++++++++++ 13 files changed, 255 insertions(+), 223 deletions(-) create mode 100644 host/utils/usrp_init_eeprom.cpp (limited to 'firmware/fx2/src') diff --git a/firmware/fx2/src/common/build_eeprom.py b/firmware/fx2/src/common/build_eeprom.py index 023c4b3f5..ae62587db 100755 --- a/firmware/fx2/src/common/build_eeprom.py +++ b/firmware/fx2/src/common/build_eeprom.py @@ -29,15 +29,6 @@ from optparse import OptionParser VID = 0xfffe # Free Software Folks PID = 0x0002 # Universal Software Radio Peripheral - - -def hex_to_bytes (s): - if len (s) & 0x1: - raise ValueError, "Length must be even" - r = [] - for i in range (0, len(s), 2): - r.append (int (s[i:i+2], 16)) - return r def msb (x): return (x >> 8) & 0xff @@ -45,56 +36,6 @@ def msb (x): def lsb (x): return x & 0xff -class ihx_rec (object): - def __init__ (self, addr, type, data): - self.addr = addr - self.type = type - self.data = data - -class ihx_file (object): - def __init__ (self): - self.pat = re.compile (r':[0-9A-F]{10,}') - def read (self, file): - r = [] - for line in file: - line = line.strip().upper () - if not self.pat.match (line): - raise ValueError, "Invalid hex record format" - bytes = hex_to_bytes (line[1:]) - sum = reduce (lambda x, y: x + y, bytes, 0) % 256 - if sum != 0: - raise ValueError, "Bad hex checksum" - lenx = bytes[0] - addr = (bytes[1] << 8) + bytes[2] - type = bytes[3] - data = bytes[4:-1] - if lenx != len (data): - raise ValueError, "Invalid hex record (bad length)" - if type != 0: - break; - r.append (ihx_rec (addr, type, data)) - - return r - -def get_code (filename): - """Read the intel hex format file FILENAME and return a tuple - of the code starting address and a list of bytes to load there. - """ - f = open (filename, 'r') - ifx = ihx_file () - r = ifx.read (f) - r.sort (lambda a,b: a.addr - b.addr) - code_start = r[0].addr - code_end = r[-1].addr + len (r[-1].data) - code_len = code_end - code_start - code = [0] * code_len - for x in r: - a = x.addr - l = len (x.data) - code[a-code_start:a-code_start+l] = x.data - return (code_start, code) - - def build_eeprom_image (filename, rev): """Build a ``C2 Load'' EEPROM image. @@ -102,9 +43,11 @@ def build_eeprom_image (filename, rev): the EZ-USB FX2 Technical Reference Manual """ # get the code we want to run - (start_addr, bytes) = get_code (filename) + f = open(filename, 'rb') + bytes = f.read() devid = rev + start_addr = 0 #prove me wrong rom_header = [ 0xC2, # boot from EEPROM @@ -135,41 +78,18 @@ def build_eeprom_image (filename, rev): 0x00 ] - image = rom_header + code_header + bytes + trailer + image = rom_header + code_header + [ord(c) for c in bytes] + trailer assert (len (image) <= 256) - return image - -def build_shell_script (out, ihx_filename, rev): - - image = build_eeprom_image (ihx_filename, rev) - - out.write ('#!/bin/sh\n') - out.write ('usrper -x load_firmware /usr/local/share/usrp/rev%d/std.ihx\n' % rev) - out.write ('sleep 1\n') - - # print "len(image) =", len(image) - - i2c_addr = 0x50 - rom_addr = 0x00 - - hex_image = map (lambda x : "%02x" % (x,), image) - - while (len (hex_image) > 0): - l = min (len (hex_image), 16) - out.write ('usrper i2c_write 0x%02x %02x%s\n' % - (i2c_addr, rom_addr, ''.join (hex_image[0:l]))) - hex_image = hex_image[l:] - rom_addr = rom_addr + l - out.write ('sleep 1\n') + return image if __name__ == '__main__': - usage = "usage: %prog -r REV [options] bootfile.ihx" + usage = "usage: %prog -r REV [options] bootfile.bin outfile.bin" parser = OptionParser (usage=usage) parser.add_option ("-r", "--rev", type="int", default=-1, help="Specify USRP revision number REV (2 or 4)") (options, args) = parser.parse_args () - if len (args) != 1: + if len (args) != 2: parser.print_help () sys.exit (1) if options.rev < 0: @@ -177,6 +97,11 @@ if __name__ == '__main__': "You must specify the USRP revision number (2 or 4) with -r REV\n") sys.exit (1) - ihx_filename = args[0] + infile = args[0] + outfile = args[1] + + image = "".join(chr(c) for c in build_eeprom_image(infile, options.rev)) - build_shell_script (sys.stdout, ihx_filename, options.rev) + f = open(outfile, 'wb') + f.write(str(image)) + f.close() diff --git a/firmware/fx2/src/usrp1/Makefile.am b/firmware/fx2/src/usrp1/Makefile.am index 5586e83a3..a964f9198 100644 --- a/firmware/fx2/src/usrp1/Makefile.am +++ b/firmware/fx2/src/usrp1/Makefile.am @@ -19,12 +19,12 @@ # Boston, MA 02110-1301, USA. # -firmware2dir = $(prefix)/share/usrp/rev2 -firmware2_DATA = std.ihx +#firmwaredir = $(prefix)/share/uhd/images +#firmware_DATA = usrp1_fw.ihx -# we put the same stuff in the rev4 directory -firmware4dir = $(prefix)/share/usrp/rev4 -firmware4_DATA = std.ihx +#eepromdir = $(firmwaredir) +#eepromfile = eeprom_boot.ihx +#eeprom_DATA = usrp1_eeprom.bin EXTRA_DIST = \ edit-gpif \ @@ -85,11 +85,6 @@ EXECUTABLES = \ STARTUP = _startup.rel -noinst_SCRIPTS = \ - burn-usrp2-eeprom \ - burn-usrp4-eeprom - - .c.rel: $(XCC) $(FW_INCLUDES) $(DEFINES) \ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< @@ -107,34 +102,11 @@ EEPROM_BOOT_OBJS = eeprom_boot.rel eeprom_init.rel $(STARTUP) eeprom_boot.ihx: $(EEPROM_BOOT_OBJS) $(LIBDEP) $(XCC) $(LINKOPTS) -o $@ $(EEPROM_BOOT_OBJS) -burn-usrp2-eeprom: eeprom_boot.ihx - $(PYTHON) $(srcdir)/../common/build_eeprom.py -r2 eeprom_boot.ihx > $@ - chmod +x $@ - -burn-usrp4-eeprom: eeprom_boot.ihx - $(PYTHON) $(srcdir)/../common/build_eeprom.py -r4 eeprom_boot.ihx > $@ - chmod +x $@ - - -BLINK_LEDS_OBJS = blink_leds.rel usrp_common.rel board_specific.rel spi.rel $(STARTUP) - -blink_leds.ihx: $(BLINK_LEDS_OBJS) $(LIBDEP) - $(XCC) $(LINKOPTS) -o $@ $(BLINK_LEDS_OBJS) - - -CHECK_MDELAY_OBJS = check_mdelay.rel usrp_common.rel board_specific.rel spi.rel $(STARTUP) - -check_mdelay.ihx: $(CHECK_MDELAY_OBJS) $(LIBDEP) - $(XCC) $(LINKOPTS) -o $@ $(CHECK_MDELAY_OBJS) - - - -CHECK_UDELAY_OBJS = check_udelay.rel usrp_common.rel board_specific.rel spi.rel $(STARTUP) - -check_udelay.ihx: $(CHECK_UDELAY_OBJS) $(LIBDEP) - $(XCC) $(LINKOPTS) -o $@ $(CHECK_UDELAY_OBJS) - +usrp1_eeprom.bin: eeprom_boot.bin + $(PYTHON) ../common/build_eeprom.py -r4 $< $@ +eeprom_boot.bin: eeprom_boot.ihx + objcopy -I ihex -O binary $< $@ USRP_OBJS = \ vectors.rel \ @@ -146,25 +118,23 @@ std.ihx: $(USRP_OBJS) $(LIBDEP) $(XCC) $(LINKOPTS) -o $@ $(USRP_OBJS) CLEANFILES = \ - *.ihx *.lnk *.lst *.map *.mem *.rel *.rst *.sym *.asm *.lib \ - usrp_gpif.c usrp_gpif_inline.h \ - burn-usrp2-eeprom \ - burn-usrp4-eeprom + *.ihx *.lnk *.lst *.map *.mem *.rel *.rst *.sym *.asm *.lib *.bin \ + usrp_gpif.c usrp_gpif_inline.h DISTCLEANFILES = \ - *.ihx *.lnk *.lst *.map *.mem *.rel *.rst *.sym *.asm *.lib + *.ihx *.lnk *.lst *.map *.mem *.rel *.rst *.sym *.asm *.lib *.bin # build gpif stuff -all: usrp_gpif.c +all: usrp_gpif.c std.ihx usrp1_eeprom.bin usrp_gpif.c usrp_gpif_inline.h : gpif.c srcdir=$(srcdir) $(PYTHON) $(srcdir)/edit-gpif $(srcdir)/gpif.c usrp_gpif.c usrp_gpif_inline.h - # dependencies usrp_main.rel: usrp_gpif_inline.h + #usrp_main.rel: fpga.h usrp_common.h ../../include/usrp_commands.h usrp_gpif_inline.h ../../include/usrp_config.h usrp_rev2_regs.h ../../include/fx2regs.h #usrp_common.rel: usrp_common.h ../../include/usrp_commands.h ../../include/usrp_config.h usrp_rev2_regs.h ../../include/fx2regs.h #fpga.rel: usrp_common.h ../../include/usrp_commands.h fpga.h ../../include/usrp_config.h usrp_rev2_regs.h ../../include/fx2regs.h diff --git a/host/include/uhd/transport/usb_device_handle.hpp b/host/include/uhd/transport/usb_device_handle.hpp index 78c78f6b5..c3eb72b00 100644 --- a/host/include/uhd/transport/usb_device_handle.hpp +++ b/host/include/uhd/transport/usb_device_handle.hpp @@ -68,9 +68,9 @@ public: /*! * Return a vector of USB devices on this host - * \return a vector of USB device handles + * \return a vector of USB device handles that match vid and pid */ - static UHD_API std::vector get_device_list(); + static UHD_API std::vector get_device_list(boost::uint16_t vid, boost::uint16_t pid); }; //namespace usb diff --git a/host/lib/transport/libusb1_base.cpp b/host/lib/transport/libusb1_base.cpp index 92dcd969f..e21c39aa3 100644 --- a/host/lib/transport/libusb1_base.cpp +++ b/host/lib/transport/libusb1_base.cpp @@ -24,22 +24,6 @@ using namespace uhd::transport; /********************************************************** * Helper Methods **********************************************************/ -/* - * Check for FSF device - * Compare the device's descriptor Vendor ID - * \param dev pointer to libusb_device - * \return true if Vendor ID matches 0xfffe - */ -bool check_fsf_device(libusb_device *dev) -{ - libusb_device_descriptor desc; - - if (libusb_get_device_descriptor(dev, &desc) < 0) { - UHD_ASSERT_THROW("USB: failed to get device descriptor"); - } - - return desc.idVendor == 0xfffe; -} /********************************************************** * libusb namespace @@ -52,37 +36,16 @@ void libusb::init(libusb_context **ctx, int debug_level) libusb_set_debug(*ctx, debug_level); } -std::vector libusb::get_fsf_device_list(libusb_context *ctx) -{ - libusb_device **libusb_dev_list; - std::vector fsf_dev_list; - - ssize_t dev_cnt = libusb_get_device_list(ctx, &libusb_dev_list); - - //find the FSF devices - for (ssize_t i = 0; i < dev_cnt; i++) { - libusb_device *dev = libusb_dev_list[i]; - - if (check_fsf_device(dev)) - fsf_dev_list.push_back(dev); - else - libusb_unref_device(dev); - } - - libusb_free_device_list(libusb_dev_list, 0); - - return fsf_dev_list; -} - libusb_device_handle *libusb::open_device(libusb_context *ctx, usb_device_handle::sptr handle) { libusb_device_handle *dev_handle = NULL; - std::vector fsf_dev_list = get_fsf_device_list(ctx); + libusb_device **libusb_dev_list; + size_t dev_cnt = libusb_get_device_list(ctx, &libusb_dev_list); //find and open the USB device - for (size_t i = 0; i < fsf_dev_list.size(); i++) { - libusb_device *dev = fsf_dev_list[i]; + for (size_t i = 0; i < dev_cnt; i++) { + libusb_device *dev = libusb_dev_list[i]; if (compare_device(dev, handle)) { libusb_open(dev, &dev_handle); @@ -96,7 +59,8 @@ libusb_device_handle *libusb::open_device(libusb_context *ctx, return dev_handle; } - +//note: changed order of checks so it only tries to get_serial and get_device_address if vid and pid match +//doing this so it doesn't try to open the device if it's not ours bool libusb::compare_device(libusb_device *dev, usb_device_handle::sptr handle) { @@ -108,12 +72,12 @@ bool libusb::compare_device(libusb_device *dev, libusb_device_descriptor libusb_desc; if (libusb_get_device_descriptor(dev, &libusb_desc) < 0) return false; - if (serial != get_serial(dev)) - return false; if (vendor_id != libusb_desc.idVendor) return false; if (product_id != libusb_desc.idProduct) return false; + if (serial != get_serial(dev)) + return false; if (device_addr != libusb_get_device_address(dev)) return false; diff --git a/host/lib/transport/libusb1_base.hpp b/host/lib/transport/libusb1_base.hpp index 442f89ded..abe5e22a2 100644 --- a/host/lib/transport/libusb1_base.hpp +++ b/host/lib/transport/libusb1_base.hpp @@ -41,16 +41,6 @@ namespace libusb { */ void init(libusb_context **ctx, int debug_level); - /* - * Get a list of Free Software Foundation devices (Vendor ID 0xfffe) - * As opposed to the public USB device handle interface, which returns - * generic identifiers, this call returns device pointers speficic - * to libusb. - * \param ctx the libusb context used for init - * \return a vector of libusb devices - */ - std::vector get_fsf_device_list(libusb_context *ctx); - /* * Open the device specified by a generic handle * Find the libusb_device cooresponding to the generic handle diff --git a/host/lib/transport/libusb1_device_handle.cpp b/host/lib/transport/libusb1_device_handle.cpp index 5d9d8faf0..43d0f0e26 100644 --- a/host/lib/transport/libusb1_device_handle.cpp +++ b/host/lib/transport/libusb1_device_handle.cpp @@ -17,6 +17,7 @@ #include "libusb1_base.hpp" #include +#include using namespace uhd::transport; @@ -91,19 +92,24 @@ usb_device_handle::sptr make_usb_device_handle(libusb_device *dev) device_addr)); } -std::vector usb_device_handle::get_device_list() +std::vector usb_device_handle::get_device_list(boost::uint16_t vid, boost::uint16_t pid) { libusb_context *ctx = NULL; - std::vector libusb_device_list; + libusb_device** libusb_device_list; std::vector device_handle_list; + libusb_device_descriptor desc; libusb::init(&ctx, libusb_debug_level); - libusb_device_list = libusb::get_fsf_device_list(ctx); - - for (size_t i = 0; i < libusb_device_list.size(); i++) { + size_t dev_size = libusb_get_device_list(ctx, &libusb_device_list); + for (size_t i = 0; i < dev_size; i++) { libusb_device *dev = libusb_device_list[i]; - device_handle_list.push_back(make_usb_device_handle(dev)); + if(libusb_get_device_descriptor(dev, &desc) < 0) { + UHD_ASSERT_THROW("USB: failed to get device descriptor"); + } + if(desc.idVendor == vid && desc.idProduct == pid) { + device_handle_list.push_back(make_usb_device_handle(dev)); + } } libusb_exit(ctx); diff --git a/host/lib/usrp/usrp1/mboard_impl.cpp b/host/lib/usrp/usrp1/mboard_impl.cpp index 75129c32f..1409855cb 100644 --- a/host/lib/usrp/usrp1/mboard_impl.cpp +++ b/host/lib/usrp/usrp1/mboard_impl.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -318,6 +319,16 @@ void usrp1_impl::mboard_get(const wax::obj &key_, wax::obj &val) **********************************************************************/ void usrp1_impl::mboard_set(const wax::obj &key, const wax::obj &val) { + if(key.type() == typeid(std::string)) { + if(key.as() == "load_eeprom") { + std::string usrp1_fpga_image = val.as(); + std::cout << "USRP1 EEPROM image: " << usrp1_fpga_image << std::endl; + _ctrl_transport->usrp_load_eeprom(val.as()); + } + + return; + } + //handle the get request conditioned on the key switch(key.as()){ diff --git a/host/lib/usrp/usrp1/usrp1_ctrl.cpp b/host/lib/usrp/usrp1/usrp1_ctrl.cpp index 98226b738..451129ef5 100644 --- a/host/lib/usrp/usrp1/usrp1_ctrl.cpp +++ b/host/lib/usrp/usrp1/usrp1_ctrl.cpp @@ -25,6 +25,7 @@ #include #include #include +#include using namespace uhd; @@ -203,7 +204,7 @@ public: return -1; } } - //type 0x00 is end + //type 0x01 is end else if (type == 0x01) { usrp_control_write(FX2_FIRMWARE_LOAD, 0xe600, 0, &reset_n, 1); @@ -283,6 +284,55 @@ public: return 0; } + int usrp_load_eeprom(std::string filestring) + { + const char *filename = filestring.c_str(); + const uint16_t i2c_addr = 0x50; + + //FIXME: verify types + int len; + unsigned int addr; + unsigned char data[256]; + unsigned char sendbuf[17]; + + int ret; + std::ifstream file; + file.open(filename, std::ifstream::in); + + if (!file.good()) { + std::cerr << "cannot open EEPROM input file" << std::endl; + return -1; + } + + file.read((char *)data, 256); + len = file.gcount(); + + if(len == 256) { + std::cerr << "error: image size too large" << std::endl; + file.close(); + return -1; + } + + const int pagesize = 16; + addr = 0; + while(len > 0) { + sendbuf[0] = addr; + memcpy(sendbuf+1, &data[addr], len > pagesize ? pagesize : len); + ret = usrp_i2c_write(i2c_addr, sendbuf, (len > pagesize ? pagesize : len)+1); + if (ret < 0) { + std::cerr << "error: usrp_i2c_write failed: "; + std::cerr << ret << std::endl; + file.close(); + return -1; + } + addr += pagesize; + len -= pagesize; + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + } + file.close(); + return 0; + } + int usrp_set_led(int led_num, bool on) { @@ -371,6 +421,17 @@ public: return usrp_control_write(request, value, index, 0, 0); } + int usrp_i2c_write(boost::uint16_t i2c_addr, unsigned char *buf, boost::uint16_t len) + { + return usrp_control_write(VRQ_I2C_WRITE, i2c_addr, 0, buf, len); + } + + int usrp_i2c_read(boost::uint16_t i2c_addr, unsigned char *buf, boost::uint16_t len) + { + return usrp_control_read(VRQ_I2C_READ, i2c_addr, 0, buf, len); + } + + private: uhd::transport::usb_control::sptr _ctrl_transport; diff --git a/host/lib/usrp/usrp1/usrp1_ctrl.hpp b/host/lib/usrp/usrp1/usrp1_ctrl.hpp index deedec4e8..a02d9f96c 100644 --- a/host/lib/usrp/usrp1/usrp1_ctrl.hpp +++ b/host/lib/usrp/usrp1/usrp1_ctrl.hpp @@ -49,6 +49,13 @@ public: */ virtual int usrp_load_fpga(std::string filename) = 0; + /*! + * Load USB descriptor file in Intel HEX format into EEPROM + * \param filename name of EEPROM image + * \return 0 on success, error code otherwise + */ + virtual int usrp_load_eeprom(std::string filestring) = 0; + /*! * Set led usrp * \param led_num which LED to control (0 or 1) @@ -127,6 +134,30 @@ public: unsigned char *buff, boost::uint16_t length) = 0; + /*! + * Perform an I2C write + * \param i2c_addr I2C device address + * \param buf data to be written + * \param len length of data in bytes + * \return number of bytes written or error + */ + + virtual int usrp_i2c_write(boost::uint16_t i2c_addr, + unsigned char *buf, + boost::uint16_t len) = 0; + + /*! + * Perform an I2C read + * \param i2c_addr I2C device address + * \param buf data to be read + * \param len length of data in bytes + * \return number of bytes read or error + */ + + virtual int usrp_i2c_read(boost::uint16_t i2c_addr, + unsigned char *buf, + boost::uint16_t len) = 0; + }; #endif /* INCLUDED_USRP_CTRL_HPP */ diff --git a/host/lib/usrp/usrp1/usrp1_iface.cpp b/host/lib/usrp/usrp1/usrp1_iface.cpp index 8756a21c9..4bc18dd16 100644 --- a/host/lib/usrp/usrp1/usrp1_iface.cpp +++ b/host/lib/usrp/usrp1/usrp1_iface.cpp @@ -109,18 +109,19 @@ public: ******************************************************************/ static const size_t max_i2c_data_bytes = 64; + //TODO: make this handle EEPROM page sizes. right now you can't write over a 16-byte boundary. + //to accomplish this you'll have to have addr offset as a separate parameter. + void write_i2c(boost::uint8_t addr, const byte_vector_t &bytes) { UHD_ASSERT_THROW(bytes.size() < max_i2c_data_bytes); unsigned char buff[max_i2c_data_bytes]; - std::copy(bytes.begin(), bytes.end(), buff); + std::copy(bytes.begin(), bytes.end(), buff); - int ret = _ctrl_transport->usrp_control_write(VRQ_I2C_WRITE, - addr & 0xff, - 0, - buff, - bytes.size()); + int ret = _ctrl_transport->usrp_i2c_write(addr & 0xff, + buff, + bytes.size()); // TODO throw and catch i2c failures during eeprom read if (iface_debug && (ret < 0)) @@ -132,11 +133,9 @@ public: UHD_ASSERT_THROW(num_bytes < max_i2c_data_bytes); unsigned char buff[max_i2c_data_bytes]; - int ret = _ctrl_transport->usrp_control_read(VRQ_I2C_READ, - addr & 0xff, - 0, - buff, - num_bytes); + int ret = _ctrl_transport->usrp_i2c_read(addr & 0xff, + buff, + num_bytes); // TODO throw and catch i2c failures during eeprom read if (iface_debug && ((ret < 0) || (unsigned)ret < (num_bytes))) { diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 3c3306525..8ad148274 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -34,6 +34,11 @@ using namespace uhd; using namespace uhd::usrp; using namespace uhd::transport; +const boost::uint16_t USRP1_VENDOR_ID = 0xfffe; +const boost::uint16_t USRP1_PRODUCT_ID = 0x0002; +const boost::uint16_t FX2_VENDOR_ID = 0x04b4; +const boost::uint16_t FX2_PRODUCT_ID = 0x8613; + const std::vector usrp1_impl::_dboard_slots = boost::assign::list_of (usrp1_impl::DBOARD_SLOT_A)(usrp1_impl::DBOARD_SLOT_B) ; @@ -54,33 +59,32 @@ static device_addrs_t usrp1_find(const device_addr_t &hint) ); std::cout << "USRP1 firmware image: " << usrp1_fw_image << std::endl; + boost::uint16_t vid = hint.has_key("uninit") ? FX2_VENDOR_ID : USRP1_VENDOR_ID; + boost::uint16_t pid = hint.has_key("uninit") ? FX2_PRODUCT_ID : USRP1_PRODUCT_ID; + //see what we got on the USB bus std::vector device_list = - usb_device_handle::get_device_list(); + usb_device_handle::get_device_list(vid, pid); + + if(device_list.size() == 0) return usrp1_addrs; //return nothing if no USRPs found //find the usrps and load firmware BOOST_FOREACH(usb_device_handle::sptr handle, device_list) { - if (handle->get_vendor_id() == 0xfffe && - handle->get_product_id() == 0x0002) { - usb_control::sptr ctrl_transport = usb_control::make(handle); usrp_ctrl::sptr usrp_ctrl = usrp_ctrl::make(ctrl_transport); usrp_ctrl->usrp_load_firmware(usrp1_fw_image); - } } - //get descriptors again with serial number - device_list = usb_device_handle::get_device_list(); + //get descriptors again with serial number, but using the initialized VID/PID now since we have firmware + vid = USRP1_VENDOR_ID; + pid = USRP1_PRODUCT_ID; + device_list = usb_device_handle::get_device_list(vid, pid); BOOST_FOREACH(usb_device_handle::sptr handle, device_list) { - if (handle->get_vendor_id() == 0xfffe && - handle->get_product_id() == 0x0002) { - device_addr_t new_addr; new_addr["type"] = "usrp1"; new_addr["serial"] = handle->get_serial(); usrp1_addrs.push_back(new_addr); - } } return usrp1_addrs; @@ -99,17 +103,15 @@ static device::sptr usrp1_make(const device_addr_t &device_addr) //try to match the given device address with something on the USB bus std::vector device_list = - usb_device_handle::get_device_list(); + usb_device_handle::get_device_list(USRP1_VENDOR_ID, USRP1_PRODUCT_ID); //create data and control transports usb_zero_copy::sptr data_transport; usrp_ctrl::sptr usrp_ctrl; - BOOST_FOREACH(usb_device_handle::sptr handle, device_list) { - if (handle->get_vendor_id() == 0xfffe && - handle->get_product_id() == 0x0002 && - handle->get_serial() == device_addr["serial"]) { + BOOST_FOREACH(usb_device_handle::sptr handle, device_list) { + if (handle->get_serial() == device_addr["serial"]) { usb_control::sptr ctrl_transport = usb_control::make(handle); usrp_ctrl = usrp_ctrl::make(ctrl_transport); usrp_ctrl->usrp_load_fpga(usrp1_fpga_image); diff --git a/host/utils/CMakeLists.txt b/host/utils/CMakeLists.txt index c349a9018..9d788b06c 100644 --- a/host/utils/CMakeLists.txt +++ b/host/utils/CMakeLists.txt @@ -39,9 +39,13 @@ TARGET_LINK_LIBRARIES(usrp2_addr_burner uhd) ADD_EXECUTABLE(usrp_burn_db_eeprom usrp_burn_db_eeprom.cpp) TARGET_LINK_LIBRARIES(usrp_burn_db_eeprom uhd) +ADD_EXECUTABLE(usrp_init_eeprom usrp_init_eeprom.cpp) +TARGET_LINK_LIBRARIES(usrp_init_eeprom uhd) + INSTALL(TARGETS usrp2_addr_burner usrp_burn_db_eeprom + usrp_init_eeprom RUNTIME DESTINATION ${PKG_DATA_DIR}/utils ) diff --git a/host/utils/usrp_init_eeprom.cpp b/host/utils/usrp_init_eeprom.cpp new file mode 100644 index 000000000..28c7c5745 --- /dev/null +++ b/host/utils/usrp_init_eeprom.cpp @@ -0,0 +1,69 @@ +// +// Copyright 2010 Ettus Research LLC +// +// 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 3 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, see . +// + +#include +#include +#include +#include +#include +#include + +namespace po = boost::program_options; + +int UHD_SAFE_MAIN(int argc, char *argv[]){ + po::options_description desc("Allowed options"); + desc.add_options() + ("help", "help message") + ("image", po::value(), "IHX image file") + ; + + po::variables_map vm; + po::store(po::parse_command_line(argc, argv, desc), vm); + po::notify(vm); + + //print the help message + if (vm.count("help")){ + std::cout << boost::format("USRP EEPROM initialization %s") % desc << std::endl; + return ~0; + } + + //load the options into the address + uhd::device_addr_t device_addr; + device_addr["type"] = "usrp1"; + device_addr["uninit"] = "yeah"; //tell find to look for an uninitialized FX2 + + //find and create a control transport to do the writing. + + uhd::device_addrs_t found_addrs = uhd::device::find(device_addr); + + if (found_addrs.size() == 0){ + std::cerr << "No uninitialized USRP devices found" << std::endl; + return ~0; + } + + for (size_t i = 0; i < found_addrs.size(); i++){ + std::cout << "Writing EEPROM data..." << std::endl; + //uhd::device_addrs_t devs = uhd::device::find(found_addrs[i]); + uhd::device::sptr dev = uhd::device::make(found_addrs[i]); + wax::obj mb = (*dev)[uhd::usrp::DEVICE_PROP_MBOARD]; + mb[std::string("load_eeprom")] = vm["image"].as(); + } + + + std::cout << "Power-cycle the usrp for the changes to take effect." << std::endl; + return 0; +} -- cgit v1.2.3