Merge pull request #104 from jboone/master
The Pull Request to End All Pull Requests
This commit is contained in:
66
.gitignore
vendored
Normal file
66
.gitignore
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
# Compiled output
|
||||
*.bin
|
||||
*.d
|
||||
*.elf
|
||||
*.hex
|
||||
*.srec
|
||||
host/build/
|
||||
|
||||
# Operating system spew
|
||||
.DS_Store
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
||||
|
||||
# Editor junk
|
||||
*.swp
|
||||
*.sublime-project
|
||||
*.sublime-workspace
|
||||
|
||||
# Xilinx tools create an enormous amount of poop:
|
||||
firmware/cpld/**/isim/
|
||||
firmware/cpld/**/_ngo/
|
||||
firmware/cpld/**/_xmsgs/
|
||||
firmware/cpld/**/iseconfig/
|
||||
firmware/cpld/**/*_html/
|
||||
firmware/cpld/**/xlnx_auto_0_xdb/
|
||||
firmware/cpld/**/xst/
|
||||
firmware/cpld/**/_*.cmd
|
||||
firmware/cpld/**/_*.log
|
||||
firmware/cpld/**/*.bld
|
||||
firmware/cpld/**/*.chk
|
||||
firmware/cpld/**/*.cmd
|
||||
firmware/cpld/**/*.cmd_log
|
||||
firmware/cpld/**/*.csv
|
||||
firmware/cpld/**/*.cxt
|
||||
firmware/cpld/**/*.dat
|
||||
firmware/cpld/**/*.err
|
||||
firmware/cpld/**/*.exe
|
||||
firmware/cpld/**/*.gise
|
||||
firmware/cpld/**/*.gyd
|
||||
firmware/cpld/**/*.html
|
||||
firmware/cpld/**/*.ini
|
||||
firmware/cpld/**/*.ipf
|
||||
firmware/cpld/**/*.log
|
||||
firmware/cpld/**/*.lso
|
||||
firmware/cpld/**/*.mfd
|
||||
firmware/cpld/**/*.ng[acdr]
|
||||
firmware/cpld/**/*.pad
|
||||
firmware/cpld/**/*.phd
|
||||
firmware/cpld/**/*.pnx
|
||||
firmware/cpld/**/*.prj
|
||||
firmware/cpld/**/*.rpt
|
||||
firmware/cpld/**/*.stx
|
||||
firmware/cpld/**/*.syr
|
||||
firmware/cpld/**/*.tim
|
||||
firmware/cpld/**/*.tspec
|
||||
firmware/cpld/**/*.vm6
|
||||
firmware/cpld/**/*.wcfg
|
||||
firmware/cpld/**/*.wdb
|
||||
firmware/cpld/**/*.xml
|
||||
firmware/cpld/**/*.xmsgs
|
||||
firmware/cpld/**/*.xrpt
|
||||
firmware/cpld/**/*.xsl
|
||||
firmware/cpld/**/*.xst
|
||||
firmware/cpld/**/*.xwbt
|
@ -21,7 +21,6 @@
|
||||
#
|
||||
|
||||
TARGETS = blinky \
|
||||
blinky_rom_to_ram \
|
||||
mixertx \
|
||||
sgpio \
|
||||
sgpio-rx \
|
||||
@ -29,12 +28,7 @@ TARGETS = blinky \
|
||||
startup \
|
||||
startup_systick \
|
||||
startup_systick_perfo \
|
||||
hackrf_usb \
|
||||
hackrf_usb_rom_to_ram
|
||||
|
||||
# blinky_rom_to_ram
|
||||
# sgpio_passthrough_rom_to_ram
|
||||
# startup_systick_perfo_rom_to_ram
|
||||
hackrf_usb
|
||||
|
||||
all: build
|
||||
|
||||
|
@ -25,7 +25,11 @@ BINARY = blinky
|
||||
|
||||
SRC = $(BINARY).c \
|
||||
../common/hackrf_core.c \
|
||||
../common/sgpio.c \
|
||||
../common/rf_path.c \
|
||||
../common/si5351c.c \
|
||||
../common/max2837.c
|
||||
../common/max2837.c \
|
||||
../common/max5864.c \
|
||||
../common/rffc5071.c
|
||||
|
||||
include ../common/Makefile_inc.mk
|
||||
|
@ -1,3 +0,0 @@
|
||||
This is the simplest example firmware for HackRF. It flashes three LEDs.
|
||||
This Example Start execution in SPIFI(ROM) and at startup, code from ROM is copied to RAM and shadow pointer is modified to RAM.
|
||||
So at end all the code and vector table is executed from RAM.
|
34
firmware/common/LPC4320_M4_memory.ld
Normal file
34
firmware/common/LPC4320_M4_memory.ld
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2012 Michael Ossmann <mike@ossmann.com>
|
||||
* Copyright 2012 Jared Boone <jared@sharebrained.com>
|
||||
*
|
||||
* This file is part of HackRF
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/* Linker script for HackRF One (LPC4320, 1M SPI flash, 200K SRAM). */
|
||||
|
||||
MEMORY
|
||||
{
|
||||
/* rom is really the shadow region that points to SPI flash or elsewhere */
|
||||
rom (rx) : ORIGIN = 0x00000000, LENGTH = 96K
|
||||
ram_local1 (rwx) : ORIGIN = 0x10000000, LENGTH = 96K
|
||||
ram_local2 (rwx) : ORIGIN = 0x10080000, LENGTH = 32K
|
||||
ram_sleep (rwx) : ORIGIN = 0x10088000, LENGTH = 8K
|
||||
}
|
||||
|
||||
INCLUDE LPC43xx_M4_memory.ld
|
@ -20,22 +20,15 @@
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/* Linker script for HackRF Jellybean (LPC4330, 1M SPI flash, 264K SRAM). */
|
||||
/* Linker script for HackRF Jellybean/Jawbreaker (LPC4330, 1M SPI flash, 264K SRAM). */
|
||||
|
||||
MEMORY
|
||||
{
|
||||
/* rom is really the shadow region that points to SPI flash or elsewhere */
|
||||
rom (rx) : ORIGIN = 0x00000000, LENGTH = 1M
|
||||
rom (rx) : ORIGIN = 0x00000000, LENGTH = 128K
|
||||
ram_local1 (rwx) : ORIGIN = 0x10000000, LENGTH = 128K
|
||||
ram_local2 (rwx) : ORIGIN = 0x10080000, LENGTH = 72K
|
||||
/* there are some additional RAM regions */
|
||||
ram_ahb1 (rwx) : ORIGIN = 0x20000000, LENGTH = 16K
|
||||
/* Removed 32K of AHB SRAM for USB buffer. Straddles two blocks of RAM
|
||||
* to get performance benefit of having two USB buffers addressable
|
||||
* simultaneously (on two different buses of the AHB multilayer matrix)
|
||||
*/
|
||||
ram_ahb2 (rwx) : ORIGIN = 0x2000C000, LENGTH = 16K
|
||||
ram_local2 (rwx) : ORIGIN = 0x10080000, LENGTH = 64K
|
||||
ram_sleep (rwx) : ORIGIN = 0x10090000, LENGTH = 8K
|
||||
}
|
||||
|
||||
/* Include the common ld script. */
|
||||
INCLUDE libopencm3_lpc43xx.ld
|
||||
INCLUDE LPC43xx_M4_memory.ld
|
26
firmware/common/LPC43xx_M0_memory.ld
Normal file
26
firmware/common/LPC43xx_M0_memory.ld
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2012 Michael Ossmann <mike@ossmann.com>
|
||||
* Copyright 2012 Jared Boone <jared@sharebrained.com>
|
||||
*
|
||||
* This file is part of HackRF
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
MEMORY
|
||||
{
|
||||
ram (rwx) : ORIGIN = 0x00000000, LENGTH = 28K
|
||||
}
|
31
firmware/common/LPC43xx_M4_M0_image_from_text.ld
Normal file
31
firmware/common/LPC43xx_M4_M0_image_from_text.ld
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2012 Michael Ossmann <mike@ossmann.com>
|
||||
* Copyright 2012 Jared Boone <jared@sharebrained.com>
|
||||
*
|
||||
* This file is part of HackRF
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text : {
|
||||
PROVIDE(__m0_start__ = .);
|
||||
KEEP(*(.m0_bin*));
|
||||
. = ALIGN(4);
|
||||
PROVIDE(__m0_end__ = .);
|
||||
} >rom
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012 Michael Ossmann <mike@ossmann.com>
|
||||
* Copyright (C) 2012 Benjamin Vernoux <titanmkd@gmail.com>
|
||||
* Copyright 2012 Jared Boone <jared@sharebrained.com>
|
||||
*
|
||||
* This file is part of HackRF
|
||||
@ -21,23 +20,17 @@
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/* Linker script for HackRF Jellybean (LPC4330, 1M SPI flash, 264K SRAM). */
|
||||
|
||||
MEMORY
|
||||
{
|
||||
/* Physical address in Flash used to copy Code from Flash to RAM */
|
||||
rom_flash (rx) : ORIGIN = 0x80000000, LENGTH = 1M
|
||||
/* rom is really the shadow region that points to SPI flash or elsewhere */
|
||||
rom (rx) : ORIGIN = 0x00000000, LENGTH = 1M
|
||||
ram_local1 (rwx) : ORIGIN = 0x10000000, LENGTH = 128K
|
||||
ram_local2 (rwx) : ORIGIN = 0x10080000, LENGTH = 72K
|
||||
ram_ahb1 (rwx) : ORIGIN = 0x20000000, LENGTH = 16K
|
||||
/* Removed 32K of AHB SRAM for USB buffer. Straddles two blocks of RAM
|
||||
ram_m0 (rwx) : ORIGIN = 0x20000000, LENGTH = 28K
|
||||
ram_shared (rwx) : ORIGIN = 0x20007000, LENGTH = 4K
|
||||
ram_usb (rwx) : ORIGIN = 0x20008000, LENGTH = 32K
|
||||
/* ram_usb: USB buffer. Straddles two blocks of RAM
|
||||
* to get performance benefit of having two USB buffers addressable
|
||||
* simultaneously (on two different buses of the AHB multilayer matrix)
|
||||
*/
|
||||
ram_ahb2 (rwx) : ORIGIN = 0x2000C000, LENGTH = 16K
|
||||
}
|
||||
|
||||
/* Include the common ld script. */
|
||||
INCLUDE libopencm3_lpc43xx_rom_to_ram.ld
|
||||
usb_bulk_buffer = ORIGIN(ram_usb);
|
@ -26,10 +26,16 @@
|
||||
|
||||
# derived primarily from Makefiles in libopencm3
|
||||
|
||||
#BOARD ?= JELLYBEAN
|
||||
BOARD ?= JAWBREAKER
|
||||
BOARD ?= HACKRF_ONE
|
||||
RUN_FROM ?= SPIFI
|
||||
|
||||
HACKRF_OPTS = -D$(BOARD) -DLPC43XX -DLPC43XX_M4
|
||||
ifeq ($(BOARD),HACKRF_ONE)
|
||||
MCU_PARTNO=LPC4320
|
||||
else
|
||||
MCU_PARTNO=LPC4330
|
||||
endif
|
||||
|
||||
HACKRF_OPTS = -D$(BOARD) -DLPC43XX -D$(MCU_PARTNO)
|
||||
|
||||
# comment to disable RF transmission
|
||||
HACKRF_OPTS += -DTX_ENABLE
|
||||
@ -38,9 +44,39 @@ HACKRF_OPTS += -DTX_ENABLE
|
||||
VERSION_STRING ?= -D'VERSION_STRING="git-$(shell git log -n 1 --format=%h)"'
|
||||
HACKRF_OPTS += $(VERSION_STRING)
|
||||
|
||||
LDSCRIPT ?= ../common/LPC4330_M4.ld
|
||||
PATH_HACKRF ?= ../..
|
||||
|
||||
LIBOPENCM3 ?= ../libopencm3
|
||||
PATH_HACKRF_FIRMWARE = $(PATH_HACKRF)/firmware
|
||||
PATH_HACKRF_FIRMWARE_COMMON = $(PATH_HACKRF_FIRMWARE)/common
|
||||
|
||||
LIBOPENCM3 ?= $(PATH_HACKRF_FIRMWARE)/libopencm3
|
||||
|
||||
VPATH += $(PATH_HACKRF_FIRMWARE_COMMON)/xapp058
|
||||
VPATH += $(PATH_HACKRF_FIRMWARE_COMMON)
|
||||
|
||||
SRC_M4_C ?= $(SRC)
|
||||
SRC_M0_C ?= $(PATH_HACKRF_FIRMWARE_COMMON)/m0_sleep.c
|
||||
|
||||
BUILD_DIR = build
|
||||
OBJDIR_M4 = $(BUILD_DIR)/m4
|
||||
OBJDIR_M0 = $(BUILD_DIR)/m0
|
||||
|
||||
OBJ_M4_C = $(patsubst %.c, $(OBJDIR_M4)/%.o, $(notdir $(SRC_M4_C)))
|
||||
OBJ_M4_S = $(patsubst %.s, $(OBJDIR_M4)/%.o, $(notdir $(SRC_M4_S)))
|
||||
|
||||
OBJ_M0_C = $(patsubst %.c, $(OBJDIR_M0)/%.o, $(notdir $(SRC_M0_C)))
|
||||
OBJ_M0_S = $(patsubst %.s, $(OBJDIR_M0)/%.o, $(notdir $(SRC_M0_S)))
|
||||
|
||||
LDSCRIPT_M4 += -T$(PATH_HACKRF_FIRMWARE_COMMON)/$(MCU_PARTNO)_M4_memory.ld
|
||||
ifeq ($(RUN_FROM),RAM)
|
||||
LDSCRIPT_M4 += -Tlibopencm3_lpc43xx.ld
|
||||
else
|
||||
LDSCRIPT_M4 += -Tlibopencm3_lpc43xx_rom_to_ram.ld
|
||||
endif
|
||||
LDSCRIPT_M4 += -T$(PATH_HACKRF_FIRMWARE_COMMON)/LPC43xx_M4_M0_image_from_text.ld
|
||||
|
||||
LDSCRIPT_M0 += -T$(PATH_HACKRF_FIRMWARE_COMMON)/LPC43xx_M0_memory.ld
|
||||
LDSCRIPT_M0 += -Tlibopencm3_lpc43xx_m0.ld
|
||||
|
||||
PREFIX ?= arm-none-eabi
|
||||
CC = $(PREFIX)-gcc
|
||||
@ -50,23 +86,34 @@ OBJDUMP = $(PREFIX)-objdump
|
||||
GDB = $(PREFIX)-gdb
|
||||
TOOLCHAIN_DIR := $(shell dirname `which $(CC)`)/../$(PREFIX)
|
||||
|
||||
CFLAGS += -std=gnu99 -Os -g3 -Wall -Wextra -I$(LIBOPENCM3)/include -I../common \
|
||||
-fno-common -mcpu=cortex-m4 -mthumb -MD \
|
||||
-mfloat-abi=hard -mfpu=fpv4-sp-d16 \
|
||||
$(HACKRF_OPTS)
|
||||
LDFLAGS += -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 \
|
||||
-L$(TOOLCHAIN_DIR)/lib/armv7e-m/fpu -L../common \
|
||||
CFLAGS_COMMON += -std=gnu99 -Os -g3 -Wall -Wextra -I$(LIBOPENCM3)/include -I$(PATH_HACKRF_FIRMWARE_COMMON) \
|
||||
$(HACKRF_OPTS) -fno-common -mthumb -MD
|
||||
LDFLAGS_COMMON += -mthumb \
|
||||
-L$(PATH_HACKRF_FIRMWARE_COMMON) \
|
||||
-L$(LIBOPENCM3)/lib -L$(LIBOPENCM3)/lib/lpc43xx \
|
||||
-T$(LDSCRIPT) -nostartfiles \
|
||||
-Wl,--gc-sections -Xlinker -Map=$(BINARY).map
|
||||
OBJ = $(SRC:.c=.o)
|
||||
-nostartfiles \
|
||||
-Wl,--gc-sections \
|
||||
-lc -lnosys
|
||||
CFLAGS_M0 += -mcpu=cortex-m0 -DLPC43XX_M0
|
||||
LDFLAGS_M0 += -mcpu=cortex-m0 -DLPC43XX_M0
|
||||
LDFLAGS_M0 += $(LDSCRIPT_M0)
|
||||
LDFLAGS_M0 += --specs=nano.specs
|
||||
LDFLAGS_M0 += -Xlinker -Map=$(OBJDIR_M0)/m0.map
|
||||
LDFLAGS_M0 += -lopencm3_lpc43xx_m0
|
||||
|
||||
CFLAGS_M4 += -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -DLPC43XX_M4
|
||||
LDFLAGS_M4 += -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -DLPC43XX_M4
|
||||
LDFLAGS_M4 += -L$(TOOLCHAIN_DIR)/lib/armv7e-m/fpu
|
||||
LDFLAGS_M4 += $(LDSCRIPT_M4)
|
||||
LDFLAGS_M4 += -Xlinker -Map=$(OBJDIR_M4)/m4.map
|
||||
LDFLAGS_M4 += -lopencm3_lpc43xx -lm
|
||||
|
||||
# Be silent per default, but 'make V=1' will show all compiler calls.
|
||||
ifneq ($(V),1)
|
||||
Q := @
|
||||
NULL := 2>/dev/null
|
||||
else
|
||||
LDFLAGS += -Wl,--print-gc-sections
|
||||
LDFLAGS_COMMON += -Wl,--print-gc-sections
|
||||
endif
|
||||
|
||||
.SUFFIXES: .elf .bin .hex .srec .list .images
|
||||
@ -81,40 +128,77 @@ flash: $(BINARY).flash
|
||||
program: $(BINARY).dfu
|
||||
$(Q)dfu-util --device 1fc9:000c --alt 0 --download $(BINARY).dfu
|
||||
|
||||
%.images: %.bin %.hex %.srec %.list
|
||||
$(BINARY).images: $(BINARY).bin $(BINARY).hex $(BINARY).srec $(BINARY).list
|
||||
@#echo "*** $* images generated ***"
|
||||
|
||||
%.dfu: %.bin
|
||||
$(BINARY).dfu: $(BINARY).bin
|
||||
$(Q)rm -f _tmp.dfu _header.bin
|
||||
$(Q)cp $(*).bin _tmp.dfu
|
||||
$(Q)cp $(BINARY).bin _tmp.dfu
|
||||
$(Q)dfu-suffix --vid=0x1fc9 --pid=0x000c --did=0x0 -s 0 -a _tmp.dfu
|
||||
$(Q)python -c "import os.path; import struct; print('0000000: da ff ' + ' '.join(map(lambda s: '%02x' % ord(s), struct.pack('<H', os.path.getsize('$(*).bin') / 512 + 1))) + ' ff ff ff ff')" | xxd -g1 -r > _header.bin
|
||||
$(Q)cat _header.bin _tmp.dfu >$(*).dfu
|
||||
$(Q)python -c "import os.path; import struct; print('0000000: da ff ' + ' '.join(map(lambda s: '%02x' % ord(s), struct.pack('<H', os.path.getsize('$(BINARY).bin') / 512 + 1))) + ' ff ff ff ff')" | xxd -g1 -r > _header.bin
|
||||
$(Q)cat _header.bin _tmp.dfu >$(BINARY).dfu
|
||||
$(Q)rm -f _tmp.dfu _header.bin
|
||||
|
||||
%.bin: %.elf
|
||||
$(BINARY).bin: $(BINARY).elf
|
||||
@#printf " OBJCOPY $(*).bin\n"
|
||||
$(Q)$(OBJCOPY) -Obinary $(*).elf $(*).bin
|
||||
$(Q)$(OBJCOPY) -Obinary $(BINARY).elf $(BINARY).bin
|
||||
|
||||
%.hex: %.elf
|
||||
@#printf " OBJCOPY $(*).hex\n"
|
||||
$(Q)$(OBJCOPY) -Oihex $(*).elf $(*).hex
|
||||
$(OBJDIR_M0)/m0.bin: $(OBJDIR_M0)/m0.elf
|
||||
@#printf " OBJCOPY $(*).bin\n"
|
||||
$(Q)$(OBJCOPY) -Obinary $(OBJDIR_M0)/m0.elf $(OBJDIR_M0)/m0.bin
|
||||
|
||||
%.srec: %.elf
|
||||
@#printf " OBJCOPY $(*).srec\n"
|
||||
$(Q)$(OBJCOPY) -Osrec $(*).elf $(*).srec
|
||||
#$(OBJDIR_M0)/m0.o: $(OBJDIR_M0)/m0.bin
|
||||
# $(Q)$(OBJCOPY) -I binary -B arm -O elf32-littlearm $(OBJDIR_M0)/m0.bin $(OBJDIR_M0)/m0.o
|
||||
|
||||
%.list: %.elf
|
||||
@#printf " OBJDUMP $(*).list\n"
|
||||
$(Q)$(OBJDUMP) -S $(*).elf > $(*).list
|
||||
$(BINARY).hex: $(BINARY).elf
|
||||
@#printf " OBJCOPY $(BINARY).hex\n"
|
||||
$(Q)$(OBJCOPY) -Oihex $(BINARY).elf $(BINARY).hex
|
||||
|
||||
%.elf: $(OBJ) $(LDSCRIPT)
|
||||
$(BINARY).srec: $(BINARY).elf
|
||||
@#printf " OBJCOPY $(BINARY).srec\n"
|
||||
$(Q)$(OBJCOPY) -Osrec $(BINARY).elf $(BINARY).srec
|
||||
|
||||
$(BINARY).list: $(BINARY).elf
|
||||
@#printf " OBJDUMP $(BINARY).list\n"
|
||||
$(Q)$(OBJDUMP) -S $(BINARY).elf > $(BINARY).list
|
||||
|
||||
$(BINARY).elf: obj_m4
|
||||
@#printf " LD $(subst $(shell pwd)/,,$(@))\n"
|
||||
$(Q)$(LD) $(LDFLAGS) -o $(*).elf $(OBJ) -lopencm3_lpc43xx
|
||||
$(Q)$(LD) -o $(BINARY).elf $(OBJ_M4_C) $(OBJ_M4_S) $(OBJDIR_M4)/m0_bin.o $(LDFLAGS_COMMON) $(LDFLAGS_M4)
|
||||
|
||||
%.o: %.c Makefile
|
||||
@#printf " CC $(subst $(shell pwd)/,,$(@))\n"
|
||||
$(Q)$(CC) $(CFLAGS) -o $@ -c $<
|
||||
$(OBJDIR_M0)/m0.elf: obj_m0
|
||||
@#printf " LD $(subst $(shell pwd)/,,$(@))\n"
|
||||
$(Q)$(LD) -o $(OBJDIR_M0)/m0.elf $(OBJ_M0_C) $(OBJ_M0_S) $(LDFLAGS_COMMON) $(LDFLAGS_M0)
|
||||
|
||||
obj_m4: $(OBJ_M4_C) $(OBJ_M4_S) $(OBJDIR_M4)/m0_bin.o
|
||||
|
||||
obj_m0: $(OBJ_M0_C) $(OBJ_M0_S)
|
||||
|
||||
$(OBJDIR_M4)/%.o: %.c | $(OBJDIR_M4)
|
||||
@printf " CC $(subst $(shell pwd)/,,$(@))\n"
|
||||
$(Q)$(CC) $(CFLAGS_COMMON) $(CFLAGS_M4) -o $@ -c $<
|
||||
|
||||
$(OBJDIR_M4)/%.o: %.s | $(OBJDIR_M4)
|
||||
@printf " CC $(subst $(shell pwd)/,,$(@))\n"
|
||||
$(Q)$(CC) $(CFLAGS_COMMON) $(CFLAGS_M4) -o $@ -c $<
|
||||
|
||||
$(OBJDIR_M4)/m0_bin.o: m0_bin.s $(OBJDIR_M0)/m0.bin | $(OBJDIR_M4)
|
||||
@printf " CC $(subst $(shell pwd)/,,$(@))\n"
|
||||
$(Q)$(CC) $(CFLAGS_COMMON) $(CFLAGS_M4) -o $@ -c $<
|
||||
|
||||
$(OBJDIR_M0)/%.o: %.c | $(OBJDIR_M0)
|
||||
@printf " CC $(subst $(shell pwd)/,,$(@))\n"
|
||||
$(Q)$(CC) $(CFLAGS_COMMON) $(CFLAGS_M0) -o $@ -c $<
|
||||
|
||||
$(OBJDIR_M0)/%.o: %.s | $(OBJDIR_M0)
|
||||
@printf " CC $(subst $(shell pwd)/,,$(@))\n"
|
||||
$(Q)$(CC) $(CFLAGS_COMMON) $(CFLAGS_M0) -o $@ -c $<
|
||||
|
||||
$(OBJDIR_M4):
|
||||
$(Q)mkdir -p $@
|
||||
|
||||
$(OBJDIR_M0):
|
||||
$(Q)mkdir -p $@
|
||||
|
||||
clean:
|
||||
$(Q)rm -f *.o
|
||||
@ -128,12 +212,27 @@ clean:
|
||||
$(Q)rm -f *.list
|
||||
$(Q)rm -f *.map
|
||||
$(Q)rm -f *.lst
|
||||
$(Q)rm -f ../common/*.o
|
||||
$(Q)rm -f ../common/*.d
|
||||
$(Q)rm -f ../common/*.lst
|
||||
$(Q)rm -f ../common/xapp058/*.o
|
||||
$(Q)rm -f ../common/xapp058/*.d
|
||||
$(Q)rm -f $(PATH_HACKRF_FIRMWARE)/hackrf_usb/*.o
|
||||
$(Q)rm -f $(PATH_HACKRF_FIRMWARE)/hackrf_usb/*.d
|
||||
$(Q)rm -f $(PATH_HACKRF_FIRMWARE)/hackrf_usb/*.lst
|
||||
$(Q)rm -f $(PATH_HACKRF_FIRMWARE_COMMON)/*.o
|
||||
$(Q)rm -f $(PATH_HACKRF_FIRMWARE_COMMON)/*.d
|
||||
$(Q)rm -f $(PATH_HACKRF_FIRMWARE_COMMON)/*.lst
|
||||
$(Q)rm -f $(PATH_HACKRF_FIRMWARE_COMMON)/xapp058/*.o
|
||||
$(Q)rm -f $(PATH_HACKRF_FIRMWARE_COMMON)/xapp058/*.d
|
||||
$(Q)rm -f $(OBJDIR_M4)/*.o
|
||||
$(Q)rm -f $(OBJDIR_M4)/*.d
|
||||
$(Q)rm -f $(OBJDIR_M4)/*.elf
|
||||
$(Q)rm -f $(OBJDIR_M4)/*.bin
|
||||
$(Q)rm -f $(OBJDIR_M4)/*.map
|
||||
$(Q)rm -f $(OBJDIR_M0)/*.o
|
||||
$(Q)rm -f $(OBJDIR_M0)/*.d
|
||||
$(Q)rm -f $(OBJDIR_M0)/*.elf
|
||||
$(Q)rm -f $(OBJDIR_M0)/*.bin
|
||||
$(Q)rm -f $(OBJDIR_M0)/*.map
|
||||
$(Q)rm -rf $(BUILD_DIR)
|
||||
|
||||
.PHONY: images clean
|
||||
|
||||
-include $(OBJ:.o=.d)
|
||||
-include $(OBJ_M4_C:.o=.d)
|
||||
-include $(OBJ_M0_C:.o=.d)
|
||||
|
@ -26,8 +26,9 @@
|
||||
#include <libopencm3/lpc43xx/scu.h>
|
||||
#include <stdint.h>
|
||||
|
||||
uint32_t xsvf_len;
|
||||
unsigned char* xsvf_data;
|
||||
static refill_buffer_cb refill_buffer;
|
||||
static uint32_t xsvf_buffer_len, xsvf_pos;
|
||||
static unsigned char* xsvf_buffer;
|
||||
|
||||
void cpld_jtag_setup(void) {
|
||||
scu_pinmux(SCU_PINMUX_CPLD_TDO, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION4);
|
||||
@ -58,11 +59,16 @@ void cpld_jtag_release(void) {
|
||||
}
|
||||
|
||||
/* return 0 if success else return error code see xsvfExecute() */
|
||||
int cpld_jtag_program(const uint32_t len, unsigned char* const data) {
|
||||
int cpld_jtag_program(
|
||||
const uint32_t buffer_length,
|
||||
unsigned char* const buffer,
|
||||
refill_buffer_cb refill
|
||||
) {
|
||||
int error;
|
||||
cpld_jtag_setup();
|
||||
xsvf_data = data;
|
||||
xsvf_len = len;
|
||||
xsvf_buffer = buffer;
|
||||
xsvf_buffer_len = buffer_length;
|
||||
refill_buffer = refill;
|
||||
error = xsvfExecute();
|
||||
cpld_jtag_release();
|
||||
|
||||
@ -71,12 +77,12 @@ int cpld_jtag_program(const uint32_t len, unsigned char* const data) {
|
||||
|
||||
/* this gets called by the XAPP058 code */
|
||||
unsigned char cpld_jtag_get_next_byte(void) {
|
||||
unsigned char byte = *xsvf_data;
|
||||
|
||||
if (xsvf_len > 1) {
|
||||
xsvf_data++;
|
||||
xsvf_len--;
|
||||
}
|
||||
if (xsvf_pos == xsvf_buffer_len) {
|
||||
refill_buffer();
|
||||
xsvf_pos = 0;
|
||||
}
|
||||
|
||||
unsigned char byte = xsvf_buffer[xsvf_pos];
|
||||
xsvf_pos++;
|
||||
return byte;
|
||||
}
|
||||
|
@ -24,9 +24,20 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef void (*refill_buffer_cb)(void);
|
||||
|
||||
void cpld_jtag_release(void);
|
||||
/* return 0 if success else return error code see xsvfExecute() see micro.h */
|
||||
int cpld_jtag_program(const uint32_t len, unsigned char* const data);
|
||||
|
||||
/* Return 0 if success else return error code see xsvfExecute() see micro.h.
|
||||
*
|
||||
* We expect the buffer to be initially full of data. After the entire
|
||||
* contents of the buffer has been streamed to the CPLD the given
|
||||
* refill_buffer callback will be called. */
|
||||
int cpld_jtag_program(
|
||||
const uint32_t buffer_length,
|
||||
unsigned char* const buffer,
|
||||
refill_buffer_cb refill
|
||||
);
|
||||
unsigned char cpld_jtag_get_next_byte(void);
|
||||
|
||||
#endif//__CPLD_JTAG_H__
|
||||
|
62
firmware/common/gpdma.c
Normal file
62
firmware/common/gpdma.c
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2013 Jared Boone <jared@sharebrained.com>
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <gpdma.h>
|
||||
|
||||
#include <libopencm3/lpc43xx/gpdma.h>
|
||||
|
||||
void gpdma_controller_enable() {
|
||||
GPDMA_CONFIG |= GPDMA_CONFIG_E(1);
|
||||
while( (GPDMA_CONFIG & GPDMA_CONFIG_E_MASK) == 0 );
|
||||
}
|
||||
|
||||
void gpdma_channel_enable(const uint_fast8_t channel) {
|
||||
GPDMA_CCONFIG(channel) |= GPDMA_CCONFIG_E(1);
|
||||
}
|
||||
|
||||
void gpdma_channel_disable(const uint_fast8_t channel) {
|
||||
GPDMA_CCONFIG(channel) &= ~GPDMA_CCONFIG_E_MASK;
|
||||
while( (GPDMA_ENBLDCHNS & GPDMA_ENBLDCHNS_ENABLEDCHANNELS(1 << channel)) );
|
||||
}
|
||||
|
||||
void gpdma_channel_interrupt_tc_clear(const uint_fast8_t channel) {
|
||||
GPDMA_INTTCCLEAR = GPDMA_INTTCCLEAR_INTTCCLEAR(1 << channel);
|
||||
}
|
||||
|
||||
void gpdma_channel_interrupt_error_clear(const uint_fast8_t channel) {
|
||||
GPDMA_INTERRCLR = GPDMA_INTERRCLR_INTERRCLR(1 << channel);
|
||||
}
|
||||
|
||||
void gpdma_lli_enable_interrupt(gpdma_lli_t* const lli) {
|
||||
lli->ccontrol |= GPDMA_CCONTROL_I(1);
|
||||
}
|
||||
|
||||
void gpdma_lli_create_loop(gpdma_lli_t* const lli, const size_t lli_count) {
|
||||
for(size_t i=0; i<lli_count; i++) {
|
||||
gpdma_lli_t* const next_lli = &lli[(i + 1) % lli_count];
|
||||
lli[i].clli = (lli[i].clli & ~GPDMA_CLLI_LLI_MASK) | GPDMA_CLLI_LLI((uint32_t)next_lli >> 2);
|
||||
}
|
||||
}
|
||||
|
||||
void gpdma_lli_create_oneshot(gpdma_lli_t* const lli, const size_t lli_count) {
|
||||
gpdma_lli_create_loop(lli, lli_count);
|
||||
lli[lli_count - 1].clli &= ~GPDMA_CLLI_LLI_MASK;
|
||||
}
|
43
firmware/common/gpdma.h
Normal file
43
firmware/common/gpdma.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2013 Jared Boone <jared@sharebrained.com>
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GPDMA_H__
|
||||
#define __GPDMA_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <libopencm3/lpc43xx/gpdma.h>
|
||||
|
||||
void gpdma_controller_enable();
|
||||
|
||||
void gpdma_channel_enable(const uint_fast8_t channel);
|
||||
void gpdma_channel_disable(const uint_fast8_t channel);
|
||||
|
||||
void gpdma_channel_interrupt_tc_clear(const uint_fast8_t channel);
|
||||
void gpdma_channel_interrupt_error_clear(const uint_fast8_t channel);
|
||||
|
||||
void gpdma_lli_enable_interrupt(gpdma_lli_t* const lli);
|
||||
|
||||
void gpdma_lli_create_loop(gpdma_lli_t* const lli, const size_t lli_count);
|
||||
void gpdma_lli_create_oneshot(gpdma_lli_t* const lli, const size_t lli_count);
|
||||
|
||||
#endif/*__GPDMA_H__*/
|
@ -25,12 +25,16 @@
|
||||
#include "si5351c.h"
|
||||
#include "max2837.h"
|
||||
#include "rffc5071.h"
|
||||
#include "sgpio.h"
|
||||
#include "rf_path.h"
|
||||
#include <libopencm3/lpc43xx/i2c.h>
|
||||
#include <libopencm3/lpc43xx/cgu.h>
|
||||
#include <libopencm3/lpc43xx/gpio.h>
|
||||
#include <libopencm3/lpc43xx/scu.h>
|
||||
#include <libopencm3/lpc43xx/ssp.h>
|
||||
|
||||
#define WAIT_CPU_CLOCK_INIT_DELAY (10000)
|
||||
|
||||
void delay(uint32_t duration)
|
||||
{
|
||||
uint32_t i;
|
||||
@ -186,16 +190,32 @@ bool sample_rate_set(const uint32_t sample_rate_hz) {
|
||||
|
||||
#if (defined JAWBREAKER || defined HACKRF_ONE)
|
||||
uint32_t p1 = 4608;
|
||||
uint32_t p2 = 0;
|
||||
uint32_t p3 = 0;
|
||||
|
||||
switch(sample_rate_hz) {
|
||||
case 8000000:
|
||||
p1 = SI_INTDIV(50); // 800MHz / 50 = 16 MHz (SGPIO), 8 MHz (codec)
|
||||
break;
|
||||
|
||||
case 9216000:
|
||||
// 43.40277777777778: a = 43; b = 29; c = 72
|
||||
p1 = 5043;
|
||||
p2 = 40;
|
||||
p3 = 72;
|
||||
break;
|
||||
|
||||
case 10000000:
|
||||
p1 = SI_INTDIV(40); // 800MHz / 40 = 20 MHz (SGPIO), 10 MHz (codec)
|
||||
break;
|
||||
|
||||
case 12288000:
|
||||
// 32.552083333333336: a = 32; b = 159; c = 288
|
||||
p1 = 3654;
|
||||
p2 = 192;
|
||||
p3 = 288;
|
||||
break;
|
||||
|
||||
case 12500000:
|
||||
p1 = SI_INTDIV(32); // 800MHz / 32 = 25 MHz (SGPIO), 12.5 MHz (codec)
|
||||
break;
|
||||
@ -204,6 +224,13 @@ bool sample_rate_set(const uint32_t sample_rate_hz) {
|
||||
p1 = SI_INTDIV(25); // 800MHz / 25 = 32 MHz (SGPIO), 16 MHz (codec)
|
||||
break;
|
||||
|
||||
case 18432000:
|
||||
// 21.70138888889: a = 21; b = 101; c = 144
|
||||
p1 = 2265;
|
||||
p2 = 112;
|
||||
p3 = 144;
|
||||
break;
|
||||
|
||||
case 20000000:
|
||||
p1 = SI_INTDIV(20); // 800MHz / 20 = 40 MHz (SGPIO), 20 MHz (codec)
|
||||
break;
|
||||
@ -213,7 +240,7 @@ bool sample_rate_set(const uint32_t sample_rate_hz) {
|
||||
}
|
||||
|
||||
/* MS0/CLK0 is the source for the MAX5864/CPLD (CODEC_CLK). */
|
||||
si5351c_configure_multisynth(0, p1, 0, 1, 1);
|
||||
si5351c_configure_multisynth(0, p1, p2, p3, 1);
|
||||
|
||||
/* MS0/CLK1 is the source for the CPLD (CODEC_X2_CLK). */
|
||||
si5351c_configure_multisynth(1, p1, 0, 1, 0);//p1 doesn't matter
|
||||
@ -232,7 +259,9 @@ bool baseband_filter_bandwidth_set(const uint32_t bandwidth_hz) {
|
||||
return max2837_set_lpf_bandwidth(bandwidth_hz);
|
||||
}
|
||||
|
||||
/* clock startup for Jellybean with Lemondrop attached */
|
||||
/* clock startup for Jellybean with Lemondrop attached
|
||||
Configure PLL1 to max speed (204MHz).
|
||||
Note: PLL1 clock is used by M4/M0 core, Peripheral, APB1. */
|
||||
void cpu_clock_init(void)
|
||||
{
|
||||
/* use IRC as clock source for APB1 (including I2C0) */
|
||||
@ -290,9 +319,10 @@ void cpu_clock_init(void)
|
||||
/* MS5/CLK5 is the source for the MAX2837 clock input. */
|
||||
si5351c_configure_multisynth(5, 20*128-512, 0, 1, 0); /* 800/20 = 40MHz */
|
||||
|
||||
/* MS6/CLK6 is unused. */
|
||||
/* MS7/CLK7 is the source for the LPC43xx microcontroller. */
|
||||
//uint8_t ms7data[] = { 91, 40, 0x0 };
|
||||
//si5351c_write(ms7data, sizeof(ms7data));
|
||||
uint8_t ms7data[] = { 90, 255, 20, 0 };
|
||||
si5351c_write(ms7data, sizeof(ms7data));
|
||||
#endif
|
||||
|
||||
/* Set to 10 MHz, the common rate between Jellybean and Jawbreaker. */
|
||||
@ -323,76 +353,149 @@ void cpu_clock_init(void)
|
||||
#endif
|
||||
|
||||
/* set xtal oscillator to low frequency mode */
|
||||
CGU_XTAL_OSC_CTRL &= ~CGU_XTAL_OSC_CTRL_HF;
|
||||
CGU_XTAL_OSC_CTRL &= ~CGU_XTAL_OSC_CTRL_HF_MASK;
|
||||
|
||||
/* power on the oscillator and wait until stable */
|
||||
CGU_XTAL_OSC_CTRL &= ~CGU_XTAL_OSC_CTRL_ENABLE;
|
||||
CGU_XTAL_OSC_CTRL &= ~CGU_XTAL_OSC_CTRL_ENABLE_MASK;
|
||||
|
||||
/* Wait about 100us after Crystal Power ON */
|
||||
delay(WAIT_CPU_CLOCK_INIT_DELAY);
|
||||
|
||||
/* use XTAL_OSC as clock source for BASE_M4_CLK (CPU) */
|
||||
CGU_BASE_M4_CLK = CGU_BASE_M4_CLK_CLK_SEL(CGU_SRC_XTAL);
|
||||
CGU_BASE_M4_CLK = (CGU_BASE_M4_CLK_CLK_SEL(CGU_SRC_XTAL) | CGU_BASE_M4_CLK_AUTOBLOCK(1));
|
||||
|
||||
/* use XTAL_OSC as clock source for APB1 */
|
||||
CGU_BASE_APB1_CLK = CGU_BASE_APB1_CLK_AUTOBLOCK
|
||||
CGU_BASE_APB1_CLK = CGU_BASE_APB1_CLK_AUTOBLOCK(1)
|
||||
| CGU_BASE_APB1_CLK_CLK_SEL(CGU_SRC_XTAL);
|
||||
|
||||
/* use XTAL_OSC as clock source for PLL1 */
|
||||
/* Start PLL1 at 12MHz * 17 / (2+2) = 51MHz. */
|
||||
CGU_PLL1_CTRL = CGU_PLL1_CTRL_CLK_SEL(CGU_SRC_XTAL)
|
||||
| CGU_PLL1_CTRL_PSEL(1)
|
||||
| CGU_PLL1_CTRL_NSEL(0)
|
||||
| CGU_PLL1_CTRL_MSEL(16)
|
||||
| CGU_PLL1_CTRL_PD;
|
||||
|
||||
/* power on PLL1 and wait until stable */
|
||||
CGU_PLL1_CTRL &= ~CGU_PLL1_CTRL_PD;
|
||||
while (!(CGU_PLL1_STAT & CGU_PLL1_STAT_LOCK));
|
||||
cpu_clock_pll1_low_speed();
|
||||
|
||||
/* use PLL1 as clock source for BASE_M4_CLK (CPU) */
|
||||
CGU_BASE_M4_CLK = CGU_BASE_M4_CLK_CLK_SEL(CGU_SRC_PLL1);
|
||||
|
||||
/* Move PLL1 up to 12MHz * 17 = 204MHz. */
|
||||
CGU_PLL1_CTRL = CGU_PLL1_CTRL_CLK_SEL(CGU_SRC_XTAL)
|
||||
| CGU_PLL1_CTRL_PSEL(0)
|
||||
| CGU_PLL1_CTRL_NSEL(0)
|
||||
| CGU_PLL1_CTRL_MSEL(16)
|
||||
| CGU_PLL1_CTRL_FBSEL;
|
||||
//| CGU_PLL1_CTRL_DIRECT;
|
||||
|
||||
/* wait until stable */
|
||||
while (!(CGU_PLL1_STAT & CGU_PLL1_STAT_LOCK));
|
||||
CGU_BASE_M4_CLK = (CGU_BASE_M4_CLK_CLK_SEL(CGU_SRC_PLL1) | CGU_BASE_M4_CLK_AUTOBLOCK(1));
|
||||
|
||||
/* use XTAL_OSC as clock source for PLL0USB */
|
||||
CGU_PLL0USB_CTRL = CGU_PLL0USB_CTRL_PD
|
||||
| CGU_PLL0USB_CTRL_AUTOBLOCK
|
||||
CGU_PLL0USB_CTRL = CGU_PLL0USB_CTRL_PD(1)
|
||||
| CGU_PLL0USB_CTRL_AUTOBLOCK(1)
|
||||
| CGU_PLL0USB_CTRL_CLK_SEL(CGU_SRC_XTAL);
|
||||
while (CGU_PLL0USB_STAT & CGU_PLL0USB_STAT_LOCK);
|
||||
while (CGU_PLL0USB_STAT & CGU_PLL0USB_STAT_LOCK_MASK);
|
||||
|
||||
/* configure PLL0USB to produce 480 MHz clock from 12 MHz XTAL_OSC */
|
||||
/* Values from User Manual v1.4 Table 94, for 12MHz oscillator. */
|
||||
CGU_PLL0USB_MDIV = 0x06167FFA;
|
||||
CGU_PLL0USB_NP_DIV = 0x00302062;
|
||||
CGU_PLL0USB_CTRL |= (CGU_PLL0USB_CTRL_PD
|
||||
| CGU_PLL0USB_CTRL_DIRECTI
|
||||
| CGU_PLL0USB_CTRL_DIRECTO
|
||||
| CGU_PLL0USB_CTRL_CLKEN);
|
||||
CGU_PLL0USB_CTRL |= (CGU_PLL0USB_CTRL_PD(1)
|
||||
| CGU_PLL0USB_CTRL_DIRECTI(1)
|
||||
| CGU_PLL0USB_CTRL_DIRECTO(1)
|
||||
| CGU_PLL0USB_CTRL_CLKEN(1));
|
||||
|
||||
/* power on PLL0USB and wait until stable */
|
||||
CGU_PLL0USB_CTRL &= ~CGU_PLL0USB_CTRL_PD;
|
||||
while (!(CGU_PLL0USB_STAT & CGU_PLL0USB_STAT_LOCK));
|
||||
CGU_PLL0USB_CTRL &= ~CGU_PLL0USB_CTRL_PD_MASK;
|
||||
while (!(CGU_PLL0USB_STAT & CGU_PLL0USB_STAT_LOCK_MASK));
|
||||
|
||||
/* use PLL0USB as clock source for USB0 */
|
||||
CGU_BASE_USB0_CLK = CGU_BASE_USB0_CLK_AUTOBLOCK
|
||||
CGU_BASE_USB0_CLK = CGU_BASE_USB0_CLK_AUTOBLOCK(1)
|
||||
| CGU_BASE_USB0_CLK_CLK_SEL(CGU_SRC_PLL0USB);
|
||||
|
||||
/* Switch peripheral clock over to use PLL1 (204MHz) */
|
||||
CGU_BASE_PERIPH_CLK = CGU_BASE_PERIPH_CLK_AUTOBLOCK
|
||||
CGU_BASE_PERIPH_CLK = CGU_BASE_PERIPH_CLK_AUTOBLOCK(1)
|
||||
| CGU_BASE_PERIPH_CLK_CLK_SEL(CGU_SRC_PLL1);
|
||||
|
||||
/* Switch APB1 clock over to use PLL1 (204MHz) */
|
||||
CGU_BASE_APB1_CLK = CGU_BASE_APB1_CLK_AUTOBLOCK
|
||||
CGU_BASE_APB1_CLK = CGU_BASE_APB1_CLK_AUTOBLOCK(1)
|
||||
| CGU_BASE_APB1_CLK_CLK_SEL(CGU_SRC_PLL1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Configure PLL1 to low speed (48MHz).
|
||||
Note: PLL1 clock is used by M4/M0 core, Peripheral, APB1.
|
||||
This function shall be called after cpu_clock_init().
|
||||
This function is mainly used to lower power consumption.
|
||||
*/
|
||||
void cpu_clock_pll1_low_speed(void)
|
||||
{
|
||||
uint32_t pll_reg;
|
||||
|
||||
/* Configure PLL1 Clock (48MHz) */
|
||||
/* Integer mode:
|
||||
FCLKOUT = M*(FCLKIN/N)
|
||||
FCCO = 2*P*FCLKOUT = 2*P*M*(FCLKIN/N)
|
||||
*/
|
||||
pll_reg = CGU_PLL1_CTRL;
|
||||
/* Clear PLL1 bits */
|
||||
pll_reg &= ~( CGU_PLL1_CTRL_CLK_SEL_MASK | CGU_PLL1_CTRL_PD_MASK | CGU_PLL1_CTRL_FBSEL_MASK | /* CLK SEL, PowerDown , FBSEL */
|
||||
CGU_PLL1_CTRL_BYPASS_MASK | /* BYPASS */
|
||||
CGU_PLL1_CTRL_DIRECT_MASK | /* DIRECT */
|
||||
CGU_PLL1_CTRL_PSEL_MASK | CGU_PLL1_CTRL_MSEL_MASK | CGU_PLL1_CTRL_NSEL_MASK ); /* PSEL, MSEL, NSEL- divider ratios */
|
||||
/* Set PLL1 up to 12MHz * 4 = 48MHz. */
|
||||
pll_reg |= CGU_PLL1_CTRL_CLK_SEL(CGU_SRC_XTAL)
|
||||
| CGU_PLL1_CTRL_PSEL(0)
|
||||
| CGU_PLL1_CTRL_NSEL(0)
|
||||
| CGU_PLL1_CTRL_MSEL(3)
|
||||
| CGU_PLL1_CTRL_FBSEL(1)
|
||||
| CGU_PLL1_CTRL_DIRECT(1);
|
||||
CGU_PLL1_CTRL = pll_reg;
|
||||
/* wait until stable */
|
||||
while (!(CGU_PLL1_STAT & CGU_PLL1_STAT_LOCK_MASK));
|
||||
|
||||
/* Wait a delay after switch to new frequency with Direct mode */
|
||||
delay(WAIT_CPU_CLOCK_INIT_DELAY);
|
||||
}
|
||||
|
||||
/*
|
||||
Configure PLL1 (Main MCU Clock) to max speed (204MHz).
|
||||
Note: PLL1 clock is used by M4/M0 core, Peripheral, APB1.
|
||||
This function shall be called after cpu_clock_init().
|
||||
*/
|
||||
void cpu_clock_pll1_max_speed(void)
|
||||
{
|
||||
uint32_t pll_reg;
|
||||
|
||||
/* Configure PLL1 to Intermediate Clock (between 90 MHz and 110 MHz) */
|
||||
/* Integer mode:
|
||||
FCLKOUT = M*(FCLKIN/N)
|
||||
FCCO = 2*P*FCLKOUT = 2*P*M*(FCLKIN/N)
|
||||
*/
|
||||
pll_reg = CGU_PLL1_CTRL;
|
||||
/* Clear PLL1 bits */
|
||||
pll_reg &= ~( CGU_PLL1_CTRL_CLK_SEL_MASK | CGU_PLL1_CTRL_PD_MASK | CGU_PLL1_CTRL_FBSEL_MASK | /* CLK SEL, PowerDown , FBSEL */
|
||||
CGU_PLL1_CTRL_BYPASS_MASK | /* BYPASS */
|
||||
CGU_PLL1_CTRL_DIRECT_MASK | /* DIRECT */
|
||||
CGU_PLL1_CTRL_PSEL_MASK | CGU_PLL1_CTRL_MSEL_MASK | CGU_PLL1_CTRL_NSEL_MASK ); /* PSEL, MSEL, NSEL- divider ratios */
|
||||
/* Set PLL1 up to 12MHz * 8 = 96MHz. */
|
||||
pll_reg |= CGU_PLL1_CTRL_CLK_SEL(CGU_SRC_XTAL)
|
||||
| CGU_PLL1_CTRL_PSEL(0)
|
||||
| CGU_PLL1_CTRL_NSEL(0)
|
||||
| CGU_PLL1_CTRL_MSEL(7)
|
||||
| CGU_PLL1_CTRL_FBSEL(1);
|
||||
CGU_PLL1_CTRL = pll_reg;
|
||||
/* wait until stable */
|
||||
while (!(CGU_PLL1_STAT & CGU_PLL1_STAT_LOCK_MASK));
|
||||
|
||||
/* Wait before to switch to max speed */
|
||||
delay(WAIT_CPU_CLOCK_INIT_DELAY);
|
||||
|
||||
/* Configure PLL1 Max Speed */
|
||||
/* Direct mode: FCLKOUT = FCCO = M*(FCLKIN/N) */
|
||||
pll_reg = CGU_PLL1_CTRL;
|
||||
/* Clear PLL1 bits */
|
||||
pll_reg &= ~( CGU_PLL1_CTRL_CLK_SEL_MASK | CGU_PLL1_CTRL_PD_MASK | CGU_PLL1_CTRL_FBSEL_MASK | /* CLK SEL, PowerDown , FBSEL */
|
||||
CGU_PLL1_CTRL_BYPASS_MASK | /* BYPASS */
|
||||
CGU_PLL1_CTRL_DIRECT_MASK | /* DIRECT */
|
||||
CGU_PLL1_CTRL_PSEL_MASK | CGU_PLL1_CTRL_MSEL_MASK | CGU_PLL1_CTRL_NSEL_MASK ); /* PSEL, MSEL, NSEL- divider ratios */
|
||||
/* Set PLL1 up to 12MHz * 17 = 204MHz. */
|
||||
pll_reg |= CGU_PLL1_CTRL_CLK_SEL(CGU_SRC_XTAL)
|
||||
| CGU_PLL1_CTRL_PSEL(0)
|
||||
| CGU_PLL1_CTRL_NSEL(0)
|
||||
| CGU_PLL1_CTRL_MSEL(16)
|
||||
| CGU_PLL1_CTRL_FBSEL(1)
|
||||
| CGU_PLL1_CTRL_DIRECT(1);
|
||||
CGU_PLL1_CTRL = pll_reg;
|
||||
/* wait until stable */
|
||||
while (!(CGU_PLL1_STAT & CGU_PLL1_STAT_LOCK_MASK));
|
||||
|
||||
}
|
||||
|
||||
void ssp1_init(void)
|
||||
{
|
||||
/*
|
||||
@ -487,26 +590,6 @@ void pin_setup(void) {
|
||||
scu_pinmux(SCU_PINMUX_USB_LED0, SCU_CONF_FUNCTION3);
|
||||
scu_pinmux(SCU_PINMUX_USB_LED1, SCU_CONF_FUNCTION3);
|
||||
|
||||
#ifdef HACKRF_ONE
|
||||
/* Configure RF switch control signals */
|
||||
scu_pinmux(SCU_HP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
|
||||
scu_pinmux(SCU_LP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
|
||||
scu_pinmux(SCU_TX_MIX_BP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
|
||||
scu_pinmux(SCU_NO_MIX_BYPASS, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
|
||||
scu_pinmux(SCU_RX_MIX_BP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
|
||||
scu_pinmux(SCU_TX_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
|
||||
scu_pinmux(SCU_TX, SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
|
||||
scu_pinmux(SCU_MIX_BYPASS, SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
|
||||
scu_pinmux(SCU_RX, SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
|
||||
scu_pinmux(SCU_NO_TX_AMP_PWR, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
|
||||
scu_pinmux(SCU_AMP_BYPASS, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
|
||||
scu_pinmux(SCU_RX_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
|
||||
scu_pinmux(SCU_NO_RX_AMP_PWR, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
|
||||
|
||||
/* Configure RF power supply (VAA) switch */
|
||||
scu_pinmux(SCU_NO_VAA_ENABLE, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
|
||||
#endif
|
||||
|
||||
/* Configure all GPIO as Input (safe state) */
|
||||
GPIO0_DIR = 0;
|
||||
GPIO1_DIR = 0;
|
||||
@ -523,27 +606,8 @@ void pin_setup(void) {
|
||||
/* GPIO3[6] on P6_10 as output. */
|
||||
GPIO3_DIR |= PIN_EN1V8;
|
||||
|
||||
#ifdef HACKRF_ONE
|
||||
/* Configure RF switch control signals as outputs */
|
||||
GPIO0_DIR |= PIN_AMP_BYPASS;
|
||||
GPIO1_DIR |= (PIN_NO_MIX_BYPASS | PIN_RX_AMP | PIN_NO_RX_AMP_PWR);
|
||||
GPIO2_DIR |= (PIN_HP | PIN_LP | PIN_TX_MIX_BP | PIN_RX_MIX_BP | PIN_TX_AMP);
|
||||
GPIO3_DIR |= PIN_NO_TX_AMP_PWR;
|
||||
GPIO5_DIR |= (PIN_TX | PIN_MIX_BYPASS | PIN_RX);
|
||||
|
||||
/*
|
||||
* Safe (initial) switch settings turn off both amplifiers and enable both
|
||||
* amp bypass and mixer bypass.
|
||||
*/
|
||||
switchctrl_set(SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_MIX_BYPASS);
|
||||
|
||||
/* Configure RF power supply (VAA) switch control signal as output */
|
||||
GPIO_DIR(PORT_NO_VAA_ENABLE) |= PIN_NO_VAA_ENABLE;
|
||||
|
||||
/* Safe state: start with VAA turned off: */
|
||||
disable_rf_power();
|
||||
#endif
|
||||
|
||||
rf_path_pin_setup();
|
||||
|
||||
/* Configure SSP1 Peripheral (to be moved later in SSP driver) */
|
||||
scu_pinmux(SCU_SSP1_MISO, (SCU_SSP_IO | SCU_CONF_FUNCTION5));
|
||||
scu_pinmux(SCU_SSP1_MOSI, (SCU_SSP_IO | SCU_CONF_FUNCTION5));
|
||||
@ -551,7 +615,9 @@ void pin_setup(void) {
|
||||
scu_pinmux(SCU_SSP1_SSEL, (SCU_SSP_IO | SCU_CONF_FUNCTION1));
|
||||
|
||||
/* Configure external clock in */
|
||||
//scu_pinmux(P4_7, SCU_CLK_IN | SCU_CONF_FUNCTION1);
|
||||
scu_pinmux(SCU_PINMUX_GP_CLKIN, SCU_CLK_IN | SCU_CONF_FUNCTION1);
|
||||
|
||||
sgpio_configure_pin_functions();
|
||||
}
|
||||
|
||||
void enable_1v8_power(void) {
|
||||
@ -570,69 +636,4 @@ void enable_rf_power(void) {
|
||||
void disable_rf_power(void) {
|
||||
gpio_set(PORT_NO_VAA_ENABLE, PIN_NO_VAA_ENABLE);
|
||||
}
|
||||
|
||||
void switchctrl_set(uint8_t ctrl) {
|
||||
if (ctrl & SWITCHCTRL_TX) {
|
||||
gpio_set(PORT_TX, PIN_TX);
|
||||
gpio_clear(PORT_RX, PIN_RX);
|
||||
} else {
|
||||
gpio_clear(PORT_TX, PIN_TX);
|
||||
gpio_set(PORT_RX, PIN_RX);
|
||||
}
|
||||
|
||||
if (ctrl & SWITCHCTRL_MIX_BYPASS) {
|
||||
gpio_set(PORT_MIX_BYPASS, PIN_MIX_BYPASS);
|
||||
gpio_clear(PORT_NO_MIX_BYPASS, PIN_NO_MIX_BYPASS);
|
||||
if (ctrl & SWITCHCTRL_TX) {
|
||||
gpio_set(PORT_TX_MIX_BP, PIN_TX_MIX_BP);
|
||||
gpio_clear(PORT_RX_MIX_BP, PIN_RX_MIX_BP);
|
||||
} else {
|
||||
gpio_clear(PORT_TX_MIX_BP, PIN_TX_MIX_BP);
|
||||
gpio_set(PORT_RX_MIX_BP, PIN_RX_MIX_BP);
|
||||
}
|
||||
} else {
|
||||
gpio_clear(PORT_MIX_BYPASS, PIN_MIX_BYPASS);
|
||||
gpio_set(PORT_NO_MIX_BYPASS, PIN_NO_MIX_BYPASS);
|
||||
gpio_clear(PORT_TX_MIX_BP, PIN_TX_MIX_BP);
|
||||
gpio_clear(PORT_RX_MIX_BP, PIN_RX_MIX_BP);
|
||||
}
|
||||
|
||||
if (ctrl & SWITCHCTRL_HP) {
|
||||
gpio_set(PORT_HP, PIN_HP);
|
||||
gpio_clear(PORT_LP, PIN_LP);
|
||||
} else {
|
||||
gpio_clear(PORT_HP, PIN_HP);
|
||||
gpio_set(PORT_LP, PIN_LP);
|
||||
}
|
||||
|
||||
if (ctrl & SWITCHCTRL_AMP_BYPASS) {
|
||||
gpio_set(PORT_AMP_BYPASS, PIN_AMP_BYPASS);
|
||||
gpio_clear(PORT_TX_AMP, PIN_TX_AMP);
|
||||
gpio_set(PORT_NO_TX_AMP_PWR, PIN_NO_TX_AMP_PWR);
|
||||
gpio_clear(PORT_RX_AMP, PIN_RX_AMP);
|
||||
gpio_set(PORT_NO_RX_AMP_PWR, PIN_NO_RX_AMP_PWR);
|
||||
} else if (ctrl & SWITCHCTRL_TX) {
|
||||
gpio_clear(PORT_AMP_BYPASS, PIN_AMP_BYPASS);
|
||||
gpio_set(PORT_TX_AMP, PIN_TX_AMP);
|
||||
gpio_clear(PORT_NO_TX_AMP_PWR, PIN_NO_TX_AMP_PWR);
|
||||
gpio_clear(PORT_RX_AMP, PIN_RX_AMP);
|
||||
gpio_set(PORT_NO_RX_AMP_PWR, PIN_NO_RX_AMP_PWR);
|
||||
} else {
|
||||
gpio_clear(PORT_AMP_BYPASS, PIN_AMP_BYPASS);
|
||||
gpio_clear(PORT_TX_AMP, PIN_TX_AMP);
|
||||
gpio_set(PORT_NO_TX_AMP_PWR, PIN_NO_TX_AMP_PWR);
|
||||
gpio_set(PORT_RX_AMP, PIN_RX_AMP);
|
||||
gpio_clear(PORT_NO_RX_AMP_PWR, PIN_NO_RX_AMP_PWR);
|
||||
}
|
||||
|
||||
/*
|
||||
* These normally shouldn't be set post-Jawbreaker, but they can be
|
||||
* used to explicitly turn off power to the amplifiers while AMP_BYPASS
|
||||
* is unset:
|
||||
*/
|
||||
if (ctrl & SWITCHCTRL_NO_TX_AMP_PWR)
|
||||
gpio_set(PORT_NO_TX_AMP_PWR, PIN_NO_TX_AMP_PWR);
|
||||
if (ctrl & SWITCHCTRL_NO_RX_AMP_PWR)
|
||||
gpio_set(PORT_NO_RX_AMP_PWR, PIN_NO_RX_AMP_PWR);
|
||||
}
|
||||
#endif
|
||||
|
@ -79,8 +79,13 @@ extern "C"
|
||||
/* CPLD JTAG interface */
|
||||
#define SCU_PINMUX_CPLD_TDO (P9_5) /* GPIO5[18] */
|
||||
#define SCU_PINMUX_CPLD_TCK (P6_1) /* GPIO3[ 0] */
|
||||
#ifdef HACKRF_ONE
|
||||
#define SCU_PINMUX_CPLD_TMS (P6_5) /* GPIO3[ 4] */
|
||||
#define SCU_PINMUX_CPLD_TDI (P6_2) /* GPIO3[ 1] */
|
||||
#else
|
||||
#define SCU_PINMUX_CPLD_TMS (P6_2) /* GPIO3[ 1] */
|
||||
#define SCU_PINMUX_CPLD_TDI (P6_5) /* GPIO3[ 4] */
|
||||
#endif
|
||||
|
||||
/* CPLD SGPIO interface */
|
||||
#define SCU_PINMUX_SGPIO0 (P0_0)
|
||||
@ -173,6 +178,32 @@ extern "C"
|
||||
#define SCU_NO_RX_AMP_PWR (P2_12) /* GPIO1[12] on P2_12 */
|
||||
#endif
|
||||
|
||||
/* TODO add other Pins */
|
||||
#define SCU_PINMUX_GPIO3_8 (P7_0) /* GPIO3[8] */
|
||||
#define SCU_PINMUX_GPIO3_9 (P7_1) /* GPIO3[9] */
|
||||
#define SCU_PINMUX_GPIO3_10 (P7_2) /* GPIO3[10] */
|
||||
#define SCU_PINMUX_GPIO3_11 (P7_3) /* GPIO3[11] */
|
||||
#define SCU_PINMUX_GPIO3_12 (P7_4) /* GPIO3[12] */
|
||||
#define SCU_PINMUX_GPIO3_13 (P7_5) /* GPIO3[13] */
|
||||
#define SCU_PINMUX_GPIO3_14 (P7_6) /* GPIO3[14] */
|
||||
#define SCU_PINMUX_GPIO3_15 (P7_7) /* GPIO3[15] */
|
||||
|
||||
#define SCU_PINMUX_SD_POW (P1_5) /* GPIO1[8] */
|
||||
#define SCU_PINMUX_SD_CMD (P1_6) /* GPIO1[9] */
|
||||
#define SCU_PINMUX_SD_VOLT0 (P1_8) /* GPIO1[1] */
|
||||
#define SCU_PINMUX_SD_DAT0 (P1_9) /* GPIO1[2] */
|
||||
#define SCU_PINMUX_SD_DAT1 (P1_10) /* GPIO1[3] */
|
||||
#define SCU_PINMUX_SD_DAT2 (P1_11) /* GPIO1[4] */
|
||||
#define SCU_PINMUX_SD_DAT3 (P1_12) /* GPIO1[5] */
|
||||
#define SCU_PINMUX_SD_CD (P1_13) /* GPIO1[6] */
|
||||
|
||||
#define SCU_PINMUX_U0_TXD (P2_0) /* GPIO5[0] */
|
||||
#define SCU_PINMUX_U0_RXD (P2_1) /* GPIO5[1] */
|
||||
|
||||
#define SCU_PINMUX_ISP (P2_7) /* GPIO0[7] */
|
||||
|
||||
#define SCU_PINMUX_GP_CLKIN (P4_7)
|
||||
|
||||
/*
|
||||
* GPIO Pins
|
||||
*/
|
||||
@ -286,11 +317,18 @@ extern "C"
|
||||
#define PORT_CPLD_TDO (GPIO5)
|
||||
#define PIN_CPLD_TCK (GPIOPIN0)
|
||||
#define PORT_CPLD_TCK (GPIO3)
|
||||
#ifdef HACKRF_ONE
|
||||
#define PIN_CPLD_TMS (GPIOPIN4)
|
||||
#define PORT_CPLD_TMS (GPIO3)
|
||||
#define PIN_CPLD_TDI (GPIOPIN1)
|
||||
#define PORT_CPLD_TDI (GPIO3)
|
||||
|
||||
#else
|
||||
#define PIN_CPLD_TMS (GPIOPIN1)
|
||||
#define PORT_CPLD_TMS (GPIO3)
|
||||
#define PIN_CPLD_TDI (GPIOPIN4)
|
||||
#define PORT_CPLD_TDI (GPIO3)
|
||||
#endif
|
||||
|
||||
/* Read GPIO Pin */
|
||||
#define GPIO_STATE(port, pin) ((GPIO_PIN(port) & (pin)) == (pin))
|
||||
#define BOOT0_STATE GPIO_STATE(GPIO0, PIN_BOOT0)
|
||||
@ -300,27 +338,7 @@ extern "C"
|
||||
#define MIXER_SDATA_STATE GPIO_STATE(PORT_MIXER_SDATA, PIN_MIXER_SDATA)
|
||||
#define CPLD_TDO_STATE GPIO_STATE(PORT_CPLD_TDO, PIN_CPLD_TDO)
|
||||
|
||||
/*
|
||||
* RF switches on Jawbreaker are controlled by General Purpose Outputs (GPO) on
|
||||
* the RFFC5072.
|
||||
*
|
||||
* On HackRF One, the same signals are controlled by GPIO on the LPC.
|
||||
* SWITCHCTRL_NO_TX_AMP_PWR and SWITCHCTRL_NO_RX_AMP_PWR are not normally used
|
||||
* on HackRF One as the amplifier power is instead controlled only by
|
||||
* SWITCHCTRL_AMP_BYPASS.
|
||||
*/
|
||||
#define SWITCHCTRL_NO_TX_AMP_PWR (1 << 0) /* GPO1 turn off TX amp power */
|
||||
#define SWITCHCTRL_AMP_BYPASS (1 << 1) /* GPO2 bypass amp section */
|
||||
#define SWITCHCTRL_TX (1 << 2) /* GPO3 1 for TX mode, 0 for RX mode */
|
||||
#define SWITCHCTRL_MIX_BYPASS (1 << 3) /* GPO4 bypass RFFC5072 mixer section */
|
||||
#define SWITCHCTRL_HP (1 << 4) /* GPO5 1 for high-pass, 0 for low-pass */
|
||||
#define SWITCHCTRL_NO_RX_AMP_PWR (1 << 5) /* GPO6 turn off RX amp power */
|
||||
|
||||
/*
|
||||
* Safe (initial) switch settings turn off both amplifiers and enable both amp
|
||||
* bypass and mixer bypass.
|
||||
*/
|
||||
#define SWITCHCTRL_SAFE (SWITCHCTRL_NO_TX_AMP_PWR | SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_TX | SWITCHCTRL_MIX_BYPASS | SWITCHCTRL_HP | SWITCHCTRL_NO_RX_AMP_PWR)
|
||||
/* TODO add other Pins */
|
||||
|
||||
typedef enum {
|
||||
TRANSCEIVER_MODE_OFF = 0,
|
||||
@ -331,6 +349,8 @@ typedef enum {
|
||||
void delay(uint32_t duration);
|
||||
|
||||
void cpu_clock_init(void);
|
||||
void cpu_clock_pll1_low_speed(void);
|
||||
void cpu_clock_pll1_max_speed(void);
|
||||
void ssp1_init(void);
|
||||
void ssp1_set_mode_max2837(void);
|
||||
void ssp1_set_mode_max5864(void);
|
||||
@ -347,7 +367,6 @@ bool baseband_filter_bandwidth_set(const uint32_t bandwidth_hz);
|
||||
#ifdef HACKRF_ONE
|
||||
void enable_rf_power(void);
|
||||
void disable_rf_power(void);
|
||||
void switchctrl_set(uint8_t ctrl);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -1,6 +1,4 @@
|
||||
# Hey Emacs, this is a -*- makefile -*-
|
||||
#
|
||||
# Copyright 2013 Benjamin Vernoux <titanmkd@gmail.com>
|
||||
# Copyright 2013 Jared Boone <jared@sharebrained.com>
|
||||
#
|
||||
# This file is part of HackRF.
|
||||
#
|
||||
@ -18,21 +16,8 @@
|
||||
# along with this program; see the file COPYING. If not, write to
|
||||
# the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
# Boston, MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
BINARY = blinky_rom_to_ram
|
||||
|
||||
SRC_DIR = blinky
|
||||
|
||||
SRC = blinky.c \
|
||||
../common/hackrf_core.c \
|
||||
../common/si5351c.c \
|
||||
../common/max2837.c
|
||||
|
||||
LDSCRIPT = ../common/LPC4330_M4_rom_to_ram.ld
|
||||
|
||||
%.o: ../$(SRC_DIR)/%.c Makefile
|
||||
@printf " CC $(subst $(shell pwd)/,,$(@))\n"
|
||||
$(Q)$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
include ../common/Makefile_inc.mk
|
||||
.data
|
||||
.section .m0_bin, "ax"
|
||||
|
||||
.incbin "build/m0/m0.bin"
|
26
firmware/common/m0_sleep.c
Normal file
26
firmware/common/m0_sleep.c
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2013 Jared Boone <jared@sharebrained.com>
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
int main() {
|
||||
while(1) {
|
||||
|
||||
}
|
||||
}
|
@ -116,9 +116,7 @@ void max2837_setup(void)
|
||||
;
|
||||
#endif
|
||||
|
||||
/* disable everything */
|
||||
gpio_clear(PORT_XCVR_ENABLE,
|
||||
(PIN_XCVR_ENABLE | PIN_XCVR_RXENABLE | PIN_XCVR_TXENABLE));
|
||||
max2837_mode_shutdown();
|
||||
#ifdef JELLYBEAN
|
||||
gpio_set(PORT_XCVR_RXHP, PIN_XCVR_RXHP);
|
||||
gpio_set(PORT_XCVR_B,
|
||||
@ -220,14 +218,90 @@ void max2837_regs_commit(void)
|
||||
}
|
||||
}
|
||||
|
||||
void max2837_mode_shutdown(void) {
|
||||
/* All circuit blocks are powered down, except the 4-wire serial bus
|
||||
* and its internal programmable registers.
|
||||
*/
|
||||
gpio_clear(PORT_XCVR_ENABLE,
|
||||
(PIN_XCVR_ENABLE | PIN_XCVR_RXENABLE | PIN_XCVR_TXENABLE));
|
||||
}
|
||||
|
||||
void max2837_mode_standby(void) {
|
||||
/* Used to enable the frequency synthesizer block while the rest of the
|
||||
* device is powered down. In this mode, PLL, VCO, and LO generator
|
||||
* are on, so that Tx or Rx modes can be quickly enabled from this mode.
|
||||
* These and other blocks can be selectively enabled in this mode.
|
||||
*/
|
||||
gpio_clear(PORT_XCVR_ENABLE, (PIN_XCVR_RXENABLE | PIN_XCVR_TXENABLE));
|
||||
gpio_set(PORT_XCVR_ENABLE, PIN_XCVR_ENABLE);
|
||||
}
|
||||
|
||||
void max2837_mode_tx(void) {
|
||||
/* All Tx circuit blocks are powered on. The external PA is powered on
|
||||
* after a programmable delay using the on-chip PA bias DAC. The slow-
|
||||
* charging Rx circuits are in a precharged “idle-off” state for fast
|
||||
* Tx-to-Rx turnaround time.
|
||||
*/
|
||||
gpio_clear(PORT_XCVR_ENABLE, PIN_XCVR_RXENABLE);
|
||||
gpio_set(PORT_XCVR_ENABLE,
|
||||
(PIN_XCVR_ENABLE | PIN_XCVR_TXENABLE));
|
||||
}
|
||||
|
||||
void max2837_mode_rx(void) {
|
||||
/* All Rx circuit blocks are powered on and active. Antenna signal is
|
||||
* applied; RF is downconverted, filtered, and buffered at Rx BB I and Q
|
||||
* outputs. The slow- charging Tx circuits are in a precharged “idle-off”
|
||||
* state for fast Rx-to-Tx turnaround time.
|
||||
*/
|
||||
gpio_clear(PORT_XCVR_ENABLE, PIN_XCVR_TXENABLE);
|
||||
gpio_set(PORT_XCVR_ENABLE,
|
||||
(PIN_XCVR_ENABLE | PIN_XCVR_RXENABLE));
|
||||
}
|
||||
|
||||
max2837_mode_t max2837_mode(void) {
|
||||
if( gpio_get(PORT_XCVR_ENABLE, PIN_XCVR_ENABLE) ) {
|
||||
if( gpio_get(PORT_XCVR_ENABLE, PIN_XCVR_TXENABLE) ) {
|
||||
return MAX2837_MODE_TX;
|
||||
} else if( gpio_get(PORT_XCVR_ENABLE, PIN_XCVR_RXENABLE) ) {
|
||||
return MAX2837_MODE_RX;
|
||||
} else {
|
||||
return MAX2837_MODE_STANDBY;
|
||||
}
|
||||
} else {
|
||||
return MAX2837_MODE_SHUTDOWN;
|
||||
}
|
||||
}
|
||||
|
||||
void max2837_set_mode(const max2837_mode_t new_mode) {
|
||||
switch(new_mode) {
|
||||
case MAX2837_MODE_SHUTDOWN:
|
||||
max2837_mode_shutdown();
|
||||
break;
|
||||
|
||||
case MAX2837_MODE_STANDBY:
|
||||
max2837_mode_standby();
|
||||
break;
|
||||
|
||||
case MAX2837_MODE_TX:
|
||||
max2837_mode_tx();
|
||||
break;
|
||||
|
||||
case MAX2837_MODE_RX:
|
||||
max2837_mode_rx();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void max2837_start(void)
|
||||
{
|
||||
LOG("# max2837_start\n");
|
||||
set_MAX2837_EN_SPI(1);
|
||||
max2837_regs_commit();
|
||||
#if !defined TEST
|
||||
gpio_clear(PORT_XCVR_ENABLE, (PIN_XCVR_RXENABLE | PIN_XCVR_TXENABLE));
|
||||
gpio_set(PORT_XCVR_ENABLE, PIN_XCVR_ENABLE);
|
||||
max2837_mode_standby();
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -238,9 +312,7 @@ void max2837_tx(void)
|
||||
|
||||
set_MAX2837_ModeCtrl(MAX2837_ModeCtrl_TxLPF);
|
||||
max2837_regs_commit();
|
||||
|
||||
gpio_clear(PORT_XCVR_ENABLE, PIN_XCVR_RXENABLE);
|
||||
gpio_set(PORT_XCVR_ENABLE, PIN_XCVR_TXENABLE);
|
||||
max2837_mode_tx();
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -252,8 +324,7 @@ void max2837_rx(void)
|
||||
max2837_regs_commit();
|
||||
|
||||
#if !defined TEST
|
||||
gpio_clear(PORT_XCVR_ENABLE, PIN_XCVR_TXENABLE);
|
||||
gpio_set(PORT_XCVR_ENABLE, PIN_XCVR_RXENABLE);
|
||||
max2837_mode_rx();
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -263,8 +334,7 @@ void max2837_stop(void)
|
||||
set_MAX2837_EN_SPI(0);
|
||||
max2837_regs_commit();
|
||||
#if !defined TEST
|
||||
gpio_clear(PORT_XCVR_ENABLE,
|
||||
(PIN_XCVR_ENABLE | PIN_XCVR_RXENABLE | PIN_XCVR_TXENABLE));
|
||||
max2837_mode_shutdown();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,21 @@ extern void max2837_regs_read(void);
|
||||
* provided routines for those operations. */
|
||||
extern void max2837_regs_commit(void);
|
||||
|
||||
typedef enum {
|
||||
MAX2837_MODE_SHUTDOWN,
|
||||
MAX2837_MODE_STANDBY,
|
||||
MAX2837_MODE_TX,
|
||||
MAX2837_MODE_RX
|
||||
} max2837_mode_t;
|
||||
|
||||
void max2837_mode_shutdown(void);
|
||||
void max2837_mode_standby(void);
|
||||
void max2837_mode_tx(void);
|
||||
void max2837_mode_rx(void);
|
||||
|
||||
max2837_mode_t max2837_mode(void);
|
||||
void max2837_set_mode(const max2837_mode_t new_mode);
|
||||
|
||||
/* Turn on/off all chip functions. Does not control oscillator and CLKOUT */
|
||||
extern void max2837_start(void);
|
||||
extern void max2837_stop(void);
|
||||
|
306
firmware/common/rf_path.c
Normal file
306
firmware/common/rf_path.c
Normal file
@ -0,0 +1,306 @@
|
||||
/*
|
||||
* Copyright 2012 Jared Boone
|
||||
* Copyright 2013 Benjamin Vernoux
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "rf_path.h"
|
||||
|
||||
#include <libopencm3/lpc43xx/gpio.h>
|
||||
#include <libopencm3/lpc43xx/scu.h>
|
||||
|
||||
#include <hackrf_core.h>
|
||||
|
||||
#include <rffc5071.h>
|
||||
#include <max2837.h>
|
||||
#include <max5864.h>
|
||||
#include <sgpio.h>
|
||||
|
||||
#if (defined JAWBREAKER || defined HACKRF_ONE)
|
||||
/*
|
||||
* RF switches on Jawbreaker are controlled by General Purpose Outputs (GPO) on
|
||||
* the RFFC5072.
|
||||
*
|
||||
* On HackRF One, the same signals are controlled by GPIO on the LPC.
|
||||
* SWITCHCTRL_NO_TX_AMP_PWR and SWITCHCTRL_NO_RX_AMP_PWR are not normally used
|
||||
* on HackRF One as the amplifier power is instead controlled only by
|
||||
* SWITCHCTRL_AMP_BYPASS.
|
||||
*/
|
||||
#define SWITCHCTRL_NO_TX_AMP_PWR (1 << 0) /* GPO1 turn off TX amp power */
|
||||
#define SWITCHCTRL_AMP_BYPASS (1 << 1) /* GPO2 bypass amp section */
|
||||
#define SWITCHCTRL_TX (1 << 2) /* GPO3 1 for TX mode, 0 for RX mode */
|
||||
#define SWITCHCTRL_MIX_BYPASS (1 << 3) /* GPO4 bypass RFFC5072 mixer section */
|
||||
#define SWITCHCTRL_HP (1 << 4) /* GPO5 1 for high-pass, 0 for low-pass */
|
||||
#define SWITCHCTRL_NO_RX_AMP_PWR (1 << 5) /* GPO6 turn off RX amp power */
|
||||
|
||||
/*
|
||||
GPO6 GPO5 GPO4 GPO3 GPO2 GPO1
|
||||
!RXAMP HP MIXBP TX AMPBP !TXAMP Mix mode Amp mode
|
||||
1 X 1 1 1 1 TX bypass Bypass
|
||||
1 X 1 1 0 0 TX bypass TX amplified
|
||||
1 1 0 1 1 1 TX high Bypass
|
||||
1 1 0 1 0 0 TX high TX amplified
|
||||
1 0 0 1 1 1 TX low Bypass
|
||||
1 0 0 1 0 0 TX low TX amplified
|
||||
1 X 1 0 1 1 RX bypass Bypass
|
||||
0 X 1 0 0 1 RX bypass RX amplified
|
||||
1 1 0 0 1 1 RX high Bypass
|
||||
0 1 0 0 0 1 RX high RX amplified
|
||||
1 0 0 0 1 1 RX low Bypass
|
||||
0 0 0 0 0 1 RX low RX amplified
|
||||
*/
|
||||
|
||||
/*
|
||||
* Safe (initial) switch settings turn off both amplifiers and enable both amp
|
||||
* bypass and mixer bypass.
|
||||
*/
|
||||
#define SWITCHCTRL_SAFE (SWITCHCTRL_NO_TX_AMP_PWR | SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_TX | SWITCHCTRL_MIX_BYPASS | SWITCHCTRL_HP | SWITCHCTRL_NO_RX_AMP_PWR)
|
||||
#endif
|
||||
|
||||
uint8_t switchctrl = SWITCHCTRL_SAFE;
|
||||
|
||||
#ifdef HACKRF_ONE
|
||||
static void switchctrl_set_hackrf_one(uint8_t ctrl) {
|
||||
if (ctrl & SWITCHCTRL_TX) {
|
||||
gpio_set(PORT_TX, PIN_TX);
|
||||
gpio_clear(PORT_RX, PIN_RX);
|
||||
} else {
|
||||
gpio_clear(PORT_TX, PIN_TX);
|
||||
gpio_set(PORT_RX, PIN_RX);
|
||||
}
|
||||
|
||||
if (ctrl & SWITCHCTRL_MIX_BYPASS) {
|
||||
gpio_set(PORT_MIX_BYPASS, PIN_MIX_BYPASS);
|
||||
gpio_clear(PORT_NO_MIX_BYPASS, PIN_NO_MIX_BYPASS);
|
||||
if (ctrl & SWITCHCTRL_TX) {
|
||||
gpio_set(PORT_TX_MIX_BP, PIN_TX_MIX_BP);
|
||||
gpio_clear(PORT_RX_MIX_BP, PIN_RX_MIX_BP);
|
||||
} else {
|
||||
gpio_clear(PORT_TX_MIX_BP, PIN_TX_MIX_BP);
|
||||
gpio_set(PORT_RX_MIX_BP, PIN_RX_MIX_BP);
|
||||
}
|
||||
} else {
|
||||
gpio_clear(PORT_MIX_BYPASS, PIN_MIX_BYPASS);
|
||||
gpio_set(PORT_NO_MIX_BYPASS, PIN_NO_MIX_BYPASS);
|
||||
gpio_clear(PORT_TX_MIX_BP, PIN_TX_MIX_BP);
|
||||
gpio_clear(PORT_RX_MIX_BP, PIN_RX_MIX_BP);
|
||||
}
|
||||
|
||||
if (ctrl & SWITCHCTRL_HP) {
|
||||
gpio_set(PORT_HP, PIN_HP);
|
||||
gpio_clear(PORT_LP, PIN_LP);
|
||||
} else {
|
||||
gpio_clear(PORT_HP, PIN_HP);
|
||||
gpio_set(PORT_LP, PIN_LP);
|
||||
}
|
||||
|
||||
if (ctrl & SWITCHCTRL_AMP_BYPASS) {
|
||||
gpio_set(PORT_AMP_BYPASS, PIN_AMP_BYPASS);
|
||||
gpio_clear(PORT_TX_AMP, PIN_TX_AMP);
|
||||
gpio_set(PORT_NO_TX_AMP_PWR, PIN_NO_TX_AMP_PWR);
|
||||
gpio_clear(PORT_RX_AMP, PIN_RX_AMP);
|
||||
gpio_set(PORT_NO_RX_AMP_PWR, PIN_NO_RX_AMP_PWR);
|
||||
} else if (ctrl & SWITCHCTRL_TX) {
|
||||
gpio_clear(PORT_AMP_BYPASS, PIN_AMP_BYPASS);
|
||||
gpio_set(PORT_TX_AMP, PIN_TX_AMP);
|
||||
gpio_clear(PORT_NO_TX_AMP_PWR, PIN_NO_TX_AMP_PWR);
|
||||
gpio_clear(PORT_RX_AMP, PIN_RX_AMP);
|
||||
gpio_set(PORT_NO_RX_AMP_PWR, PIN_NO_RX_AMP_PWR);
|
||||
} else {
|
||||
gpio_clear(PORT_AMP_BYPASS, PIN_AMP_BYPASS);
|
||||
gpio_clear(PORT_TX_AMP, PIN_TX_AMP);
|
||||
gpio_set(PORT_NO_TX_AMP_PWR, PIN_NO_TX_AMP_PWR);
|
||||
gpio_set(PORT_RX_AMP, PIN_RX_AMP);
|
||||
gpio_clear(PORT_NO_RX_AMP_PWR, PIN_NO_RX_AMP_PWR);
|
||||
}
|
||||
|
||||
/*
|
||||
* These normally shouldn't be set post-Jawbreaker, but they can be
|
||||
* used to explicitly turn off power to the amplifiers while AMP_BYPASS
|
||||
* is unset:
|
||||
*/
|
||||
if (ctrl & SWITCHCTRL_NO_TX_AMP_PWR)
|
||||
gpio_set(PORT_NO_TX_AMP_PWR, PIN_NO_TX_AMP_PWR);
|
||||
if (ctrl & SWITCHCTRL_NO_RX_AMP_PWR)
|
||||
gpio_set(PORT_NO_RX_AMP_PWR, PIN_NO_RX_AMP_PWR);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void switchctrl_set(const uint8_t gpo) {
|
||||
#ifdef JAWBREAKER
|
||||
rffc5071_set_gpo(gpo);
|
||||
#elif HACKRF_ONE
|
||||
switchctrl_set_hackrf_one(gpo);
|
||||
#else
|
||||
(void)gpo;
|
||||
#endif
|
||||
}
|
||||
|
||||
void rf_path_pin_setup() {
|
||||
#ifdef HACKRF_ONE
|
||||
/* Configure RF switch control signals */
|
||||
scu_pinmux(SCU_HP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
|
||||
scu_pinmux(SCU_LP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
|
||||
scu_pinmux(SCU_TX_MIX_BP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
|
||||
scu_pinmux(SCU_NO_MIX_BYPASS, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
|
||||
scu_pinmux(SCU_RX_MIX_BP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
|
||||
scu_pinmux(SCU_TX_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
|
||||
scu_pinmux(SCU_TX, SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
|
||||
scu_pinmux(SCU_MIX_BYPASS, SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
|
||||
scu_pinmux(SCU_RX, SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
|
||||
scu_pinmux(SCU_NO_TX_AMP_PWR, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
|
||||
scu_pinmux(SCU_AMP_BYPASS, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
|
||||
scu_pinmux(SCU_RX_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
|
||||
scu_pinmux(SCU_NO_RX_AMP_PWR, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
|
||||
|
||||
/* Configure RF power supply (VAA) switch */
|
||||
scu_pinmux(SCU_NO_VAA_ENABLE, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
|
||||
|
||||
/* Configure RF switch control signals as outputs */
|
||||
GPIO0_DIR |= PIN_AMP_BYPASS;
|
||||
GPIO1_DIR |= (PIN_NO_MIX_BYPASS | PIN_RX_AMP | PIN_NO_RX_AMP_PWR);
|
||||
GPIO2_DIR |= (PIN_HP | PIN_LP | PIN_TX_MIX_BP | PIN_RX_MIX_BP | PIN_TX_AMP);
|
||||
GPIO3_DIR |= PIN_NO_TX_AMP_PWR;
|
||||
GPIO5_DIR |= (PIN_TX | PIN_MIX_BYPASS | PIN_RX);
|
||||
|
||||
/*
|
||||
* Safe (initial) switch settings turn off both amplifiers and enable both
|
||||
* amp bypass and mixer bypass.
|
||||
*/
|
||||
switchctrl_set(SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_MIX_BYPASS);
|
||||
|
||||
/* Configure RF power supply (VAA) switch control signal as output */
|
||||
GPIO_DIR(PORT_NO_VAA_ENABLE) |= PIN_NO_VAA_ENABLE;
|
||||
|
||||
/* Safe state: start with VAA turned off: */
|
||||
disable_rf_power();
|
||||
#endif
|
||||
}
|
||||
|
||||
void rf_path_init(void) {
|
||||
ssp1_set_mode_max5864();
|
||||
max5864_shutdown();
|
||||
|
||||
ssp1_set_mode_max2837();
|
||||
max2837_setup();
|
||||
max2837_start();
|
||||
|
||||
rffc5071_setup();
|
||||
switchctrl_set(switchctrl);
|
||||
}
|
||||
|
||||
void rf_path_set_direction(const rf_path_direction_t direction) {
|
||||
/* Turn off TX and RX amplifiers, then enable based on direction and bypass state. */
|
||||
switchctrl |= SWITCHCTRL_NO_TX_AMP_PWR | SWITCHCTRL_NO_RX_AMP_PWR;
|
||||
switch(direction) {
|
||||
case RF_PATH_DIRECTION_TX:
|
||||
switchctrl |= SWITCHCTRL_TX;
|
||||
if( (switchctrl & SWITCHCTRL_AMP_BYPASS) == 0 ) {
|
||||
/* TX amplifier is in path, be sure to enable TX amplifier. */
|
||||
switchctrl &= ~SWITCHCTRL_NO_TX_AMP_PWR;
|
||||
}
|
||||
rffc5071_tx();
|
||||
if( switchctrl & SWITCHCTRL_MIX_BYPASS ) {
|
||||
rffc5071_disable();
|
||||
} else {
|
||||
rffc5071_enable();
|
||||
}
|
||||
ssp1_set_mode_max5864();
|
||||
max5864_tx();
|
||||
ssp1_set_mode_max2837();
|
||||
max2837_tx();
|
||||
sgpio_configure(SGPIO_DIRECTION_TX);
|
||||
break;
|
||||
|
||||
case RF_PATH_DIRECTION_RX:
|
||||
switchctrl &= ~SWITCHCTRL_TX;
|
||||
if( (switchctrl & SWITCHCTRL_AMP_BYPASS) == 0 ) {
|
||||
/* RX amplifier is in path, be sure to enable RX amplifier. */
|
||||
switchctrl &= ~SWITCHCTRL_NO_RX_AMP_PWR;
|
||||
}
|
||||
rffc5071_rx();
|
||||
if( switchctrl & SWITCHCTRL_MIX_BYPASS ) {
|
||||
rffc5071_disable();
|
||||
} else {
|
||||
rffc5071_enable();
|
||||
}
|
||||
ssp1_set_mode_max5864();
|
||||
max5864_rx();
|
||||
ssp1_set_mode_max2837();
|
||||
max2837_rx();
|
||||
sgpio_configure(SGPIO_DIRECTION_RX);
|
||||
break;
|
||||
|
||||
case RF_PATH_DIRECTION_OFF:
|
||||
default:
|
||||
/* Set RF path to receive direction when "off" */
|
||||
switchctrl &= ~SWITCHCTRL_TX;
|
||||
rffc5071_disable();
|
||||
ssp1_set_mode_max5864();
|
||||
max5864_standby();
|
||||
ssp1_set_mode_max2837();
|
||||
max2837_set_mode(MAX2837_MODE_STANDBY);
|
||||
sgpio_configure(SGPIO_DIRECTION_RX);
|
||||
break;
|
||||
}
|
||||
|
||||
switchctrl_set(switchctrl);
|
||||
}
|
||||
|
||||
void rf_path_set_filter(const rf_path_filter_t filter) {
|
||||
switch(filter) {
|
||||
default:
|
||||
case RF_PATH_FILTER_BYPASS:
|
||||
switchctrl |= SWITCHCTRL_MIX_BYPASS;
|
||||
rffc5071_disable();
|
||||
break;
|
||||
|
||||
case RF_PATH_FILTER_LOW_PASS:
|
||||
switchctrl &= ~(SWITCHCTRL_HP | SWITCHCTRL_MIX_BYPASS);
|
||||
rffc5071_enable();
|
||||
break;
|
||||
|
||||
case RF_PATH_FILTER_HIGH_PASS:
|
||||
switchctrl &= ~SWITCHCTRL_MIX_BYPASS;
|
||||
switchctrl |= SWITCHCTRL_HP;
|
||||
rffc5071_enable();
|
||||
break;
|
||||
}
|
||||
|
||||
switchctrl_set(switchctrl);
|
||||
}
|
||||
|
||||
void rf_path_set_lna(const uint_fast8_t enable) {
|
||||
if( enable ) {
|
||||
if( switchctrl & SWITCHCTRL_TX ) {
|
||||
/* AMP_BYPASS=0, NO_RX_AMP_PWR=1, NO_TX_AMP_PWR=0 */
|
||||
switchctrl |= SWITCHCTRL_NO_RX_AMP_PWR;
|
||||
switchctrl &= ~(SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_NO_TX_AMP_PWR);
|
||||
} else {
|
||||
/* AMP_BYPASS=0, NO_RX_AMP_PWR=0, NO_TX_AMP_PWR=1 */
|
||||
switchctrl |= SWITCHCTRL_NO_TX_AMP_PWR;
|
||||
switchctrl &= ~(SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_NO_RX_AMP_PWR);
|
||||
}
|
||||
} else {
|
||||
/* AMP_BYPASS=1, NO_RX_AMP_PWR=1, NO_TX_AMP_PWR=1 */
|
||||
switchctrl |= SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_NO_TX_AMP_PWR | SWITCHCTRL_NO_RX_AMP_PWR;
|
||||
}
|
||||
|
||||
switchctrl_set(switchctrl);
|
||||
}
|
49
firmware/common/rf_path.h
Normal file
49
firmware/common/rf_path.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2012 Jared Boone
|
||||
* Copyright 2013 Benjamin Vernoux
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __RFPATH_H__
|
||||
#define __RFPATH_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void rf_path_pin_setup(void);
|
||||
void rf_path_init(void);
|
||||
|
||||
typedef enum {
|
||||
RF_PATH_DIRECTION_OFF,
|
||||
RF_PATH_DIRECTION_RX,
|
||||
RF_PATH_DIRECTION_TX,
|
||||
} rf_path_direction_t;
|
||||
|
||||
void rf_path_set_direction(const rf_path_direction_t direction);
|
||||
|
||||
typedef enum {
|
||||
RF_PATH_FILTER_BYPASS,
|
||||
RF_PATH_FILTER_LOW_PASS,
|
||||
RF_PATH_FILTER_HIGH_PASS,
|
||||
} rf_path_filter_t;
|
||||
|
||||
void rf_path_set_filter(const rf_path_filter_t filter);
|
||||
|
||||
void rf_path_set_lna(const uint_fast8_t enable);
|
||||
|
||||
#endif/*__RFPATH_H__*/
|
@ -145,11 +145,6 @@ void rffc5071_setup(void)
|
||||
* not control pins. */
|
||||
set_RFFC5071_SIPIN(1);
|
||||
|
||||
#ifdef JAWBREAKER
|
||||
/* initial safe switch control settings */
|
||||
rffc5071_set_gpo(SWITCHCTRL_SAFE);
|
||||
#endif
|
||||
|
||||
/* GPOs are active at all times */
|
||||
set_RFFC5071_GATE(1);
|
||||
|
||||
@ -367,60 +362,20 @@ void rffc5071_regs_commit(void)
|
||||
}
|
||||
}
|
||||
|
||||
void rffc5071_tx(uint8_t gpo) {
|
||||
void rffc5071_tx(void) {
|
||||
LOG("# rffc5071_tx\n");
|
||||
set_RFFC5071_ENBL(0);
|
||||
set_RFFC5071_FULLD(0);
|
||||
set_RFFC5071_MODE(1); /* mixer 2 used for both RX and TX */
|
||||
/* honor SWITCHCTRL_AMP_BYPASS and SWITCHCTRL_HP settings from caller */
|
||||
gpo &= (SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_HP | SWITCHCTRL_MIX_BYPASS);
|
||||
if ((gpo & SWITCHCTRL_AMP_BYPASS) == SWITCHCTRL_AMP_BYPASS)
|
||||
gpo |= SWITCHCTRL_NO_TX_AMP_PWR;
|
||||
gpo |= (SWITCHCTRL_TX | SWITCHCTRL_NO_RX_AMP_PWR);
|
||||
#ifdef JAWBREAKER
|
||||
rffc5071_set_gpo(gpo);
|
||||
#elif HACKRF_ONE
|
||||
switchctrl_set(gpo);
|
||||
#else
|
||||
(void)gpo;
|
||||
#endif
|
||||
rffc5071_regs_commit();
|
||||
|
||||
#if (defined JAWBREAKER || defined HACKRF_ONE)
|
||||
/* honor SWITCHCTRL_MIX_BYPASS setting from caller */
|
||||
if ((gpo & SWITCHCTRL_MIX_BYPASS) == SWITCHCTRL_MIX_BYPASS)
|
||||
rffc5071_disable();
|
||||
else
|
||||
#endif
|
||||
rffc5071_enable();
|
||||
}
|
||||
|
||||
void rffc5071_rx(uint8_t gpo) {
|
||||
void rffc5071_rx(void) {
|
||||
LOG("# rfc5071_rx\n");
|
||||
set_RFFC5071_ENBL(0);
|
||||
set_RFFC5071_FULLD(0);
|
||||
set_RFFC5071_MODE(1); /* mixer 2 used for both RX and TX */
|
||||
/* honor SWITCHCTRL_AMP_BYPASS and SWITCHCTRL_HP settings from caller */
|
||||
gpo &= (SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_HP | SWITCHCTRL_MIX_BYPASS);
|
||||
if ((gpo & SWITCHCTRL_AMP_BYPASS) == SWITCHCTRL_AMP_BYPASS)
|
||||
gpo |= SWITCHCTRL_NO_RX_AMP_PWR;
|
||||
gpo |= SWITCHCTRL_NO_TX_AMP_PWR;
|
||||
#ifdef JAWBREAKER
|
||||
rffc5071_set_gpo(gpo);
|
||||
#elif HACKRF_ONE
|
||||
switchctrl_set(gpo);
|
||||
#else
|
||||
(void)gpo;
|
||||
#endif
|
||||
rffc5071_regs_commit();
|
||||
|
||||
#if (defined JAWBREAKER || defined HACKRF_ONE)
|
||||
/* honor SWITCHCTRL_MIX_BYPASS setting from caller */
|
||||
if ((gpo & SWITCHCTRL_MIX_BYPASS) == SWITCHCTRL_MIX_BYPASS)
|
||||
rffc5071_disable();
|
||||
else
|
||||
#endif
|
||||
rffc5071_enable();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -53,8 +53,8 @@ extern uint32_t rffc5071_set_frequency(uint16_t mhz);
|
||||
|
||||
/* Set up rx only, tx only, or full duplex. Chip should be disabled
|
||||
* before _tx, _rx, or _rxtx are called. */
|
||||
extern void rffc5071_tx(uint8_t);
|
||||
extern void rffc5071_rx(uint8_t);
|
||||
extern void rffc5071_tx(void);
|
||||
extern void rffc5071_rx(void);
|
||||
extern void rffc5071_rxtx(void);
|
||||
extern void rffc5071_enable(void);
|
||||
extern void rffc5071_disable(void);
|
||||
|
@ -20,11 +20,16 @@
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <libopencm3/lpc43xx/gpio.h>
|
||||
#include <libopencm3/lpc43xx/scu.h>
|
||||
#include <libopencm3/lpc43xx/sgpio.h>
|
||||
|
||||
#include <hackrf_core.h>
|
||||
|
||||
#include <sgpio.h>
|
||||
|
||||
static bool sgpio_slice_mode_multislice = true;
|
||||
|
||||
void sgpio_configure_pin_functions() {
|
||||
scu_pinmux(SCU_PINMUX_SGPIO0, SCU_GPIO_FAST | SCU_CONF_FUNCTION3);
|
||||
scu_pinmux(SCU_PINMUX_SGPIO1, SCU_GPIO_FAST | SCU_CONF_FUNCTION3);
|
||||
@ -39,9 +44,13 @@ void sgpio_configure_pin_functions() {
|
||||
scu_pinmux(SCU_PINMUX_SGPIO10, SCU_GPIO_FAST | SCU_CONF_FUNCTION6);
|
||||
scu_pinmux(SCU_PINMUX_SGPIO11, SCU_GPIO_FAST | SCU_CONF_FUNCTION6);
|
||||
scu_pinmux(SCU_PINMUX_SGPIO12, SCU_GPIO_FAST | SCU_CONF_FUNCTION6);
|
||||
scu_pinmux(SCU_PINMUX_SGPIO13, SCU_GPIO_FAST | SCU_CONF_FUNCTION7);
|
||||
scu_pinmux(SCU_PINMUX_SGPIO14, SCU_GPIO_FAST | SCU_CONF_FUNCTION7);
|
||||
scu_pinmux(SCU_PINMUX_SGPIO15, SCU_GPIO_FAST | SCU_CONF_FUNCTION7);
|
||||
scu_pinmux(SCU_PINMUX_SGPIO13, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); /* GPIO5[12] */
|
||||
scu_pinmux(SCU_PINMUX_SGPIO14, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); /* GPIO5[13] */
|
||||
scu_pinmux(SCU_PINMUX_SGPIO15, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); /* GPIO5[14] */
|
||||
|
||||
sgpio_cpld_stream_rx_set_decimation(0);
|
||||
|
||||
GPIO_DIR(GPIO5) |= GPIOPIN14 | GPIOPIN13 | GPIOPIN12;
|
||||
}
|
||||
|
||||
|
||||
@ -56,8 +65,6 @@ void sgpio_test_interface() {
|
||||
// Disable all counters during configuration
|
||||
SGPIO_CTRL_ENABLE = 0;
|
||||
|
||||
sgpio_configure_pin_functions();
|
||||
|
||||
// Make all SGPIO controlled by SGPIO's "GPIO" registers
|
||||
for (uint_fast8_t i = 0; i < 16; i++) {
|
||||
SGPIO_OUT_MUX_CFG(i) =
|
||||
@ -90,6 +97,11 @@ void sgpio_test_interface() {
|
||||
}
|
||||
}
|
||||
|
||||
void sgpio_set_slice_mode(
|
||||
const bool multi_slice
|
||||
) {
|
||||
sgpio_slice_mode_multislice = multi_slice;
|
||||
}
|
||||
|
||||
/*
|
||||
SGPIO0 to 7 = DAC/ADC data bits 0 to 7 (Nota: DAC is 10bits but only bit9 to bit2 are used bit1 & 0 are forced to 0 by CPLD)
|
||||
@ -104,17 +116,14 @@ void sgpio_test_interface() {
|
||||
SGPIO11 Direction Output (1/High=TX mode LPC43xx=>CPLD=>DAC, 0/Low=RX mode LPC43xx<=CPLD<=ADC)
|
||||
*/
|
||||
void sgpio_configure(
|
||||
const transceiver_mode_t transceiver_mode,
|
||||
const bool multi_slice
|
||||
const sgpio_direction_t direction
|
||||
) {
|
||||
// Disable all counters during configuration
|
||||
SGPIO_CTRL_ENABLE = 0;
|
||||
|
||||
sgpio_configure_pin_functions();
|
||||
|
||||
// Set SGPIO output values.
|
||||
const uint_fast8_t cpld_direction =
|
||||
(transceiver_mode == TRANSCEIVER_MODE_TX) ? 1 : 0;
|
||||
(direction == SGPIO_DIRECTION_TX) ? 1 : 0;
|
||||
SGPIO_GPIO_OUTREG =
|
||||
(cpld_direction << 11) /* 1=Output SGPIO11 High(TX mode), 0=Output SGPIO11 Low(RX mode)*/
|
||||
| (1L << 10) // disable codec data stream during configuration (Output SGPIO10 High)
|
||||
@ -122,11 +131,12 @@ void sgpio_configure(
|
||||
|
||||
// Enable SGPIO pin outputs.
|
||||
const uint_fast16_t sgpio_gpio_data_direction =
|
||||
(transceiver_mode == TRANSCEIVER_MODE_TX)
|
||||
(direction == SGPIO_DIRECTION_TX)
|
||||
? (0xFF << 0)
|
||||
: (0x00 << 0);
|
||||
SGPIO_GPIO_OENREG =
|
||||
(1L << 11) // direction output SGPIO11 active
|
||||
(1L << 14) // GPDMA burst request SGPIO14 active
|
||||
| (1L << 11) // direction output SGPIO11 active
|
||||
| (1L << 10) // disable output SGPIO10 active
|
||||
| (0L << 9) // capture input SGPIO9 (output i is tri-stated)
|
||||
| (0L << 8) // clock input SGPIO8 (output i is tri-stated)
|
||||
@ -149,9 +159,13 @@ void sgpio_configure(
|
||||
SGPIO_OUT_MUX_CFG_P_OE_CFG(0) /* 0x0 gpio_oe (state set by GPIO_OEREG) */
|
||||
| SGPIO_OUT_MUX_CFG_P_OUT_CFG(4) /* 0x4=gpio_out (level set by GPIO_OUTREG) */
|
||||
;
|
||||
SGPIO_OUT_MUX_CFG(14) = // SGPIO14: Output: internal GPDMA burst request
|
||||
SGPIO_OUT_MUX_CFG_P_OE_CFG(0) /* 0x4 dout_oem1 (1-bit mode) */
|
||||
| SGPIO_OUT_MUX_CFG_P_OUT_CFG(0) /* 0x0 dout_doutm1 (1-bit mode) */
|
||||
;
|
||||
|
||||
const uint_fast8_t output_multiplexing_mode =
|
||||
multi_slice ? 11 : 9;
|
||||
sgpio_slice_mode_multislice ? 11 : 9;
|
||||
/* SGPIO0 to SGPIO7 */
|
||||
for(uint_fast8_t i=0; i<8; i++) {
|
||||
// SGPIO pin 0 outputs slice A bit "i".
|
||||
@ -171,20 +185,21 @@ void sgpio_configure(
|
||||
SGPIO_SLICE_F,
|
||||
SGPIO_SLICE_L,
|
||||
};
|
||||
const uint_fast8_t slice_gpdma = SGPIO_SLICE_H;
|
||||
|
||||
const uint_fast8_t pos = multi_slice ? 0x1f : 0x03;
|
||||
const bool single_slice = !multi_slice;
|
||||
const uint_fast8_t slice_count = multi_slice ? 8 : 1;
|
||||
const uint_fast8_t pos = sgpio_slice_mode_multislice ? 0x1f : 0x03;
|
||||
const bool single_slice = !sgpio_slice_mode_multislice;
|
||||
const uint_fast8_t slice_count = sgpio_slice_mode_multislice ? 8 : 1;
|
||||
const uint_fast8_t clk_capture_mode = (direction == SGPIO_DIRECTION_TX) ? 0 : 1;
|
||||
|
||||
uint32_t slice_enable_mask = 0;
|
||||
/* Configure Slice A, I, E, J, C, K, F, L (multi_slice mode) */
|
||||
/* Configure Slice A, I, E, J, C, K, F, L (sgpio_slice_mode_multislice mode) */
|
||||
for(uint_fast8_t i=0; i<slice_count; i++)
|
||||
{
|
||||
const uint_fast8_t slice_index = slice_indices[i];
|
||||
const bool input_slice = (i == 0) && (transceiver_mode == TRANSCEIVER_MODE_RX); /* Only for slice0/A and RX mode set input_slice to 1 */
|
||||
const bool input_slice = (i == 0) && (direction != SGPIO_DIRECTION_TX); /* Only for slice0/A and RX mode set input_slice to 1 */
|
||||
const uint_fast8_t concat_order = (input_slice || single_slice) ? 0 : 3; /* 0x0=Self-loop(slice0/A RX mode), 0x3=8 slices */
|
||||
const uint_fast8_t concat_enable = (input_slice || single_slice) ? 0 : 1; /* 0x0=External data pin(slice0/A RX mode), 0x1=Concatenate data */
|
||||
const uint_fast8_t clk_capture_mode = (transceiver_mode == TRANSCEIVER_MODE_RX) ? 1 : 0;
|
||||
|
||||
SGPIO_MUX_CFG(slice_index) =
|
||||
SGPIO_MUX_CFG_CONCAT_ORDER(concat_order)
|
||||
@ -213,12 +228,46 @@ void sgpio_configure(
|
||||
SGPIO_POS_POS_RESET(pos)
|
||||
| SGPIO_POS_POS(pos)
|
||||
;
|
||||
SGPIO_REG(slice_index) = 0x80808080; // Primary output data register
|
||||
SGPIO_REG_SS(slice_index) = 0x80808080; // Shadow output data register
|
||||
SGPIO_REG(slice_index) = 0x00000000; // Primary output data register
|
||||
SGPIO_REG_SS(slice_index) = 0x00000000; // Shadow output data register
|
||||
|
||||
slice_enable_mask |= (1 << slice_index);
|
||||
}
|
||||
|
||||
|
||||
if( sgpio_slice_mode_multislice == false ) {
|
||||
SGPIO_MUX_CFG(slice_gpdma) =
|
||||
SGPIO_MUX_CFG_CONCAT_ORDER(0) /* Self-loop */
|
||||
| SGPIO_MUX_CFG_CONCAT_ENABLE(1)
|
||||
| SGPIO_MUX_CFG_QUALIFIER_SLICE_MODE(0) /* Select qualifier slice A(0x0) */
|
||||
| SGPIO_MUX_CFG_QUALIFIER_PIN_MODE(1) /* Select qualifier pin SGPIO9(0x1) */
|
||||
| SGPIO_MUX_CFG_QUALIFIER_MODE(3) /* External SGPIO */
|
||||
| SGPIO_MUX_CFG_CLK_SOURCE_SLICE_MODE(0) /* Select clock source slice D(0x0) */
|
||||
| SGPIO_MUX_CFG_CLK_SOURCE_PIN_MODE(0) /* Source Clock Pin 0x0 = SGPIO8 */
|
||||
| SGPIO_MUX_CFG_EXT_CLK_ENABLE(1) /* External clock signal(pin) selected */
|
||||
;
|
||||
|
||||
SGPIO_SLICE_MUX_CFG(slice_gpdma) =
|
||||
SGPIO_SLICE_MUX_CFG_INV_QUALIFIER(0) /* 0x0=Use normal qualifier. */
|
||||
| SGPIO_SLICE_MUX_CFG_PARALLEL_MODE(0) /* 0x0=Shift 1 bit per clock. */
|
||||
| SGPIO_SLICE_MUX_CFG_DATA_CAPTURE_MODE(0) /* 0x0=Detect rising edge. (Condition for input bit match interrupt) */
|
||||
| SGPIO_SLICE_MUX_CFG_INV_OUT_CLK(0) /* 0x0=Normal clock. */
|
||||
| SGPIO_SLICE_MUX_CFG_CLKGEN_MODE(1) /* 0x1=Use external clock from a pin or other slice */
|
||||
| SGPIO_SLICE_MUX_CFG_CLK_CAPTURE_MODE(clk_capture_mode) /* 0x0=Use rising clock edge, 0x1=Use falling clock edge */
|
||||
| SGPIO_SLICE_MUX_CFG_MATCH_MODE(0) /* 0x0=Do not match data */
|
||||
;
|
||||
|
||||
SGPIO_PRESET(slice_gpdma) = 0; // External clock, don't care
|
||||
SGPIO_COUNT(slice_gpdma) = 0; // External clock, don't care
|
||||
SGPIO_POS(slice_gpdma) =
|
||||
SGPIO_POS_POS_RESET(0x1f)
|
||||
| SGPIO_POS_POS(0x1f)
|
||||
;
|
||||
SGPIO_REG(slice_gpdma) = 0x11111111; // Primary output data register, LSB -> out
|
||||
SGPIO_REG_SS(slice_gpdma) = 0x11111111; // Shadow output data register, LSB -> out1
|
||||
|
||||
slice_enable_mask |= (1 << slice_gpdma);
|
||||
}
|
||||
|
||||
// Start SGPIO operation by enabling slice clocks.
|
||||
SGPIO_CTRL_ENABLE = slice_enable_mask;
|
||||
}
|
||||
@ -236,3 +285,17 @@ void sgpio_cpld_stream_disable() {
|
||||
bool sgpio_cpld_stream_is_enabled() {
|
||||
return (SGPIO_GPIO_OUTREG & (1L << 10)) == 0; /* SGPIO10 */
|
||||
}
|
||||
|
||||
bool sgpio_cpld_stream_rx_set_decimation(const uint_fast8_t skip_n) {
|
||||
/* CPLD interface is three bits, SGPIO[15:13]:
|
||||
* 111: decimate by 1 (skip_n=0, skip no samples)
|
||||
* 110: decimate by 2 (skip_n=1, skip every other sample)
|
||||
* 101: decimate by 3 (skip_n=2, skip two of three samples)
|
||||
* ...
|
||||
* 000: decimate by 8 (skip_n=7, skip seven of eight samples)
|
||||
*/
|
||||
GPIO_SET(GPIO5) = GPIOPIN14 | GPIOPIN13 | GPIOPIN12;
|
||||
GPIO_CLR(GPIO5) = (skip_n & 7) << 12;
|
||||
|
||||
return (skip_n < 8);
|
||||
}
|
||||
|
@ -24,14 +24,23 @@
|
||||
|
||||
#include <hackrf_core.h>
|
||||
|
||||
typedef enum {
|
||||
SGPIO_DIRECTION_RX,
|
||||
SGPIO_DIRECTION_TX,
|
||||
} sgpio_direction_t;
|
||||
|
||||
void sgpio_configure_pin_functions();
|
||||
void sgpio_test_interface();
|
||||
void sgpio_configure(
|
||||
const transceiver_mode_t transceiver_mode,
|
||||
void sgpio_set_slice_mode(
|
||||
const bool multi_slice
|
||||
);
|
||||
void sgpio_configure(
|
||||
const sgpio_direction_t direction
|
||||
);
|
||||
void sgpio_cpld_stream_enable();
|
||||
void sgpio_cpld_stream_disable();
|
||||
bool sgpio_cpld_stream_is_enabled();
|
||||
|
||||
bool sgpio_cpld_stream_rx_set_decimation(const uint_fast8_t skip_n);
|
||||
|
||||
#endif//__SGPIO_H__
|
||||
|
142
firmware/common/sgpio_dma.c
Normal file
142
firmware/common/sgpio_dma.c
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright 2013 Jared Boone <jared@sharebrained.com>
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <sgpio_dma.h>
|
||||
|
||||
#include <libopencm3/lpc43xx/creg.h>
|
||||
#include <libopencm3/lpc43xx/gpdma.h>
|
||||
#include <libopencm3/lpc43xx/scu.h>
|
||||
#include <libopencm3/lpc43xx/sgpio.h>
|
||||
|
||||
#include <sgpio.h>
|
||||
#include <gpdma.h>
|
||||
|
||||
void sgpio_dma_configure_lli(
|
||||
gpdma_lli_t* const lli,
|
||||
const size_t lli_count,
|
||||
const bool direction_transmit,
|
||||
void* const buffer,
|
||||
const size_t transfer_bytes
|
||||
) {
|
||||
const size_t bytes_per_word = 4;
|
||||
const size_t transfer_words = (transfer_bytes + bytes_per_word - 1) / bytes_per_word;
|
||||
|
||||
gpdma_lli_create_loop(lli, lli_count);
|
||||
|
||||
for(size_t i=0; i<lli_count; i++) {
|
||||
void* const peripheral_address = (void*)&SGPIO_REG_SS(0);
|
||||
void* const memory_address = buffer + (transfer_words * bytes_per_word * i);
|
||||
|
||||
const uint_fast8_t source_master = direction_transmit ? 1 : 0;
|
||||
const uint_fast8_t destination_master = direction_transmit ? 0 : 1;
|
||||
const uint_fast8_t lli_fetch_master = direction_transmit ? 0 : 1;
|
||||
|
||||
lli[i].csrcaddr = direction_transmit ? memory_address : peripheral_address;
|
||||
lli[i].cdestaddr = direction_transmit ? peripheral_address : memory_address;
|
||||
lli[i].clli = (lli[i].clli & ~GPDMA_CLLI_LM_MASK) | GPDMA_CLLI_LM(lli_fetch_master);
|
||||
lli[i].ccontrol =
|
||||
GPDMA_CCONTROL_TRANSFERSIZE(transfer_words) |
|
||||
GPDMA_CCONTROL_SBSIZE(0) |
|
||||
GPDMA_CCONTROL_DBSIZE(0) |
|
||||
GPDMA_CCONTROL_SWIDTH(2) |
|
||||
GPDMA_CCONTROL_DWIDTH(2) |
|
||||
GPDMA_CCONTROL_S(source_master) |
|
||||
GPDMA_CCONTROL_D(destination_master) |
|
||||
GPDMA_CCONTROL_SI(direction_transmit ? 1 : 0) |
|
||||
GPDMA_CCONTROL_DI(direction_transmit ? 0 : 1) |
|
||||
GPDMA_CCONTROL_PROT1(0) |
|
||||
GPDMA_CCONTROL_PROT2(0) |
|
||||
GPDMA_CCONTROL_PROT3(0) |
|
||||
GPDMA_CCONTROL_I(0)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
static void sgpio_dma_enable(const uint_fast8_t channel, const gpdma_lli_t* const lli, const bool direction_transmit) {
|
||||
gpdma_channel_disable(channel);
|
||||
gpdma_channel_interrupt_tc_clear(channel);
|
||||
gpdma_channel_interrupt_error_clear(channel);
|
||||
|
||||
GPDMA_CSRCADDR(channel) = (uint32_t)lli->csrcaddr;
|
||||
GPDMA_CDESTADDR(channel) = (uint32_t)lli->cdestaddr;
|
||||
GPDMA_CLLI(channel) = (uint32_t)lli->clli;
|
||||
GPDMA_CCONTROL(channel) = lli->ccontrol;
|
||||
|
||||
/* 1: Memory -> Peripheral
|
||||
* 2: Peripheral -> Memory */
|
||||
const uint_fast8_t flowcntrl = direction_transmit ? 1 : 2;
|
||||
|
||||
GPDMA_CCONFIG(channel) =
|
||||
GPDMA_CCONFIG_E(0) |
|
||||
GPDMA_CCONFIG_SRCPERIPHERAL(0) |
|
||||
GPDMA_CCONFIG_DESTPERIPHERAL(0) |
|
||||
GPDMA_CCONFIG_FLOWCNTRL(flowcntrl) |
|
||||
GPDMA_CCONFIG_IE(1) |
|
||||
GPDMA_CCONFIG_ITC(1) |
|
||||
GPDMA_CCONFIG_L(0) |
|
||||
GPDMA_CCONFIG_H(0)
|
||||
;
|
||||
|
||||
gpdma_channel_enable(channel);
|
||||
}
|
||||
|
||||
void sgpio_dma_init() {
|
||||
/* DMA peripheral/source 0, option 2 (SGPIO14) -- BREQ */
|
||||
CREG_DMAMUX &= ~(CREG_DMAMUX_DMAMUXPER0_MASK);
|
||||
CREG_DMAMUX |= CREG_DMAMUX_DMAMUXPER0(0x2);
|
||||
|
||||
// Disable sync, maybe it is causing max speed (10MT/sec) glitches?
|
||||
//GPDMA_DMACSYNC = (1 << 0);
|
||||
//GPDMA_SYNC = GPDMA_SYNC_DMACSYNC(0xFFFF); // TODO: Don't do this, I'm just going nuts here.
|
||||
|
||||
gpdma_controller_enable();
|
||||
}
|
||||
|
||||
static const uint_fast8_t dma_channel_sgpio = 0;
|
||||
|
||||
void sgpio_dma_rx_start(const gpdma_lli_t* const start_lli) {
|
||||
sgpio_dma_enable(dma_channel_sgpio, start_lli, false);
|
||||
}
|
||||
|
||||
void sgpio_dma_tx_start(const gpdma_lli_t* const start_lli) {
|
||||
sgpio_dma_enable(dma_channel_sgpio, start_lli, true);
|
||||
}
|
||||
|
||||
void sgpio_dma_irq_tc_acknowledge() {
|
||||
gpdma_channel_interrupt_tc_clear(dma_channel_sgpio);
|
||||
}
|
||||
|
||||
void sgpio_dma_stop() {
|
||||
gpdma_channel_disable(dma_channel_sgpio);
|
||||
}
|
||||
|
||||
size_t sgpio_dma_current_transfer_index(
|
||||
const gpdma_lli_t* const lli,
|
||||
const size_t lli_count
|
||||
) {
|
||||
const uint32_t next_lli = GPDMA_CLLI(dma_channel_sgpio);
|
||||
for(size_t i=0; i<lli_count; i++) {
|
||||
if( lli[i].clli == next_lli ) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
48
firmware/common/sgpio_dma.h
Normal file
48
firmware/common/sgpio_dma.h
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2013 Jared Boone <jared@sharebrained.com>
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __SGPIO_DMA_H__
|
||||
#define __SGPIO_DMA_H__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <libopencm3/lpc43xx/gpdma.h>
|
||||
|
||||
void sgpio_dma_configure_lli(
|
||||
gpdma_lli_t* const lli,
|
||||
const size_t lli_count,
|
||||
const bool direction_transmit,
|
||||
void* const buffer,
|
||||
const size_t transfer_bytes
|
||||
);
|
||||
|
||||
void sgpio_dma_init();
|
||||
void sgpio_dma_rx_start(const gpdma_lli_t* const start_lli);
|
||||
void sgpio_dma_tx_start(const gpdma_lli_t* const start_lli);
|
||||
void sgpio_dma_irq_tc_acknowledge();
|
||||
void sgpio_dma_stop();
|
||||
|
||||
size_t sgpio_dma_current_transfer_index(
|
||||
const gpdma_lli_t* const lli,
|
||||
const size_t lli_count
|
||||
);
|
||||
|
||||
#endif/*__SGPIO_DMA_H__*/
|
@ -237,16 +237,16 @@ void si5351c_configure_clock_control()
|
||||
,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_CLK_PLL_SRC_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_6MA)
|
||||
,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_CLK_PLL_SRC_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA)
|
||||
,SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE /*not connected, but: plla int mode*/
|
||||
,SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE /* pllb int mode*/| SI5351C_CLK_PLL_SRC(SI5351C_CLK_PLL_SRC_B) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA)
|
||||
,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(SI5351C_CLK_PLL_SRC_A) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA)
|
||||
};
|
||||
si5351c_write(data, sizeof(data));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Enable CLK outputs 0, 1, 2, 4, 5, ~7 only. */
|
||||
/* Enable CLK outputs 0, 1, 2, 4, 5, 7 only. */
|
||||
void si5351c_enable_clock_outputs()
|
||||
{
|
||||
uint8_t data[] = { 3, 0xC8 };
|
||||
uint8_t data[] = { 3, 0x48 };
|
||||
si5351c_write(data, sizeof(data));
|
||||
}
|
||||
|
||||
|
42
firmware/common/streaming.c
Normal file
42
firmware/common/streaming.c
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2012 Jared Boone
|
||||
* Copyright 2013 Benjamin Vernoux
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <streaming.h>
|
||||
|
||||
#include <libopencm3/lpc43xx/m4/nvic.h>
|
||||
#include <libopencm3/lpc43xx/sgpio.h>
|
||||
|
||||
#include <sgpio.h>
|
||||
|
||||
void baseband_streaming_enable() {
|
||||
nvic_set_priority(NVIC_SGPIO_IRQ, 0);
|
||||
nvic_enable_irq(NVIC_SGPIO_IRQ);
|
||||
SGPIO_SET_EN_1 = (1 << SGPIO_SLICE_A);
|
||||
|
||||
sgpio_cpld_stream_enable();
|
||||
}
|
||||
|
||||
void baseband_streaming_disable() {
|
||||
sgpio_cpld_stream_disable();
|
||||
|
||||
nvic_disable_irq(NVIC_SGPIO_IRQ);
|
||||
}
|
29
firmware/common/streaming.h
Normal file
29
firmware/common/streaming.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2012 Jared Boone
|
||||
* Copyright 2013 Benjamin Vernoux
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __STREAMING_H__
|
||||
#define __STREAMING_H__
|
||||
|
||||
void baseband_streaming_enable();
|
||||
void baseband_streaming_disable();
|
||||
|
||||
#endif/*__STREAMING_H__*/
|
126
firmware/common/tuning.c
Normal file
126
firmware/common/tuning.c
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright 2012 Jared Boone
|
||||
* Copyright 2013 Benjamin Vernoux
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "tuning.h"
|
||||
|
||||
#include <rffc5071.h>
|
||||
#include <max2837.h>
|
||||
|
||||
#include "rf_path.h"
|
||||
|
||||
#define FREQ_ONE_MHZ (1000*1000)
|
||||
|
||||
#define MIN_LP_FREQ_MHZ (5)
|
||||
#define MAX_LP_FREQ_MHZ (2300)
|
||||
|
||||
#define MIN_BYPASS_FREQ_MHZ (2300)
|
||||
#define MAX_BYPASS_FREQ_MHZ (2700)
|
||||
|
||||
#define MIN_HP_FREQ_MHZ (2700)
|
||||
#define MAX_HP_FREQ_MHZ (6800)
|
||||
|
||||
static uint32_t max2837_freq_nominal_hz=2560000000;
|
||||
|
||||
uint64_t freq_cache = 100000000;
|
||||
/*
|
||||
* Set freq/tuning between 5MHz to 6800 MHz (less than 16bits really used)
|
||||
* hz between 0 to 999999 Hz (not checked)
|
||||
* return false on error or true if success.
|
||||
*/
|
||||
bool set_freq(const uint64_t freq)
|
||||
{
|
||||
bool success;
|
||||
uint32_t RFFC5071_freq_mhz;
|
||||
uint32_t MAX2837_freq_hz;
|
||||
uint32_t real_RFFC5071_freq_hz;
|
||||
uint32_t tmp_hz;
|
||||
|
||||
const uint32_t freq_mhz = freq / 1000000;
|
||||
const uint32_t freq_hz = freq % 1000000;
|
||||
|
||||
success = true;
|
||||
|
||||
const max2837_mode_t prior_max2837_mode = max2837_mode();
|
||||
max2837_mode_standby();
|
||||
if(freq_mhz >= MIN_LP_FREQ_MHZ)
|
||||
{
|
||||
if(freq_mhz < MAX_LP_FREQ_MHZ)
|
||||
{
|
||||
rf_path_set_filter(RF_PATH_FILTER_LOW_PASS);
|
||||
RFFC5071_freq_mhz = (max2837_freq_nominal_hz / FREQ_ONE_MHZ) - freq_mhz;
|
||||
/* Set Freq and read real freq */
|
||||
real_RFFC5071_freq_hz = rffc5071_set_frequency(RFFC5071_freq_mhz);
|
||||
if(real_RFFC5071_freq_hz < RFFC5071_freq_mhz * FREQ_ONE_MHZ)
|
||||
{
|
||||
tmp_hz = -(RFFC5071_freq_mhz * FREQ_ONE_MHZ - real_RFFC5071_freq_hz);
|
||||
}else
|
||||
{
|
||||
tmp_hz = (real_RFFC5071_freq_hz - RFFC5071_freq_mhz * FREQ_ONE_MHZ);
|
||||
}
|
||||
MAX2837_freq_hz = max2837_freq_nominal_hz + tmp_hz + freq_hz;
|
||||
max2837_set_frequency(MAX2837_freq_hz);
|
||||
}else if( (freq_mhz >= MIN_BYPASS_FREQ_MHZ) && (freq_mhz < MAX_BYPASS_FREQ_MHZ) )
|
||||
{
|
||||
rf_path_set_filter(RF_PATH_FILTER_BYPASS);
|
||||
MAX2837_freq_hz = (freq_mhz * FREQ_ONE_MHZ) + freq_hz;
|
||||
/* RFFC5071_freq_mhz <= not used in Bypass mode */
|
||||
max2837_set_frequency(MAX2837_freq_hz);
|
||||
}else if( (freq_mhz >= MIN_HP_FREQ_MHZ) && (freq_mhz < MAX_HP_FREQ_MHZ) )
|
||||
{
|
||||
rf_path_set_filter(RF_PATH_FILTER_HIGH_PASS);
|
||||
RFFC5071_freq_mhz = freq_mhz - (max2837_freq_nominal_hz / FREQ_ONE_MHZ);
|
||||
/* Set Freq and read real freq */
|
||||
real_RFFC5071_freq_hz = rffc5071_set_frequency(RFFC5071_freq_mhz);
|
||||
if(real_RFFC5071_freq_hz < RFFC5071_freq_mhz * FREQ_ONE_MHZ)
|
||||
{
|
||||
tmp_hz = (RFFC5071_freq_mhz * FREQ_ONE_MHZ - real_RFFC5071_freq_hz);
|
||||
}else
|
||||
{
|
||||
tmp_hz = -(real_RFFC5071_freq_hz - RFFC5071_freq_mhz * FREQ_ONE_MHZ);
|
||||
}
|
||||
MAX2837_freq_hz = max2837_freq_nominal_hz + tmp_hz + freq_hz;
|
||||
max2837_set_frequency(MAX2837_freq_hz);
|
||||
}else
|
||||
{
|
||||
/* Error freq_mhz too high */
|
||||
success = false;
|
||||
}
|
||||
}else
|
||||
{
|
||||
/* Error freq_mhz too low */
|
||||
success = false;
|
||||
}
|
||||
max2837_set_mode(prior_max2837_mode);
|
||||
if( success ) {
|
||||
freq_cache = freq;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool set_freq_if(const uint32_t freq_if_hz) {
|
||||
bool success = false;
|
||||
if( (freq_if_hz >= MIN_BYPASS_FREQ_MHZ) && (freq_if_hz <= MAX_BYPASS_FREQ_MHZ) ) {
|
||||
max2837_freq_nominal_hz = freq_if_hz;
|
||||
success = set_freq(freq_cache);
|
||||
}
|
||||
return success;
|
||||
}
|
32
firmware/common/tuning.h
Normal file
32
firmware/common/tuning.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2012 Jared Boone
|
||||
* Copyright 2013 Benjamin Vernoux
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __TUNING_H__
|
||||
#define __TUNING_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
bool set_freq(const uint64_t freq);
|
||||
bool set_freq_if(const uint32_t freq_if_hz);
|
||||
|
||||
#endif/*__TUNING_H__*/
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include "usb.h"
|
||||
#include "usb_type.h"
|
||||
#include "usb_queue.h"
|
||||
#include "usb_standard_request.h"
|
||||
|
||||
#include <libopencm3/lpc43xx/creg.h>
|
||||
@ -34,10 +35,8 @@
|
||||
usb_device_t* usb_device_usb0 = 0;
|
||||
|
||||
usb_queue_head_t usb_qh[12] ATTR_ALIGNED(2048);
|
||||
usb_transfer_descriptor_t usb_td[12] ATTR_ALIGNED(64);
|
||||
|
||||
#define USB_QH_INDEX(endpoint_address) (((endpoint_address & 0xF) * 2) + ((endpoint_address >> 7) & 1))
|
||||
#define USB_TD_INDEX(endpoint_address) (((endpoint_address & 0xF) * 2) + ((endpoint_address >> 7) & 1))
|
||||
|
||||
usb_queue_head_t* usb_queue_head(
|
||||
const uint_fast8_t endpoint_address
|
||||
@ -45,12 +44,6 @@ usb_queue_head_t* usb_queue_head(
|
||||
return &usb_qh[USB_QH_INDEX(endpoint_address)];
|
||||
}
|
||||
|
||||
usb_transfer_descriptor_t* usb_transfer_descriptor(
|
||||
const uint_fast8_t endpoint_address
|
||||
) {
|
||||
return &usb_td[USB_TD_INDEX(endpoint_address)];
|
||||
}
|
||||
|
||||
static usb_endpoint_t* usb_endpoint_from_address(
|
||||
const uint_fast8_t endpoint_address
|
||||
) {
|
||||
@ -98,25 +91,25 @@ static void usb_clear_all_pending_interrupts() {
|
||||
static void usb_wait_for_endpoint_priming_to_finish(const uint32_t mask) {
|
||||
// Wait until controller has parsed new transfer descriptors and prepared
|
||||
// receive buffers.
|
||||
while( USB0_ENDPTPRIME & mask );
|
||||
while( USB0_ENDPTPRIME & mask );
|
||||
}
|
||||
|
||||
static void usb_flush_endpoints(const uint32_t mask) {
|
||||
// Clear any primed buffers. If a packet is in progress, that transfer
|
||||
// will continue until completion.
|
||||
USB0_ENDPTFLUSH = mask;
|
||||
USB0_ENDPTFLUSH = mask;
|
||||
}
|
||||
|
||||
static void usb_wait_for_endpoint_flushing_to_finish(const uint32_t mask) {
|
||||
// Wait until controller has flushed all endpoints / cleared any primed
|
||||
// buffers.
|
||||
while( USB0_ENDPTFLUSH & mask );
|
||||
while( USB0_ENDPTFLUSH & mask );
|
||||
}
|
||||
|
||||
static void usb_flush_primed_endpoints(const uint32_t mask) {
|
||||
usb_wait_for_endpoint_priming_to_finish(mask);
|
||||
usb_wait_for_endpoint_priming_to_finish(mask);
|
||||
usb_flush_endpoints(mask);
|
||||
usb_wait_for_endpoint_flushing_to_finish(mask);
|
||||
usb_wait_for_endpoint_flushing_to_finish(mask);
|
||||
}
|
||||
|
||||
static void usb_flush_all_primed_endpoints() {
|
||||
@ -171,6 +164,7 @@ void usb_endpoint_disable(
|
||||
} else {
|
||||
USB0_ENDPTCTRL(endpoint_number) &= ~(USB0_ENDPTCTRL_RXE);
|
||||
}
|
||||
usb_queue_flush_endpoint(endpoint);
|
||||
usb_endpoint_clear_pending_interrupts(endpoint);
|
||||
usb_endpoint_flush(endpoint);
|
||||
}
|
||||
@ -195,7 +189,7 @@ void usb_endpoint_prime(
|
||||
USB0_ENDPTPRIME = USB0_ENDPTPRIME_PERB(1 << endpoint_number);
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
||||
static bool usb_endpoint_is_priming(
|
||||
const usb_endpoint_t* const endpoint
|
||||
) {
|
||||
@ -206,11 +200,57 @@ static bool usb_endpoint_is_priming(
|
||||
return USB0_ENDPTPRIME & USB0_ENDPTPRIME_PERB(1 << endpoint_number);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Schedule an already filled-in transfer descriptor for execution on
|
||||
// the given endpoint, waiting until the endpoint has finished.
|
||||
void usb_endpoint_schedule_wait(
|
||||
const usb_endpoint_t* const endpoint,
|
||||
usb_transfer_descriptor_t* const td
|
||||
) {
|
||||
// Ensure that endpoint is ready to be primed.
|
||||
// It may have been flushed due to an aborted transaction.
|
||||
// TODO: This should be preceded by a flush?
|
||||
while( usb_endpoint_is_ready(endpoint) );
|
||||
|
||||
td->next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE;
|
||||
|
||||
usb_endpoint_prime(endpoint, td);
|
||||
}
|
||||
|
||||
// Schedule an already filled-in transfer descriptor for execution on
|
||||
// the given endpoint, appending to the end of the endpoint's queue if
|
||||
// there are pending TDs. Note that this requires that one knows the
|
||||
// tail of the endpoint's TD queue. Moreover, the user is responsible
|
||||
// for setting the TERMINATE bit of next_dtd_pointer if needed.
|
||||
void usb_endpoint_schedule_append(
|
||||
const usb_endpoint_t* const endpoint,
|
||||
usb_transfer_descriptor_t* const tail_td,
|
||||
usb_transfer_descriptor_t* const new_td
|
||||
) {
|
||||
bool done;
|
||||
|
||||
tail_td->next_dtd_pointer = new_td;
|
||||
|
||||
if (usb_endpoint_is_priming(endpoint)) {
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
USB0_USBCMD_D |= USB0_USBCMD_D_ATDTW;
|
||||
done = usb_endpoint_is_ready(endpoint);
|
||||
} while (!(USB0_USBCMD_D & USB0_USBCMD_D_ATDTW));
|
||||
|
||||
USB0_USBCMD_D &= ~USB0_USBCMD_D_ATDTW;
|
||||
if(!done) {
|
||||
usb_endpoint_prime(endpoint, new_td);
|
||||
}
|
||||
}
|
||||
|
||||
void usb_endpoint_flush(
|
||||
const usb_endpoint_t* const endpoint
|
||||
) {
|
||||
const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
|
||||
usb_queue_flush_endpoint(endpoint);
|
||||
if( usb_endpoint_is_in(endpoint->address) ) {
|
||||
usb_flush_primed_endpoints(USB0_ENDPTFLUSH_FETB(1 << endpoint_number));
|
||||
} else {
|
||||
@ -510,48 +550,13 @@ void usb_endpoint_init(
|
||||
usb_endpoint_enable(endpoint);
|
||||
}
|
||||
|
||||
void usb_endpoint_schedule(
|
||||
const usb_endpoint_t* const endpoint,
|
||||
void* const data,
|
||||
const uint32_t maximum_length
|
||||
) {
|
||||
usb_transfer_descriptor_t* const td = usb_transfer_descriptor(endpoint->address);
|
||||
|
||||
// Ensure that endpoint is ready to be primed.
|
||||
// It may have been flushed due to an aborted transaction.
|
||||
// TODO: This should be preceded by a flush?
|
||||
while( usb_endpoint_is_ready(endpoint) );
|
||||
|
||||
// Configure a transfer.
|
||||
td->next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE;
|
||||
td->total_bytes =
|
||||
USB_TD_DTD_TOKEN_TOTAL_BYTES(maximum_length)
|
||||
| USB_TD_DTD_TOKEN_IOC
|
||||
| USB_TD_DTD_TOKEN_MULTO(0)
|
||||
| USB_TD_DTD_TOKEN_STATUS_ACTIVE
|
||||
;
|
||||
td->buffer_pointer_page[0] = (uint32_t)data;
|
||||
td->buffer_pointer_page[1] = ((uint32_t)data + 0x1000) & 0xfffff000;
|
||||
td->buffer_pointer_page[2] = ((uint32_t)data + 0x2000) & 0xfffff000;
|
||||
td->buffer_pointer_page[3] = ((uint32_t)data + 0x3000) & 0xfffff000;
|
||||
td->buffer_pointer_page[4] = ((uint32_t)data + 0x4000) & 0xfffff000;
|
||||
|
||||
usb_endpoint_prime(endpoint, td);
|
||||
}
|
||||
|
||||
void usb_endpoint_schedule_ack(
|
||||
const usb_endpoint_t* const endpoint
|
||||
) {
|
||||
usb_endpoint_schedule(endpoint, 0, 0);
|
||||
}
|
||||
|
||||
static void usb_check_for_setup_events() {
|
||||
const uint32_t endptsetupstat = usb_get_endpoint_setup_status();
|
||||
if( endptsetupstat ) {
|
||||
for( uint_fast8_t i=0; i<6; i++ ) {
|
||||
const uint32_t endptsetupstat_bit = USB0_ENDPTSETUPSTAT_ENDPTSETUPSTAT(1 << i);
|
||||
if( endptsetupstat & endptsetupstat_bit ) {
|
||||
usb_endpoint_t* const endpoint =
|
||||
usb_endpoint_t* const endpoint =
|
||||
usb_endpoint_from_address(
|
||||
usb_endpoint_address(USB_TRANSFER_DIRECTION_OUT, i)
|
||||
);
|
@ -61,16 +61,6 @@ void usb_endpoint_init(
|
||||
const usb_endpoint_t* const endpoint
|
||||
);
|
||||
|
||||
void usb_endpoint_schedule(
|
||||
const usb_endpoint_t* const endpoint,
|
||||
void* const data,
|
||||
const uint32_t maximum_length
|
||||
);
|
||||
|
||||
void usb_endpoint_schedule_ack(
|
||||
const usb_endpoint_t* const endpoint
|
||||
);
|
||||
|
||||
void usb_endpoint_stall(
|
||||
const usb_endpoint_t* const endpoint
|
||||
);
|
||||
@ -92,4 +82,15 @@ void usb_endpoint_prime(
|
||||
usb_transfer_descriptor_t* const first_td
|
||||
);
|
||||
|
||||
void usb_endpoint_schedule_wait(
|
||||
const usb_endpoint_t* const endpoint,
|
||||
usb_transfer_descriptor_t* const td
|
||||
);
|
||||
|
||||
void usb_endpoint_schedule_append(
|
||||
const usb_endpoint_t* const endpoint,
|
||||
usb_transfer_descriptor_t* const tail_td,
|
||||
usb_transfer_descriptor_t* const new_td
|
||||
);
|
||||
|
||||
#endif//__USB_H__
|
227
firmware/common/usb_queue.c
Normal file
227
firmware/common/usb_queue.c
Normal file
@ -0,0 +1,227 @@
|
||||
/*
|
||||
* Copyright 2012 Jared Boone
|
||||
* Copyright 2013 Ben Gamari
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <libopencm3/cm3/cortex.h>
|
||||
#include <libopencm3/cm3/sync.h>
|
||||
|
||||
#include "usb.h"
|
||||
#include "usb_queue.h"
|
||||
|
||||
usb_queue_t* endpoint_queues[12] = {};
|
||||
|
||||
#define USB_ENDPOINT_INDEX(endpoint_address) (((endpoint_address & 0xF) * 2) + ((endpoint_address >> 7) & 1))
|
||||
|
||||
static usb_queue_t* endpoint_queue(
|
||||
const usb_endpoint_t* const endpoint
|
||||
) {
|
||||
uint32_t index = USB_ENDPOINT_INDEX(endpoint->address);
|
||||
if (endpoint_queues[index] == NULL) while (1);
|
||||
return endpoint_queues[index];
|
||||
}
|
||||
|
||||
void usb_queue_init(
|
||||
usb_queue_t* const queue
|
||||
) {
|
||||
uint32_t index = USB_ENDPOINT_INDEX(queue->endpoint->address);
|
||||
if (endpoint_queues[index] != NULL) while (1);
|
||||
endpoint_queues[index] = queue;
|
||||
|
||||
usb_transfer_t* t = queue->free_transfers;
|
||||
for (unsigned int i=0; i < queue->pool_size - 1; i++, t++) {
|
||||
t->next = t+1;
|
||||
t->queue = queue;
|
||||
}
|
||||
t->next = NULL;
|
||||
t->queue = queue;
|
||||
}
|
||||
|
||||
/* Allocate a transfer */
|
||||
static usb_transfer_t* allocate_transfer(
|
||||
usb_queue_t* const queue
|
||||
) {
|
||||
bool aborted;
|
||||
usb_transfer_t* transfer;
|
||||
if (queue->free_transfers == NULL)
|
||||
return NULL;
|
||||
|
||||
do {
|
||||
transfer = (void *) __ldrex((uint32_t *) &queue->free_transfers);
|
||||
aborted = __strex((uint32_t) transfer->next, (uint32_t *) &queue->free_transfers);
|
||||
} while (aborted);
|
||||
transfer->next = NULL;
|
||||
return transfer;
|
||||
}
|
||||
|
||||
/* Place a transfer in the free list */
|
||||
static void free_transfer(usb_transfer_t* const transfer)
|
||||
{
|
||||
usb_queue_t* const queue = transfer->queue;
|
||||
bool aborted;
|
||||
do {
|
||||
transfer->next = (void *) __ldrex((uint32_t *) &queue->free_transfers);
|
||||
aborted = __strex((uint32_t) transfer, (uint32_t *) &queue->free_transfers);
|
||||
} while (aborted);
|
||||
}
|
||||
|
||||
/* Add a transfer to the end of an endpoint's queue. Returns the old
|
||||
* tail or NULL is the queue was empty
|
||||
*/
|
||||
static usb_transfer_t* endpoint_queue_transfer(
|
||||
usb_transfer_t* const transfer
|
||||
) {
|
||||
usb_queue_t* const queue = transfer->queue;
|
||||
transfer->next = NULL;
|
||||
if (queue->active != NULL) {
|
||||
usb_transfer_t* t = queue->active;
|
||||
while (t->next != NULL) t = t->next;
|
||||
t->next = transfer;
|
||||
return t;
|
||||
} else {
|
||||
queue->active = transfer;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void usb_queue_flush_queue(usb_queue_t* const queue)
|
||||
{
|
||||
cm_disable_interrupts();
|
||||
while (queue->active) {
|
||||
usb_transfer_t* transfer = queue->active;
|
||||
queue->active = transfer->next;
|
||||
free_transfer(transfer);
|
||||
}
|
||||
cm_enable_interrupts();
|
||||
}
|
||||
|
||||
void usb_queue_flush_endpoint(const usb_endpoint_t* const endpoint)
|
||||
{
|
||||
usb_queue_flush_queue(endpoint_queue(endpoint));
|
||||
}
|
||||
|
||||
int usb_transfer_schedule(
|
||||
const usb_endpoint_t* const endpoint,
|
||||
void* const data,
|
||||
const uint32_t maximum_length,
|
||||
const transfer_completion_cb completion_cb,
|
||||
void* const user_data
|
||||
) {
|
||||
usb_queue_t* const queue = endpoint_queue(endpoint);
|
||||
usb_transfer_t* const transfer = allocate_transfer(queue);
|
||||
if (transfer == NULL) return -1;
|
||||
usb_transfer_descriptor_t* const td = &transfer->td;
|
||||
|
||||
// Configure the transfer descriptor
|
||||
td->next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE;
|
||||
td->total_bytes =
|
||||
USB_TD_DTD_TOKEN_TOTAL_BYTES(maximum_length)
|
||||
| USB_TD_DTD_TOKEN_IOC
|
||||
| USB_TD_DTD_TOKEN_MULTO(0)
|
||||
| USB_TD_DTD_TOKEN_STATUS_ACTIVE
|
||||
;
|
||||
td->buffer_pointer_page[0] = (uint32_t)data;
|
||||
td->buffer_pointer_page[1] = ((uint32_t)data + 0x1000) & 0xfffff000;
|
||||
td->buffer_pointer_page[2] = ((uint32_t)data + 0x2000) & 0xfffff000;
|
||||
td->buffer_pointer_page[3] = ((uint32_t)data + 0x3000) & 0xfffff000;
|
||||
td->buffer_pointer_page[4] = ((uint32_t)data + 0x4000) & 0xfffff000;
|
||||
|
||||
// Fill in transfer fields
|
||||
transfer->maximum_length = maximum_length;
|
||||
transfer->completion_cb = completion_cb;
|
||||
transfer->user_data = user_data;
|
||||
|
||||
cm_disable_interrupts();
|
||||
usb_transfer_t* tail = endpoint_queue_transfer(transfer);
|
||||
if (tail == NULL) {
|
||||
// The queue is currently empty, we need to re-prime
|
||||
usb_endpoint_schedule_wait(queue->endpoint, &transfer->td);
|
||||
} else {
|
||||
// The queue is currently running, try to append
|
||||
usb_endpoint_schedule_append(queue->endpoint, &tail->td, &transfer->td);
|
||||
}
|
||||
cm_enable_interrupts();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usb_transfer_schedule_block(
|
||||
const usb_endpoint_t* const endpoint,
|
||||
void* const data,
|
||||
const uint32_t maximum_length,
|
||||
const transfer_completion_cb completion_cb,
|
||||
void* const user_data
|
||||
) {
|
||||
int ret;
|
||||
do {
|
||||
ret = usb_transfer_schedule(endpoint, data, maximum_length,
|
||||
completion_cb, user_data);
|
||||
} while (ret == -1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usb_transfer_schedule_ack(
|
||||
const usb_endpoint_t* const endpoint
|
||||
) {
|
||||
return usb_transfer_schedule_block(endpoint, 0, 0, NULL, NULL);
|
||||
}
|
||||
|
||||
/* Called when an endpoint might have completed a transfer */
|
||||
void usb_queue_transfer_complete(usb_endpoint_t* const endpoint)
|
||||
{
|
||||
usb_queue_t* const queue = endpoint_queue(endpoint);
|
||||
if (queue == NULL) while(1); // Uh oh
|
||||
usb_transfer_t* transfer = queue->active;
|
||||
|
||||
while (transfer != NULL) {
|
||||
uint8_t status = transfer->td.total_bytes;
|
||||
|
||||
// Check for failures
|
||||
if ( status & USB_TD_DTD_TOKEN_STATUS_HALTED
|
||||
|| status & USB_TD_DTD_TOKEN_STATUS_BUFFER_ERROR
|
||||
|| status & USB_TD_DTD_TOKEN_STATUS_TRANSACTION_ERROR) {
|
||||
// TODO: Uh oh, do something useful here
|
||||
while (1);
|
||||
}
|
||||
|
||||
// Still not finished
|
||||
if (status & USB_TD_DTD_TOKEN_STATUS_ACTIVE)
|
||||
break;
|
||||
|
||||
// Advance the head. We need to do this before invoking the completion
|
||||
// callback as it might attempt to schedule a new transfer
|
||||
queue->active = transfer->next;
|
||||
usb_transfer_t* next = transfer->next;
|
||||
|
||||
// Invoke completion callback
|
||||
unsigned int total_bytes = (transfer->td.total_bytes & USB_TD_DTD_TOKEN_TOTAL_BYTES_MASK) >> USB_TD_DTD_TOKEN_TOTAL_BYTES_SHIFT;
|
||||
unsigned int transferred = transfer->maximum_length - total_bytes;
|
||||
if (transfer->completion_cb)
|
||||
transfer->completion_cb(transfer->user_data, transferred);
|
||||
|
||||
// Advance head and free transfer
|
||||
free_transfer(transfer);
|
||||
transfer = next;
|
||||
}
|
||||
}
|
92
firmware/common/usb_queue.h
Normal file
92
firmware/common/usb_queue.h
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2012 Jared Boone
|
||||
* Copyright 2013 Ben Gamari
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __USB_QUEUE_H__
|
||||
#define __USB_QUEUE_H__
|
||||
|
||||
#include <libopencm3/lpc43xx/usb.h>
|
||||
|
||||
#include "usb_type.h"
|
||||
|
||||
typedef struct _usb_transfer_t usb_transfer_t;
|
||||
typedef struct _usb_queue_t usb_queue_t;
|
||||
typedef void (*transfer_completion_cb)(void*, unsigned int);
|
||||
|
||||
// This is an opaque datatype. Thou shall not touch these members.
|
||||
struct _usb_transfer_t {
|
||||
struct _usb_transfer_t* next;
|
||||
usb_transfer_descriptor_t td ATTR_ALIGNED(64);
|
||||
unsigned int maximum_length;
|
||||
struct _usb_queue_t* queue;
|
||||
transfer_completion_cb completion_cb;
|
||||
void* user_data;
|
||||
};
|
||||
|
||||
// This is an opaque datatype. Thou shall not touch these members.
|
||||
struct _usb_queue_t {
|
||||
struct usb_endpoint_t* endpoint;
|
||||
const unsigned int pool_size;
|
||||
usb_transfer_t* volatile free_transfers;
|
||||
usb_transfer_t* volatile active;
|
||||
};
|
||||
|
||||
#define USB_DECLARE_QUEUE(endpoint_name) \
|
||||
struct _usb_queue_t endpoint_name##_queue;
|
||||
#define USB_DEFINE_QUEUE(endpoint_name, _pool_size) \
|
||||
struct _usb_transfer_t endpoint_name##_transfers[_pool_size]; \
|
||||
struct _usb_queue_t endpoint_name##_queue = { \
|
||||
.endpoint = &endpoint_name, \
|
||||
.free_transfers = endpoint_name##_transfers, \
|
||||
.pool_size = _pool_size \
|
||||
};
|
||||
|
||||
void usb_queue_flush_endpoint(const usb_endpoint_t* const endpoint);
|
||||
|
||||
int usb_transfer_schedule(
|
||||
const usb_endpoint_t* const endpoint,
|
||||
void* const data,
|
||||
const uint32_t maximum_length,
|
||||
const transfer_completion_cb completion_cb,
|
||||
void* const user_data
|
||||
);
|
||||
|
||||
int usb_transfer_schedule_block(
|
||||
const usb_endpoint_t* const endpoint,
|
||||
void* const data,
|
||||
const uint32_t maximum_length,
|
||||
const transfer_completion_cb completion_cb,
|
||||
void* const user_data
|
||||
);
|
||||
|
||||
int usb_transfer_schedule_ack(
|
||||
const usb_endpoint_t* const endpoint
|
||||
);
|
||||
|
||||
void usb_queue_init(
|
||||
usb_queue_t* const queue
|
||||
);
|
||||
|
||||
void usb_queue_transfer_complete(
|
||||
usb_endpoint_t* const endpoint
|
||||
);
|
||||
|
||||
#endif//__USB_QUEUE_H__
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "usb.h"
|
||||
#include "usb_request.h"
|
||||
#include "usb_queue.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
@ -75,6 +76,7 @@ void usb_control_out_complete(
|
||||
} else {
|
||||
usb_request(endpoint, USB_TRANSFER_STAGE_DATA);
|
||||
}
|
||||
usb_queue_transfer_complete(endpoint);
|
||||
}
|
||||
|
||||
void usb_control_in_complete(
|
||||
@ -87,5 +89,6 @@ void usb_control_in_complete(
|
||||
} else {
|
||||
usb_request(endpoint, USB_TRANSFER_STAGE_STATUS);
|
||||
}
|
||||
usb_queue_transfer_complete(endpoint);
|
||||
}
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
#include "usb.h"
|
||||
#include "usb_type.h"
|
||||
#include "usb_descriptor.h"
|
||||
#include "usb_queue.h"
|
||||
|
||||
const uint8_t* usb_endpoint_descriptor(
|
||||
const usb_endpoint_t* const endpoint
|
||||
@ -99,27 +99,31 @@ bool usb_set_configuration(
|
||||
if( new_configuration != device->configuration ) {
|
||||
// Configuration changed.
|
||||
device->configuration = new_configuration;
|
||||
if (usb_configuration_changed_cb)
|
||||
usb_configuration_changed_cb(device);
|
||||
}
|
||||
|
||||
if (usb_configuration_changed_cb)
|
||||
usb_configuration_changed_cb(device);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static usb_request_status_t usb_send_descriptor(
|
||||
usb_endpoint_t* const endpoint,
|
||||
uint8_t* const descriptor_data
|
||||
const uint8_t* const descriptor_data
|
||||
) {
|
||||
const uint32_t setup_length = endpoint->setup.length;
|
||||
uint32_t descriptor_length = descriptor_data[0];
|
||||
if( descriptor_data[1] == USB_DESCRIPTOR_TYPE_CONFIGURATION ) {
|
||||
descriptor_length = (descriptor_data[3] << 8) | descriptor_data[2];
|
||||
}
|
||||
usb_endpoint_schedule(
|
||||
// We cast the const away but this shouldn't be a problem as this is a write transfer
|
||||
usb_transfer_schedule_block(
|
||||
endpoint->in,
|
||||
descriptor_data,
|
||||
(setup_length > descriptor_length) ? descriptor_length : setup_length
|
||||
(uint8_t* const) descriptor_data,
|
||||
(setup_length > descriptor_length) ? descriptor_length : setup_length,
|
||||
NULL, NULL
|
||||
);
|
||||
usb_endpoint_schedule_ack(endpoint->out);
|
||||
usb_transfer_schedule_ack(endpoint->out);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
|
||||
@ -127,39 +131,58 @@ static usb_request_status_t usb_send_descriptor_string(
|
||||
usb_endpoint_t* const endpoint
|
||||
) {
|
||||
uint_fast8_t index = endpoint->setup.value_l;
|
||||
for( uint_fast8_t i=0; usb_descriptor_strings[i] != 0; i++ ) {
|
||||
for( uint_fast8_t i=0; endpoint->device->descriptor_strings[i] != 0; i++ ) {
|
||||
if( i == index ) {
|
||||
return usb_send_descriptor(endpoint, usb_descriptor_strings[i]);
|
||||
return usb_send_descriptor(endpoint, endpoint->device->descriptor_strings[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
}
|
||||
|
||||
static usb_request_status_t usb_send_descriptor_config(
|
||||
usb_endpoint_t* const endpoint,
|
||||
usb_speed_t speed,
|
||||
const uint8_t config_num
|
||||
) {
|
||||
usb_configuration_t** config = *(endpoint->device->configurations);
|
||||
unsigned int i = 0;
|
||||
for( ; *config != NULL; config++ ) {
|
||||
if( (*config)->speed == speed) {
|
||||
if (i == config_num) {
|
||||
return usb_send_descriptor(endpoint, (*config)->descriptor);
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
}
|
||||
|
||||
static usb_request_status_t usb_standard_request_get_descriptor_setup(
|
||||
usb_endpoint_t* const endpoint
|
||||
) {
|
||||
switch( endpoint->setup.value_h ) {
|
||||
case USB_DESCRIPTOR_TYPE_DEVICE:
|
||||
return usb_send_descriptor(endpoint, usb_descriptor_device);
|
||||
return usb_send_descriptor(endpoint, endpoint->device->descriptor);
|
||||
|
||||
case USB_DESCRIPTOR_TYPE_CONFIGURATION:
|
||||
// TODO: Duplicated code. Refactor.
|
||||
if( usb_speed(endpoint->device) == USB_SPEED_HIGH ) {
|
||||
return usb_send_descriptor(endpoint, usb_descriptor_configuration_high_speed);
|
||||
return usb_send_descriptor_config(endpoint, USB_SPEED_HIGH, endpoint->setup.value_l);
|
||||
} else {
|
||||
return usb_send_descriptor(endpoint, usb_descriptor_configuration_full_speed);
|
||||
return usb_send_descriptor_config(endpoint, USB_SPEED_FULL, endpoint->setup.value_l);
|
||||
}
|
||||
|
||||
case USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER:
|
||||
return usb_send_descriptor(endpoint, usb_descriptor_device_qualifier);
|
||||
return usb_send_descriptor(endpoint, endpoint->device->qualifier_descriptor);
|
||||
|
||||
case USB_DESCRIPTOR_TYPE_OTHER_SPEED_CONFIGURATION:
|
||||
// TODO: Duplicated code. Refactor.
|
||||
if( usb_speed(endpoint->device) == USB_SPEED_HIGH ) {
|
||||
return usb_send_descriptor(endpoint, usb_descriptor_configuration_full_speed);
|
||||
return usb_send_descriptor_config(endpoint, USB_SPEED_FULL, endpoint->setup.value_l);
|
||||
} else {
|
||||
return usb_send_descriptor(endpoint, usb_descriptor_configuration_high_speed);
|
||||
return usb_send_descriptor_config(endpoint, USB_SPEED_HIGH, endpoint->setup.value_l);
|
||||
}
|
||||
|
||||
case USB_DESCRIPTOR_TYPE_STRING:
|
||||
@ -195,7 +218,7 @@ static usb_request_status_t usb_standard_request_set_address_setup(
|
||||
usb_endpoint_t* const endpoint
|
||||
) {
|
||||
usb_set_address_deferred(endpoint->device, endpoint->setup.value_l);
|
||||
usb_endpoint_schedule_ack(endpoint->in);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
|
||||
@ -231,7 +254,7 @@ static usb_request_status_t usb_standard_request_set_configuration_setup(
|
||||
// TODO: Should this be done immediately?
|
||||
usb_set_address_immediate(endpoint->device, 0);
|
||||
}
|
||||
usb_endpoint_schedule_ack(endpoint->in);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
} else {
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
@ -265,8 +288,8 @@ static usb_request_status_t usb_standard_request_get_configuration_setup(
|
||||
if( endpoint->device->configuration ) {
|
||||
endpoint->buffer[0] = endpoint->device->configuration->number;
|
||||
}
|
||||
usb_endpoint_schedule(endpoint->in, &endpoint->buffer, 1);
|
||||
usb_endpoint_schedule_ack(endpoint->out);
|
||||
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1, NULL, NULL);
|
||||
usb_transfer_schedule_ack(endpoint->out);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
} else {
|
||||
return USB_REQUEST_STATUS_STALL;
|
@ -123,6 +123,8 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
const uint8_t* const descriptor;
|
||||
uint8_t** descriptor_strings;
|
||||
const uint8_t* const qualifier_descriptor;
|
||||
usb_configuration_t* (*configurations)[];
|
||||
const usb_configuration_t* configuration;
|
||||
} usb_device_t;
|
@ -10,18 +10,11 @@
|
||||
/* Add print in setPort for xapp058_example.exe.*/
|
||||
/*******************************************************/
|
||||
#include "ports.h"
|
||||
/*#include "prgispx.h"*/
|
||||
|
||||
//#include "stdio.h"
|
||||
#include "hackrf_core.h"
|
||||
#include "cpld_jtag.h"
|
||||
#include <libopencm3/lpc43xx/gpio.h>
|
||||
|
||||
//extern FILE *in;
|
||||
//static int g_iTCK = 0; /* For xapp058_example .exe */
|
||||
//static int g_iTMS = 0; /* For xapp058_example .exe */
|
||||
//static int g_iTDI = 0; /* For xapp058_example .exe */
|
||||
|
||||
void delay_jtag(uint32_t duration)
|
||||
{
|
||||
#define DIVISOR (1024)
|
||||
@ -43,94 +36,10 @@ void delay_jtag(uint32_t duration)
|
||||
__asm__("nop");
|
||||
}
|
||||
|
||||
|
||||
#ifdef WIN95PP
|
||||
#include "conio.h"
|
||||
|
||||
#define DATA_OFFSET (unsigned short) 0
|
||||
#define STATUS_OFFSET (unsigned short) 1
|
||||
#define CONTROL_OFFSET (unsigned short) 2
|
||||
|
||||
typedef union outPortUnion {
|
||||
unsigned char value;
|
||||
struct opBitsStr {
|
||||
unsigned char tdi:1;
|
||||
unsigned char tck:1;
|
||||
unsigned char tms:1;
|
||||
unsigned char zero:1;
|
||||
unsigned char one:1;
|
||||
unsigned char bit5:1;
|
||||
unsigned char bit6:1;
|
||||
unsigned char bit7:1;
|
||||
} bits;
|
||||
} outPortType;
|
||||
|
||||
typedef union inPortUnion {
|
||||
unsigned char value;
|
||||
struct ipBitsStr {
|
||||
unsigned char bit0:1;
|
||||
unsigned char bit1:1;
|
||||
unsigned char bit2:1;
|
||||
unsigned char bit3:1;
|
||||
unsigned char tdo:1;
|
||||
unsigned char bit5:1;
|
||||
unsigned char bit6:1;
|
||||
unsigned char bit7:1;
|
||||
} bits;
|
||||
} inPortType;
|
||||
|
||||
static inPortType in_word;
|
||||
static outPortType out_word;
|
||||
static unsigned short base_port = 0x378;
|
||||
static int once = 0;
|
||||
#endif
|
||||
|
||||
|
||||
/*BYTE *xsvf_data=0;*/
|
||||
|
||||
|
||||
/* setPort: Implement to set the named JTAG signal (p) to the new value (v).*/
|
||||
/* if in debugging mode, then just set the variables */
|
||||
void setPort(short p,short val)
|
||||
{
|
||||
#ifdef WIN95PP
|
||||
/* Old Win95 example that is similar to a GPIO register implementation.
|
||||
The old Win95 example maps individual bits of the
|
||||
8-bit register (out_word) to the JTAG signals: TCK, TMS, TDI.
|
||||
*/
|
||||
|
||||
/* Initialize static out_word register bits just once */
|
||||
if (once == 0) {
|
||||
out_word.bits.one = 1;
|
||||
out_word.bits.zero = 0;
|
||||
once = 1;
|
||||
}
|
||||
|
||||
/* Update the local out_word copy of the JTAG signal to the new value. */
|
||||
if (p==TMS)
|
||||
out_word.bits.tms = (unsigned char) val;
|
||||
if (p==TDI)
|
||||
out_word.bits.tdi = (unsigned char) val;
|
||||
if (p==TCK) {
|
||||
out_word.bits.tck = (unsigned char) val;
|
||||
(void) _outp( (unsigned short) (base_port + 0), out_word.value );
|
||||
/* To save HW write cycles, this example only writes the local copy
|
||||
of the JTAG signal values to the HW register when TCK changes. */
|
||||
}
|
||||
#endif
|
||||
/* Printing code for the xapp058_example.exe. You must set the specified
|
||||
JTAG signal (p) to the new value (v). See the above, old Win95 code
|
||||
as an implementation example. */
|
||||
/*
|
||||
if (p==TMS)
|
||||
g_iTMS = val;
|
||||
if (p==TDI)
|
||||
g_iTDI = val;
|
||||
if (p==TCK) {
|
||||
g_iTCK = val;
|
||||
printf( "TCK = %d; TMS = %d; TDI = %d\n", g_iTCK, g_iTMS, g_iTDI );
|
||||
}
|
||||
*/
|
||||
if (p==TMS) {
|
||||
if (val)
|
||||
gpio_set(PORT_CPLD_TMS, PIN_CPLD_TMS);
|
||||
@ -167,9 +76,6 @@ void pulseClock()
|
||||
/* read in a byte of data from the prom */
|
||||
void readByte(unsigned char *data)
|
||||
{
|
||||
/* pretend reading using a file */
|
||||
//*data = (unsigned char)fgetc( in );
|
||||
/**data=*xsvf_data++;*/
|
||||
*data = cpld_jtag_get_next_byte();
|
||||
}
|
||||
|
||||
@ -177,20 +83,6 @@ void readByte(unsigned char *data)
|
||||
/* read the TDO bit from port */
|
||||
unsigned char readTDOBit()
|
||||
{
|
||||
#ifdef WIN95PP
|
||||
/* Old Win95 example that is similar to a GPIO register implementation.
|
||||
The old Win95 reads the hardware input register and extracts the TDO
|
||||
value from the bit within the register that is assigned to the
|
||||
physical JTAG TDO signal.
|
||||
*/
|
||||
in_word.value = (unsigned char) _inp( (unsigned short) (base_port + STATUS_OFFSET) );
|
||||
if (in_word.bits.tdo == 0x1) {
|
||||
return( (unsigned char) 1 );
|
||||
}
|
||||
#endif
|
||||
/* You must return the current value of the JTAG TDO signal. */
|
||||
//return( (unsigned char) 0 );
|
||||
|
||||
delay_jtag(2000);
|
||||
return CPLD_TDO_STATE;
|
||||
}
|
||||
@ -218,39 +110,4 @@ void waitTime(long microsec)
|
||||
{
|
||||
pulseClock();
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Alternate implementation */
|
||||
/* For systems with TCK rates << 1 MHz; Consider this implementation. */
|
||||
/* This implementation does not work with Spartan-3AN or indirect flash
|
||||
programming. */
|
||||
if ( microsec >= 50L )
|
||||
{
|
||||
/* Make sure TCK is low during wait for XC18V00/XCFxxS */
|
||||
/* Or, a running TCK implementation as shown above is an OK alternate */
|
||||
setPort( TCK, 0 );
|
||||
|
||||
/* Use Windows Sleep(). Round up to the nearest millisec */
|
||||
_sleep( ( microsec + 999L ) / 1000L );
|
||||
}
|
||||
else /* Satisfy FPGA JTAG configuration, startup TCK cycles */
|
||||
{
|
||||
for ( i = 0; i < microsec; ++i )
|
||||
{
|
||||
pulseClock();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* Alternate implementation */
|
||||
/* This implementation is valid for only XC9500/XL/XV, CoolRunner/II CPLDs,
|
||||
XC18V00 PROMs, or Platform Flash XCFxxS/XCFxxP PROMs.
|
||||
This implementation does not work with FPGAs JTAG configuration. */
|
||||
/* Make sure TCK is low during wait for XC18V00/XCFxxS PROMs */
|
||||
/* Or, a running TCK implementation as shown above is an OK alternate */
|
||||
setPort( TCK, 0 );
|
||||
/* Use Windows Sleep(). Round up to the nearest millisec */
|
||||
_sleep( ( microsec + 999L ) / 1000L );
|
||||
#endif
|
||||
}
|
||||
|
@ -22,6 +22,25 @@ To program the SVF file into the CPLD:
|
||||
required, and the "program" script below expects it to be at the relative
|
||||
path "bsdl/xc2c/xc2c64.bsd".
|
||||
|
||||
Generate an XSVF
|
||||
================
|
||||
|
||||
After generating a programming file:
|
||||
|
||||
* In the ISE Project Navigator, "Processes: top - Behavioral" pane, double-click "Configure Target Device".
|
||||
* Click "OK" to open iMPACT.
|
||||
* Ctrl-N to create a "New Project".
|
||||
* "Yes" to automatically create and save a project file.
|
||||
* Select "Prepare a Boundary-Scan File", choose "XSVF".
|
||||
* Select file name "default.xsvf".
|
||||
* Click "OK" to start adding devices.
|
||||
* Assign new configuration file: "top.jed".
|
||||
* Right-click the "xc2c64a top.jed" icon and select "Erase". Accept defaults.
|
||||
* Right-click the "xc2c64a top.jed" icon and select "Program".
|
||||
* Right-click the "xc2c64a top.jed" icon and select "Verify".
|
||||
* Choose menu "Output" -> "XSVF File" -> "Stop Writing to XSVF File".
|
||||
* Close iMPACT.
|
||||
|
||||
To Program
|
||||
==========
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
BIN
firmware/cpld/sgpio_if/default.xsvf
Executable file → Normal file
BIN
firmware/cpld/sgpio_if/default.xsvf
Executable file → Normal file
Binary file not shown.
@ -9,10 +9,10 @@
|
||||
<!-- along with the project source files, is sufficient to open and -->
|
||||
<!-- implement in ISE Project Navigator. -->
|
||||
<!-- -->
|
||||
<!-- Copyright (c) 1995-2012 Xilinx, Inc. All rights reserved. -->
|
||||
<!-- Copyright (c) 1995-2013 Xilinx, Inc. All rights reserved. -->
|
||||
</header>
|
||||
|
||||
<version xil_pn:ise_version="14.1" xil_pn:schema_version="2"/>
|
||||
<version xil_pn:ise_version="14.6" xil_pn:schema_version="2"/>
|
||||
|
||||
<files>
|
||||
<file xil_pn:name="top.vhd" xil_pn:type="FILE_VHDL">
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,126 +1,67 @@
|
||||
#
|
||||
# Copyright 2012 Jared Boone
|
||||
#
|
||||
# This file is part of HackRF.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
# the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
# Boston, MA 02110-1301, USA.
|
||||
# Copyright 2012 Jared Boone
|
||||
#
|
||||
# This file is part of HackRF.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
# the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
# Boston, MA 02110-1301, USA.
|
||||
|
||||
NET "CODEC_CLK" LOC="23" |IOSTANDARD=LVCMOS33;
|
||||
NET "CODEC_CLK" LOC="23" |IOSTANDARD=LVCMOS33 | TNM=adc_data;
|
||||
NET "CODEC_X2_CLK" LOC="27" |IOSTANDARD=LVCMOS33;
|
||||
#NET "GCLK0" LOC="22" |IOSTANDARD=LVCMOS33;
|
||||
|
||||
NET "CODEC_X2_CLK" TNM_NET = CODEC_X2_CLK;
|
||||
TIMESPEC TS_codec_x2_data = PERIOD "CODEC_X2_CLK" 50 ns;
|
||||
TIMESPEC TS_codec_x2_data = PERIOD "CODEC_X2_CLK" 25 ns;
|
||||
|
||||
NET "DA<7>" LOC="35" |IOSTANDARD=LVCMOS33;
|
||||
NET "DA<6>" LOC="36" |IOSTANDARD=LVCMOS33;
|
||||
NET "DA<5>" LOC="37" |IOSTANDARD=LVCMOS33;
|
||||
NET "DA<4>" LOC="39" |IOSTANDARD=LVCMOS33;
|
||||
NET "DA<3>" LOC="40" |IOSTANDARD=LVCMOS33;
|
||||
NET "DA<2>" LOC="41" |IOSTANDARD=LVCMOS33;
|
||||
NET "DA<1>" LOC="42" |IOSTANDARD=LVCMOS33;
|
||||
NET "DA<0>" LOC="43" |IOSTANDARD=LVCMOS33;
|
||||
NET "DA<7>" LOC="35" |IOSTANDARD=LVCMOS33 | TNM=adc_data;
|
||||
NET "DA<6>" LOC="36" |IOSTANDARD=LVCMOS33 | TNM=adc_data;
|
||||
NET "DA<5>" LOC="37" |IOSTANDARD=LVCMOS33 | TNM=adc_data;
|
||||
NET "DA<4>" LOC="39" |IOSTANDARD=LVCMOS33 | TNM=adc_data;
|
||||
NET "DA<3>" LOC="40" |IOSTANDARD=LVCMOS33 | TNM=adc_data;
|
||||
NET "DA<2>" LOC="41" |IOSTANDARD=LVCMOS33 | TNM=adc_data;
|
||||
NET "DA<1>" LOC="42" |IOSTANDARD=LVCMOS33 | TNM=adc_data;
|
||||
NET "DA<0>" LOC="43" |IOSTANDARD=LVCMOS33 | TNM=adc_data;
|
||||
|
||||
NET "DD<9>" LOC="17" |IOSTANDARD=LVCMOS33;
|
||||
NET "DD<8>" LOC="18" |IOSTANDARD=LVCMOS33;
|
||||
NET "DD<7>" LOC="19" |IOSTANDARD=LVCMOS33;
|
||||
NET "DD<6>" LOC="24" |IOSTANDARD=LVCMOS33;
|
||||
NET "DD<5>" LOC="28" |IOSTANDARD=LVCMOS33;
|
||||
NET "DD<4>" LOC="29" |IOSTANDARD=LVCMOS33;
|
||||
NET "DD<3>" LOC="30" |IOSTANDARD=LVCMOS33;
|
||||
NET "DD<2>" LOC="32" |IOSTANDARD=LVCMOS33;
|
||||
NET "DD<1>" LOC="33" |IOSTANDARD=LVCMOS33;
|
||||
NET "DD<0>" LOC="34" |IOSTANDARD=LVCMOS33;
|
||||
NET "DD<9>" LOC="17" |IOSTANDARD=LVCMOS33 | SLEW=SLOW | TNM=dac_data;
|
||||
NET "DD<8>" LOC="18" |IOSTANDARD=LVCMOS33 | SLEW=SLOW | TNM=dac_data;
|
||||
NET "DD<7>" LOC="19" |IOSTANDARD=LVCMOS33 | SLEW=SLOW | TNM=dac_data;
|
||||
NET "DD<6>" LOC="24" |IOSTANDARD=LVCMOS33 | SLEW=SLOW | TNM=dac_data;
|
||||
NET "DD<5>" LOC="28" |IOSTANDARD=LVCMOS33 | SLEW=SLOW | TNM=dac_data;
|
||||
NET "DD<4>" LOC="29" |IOSTANDARD=LVCMOS33 | SLEW=SLOW | TNM=dac_data;
|
||||
NET "DD<3>" LOC="30" |IOSTANDARD=LVCMOS33 | SLEW=SLOW | TNM=dac_data;
|
||||
NET "DD<2>" LOC="32" |IOSTANDARD=LVCMOS33 | SLEW=SLOW | TNM=dac_data;
|
||||
NET "DD<1>" LOC="33" |IOSTANDARD=LVCMOS33 | SLEW=SLOW | TNM=dac_data;
|
||||
NET "DD<0>" LOC="34" |IOSTANDARD=LVCMOS33 | SLEW=SLOW | TNM=dac_data;
|
||||
|
||||
NET "B1AUX<16>" LOC="60" |IOSTANDARD=LVCMOS33;
|
||||
NET "B1AUX<15>" LOC="58" |IOSTANDARD=LVCMOS33;
|
||||
NET "B1AUX<14>" LOC="56" |IOSTANDARD=LVCMOS33;
|
||||
NET "B1AUX<13>" LOC="55" |IOSTANDARD=LVCMOS33;
|
||||
NET "B1AUX<12>" LOC="53" |IOSTANDARD=LVCMOS33;
|
||||
NET "B1AUX<11>" LOC="52" |IOSTANDARD=LVCMOS33;
|
||||
NET "B1AUX<10>" LOC="50" |IOSTANDARD=LVCMOS33;
|
||||
NET "B1AUX<9>" LOC="49" |IOSTANDARD=LVCMOS33;
|
||||
NET "HOST_DIRECTION" LOC="71" |IOSTANDARD=LVCMOS33 | SLEW=SLOW;
|
||||
NET "HOST_DISABLE" LOC="76" |IOSTANDARD=LVCMOS33 | SLEW=SLOW;
|
||||
NET "HOST_CAPTURE" LOC="91" |IOSTANDARD=LVCMOS33 | SLEW=SLOW | TNM=to_host;
|
||||
NET "HOST_DATA<7>" LOC="77" |IOSTANDARD=LVCMOS33 | SLEW=SLOW | TNM=to_host;
|
||||
NET "HOST_DATA<6>" LOC="61" |IOSTANDARD=LVCMOS33 | SLEW=SLOW | TNM=to_host;
|
||||
NET "HOST_DATA<5>" LOC="64" |IOSTANDARD=LVCMOS33 | SLEW=SLOW | TNM=to_host;
|
||||
NET "HOST_DATA<4>" LOC="67" |IOSTANDARD=LVCMOS33 | SLEW=SLOW | TNM=to_host;
|
||||
NET "HOST_DATA<3>" LOC="72" |IOSTANDARD=LVCMOS33 | SLEW=SLOW | TNM=to_host;
|
||||
NET "HOST_DATA<2>" LOC="74" |IOSTANDARD=LVCMOS33 | SLEW=SLOW | TNM=to_host;
|
||||
NET "HOST_DATA<1>" LOC="79" |IOSTANDARD=LVCMOS33 | SLEW=SLOW | TNM=to_host;
|
||||
NET "HOST_DATA<0>" LOC="89" |IOSTANDARD=LVCMOS33 | SLEW=SLOW | TNM=to_host;
|
||||
|
||||
NET "HOST_DECIM_SEL<2>" LOC="78" |IOSTANDARD=LVCMOS33;
|
||||
NET "HOST_DECIM_SEL<1>" LOC="81" |IOSTANDARD=LVCMOS33;
|
||||
NET "HOST_DECIM_SEL<0>" LOC="90" |IOSTANDARD=LVCMOS33;
|
||||
|
||||
#NET "SGPIO<15>" LOC="78" |IOSTANDARD=LVCMOS33;
|
||||
#NET "SGPIO<14>" LOC="81" |IOSTANDARD=LVCMOS33;
|
||||
#NET "SGPIO<13>" LOC="90" |IOSTANDARD=LVCMOS33;
|
||||
#NET "SGPIO<12>" LOC="70" |IOSTANDARD=LVCMOS33;
|
||||
NET "HOST_DIRECTION" LOC="71" |IOSTANDARD=LVCMOS33;
|
||||
NET "HOST_DISABLE" LOC="76" |IOSTANDARD=LVCMOS33;
|
||||
NET "HOST_CAPTURE" LOC="91" |IOSTANDARD=LVCMOS33;
|
||||
#NET "HOST_CLK" LOC="68" |IOSTANDARD=LVCMOS33;
|
||||
NET "HOST_DATA<7>" LOC="77" |IOSTANDARD=LVCMOS33;
|
||||
NET "HOST_DATA<6>" LOC="61" |IOSTANDARD=LVCMOS33;
|
||||
NET "HOST_DATA<5>" LOC="64" |IOSTANDARD=LVCMOS33;
|
||||
NET "HOST_DATA<4>" LOC="67" |IOSTANDARD=LVCMOS33;
|
||||
NET "HOST_DATA<3>" LOC="72" |IOSTANDARD=LVCMOS33;
|
||||
NET "HOST_DATA<2>" LOC="74" |IOSTANDARD=LVCMOS33;
|
||||
NET "HOST_DATA<1>" LOC="79" |IOSTANDARD=LVCMOS33;
|
||||
NET "HOST_DATA<0>" LOC="89" |IOSTANDARD=LVCMOS33;
|
||||
TIMEGRP "adc_data" OFFSET = IN 16 ns BEFORE "CODEC_X2_CLK";
|
||||
|
||||
NET "B2AUX<16>" LOC="92" |IOSTANDARD=LVCMOS33;
|
||||
NET "B2AUX<15>" LOC="94" |IOSTANDARD=LVCMOS33;
|
||||
NET "B2AUX<14>" LOC="97" |IOSTANDARD=LVCMOS33;
|
||||
NET "B2AUX<13>" LOC="99" |IOSTANDARD=LVCMOS33;
|
||||
NET "B2AUX<12>" LOC="1" |IOSTANDARD=LVCMOS33;
|
||||
NET "B2AUX<11>" LOC="2" |IOSTANDARD=LVCMOS33;
|
||||
NET "B2AUX<10>" LOC="3" |IOSTANDARD=LVCMOS33;
|
||||
NET "B2AUX<9>" LOC="4" |IOSTANDARD=LVCMOS33;
|
||||
NET "B2AUX<8>" LOC="6" |IOSTANDARD=LVCMOS33;
|
||||
NET "B2AUX<7>" LOC="7" |IOSTANDARD=LVCMOS33;
|
||||
NET "B2AUX<6>" LOC="8" |IOSTANDARD=LVCMOS33;
|
||||
NET "B2AUX<5>" LOC="9" |IOSTANDARD=LVCMOS33;
|
||||
NET "B2AUX<4>" LOC="10" |IOSTANDARD=LVCMOS33;
|
||||
NET "B2AUX<3>" LOC="11" |IOSTANDARD=LVCMOS33;
|
||||
NET "B2AUX<2>" LOC="12" |IOSTANDARD=LVCMOS33;
|
||||
NET "B2AUX<1>" LOC="13" |IOSTANDARD=LVCMOS33;
|
||||
TIMEGRP "dac_data" OFFSET = OUT 15 ns AFTER "CODEC_X2_CLK";
|
||||
|
||||
INST "DA<0>" TNM=adc_data;
|
||||
INST "DA<1>" TNM=adc_data;
|
||||
INST "DA<2>" TNM=adc_data;
|
||||
INST "DA<3>" TNM=adc_data;
|
||||
INST "DA<4>" TNM=adc_data;
|
||||
INST "DA<5>" TNM=adc_data;
|
||||
INST "DA<6>" TNM=adc_data;
|
||||
INST "DA<7>" TNM=adc_data;
|
||||
|
||||
TIMESPEC "TS_adc_data" = FROM "adc_data" TO "CODEC_X2_CLK" 16 ns;
|
||||
|
||||
INST "DD<0>" TNM=dac_data;
|
||||
INST "DD<1>" TNM=dac_data;
|
||||
INST "DD<2>" TNM=dac_data;
|
||||
INST "DD<3>" TNM=dac_data;
|
||||
INST "DD<4>" TNM=dac_data;
|
||||
INST "DD<5>" TNM=dac_data;
|
||||
INST "DD<6>" TNM=dac_data;
|
||||
INST "DD<7>" TNM=dac_data;
|
||||
INST "DD<8>" TNM=dac_data;
|
||||
INST "DD<9>" TNM=dac_data;
|
||||
|
||||
TIMESPEC "TS_dac_data" = FROM "CODEC_X2_CLK" TO "dac_data" 15 ns;
|
||||
|
||||
INST "HOST_DATA<7>" TNM=to_host;
|
||||
INST "HOST_DATA<6>" TNM=to_host;
|
||||
INST "HOST_DATA<5>" TNM=to_host;
|
||||
INST "HOST_DATA<4>" TNM=to_host;
|
||||
INST "HOST_DATA<3>" TNM=to_host;
|
||||
INST "HOST_DATA<2>" TNM=to_host;
|
||||
INST "HOST_DATA<1>" TNM=to_host;
|
||||
INST "HOST_DATA<0>" TNM=to_host;
|
||||
INST "HOST_CAPTURE" TNM=to_host;
|
||||
|
||||
#TIMESPEC "TS_to_host" = FROM "to_host" TO "HOST_CLK" 6 ns;
|
||||
#TIMEGRP "to_host" OFFSET=OUT 6 ns AFTER "HOST_CLK";
|
||||
TIMEGRP "to_host" OFFSET = OUT 20 ns AFTER "CODEC_X2_CLK";
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
|
||||
library UNISIM;
|
||||
use UNISIM.vcomponents.all;
|
||||
@ -30,16 +31,14 @@ entity top is
|
||||
HOST_DATA : inout std_logic_vector(7 downto 0);
|
||||
HOST_CAPTURE : out std_logic;
|
||||
HOST_DISABLE : in std_logic;
|
||||
HOST_DIRECTION : in std_logic;
|
||||
HOST_DIRECTION : in std_logic;
|
||||
HOST_DECIM_SEL : in std_logic_vector(2 downto 0);
|
||||
|
||||
DA : in std_logic_vector(7 downto 0);
|
||||
DD : out std_logic_vector(9 downto 0);
|
||||
|
||||
CODEC_CLK : in std_logic;
|
||||
CODEC_X2_CLK : in std_logic;
|
||||
|
||||
B1AUX : inout std_logic_vector(16 downto 9);
|
||||
B2AUX : inout std_logic_vector(16 downto 1)
|
||||
CODEC_X2_CLK : in std_logic
|
||||
);
|
||||
|
||||
end top;
|
||||
@ -60,11 +59,12 @@ architecture Behavioral of top is
|
||||
signal data_from_host_i : std_logic_vector(7 downto 0);
|
||||
signal data_to_host_o : std_logic_vector(7 downto 0);
|
||||
|
||||
signal decimate_count : std_logic_vector(2 downto 0) := "111";
|
||||
signal decimate_sel_i : std_logic_vector(2 downto 0);
|
||||
signal decimate_en : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
B1AUX <= (others => '0');
|
||||
B2AUX <= (others => '0');
|
||||
|
||||
------------------------------------------------
|
||||
-- Codec interface
|
||||
|
||||
@ -93,13 +93,36 @@ begin
|
||||
host_data_enable_i <= not HOST_DISABLE;
|
||||
transfer_direction_i <= to_dac when HOST_DIRECTION = '1'
|
||||
else from_adc;
|
||||
|
||||
------------------------------------------------
|
||||
|
||||
|
||||
decimate_sel_i <= HOST_DECIM_SEL;
|
||||
|
||||
------------------------------------------------
|
||||
|
||||
decimate_en <= '1' when decimate_count = "111" else '0';
|
||||
|
||||
process(host_clk_i)
|
||||
begin
|
||||
if rising_edge(host_clk_i) then
|
||||
if codec_clk_i = '1' then
|
||||
if decimate_count = "111" or host_data_enable_i = '0' then
|
||||
decimate_count <= decimate_sel_i;
|
||||
else
|
||||
decimate_count <= decimate_count + 1;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process(host_clk_i)
|
||||
begin
|
||||
if rising_edge(host_clk_i) then
|
||||
data_to_host_o <= adc_data_i;
|
||||
if codec_clk_i = '1' then
|
||||
-- I: non-inverted between MAX2837 and MAX5864
|
||||
data_to_host_o <= adc_data_i xor X"80";
|
||||
else
|
||||
-- Q: inverted between MAX2837 and MAX5864
|
||||
data_to_host_o <= adc_data_i xor X"7f";
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
@ -107,14 +130,14 @@ begin
|
||||
begin
|
||||
if rising_edge(host_clk_i) then
|
||||
if transfer_direction_i = to_dac then
|
||||
dac_data_o <= data_from_host_i & "00";
|
||||
dac_data_o <= (data_from_host_i xor X"7f") & "11";
|
||||
else
|
||||
dac_data_o <= (dac_data_o'high => '1', others => '0');
|
||||
dac_data_o <= (dac_data_o'high => '0', others => '1');
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process(host_clk_i, codec_clk_i)
|
||||
process(host_clk_i)
|
||||
begin
|
||||
if rising_edge(host_clk_i) then
|
||||
if transfer_direction_i = to_dac then
|
||||
@ -123,7 +146,7 @@ begin
|
||||
end if;
|
||||
else
|
||||
if codec_clk_i = '0' then
|
||||
host_data_capture_o <= host_data_enable_i;
|
||||
host_data_capture_o <= host_data_enable_i and decimate_en;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
|
@ -1,22 +1,22 @@
|
||||
--
|
||||
-- Copyright 2012 Jared Boone
|
||||
--
|
||||
-- This file is part of HackRF.
|
||||
--
|
||||
-- This program is free software; you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
-- the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
-- Boston, MA 02110-1301, USA.
|
||||
-- Copyright 2012 Jared Boone
|
||||
--
|
||||
-- This file is part of HackRF.
|
||||
--
|
||||
-- This program is free software; you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
-- the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
-- Boston, MA 02110-1301, USA.
|
||||
|
||||
LIBRARY ieee;
|
||||
USE ieee.std_logic_1164.ALL;
|
||||
@ -31,13 +31,12 @@ ARCHITECTURE behavior OF top_tb IS
|
||||
HOST_DATA : INOUT std_logic_vector(7 downto 0);
|
||||
HOST_CAPTURE : OUT std_logic;
|
||||
HOST_DISABLE : IN std_logic;
|
||||
HOST_DIRECTION : IN std_logic;
|
||||
HOST_DIRECTION : IN std_logic;
|
||||
HOST_DECIM_SEL : IN std_logic_vector(2 downto 0);
|
||||
DA : IN std_logic_vector(7 downto 0);
|
||||
DD : OUT std_logic_vector(9 downto 0);
|
||||
CODEC_CLK : IN std_logic;
|
||||
CODEC_X2_CLK : IN std_logic;
|
||||
B1AUX : INOUT std_logic_vector(16 downto 9);
|
||||
B2AUX : INOUT std_logic_vector(16 downto 1)
|
||||
CODEC_X2_CLK : IN std_logic
|
||||
);
|
||||
END COMPONENT;
|
||||
|
||||
@ -46,12 +45,11 @@ ARCHITECTURE behavior OF top_tb IS
|
||||
signal CODEC_CLK : std_logic := '0';
|
||||
signal CODEC_X2_CLK : std_logic := '0';
|
||||
signal HOST_DISABLE : std_logic := '1';
|
||||
signal HOST_DIRECTION : std_logic := '0';
|
||||
signal HOST_DIRECTION : std_logic := '0';
|
||||
signal HOST_DECIM_SEL : std_logic_vector(2 downto 0) := "010";
|
||||
|
||||
--BiDirs
|
||||
signal HOST_DATA : std_logic_vector(7 downto 0);
|
||||
signal B1AUX : std_logic_vector(16 downto 9);
|
||||
signal B2AUX : std_logic_vector(16 downto 1);
|
||||
|
||||
--Outputs
|
||||
signal DD : std_logic_vector(9 downto 0);
|
||||
@ -63,13 +61,12 @@ begin
|
||||
HOST_DATA => HOST_DATA,
|
||||
HOST_CAPTURE => HOST_CAPTURE,
|
||||
HOST_DISABLE => HOST_DISABLE,
|
||||
HOST_DIRECTION => HOST_DIRECTION,
|
||||
HOST_DIRECTION => HOST_DIRECTION,
|
||||
HOST_DECIM_SEL => HOST_DECIM_SEL,
|
||||
DA => DA,
|
||||
DD => DD,
|
||||
CODEC_CLK => CODEC_CLK,
|
||||
CODEC_X2_CLK => CODEC_X2_CLK,
|
||||
B1AUX => B1AUX,
|
||||
B2AUX => B2AUX
|
||||
CODEC_X2_CLK => CODEC_X2_CLK
|
||||
);
|
||||
|
||||
clk_process :process
|
||||
@ -90,11 +87,11 @@ begin
|
||||
begin
|
||||
wait until rising_edge(CODEC_CLK);
|
||||
wait for 9 ns;
|
||||
DA <= (others => '0');
|
||||
DA <= "00000000";
|
||||
|
||||
wait until falling_edge(CODEC_CLK);
|
||||
wait for 9 ns;
|
||||
DA <= (others => '1');
|
||||
DA <= "00000001";
|
||||
|
||||
end process;
|
||||
|
||||
@ -132,4 +129,4 @@ begin
|
||||
wait;
|
||||
end process;
|
||||
|
||||
end;
|
||||
end;
|
@ -1,42 +0,0 @@
|
||||
# Hey Emacs, this is a -*- makefile -*-
|
||||
#
|
||||
# Copyright 2013 Benjamin Vernoux <titanmkd@gmail.com>
|
||||
#
|
||||
# This file is part of HackRF.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
# the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
# Boston, MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
BINARY = cpldjtagprog_rom_to_ram
|
||||
|
||||
SRC_DIR = cpldjtagprog
|
||||
|
||||
SRC = cpldjtagprog.c \
|
||||
../common/hackrf_core.c \
|
||||
../common/si5351c.c \
|
||||
../common/max2837.c \
|
||||
../common/cpld_jtag.c \
|
||||
../common/xapp058/lenval.c \
|
||||
../common/xapp058/micro.c \
|
||||
../common/xapp058/ports.c
|
||||
|
||||
LDSCRIPT = ../common/LPC4330_M4_rom_to_ram.ld
|
||||
|
||||
%.o: ../$(SRC_DIR)/%.c Makefile
|
||||
@printf " CC $(subst $(shell pwd)/,,$(@))\n"
|
||||
$(Q)$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
include ../common/Makefile_inc.mk
|
@ -1 +0,0 @@
|
||||
This is a test program for CPLD JTAG programming.
|
@ -20,13 +20,30 @@
|
||||
# Boston, MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
BINARY = hackrf_usb
|
||||
ifeq ($(RUN_FROM),RAM)
|
||||
BINARY = hackrf_usb_ram
|
||||
else
|
||||
BINARY = hackrf_usb_rom_to_ram
|
||||
endif
|
||||
|
||||
SRC = $(BINARY).c \
|
||||
usb.c \
|
||||
usb_request.c \
|
||||
usb_standard_request.c \
|
||||
SRC_M4_C = hackrf_usb.c \
|
||||
../common/rf_path.c \
|
||||
../common/tuning.c \
|
||||
../common/streaming.c \
|
||||
sgpio_isr.c \
|
||||
usb_bulk_buffer.c \
|
||||
../common/usb.c \
|
||||
../common/usb_request.c \
|
||||
../common/usb_standard_request.c \
|
||||
usb_descriptor.c \
|
||||
usb_device.c \
|
||||
usb_endpoint.c \
|
||||
usb_api_board_info.c \
|
||||
usb_api_cpld.c \
|
||||
usb_api_register.c \
|
||||
usb_api_spiflash.c \
|
||||
usb_api_transceiver.c \
|
||||
../common/usb_queue.c \
|
||||
../common/fault_handler.c \
|
||||
../common/hackrf_core.c \
|
||||
../common/sgpio.c \
|
||||
|
@ -1,45 +0,0 @@
|
||||
# Hey Emacs, this is a -*- makefile -*-
|
||||
#
|
||||
# Copyright 2012 Jared Boone <jared@sharebrained.com>
|
||||
#
|
||||
# This file is part of HackRF.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
# the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
# Boston, MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
BINARY = hackrf_usb_rom_to_ram
|
||||
|
||||
SRC = hackrf_usb.c \
|
||||
usb.c \
|
||||
usb_request.c \
|
||||
usb_standard_request.c \
|
||||
usb_descriptor.c \
|
||||
../common/fault_handler.c \
|
||||
../common/hackrf_core.c \
|
||||
../common/sgpio.c \
|
||||
../common/si5351c.c \
|
||||
../common/max2837.c \
|
||||
../common/max5864.c \
|
||||
../common/rffc5071.c \
|
||||
../common/w25q80bv.c \
|
||||
../common/cpld_jtag.c \
|
||||
../common/xapp058/lenval.c \
|
||||
../common/xapp058/micro.c \
|
||||
../common/xapp058/ports.c \
|
||||
../common/rom_iap.c
|
||||
|
||||
LDSCRIPT = ../common/LPC4330_M4_rom_to_ram.ld
|
||||
include ../common/Makefile_inc.mk
|
File diff suppressed because it is too large
Load Diff
85
firmware/hackrf_usb/sgpio_isr.c
Normal file
85
firmware/hackrf_usb/sgpio_isr.c
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2012 Jared Boone
|
||||
* Copyright 2013 Benjamin Vernoux
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "sgpio_isr.h"
|
||||
|
||||
#include <libopencm3/lpc43xx/sgpio.h>
|
||||
|
||||
#include "usb_bulk_buffer.h"
|
||||
|
||||
void sgpio_isr_rx() {
|
||||
SGPIO_CLR_STATUS_1 = (1 << SGPIO_SLICE_A);
|
||||
|
||||
uint32_t* const p = (uint32_t*)&usb_bulk_buffer[usb_bulk_buffer_offset];
|
||||
__asm__(
|
||||
"ldr r0, [%[SGPIO_REG_SS], #44]\n\t"
|
||||
"str r0, [%[p], #0]\n\t"
|
||||
"ldr r0, [%[SGPIO_REG_SS], #20]\n\t"
|
||||
"str r0, [%[p], #4]\n\t"
|
||||
"ldr r0, [%[SGPIO_REG_SS], #40]\n\t"
|
||||
"str r0, [%[p], #8]\n\t"
|
||||
"ldr r0, [%[SGPIO_REG_SS], #8]\n\t"
|
||||
"str r0, [%[p], #12]\n\t"
|
||||
"ldr r0, [%[SGPIO_REG_SS], #36]\n\t"
|
||||
"str r0, [%[p], #16]\n\t"
|
||||
"ldr r0, [%[SGPIO_REG_SS], #16]\n\t"
|
||||
"str r0, [%[p], #20]\n\t"
|
||||
"ldr r0, [%[SGPIO_REG_SS], #32]\n\t"
|
||||
"str r0, [%[p], #24]\n\t"
|
||||
"ldr r0, [%[SGPIO_REG_SS], #0]\n\t"
|
||||
"str r0, [%[p], #28]\n\t"
|
||||
:
|
||||
: [SGPIO_REG_SS] "l" (SGPIO_PORT_BASE + 0x100),
|
||||
[p] "l" (p)
|
||||
: "r0"
|
||||
);
|
||||
usb_bulk_buffer_offset = (usb_bulk_buffer_offset + 32) & usb_bulk_buffer_mask;
|
||||
}
|
||||
|
||||
void sgpio_isr_tx() {
|
||||
SGPIO_CLR_STATUS_1 = (1 << SGPIO_SLICE_A);
|
||||
|
||||
uint32_t* const p = (uint32_t*)&usb_bulk_buffer[usb_bulk_buffer_offset];
|
||||
__asm__(
|
||||
"ldr r0, [%[p], #0]\n\t"
|
||||
"str r0, [%[SGPIO_REG_SS], #44]\n\t"
|
||||
"ldr r0, [%[p], #4]\n\t"
|
||||
"str r0, [%[SGPIO_REG_SS], #20]\n\t"
|
||||
"ldr r0, [%[p], #8]\n\t"
|
||||
"str r0, [%[SGPIO_REG_SS], #40]\n\t"
|
||||
"ldr r0, [%[p], #12]\n\t"
|
||||
"str r0, [%[SGPIO_REG_SS], #8]\n\t"
|
||||
"ldr r0, [%[p], #16]\n\t"
|
||||
"str r0, [%[SGPIO_REG_SS], #36]\n\t"
|
||||
"ldr r0, [%[p], #20]\n\t"
|
||||
"str r0, [%[SGPIO_REG_SS], #16]\n\t"
|
||||
"ldr r0, [%[p], #24]\n\t"
|
||||
"str r0, [%[SGPIO_REG_SS], #32]\n\t"
|
||||
"ldr r0, [%[p], #28]\n\t"
|
||||
"str r0, [%[SGPIO_REG_SS], #0]\n\t"
|
||||
:
|
||||
: [SGPIO_REG_SS] "l" (SGPIO_PORT_BASE + 0x100),
|
||||
[p] "l" (p)
|
||||
: "r0"
|
||||
);
|
||||
usb_bulk_buffer_offset = (usb_bulk_buffer_offset + 32) & usb_bulk_buffer_mask;
|
||||
}
|
29
firmware/hackrf_usb/sgpio_isr.h
Normal file
29
firmware/hackrf_usb/sgpio_isr.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2012 Jared Boone
|
||||
* Copyright 2013 Benjamin Vernoux
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __SGPIO_ISR_H__
|
||||
#define __SGPIO_ISR_H__
|
||||
|
||||
void sgpio_isr_rx();
|
||||
void sgpio_isr_tx();
|
||||
|
||||
#endif/*__SGPIO_ISR_H__*/
|
93
firmware/hackrf_usb/usb_api_board_info.c
Normal file
93
firmware/hackrf_usb/usb_api_board_info.c
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2012 Jared Boone
|
||||
* Copyright 2013 Benjamin Vernoux
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "usb_api_board_info.h"
|
||||
|
||||
#include <hackrf_core.h>
|
||||
#include <rom_iap.h>
|
||||
#include <usb_queue.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
char version_string[] = VERSION_STRING;
|
||||
|
||||
usb_request_status_t usb_vendor_request_read_board_id(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage)
|
||||
{
|
||||
if (stage == USB_TRANSFER_STAGE_SETUP) {
|
||||
endpoint->buffer[0] = BOARD_ID;
|
||||
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1, NULL, NULL);
|
||||
usb_transfer_schedule_ack(endpoint->out);
|
||||
}
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
|
||||
usb_request_status_t usb_vendor_request_read_version_string(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage)
|
||||
{
|
||||
uint8_t length;
|
||||
|
||||
if (stage == USB_TRANSFER_STAGE_SETUP) {
|
||||
length = (uint8_t)strlen(version_string);
|
||||
usb_transfer_schedule_block(endpoint->in, version_string, length, NULL, NULL);
|
||||
usb_transfer_schedule_ack(endpoint->out);
|
||||
}
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
|
||||
usb_request_status_t usb_vendor_request_read_partid_serialno(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage)
|
||||
{
|
||||
uint8_t length;
|
||||
read_partid_serialno_t read_partid_serialno;
|
||||
iap_cmd_res_t iap_cmd_res;
|
||||
|
||||
if (stage == USB_TRANSFER_STAGE_SETUP)
|
||||
{
|
||||
/* Read IAP Part Number Identification */
|
||||
iap_cmd_res.cmd_param.command_code = IAP_CMD_READ_PART_ID_NO;
|
||||
iap_cmd_call(&iap_cmd_res);
|
||||
if(iap_cmd_res.status_res.status_ret != CMD_SUCCESS)
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
|
||||
read_partid_serialno.part_id[0] = iap_cmd_res.status_res.iap_result[0];
|
||||
read_partid_serialno.part_id[1] = iap_cmd_res.status_res.iap_result[1];
|
||||
|
||||
/* Read IAP Serial Number Identification */
|
||||
iap_cmd_res.cmd_param.command_code = IAP_CMD_READ_SERIAL_NO;
|
||||
iap_cmd_call(&iap_cmd_res);
|
||||
if(iap_cmd_res.status_res.status_ret != CMD_SUCCESS)
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
|
||||
read_partid_serialno.serial_no[0] = iap_cmd_res.status_res.iap_result[0];
|
||||
read_partid_serialno.serial_no[1] = iap_cmd_res.status_res.iap_result[1];
|
||||
read_partid_serialno.serial_no[2] = iap_cmd_res.status_res.iap_result[2];
|
||||
read_partid_serialno.serial_no[3] = iap_cmd_res.status_res.iap_result[3];
|
||||
|
||||
length = (uint8_t)sizeof(read_partid_serialno_t);
|
||||
usb_transfer_schedule_block(endpoint->in, &read_partid_serialno, length,
|
||||
NULL, NULL);
|
||||
usb_transfer_schedule_ack(endpoint->out);
|
||||
}
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
43
firmware/hackrf_usb/usb_api_board_info.h
Normal file
43
firmware/hackrf_usb/usb_api_board_info.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2012 Jared Boone
|
||||
* Copyright 2013 Benjamin Vernoux
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __USB_API_BOARD_INFO_H__
|
||||
#define __USB_API_BOARD_INFO_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <usb_type.h>
|
||||
#include <usb_request.h>
|
||||
|
||||
typedef struct {
|
||||
uint32_t part_id[2];
|
||||
uint32_t serial_no[4];
|
||||
} read_partid_serialno_t;
|
||||
|
||||
usb_request_status_t usb_vendor_request_read_board_id(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
|
||||
usb_request_status_t usb_vendor_request_read_version_string(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
|
||||
usb_request_status_t usb_vendor_request_read_partid_serialno(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
|
||||
|
||||
#endif /* end of include guard: __USB_API_BOARD_INFO_H__ */
|
94
firmware/hackrf_usb/usb_api_cpld.c
Normal file
94
firmware/hackrf_usb/usb_api_cpld.c
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 2012 Jared Boone
|
||||
* Copyright 2013 Benjamin Vernoux
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "usb_api_cpld.h"
|
||||
|
||||
#include <libopencm3/lpc43xx/gpio.h>
|
||||
|
||||
#include <hackrf_core.h>
|
||||
#include <cpld_jtag.h>
|
||||
#include <usb_queue.h>
|
||||
|
||||
#include "usb_endpoint.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
volatile bool start_cpld_update = false;
|
||||
uint8_t cpld_xsvf_buffer[512];
|
||||
volatile bool cpld_wait = false;
|
||||
|
||||
static void cpld_buffer_refilled(void* user_data, unsigned int length)
|
||||
{
|
||||
cpld_wait = false;
|
||||
}
|
||||
|
||||
static void refill_cpld_buffer(void)
|
||||
{
|
||||
cpld_wait = true;
|
||||
usb_transfer_schedule(
|
||||
&usb_endpoint_bulk_out,
|
||||
cpld_xsvf_buffer,
|
||||
sizeof(cpld_xsvf_buffer),
|
||||
cpld_buffer_refilled,
|
||||
NULL
|
||||
);
|
||||
|
||||
// Wait until transfer finishes
|
||||
while (cpld_wait);
|
||||
}
|
||||
|
||||
void cpld_update(void)
|
||||
{
|
||||
#define WAIT_LOOP_DELAY (6000000)
|
||||
#define ALL_LEDS (PIN_LED1|PIN_LED2|PIN_LED3)
|
||||
int i;
|
||||
int error;
|
||||
|
||||
usb_queue_flush_endpoint(&usb_endpoint_bulk_in);
|
||||
usb_queue_flush_endpoint(&usb_endpoint_bulk_out);
|
||||
|
||||
refill_cpld_buffer();
|
||||
|
||||
error = cpld_jtag_program(sizeof(cpld_xsvf_buffer),
|
||||
cpld_xsvf_buffer,
|
||||
refill_cpld_buffer);
|
||||
if(error == 0)
|
||||
{
|
||||
/* blink LED1, LED2, and LED3 on success */
|
||||
while (1)
|
||||
{
|
||||
gpio_set(PORT_LED1_3, ALL_LEDS); /* LEDs on */
|
||||
for (i = 0; i < WAIT_LOOP_DELAY; i++) /* Wait a bit. */
|
||||
__asm__("nop");
|
||||
gpio_clear(PORT_LED1_3, ALL_LEDS); /* LEDs off */
|
||||
for (i = 0; i < WAIT_LOOP_DELAY; i++) /* Wait a bit. */
|
||||
__asm__("nop");
|
||||
}
|
||||
}else
|
||||
{
|
||||
/* LED3 (Red) steady on error */
|
||||
gpio_set(PORT_LED1_3, PIN_LED3); /* LEDs on */
|
||||
while (1);
|
||||
}
|
||||
}
|
32
firmware/hackrf_usb/usb_api_cpld.h
Normal file
32
firmware/hackrf_usb/usb_api_cpld.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2012 Jared Boone
|
||||
* Copyright 2013 Benjamin Vernoux
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __USB_API_CPLD_H__
|
||||
#define __USB_API_CPLD_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
extern volatile bool start_cpld_update;
|
||||
|
||||
void cpld_update(void);
|
||||
|
||||
#endif /* end of include guard: __USB_API_CPLD_H__ */
|
147
firmware/hackrf_usb/usb_api_register.c
Normal file
147
firmware/hackrf_usb/usb_api_register.c
Normal file
@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright 2012 Jared Boone
|
||||
* Copyright 2013 Benjamin Vernoux
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "usb_api_register.h"
|
||||
|
||||
#include <usb_queue.h>
|
||||
#include <max2837.h>
|
||||
#include <si5351c.h>
|
||||
#include <rffc5071.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
usb_request_status_t usb_vendor_request_write_max2837(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage
|
||||
) {
|
||||
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
||||
if( endpoint->setup.index < MAX2837_NUM_REGS ) {
|
||||
if( endpoint->setup.value < MAX2837_DATA_REGS_MAX_VALUE ) {
|
||||
max2837_reg_write(endpoint->setup.index, endpoint->setup.value);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
}
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
} else {
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
usb_request_status_t usb_vendor_request_read_max2837(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage
|
||||
) {
|
||||
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
||||
if( endpoint->setup.index < MAX2837_NUM_REGS ) {
|
||||
const uint16_t value = max2837_reg_read(endpoint->setup.index);
|
||||
endpoint->buffer[0] = value & 0xff;
|
||||
endpoint->buffer[1] = value >> 8;
|
||||
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 2,
|
||||
NULL, NULL);
|
||||
usb_transfer_schedule_ack(endpoint->out);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
} else {
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
usb_request_status_t usb_vendor_request_write_si5351c(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage
|
||||
) {
|
||||
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
||||
if( endpoint->setup.index < 256 ) {
|
||||
if( endpoint->setup.value < 256 ) {
|
||||
si5351c_write_single(endpoint->setup.index, endpoint->setup.value);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
}
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
} else {
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
usb_request_status_t usb_vendor_request_read_si5351c(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage
|
||||
) {
|
||||
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
||||
if( endpoint->setup.index < 256 ) {
|
||||
const uint8_t value = si5351c_read_single(endpoint->setup.index);
|
||||
endpoint->buffer[0] = value;
|
||||
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1,
|
||||
NULL, NULL);
|
||||
usb_transfer_schedule_ack(endpoint->out);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
} else {
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
usb_request_status_t usb_vendor_request_write_rffc5071(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage
|
||||
) {
|
||||
if( stage == USB_TRANSFER_STAGE_SETUP )
|
||||
{
|
||||
if( endpoint->setup.index < RFFC5071_NUM_REGS )
|
||||
{
|
||||
rffc5071_reg_write(endpoint->setup.index, endpoint->setup.value);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
} else {
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
usb_request_status_t usb_vendor_request_read_rffc5071(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage
|
||||
) {
|
||||
uint16_t value;
|
||||
if( stage == USB_TRANSFER_STAGE_SETUP )
|
||||
{
|
||||
if( endpoint->setup.index < RFFC5071_NUM_REGS )
|
||||
{
|
||||
value = rffc5071_reg_read(endpoint->setup.index);
|
||||
endpoint->buffer[0] = value & 0xff;
|
||||
endpoint->buffer[1] = value >> 8;
|
||||
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 2,
|
||||
NULL, NULL);
|
||||
usb_transfer_schedule_ack(endpoint->out);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
} else {
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
}
|
54
firmware/hackrf_usb/usb_api_register.h
Normal file
54
firmware/hackrf_usb/usb_api_register.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2012 Jared Boone
|
||||
* Copyright 2013 Benjamin Vernoux
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __USB_API_REGISTER_H__
|
||||
#define __USB_API_REGISTER_H__
|
||||
|
||||
#include <usb_type.h>
|
||||
#include <usb_request.h>
|
||||
|
||||
usb_request_status_t usb_vendor_request_write_max2837(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage
|
||||
);
|
||||
usb_request_status_t usb_vendor_request_read_max2837(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage
|
||||
);
|
||||
usb_request_status_t usb_vendor_request_write_si5351c(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage
|
||||
);
|
||||
usb_request_status_t usb_vendor_request_read_si5351c(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage
|
||||
);
|
||||
usb_request_status_t usb_vendor_request_write_rffc5071(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage
|
||||
);
|
||||
usb_request_status_t usb_vendor_request_read_rffc5071(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage
|
||||
);
|
||||
|
||||
#endif /* end of include guard: __USB_API_REGISTER_H__ */
|
131
firmware/hackrf_usb/usb_api_spiflash.c
Normal file
131
firmware/hackrf_usb/usb_api_spiflash.c
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright 2012 Jared Boone
|
||||
* Copyright 2013 Benjamin Vernoux
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "usb_api_spiflash.h"
|
||||
|
||||
#include "usb_queue.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <w25q80bv.h>
|
||||
|
||||
uint8_t spiflash_buffer[W25Q80BV_PAGE_LEN];
|
||||
|
||||
usb_request_status_t usb_vendor_request_erase_spiflash(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage)
|
||||
{
|
||||
//FIXME This should refuse to run if executing from SPI flash.
|
||||
|
||||
if (stage == USB_TRANSFER_STAGE_SETUP) {
|
||||
w25q80bv_setup();
|
||||
/* only chip erase is implemented */
|
||||
w25q80bv_chip_erase();
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
//FIXME probably should undo w25q80bv_setup()
|
||||
}
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
|
||||
usb_request_status_t usb_vendor_request_write_spiflash(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage)
|
||||
{
|
||||
uint32_t addr = 0;
|
||||
uint16_t len = 0;
|
||||
|
||||
//FIXME This should refuse to run if executing from SPI flash.
|
||||
|
||||
if (stage == USB_TRANSFER_STAGE_SETUP) {
|
||||
addr = (endpoint->setup.value << 16) | endpoint->setup.index;
|
||||
len = endpoint->setup.length;
|
||||
if ((len > W25Q80BV_PAGE_LEN) || (addr > W25Q80BV_NUM_BYTES)
|
||||
|| ((addr + len) > W25Q80BV_NUM_BYTES)) {
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
} else {
|
||||
usb_transfer_schedule_block(endpoint->out, &spiflash_buffer[0], len,
|
||||
NULL, NULL);
|
||||
w25q80bv_setup();
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
} else if (stage == USB_TRANSFER_STAGE_DATA) {
|
||||
addr = (endpoint->setup.value << 16) | endpoint->setup.index;
|
||||
len = endpoint->setup.length;
|
||||
/* This check is redundant but makes me feel better. */
|
||||
if ((len > W25Q80BV_PAGE_LEN) || (addr > W25Q80BV_NUM_BYTES)
|
||||
|| ((addr + len) > W25Q80BV_NUM_BYTES)) {
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
} else {
|
||||
w25q80bv_program(addr, len, &spiflash_buffer[0]);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
//FIXME probably should undo w25q80bv_setup()
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
} else {
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
usb_request_status_t usb_vendor_request_read_spiflash(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t addr;
|
||||
uint16_t len;
|
||||
uint8_t* u8_addr_pt;
|
||||
|
||||
if (stage == USB_TRANSFER_STAGE_SETUP)
|
||||
{
|
||||
addr = (endpoint->setup.value << 16) | endpoint->setup.index;
|
||||
len = endpoint->setup.length;
|
||||
if ((len > W25Q80BV_PAGE_LEN) || (addr > W25Q80BV_NUM_BYTES)
|
||||
|| ((addr + len) > W25Q80BV_NUM_BYTES)) {
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
} else {
|
||||
/* TODO flush SPIFI "cache" before to read the SPIFI memory */
|
||||
u8_addr_pt = (uint8_t*)(addr + SPIFI_DATA_UNCACHED_BASE);
|
||||
for(i=0; i<len; i++)
|
||||
{
|
||||
spiflash_buffer[i] = u8_addr_pt[i];
|
||||
}
|
||||
usb_transfer_schedule_block(endpoint->in, &spiflash_buffer[0], len,
|
||||
NULL, NULL);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
} else if (stage == USB_TRANSFER_STAGE_DATA)
|
||||
{
|
||||
addr = (endpoint->setup.value << 16) | endpoint->setup.index;
|
||||
len = endpoint->setup.length;
|
||||
/* This check is redundant but makes me feel better. */
|
||||
if ((len > W25Q80BV_PAGE_LEN) || (addr > W25Q80BV_NUM_BYTES)
|
||||
|| ((addr + len) > W25Q80BV_NUM_BYTES))
|
||||
{
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
} else
|
||||
{
|
||||
usb_transfer_schedule_ack(endpoint->out);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
} else
|
||||
{
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
36
firmware/hackrf_usb/usb_api_spiflash.h
Normal file
36
firmware/hackrf_usb/usb_api_spiflash.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2012 Jared Boone
|
||||
* Copyright 2013 Benjamin Vernoux
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __USB_API_SPIFLASH_H__
|
||||
#define __USB_API_SPIFLASH_H__
|
||||
|
||||
#include <usb_type.h>
|
||||
#include <usb_request.h>
|
||||
|
||||
usb_request_status_t usb_vendor_request_erase_spiflash(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
|
||||
usb_request_status_t usb_vendor_request_write_spiflash(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
|
||||
usb_request_status_t usb_vendor_request_read_spiflash(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
|
||||
|
||||
#endif /* end of include guard: __USB_API_SPIFLASH_H__ */
|
189
firmware/hackrf_usb/usb_api_transceiver.c
Normal file
189
firmware/hackrf_usb/usb_api_transceiver.c
Normal file
@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright 2012 Jared Boone
|
||||
* Copyright 2013 Benjamin Vernoux
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "usb_api_transceiver.h"
|
||||
|
||||
#include <libopencm3/lpc43xx/gpio.h>
|
||||
|
||||
#include <max2837.h>
|
||||
#include <rf_path.h>
|
||||
#include <tuning.h>
|
||||
#include <usb.h>
|
||||
#include <usb_queue.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "usb_endpoint.h"
|
||||
|
||||
typedef struct {
|
||||
uint32_t freq_mhz;
|
||||
uint32_t freq_hz;
|
||||
} set_freq_params_t;
|
||||
|
||||
set_freq_params_t set_freq_params;
|
||||
|
||||
typedef struct {
|
||||
uint32_t freq_hz;
|
||||
uint32_t divider;
|
||||
} set_sample_r_params_t;
|
||||
|
||||
set_sample_r_params_t set_sample_r_params;
|
||||
|
||||
usb_request_status_t usb_vendor_request_set_baseband_filter_bandwidth(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage
|
||||
) {
|
||||
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
||||
const uint32_t bandwidth = (endpoint->setup.index << 16) | endpoint->setup.value;
|
||||
if( baseband_filter_bandwidth_set(bandwidth) ) {
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
} else {
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
usb_request_status_t usb_vendor_request_set_freq(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage)
|
||||
{
|
||||
if (stage == USB_TRANSFER_STAGE_SETUP)
|
||||
{
|
||||
usb_transfer_schedule_block(endpoint->out, &set_freq_params, sizeof(set_freq_params_t),
|
||||
NULL, NULL);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
} else if (stage == USB_TRANSFER_STAGE_DATA)
|
||||
{
|
||||
const uint64_t freq = set_freq_params.freq_mhz * 1000000 + set_freq_params.freq_hz;
|
||||
if( set_freq(freq) )
|
||||
{
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
} else
|
||||
{
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
usb_request_status_t usb_vendor_request_set_sample_rate_frac(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage)
|
||||
{
|
||||
if (stage == USB_TRANSFER_STAGE_SETUP)
|
||||
{
|
||||
usb_transfer_schedule_block(endpoint->out, &set_sample_r_params, sizeof(set_sample_r_params_t),
|
||||
NULL, NULL);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
} else if (stage == USB_TRANSFER_STAGE_DATA)
|
||||
{
|
||||
if( sample_rate_frac_set(set_sample_r_params.freq_hz * 2, set_sample_r_params.divider ) )
|
||||
{
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
} else
|
||||
{
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
usb_request_status_t usb_vendor_request_set_amp_enable(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage)
|
||||
{
|
||||
if (stage == USB_TRANSFER_STAGE_SETUP) {
|
||||
switch (endpoint->setup.value) {
|
||||
case 0:
|
||||
rf_path_set_lna(0);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
case 1:
|
||||
rf_path_set_lna(1);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
default:
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
}
|
||||
} else {
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
usb_request_status_t usb_vendor_request_set_lna_gain(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage)
|
||||
{
|
||||
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
||||
const uint8_t value = max2837_set_lna_gain(endpoint->setup.index);
|
||||
endpoint->buffer[0] = value;
|
||||
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1,
|
||||
NULL, NULL);
|
||||
usb_transfer_schedule_ack(endpoint->out);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
|
||||
usb_request_status_t usb_vendor_request_set_vga_gain(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage)
|
||||
{
|
||||
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
||||
const uint8_t value = max2837_set_vga_gain(endpoint->setup.index);
|
||||
endpoint->buffer[0] = value;
|
||||
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1,
|
||||
NULL, NULL);
|
||||
usb_transfer_schedule_ack(endpoint->out);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
|
||||
usb_request_status_t usb_vendor_request_set_txvga_gain(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage)
|
||||
{
|
||||
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
||||
const uint8_t value = max2837_set_txvga_gain(endpoint->setup.index);
|
||||
endpoint->buffer[0] = value;
|
||||
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1,
|
||||
NULL, NULL);
|
||||
usb_transfer_schedule_ack(endpoint->out);
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
||||
|
||||
usb_request_status_t usb_vendor_request_set_if_freq(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage
|
||||
) {
|
||||
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
||||
if( set_freq_if((uint32_t)endpoint->setup.index * 1000 * 1000) ) {
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
} else {
|
||||
return USB_REQUEST_STATUS_STALL;
|
||||
}
|
||||
}
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
}
|
54
firmware/hackrf_usb/usb_api_transceiver.h
Normal file
54
firmware/hackrf_usb/usb_api_transceiver.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2012 Jared Boone
|
||||
* Copyright 2013 Benjamin Vernoux
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __USB_API_TRANSCEIVER_H__
|
||||
#define __USB_API_TRANSCEIVER_H__
|
||||
|
||||
#include <hackrf_core.h>
|
||||
#include <usb_type.h>
|
||||
#include <usb_request.h>
|
||||
|
||||
usb_request_status_t usb_vendor_request_set_transceiver_mode(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage);
|
||||
usb_request_status_t usb_vendor_request_set_baseband_filter_bandwidth(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage);
|
||||
usb_request_status_t usb_vendor_request_set_freq(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage);
|
||||
usb_request_status_t usb_vendor_request_set_sample_rate_frac(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage);
|
||||
usb_request_status_t usb_vendor_request_set_amp_enable(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
|
||||
usb_request_status_t usb_vendor_request_set_lna_gain(
|
||||
usb_endpoint_t* const endpoint,
|
||||
const usb_transfer_stage_t stage);
|
||||
usb_request_status_t usb_vendor_request_set_vga_gain(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
|
||||
usb_request_status_t usb_vendor_request_set_txvga_gain(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
|
||||
usb_request_status_t usb_vendor_request_set_if_freq(
|
||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
|
||||
|
||||
#endif/*__USB_API_TRANSCEIVER_H__*/
|
26
firmware/hackrf_usb/usb_bulk_buffer.c
Normal file
26
firmware/hackrf_usb/usb_bulk_buffer.c
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2012 Jared Boone
|
||||
* Copyright 2013 Benjamin Vernoux
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "usb_bulk_buffer.h"
|
||||
|
||||
const uint32_t usb_bulk_buffer_mask = 32768 - 1;
|
||||
volatile uint32_t usb_bulk_buffer_offset = 0;
|
38
firmware/hackrf_usb/usb_bulk_buffer.h
Normal file
38
firmware/hackrf_usb/usb_bulk_buffer.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2012 Jared Boone
|
||||
* Copyright 2013 Benjamin Vernoux
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __USB_BULK_BUFFER_H__
|
||||
#define __USB_BULK_BUFFER_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* Address of usb_bulk_buffer is set in ldscripts. If you change the name of this
|
||||
* variable, it won't be where it needs to be in the processor's address space,
|
||||
* unless you also adjust the ldscripts.
|
||||
*/
|
||||
extern uint8_t usb_bulk_buffer[32768];
|
||||
|
||||
extern const uint32_t usb_bulk_buffer_mask;
|
||||
|
||||
extern volatile uint32_t usb_bulk_buffer_offset;
|
||||
|
||||
#endif/*__USB_BULK_BUFFER_H__*/
|
@ -38,117 +38,191 @@
|
||||
#define USB_STRING_LANGID (0x0409)
|
||||
|
||||
uint8_t usb_descriptor_device[] = {
|
||||
18, // bLength
|
||||
USB_DESCRIPTOR_TYPE_DEVICE, // bDescriptorType
|
||||
USB_WORD(0x0200), // bcdUSB
|
||||
0x00, // bDeviceClass
|
||||
0x00, // bDeviceSubClass
|
||||
0x00, // bDeviceProtocol
|
||||
USB_MAX_PACKET0, // bMaxPacketSize0
|
||||
USB_WORD(USB_VENDOR_ID), // idVendor
|
||||
USB_WORD(USB_PRODUCT_ID), // idProduct
|
||||
USB_WORD(0x0100), // bcdDevice
|
||||
0x01, // iManufacturer
|
||||
0x02, // iProduct
|
||||
0x00, // iSerialNumber
|
||||
0x01 // bNumConfigurations
|
||||
18, // bLength
|
||||
USB_DESCRIPTOR_TYPE_DEVICE, // bDescriptorType
|
||||
USB_WORD(0x0200), // bcdUSB
|
||||
0x00, // bDeviceClass
|
||||
0x00, // bDeviceSubClass
|
||||
0x00, // bDeviceProtocol
|
||||
USB_MAX_PACKET0, // bMaxPacketSize0
|
||||
USB_WORD(USB_VENDOR_ID), // idVendor
|
||||
USB_WORD(USB_PRODUCT_ID), // idProduct
|
||||
USB_WORD(0x0100), // bcdDevice
|
||||
0x01, // iManufacturer
|
||||
0x02, // iProduct
|
||||
0x00, // iSerialNumber
|
||||
0x02 // bNumConfigurations
|
||||
};
|
||||
|
||||
uint8_t usb_descriptor_device_qualifier[] = {
|
||||
10, // bLength
|
||||
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER, // bDescriptorType
|
||||
USB_WORD(0x0200), // bcdUSB
|
||||
0x00, // bDeviceClass
|
||||
0x00, // bDeviceSubClass
|
||||
0x00, // bDeviceProtocol
|
||||
64, // bMaxPacketSize0
|
||||
0x01, // bNumOtherSpeedConfigurations
|
||||
0x00 // bReserved
|
||||
10, // bLength
|
||||
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER, // bDescriptorType
|
||||
USB_WORD(0x0200), // bcdUSB
|
||||
0x00, // bDeviceClass
|
||||
0x00, // bDeviceSubClass
|
||||
0x00, // bDeviceProtocol
|
||||
64, // bMaxPacketSize0
|
||||
0x02, // bNumOtherSpeedConfigurations
|
||||
0x00 // bReserved
|
||||
};
|
||||
|
||||
uint8_t usb_descriptor_configuration_full_speed[] = {
|
||||
9, // bLength
|
||||
USB_DESCRIPTOR_TYPE_CONFIGURATION, // bDescriptorType
|
||||
USB_WORD(32), // wTotalLength
|
||||
0x01, // bNumInterfaces
|
||||
0x01, // bConfigurationValue
|
||||
0x00, // iConfiguration
|
||||
0x80, // bmAttributes: USB-powered
|
||||
250, // bMaxPower: 500mA
|
||||
|
||||
9, // bLength
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, // bDescriptorType
|
||||
0x00, // bInterfaceNumber
|
||||
0x00, // bAlternateSetting
|
||||
0x02, // bNumEndpoints
|
||||
0xFF, // bInterfaceClass: vendor-specific
|
||||
0xFF, // bInterfaceSubClass
|
||||
0xFF, // bInterfaceProtocol: vendor-specific
|
||||
0x00, // iInterface
|
||||
|
||||
7, // bLength
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, // bDescriptorType
|
||||
USB_BULK_IN_EP_ADDR, // bEndpointAddress
|
||||
0x02, // bmAttributes: BULK
|
||||
USB_WORD(USB_MAX_PACKET_BULK_FS), // wMaxPacketSize
|
||||
0x00, // bInterval: no NAK
|
||||
|
||||
7, // bLength
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, // bDescriptorType
|
||||
USB_BULK_OUT_EP_ADDR, // bEndpointAddress
|
||||
0x02, // bmAttributes: BULK
|
||||
USB_WORD(USB_MAX_PACKET_BULK_FS), // wMaxPacketSize
|
||||
0x00, // bInterval: no NAK
|
||||
9, // bLength
|
||||
USB_DESCRIPTOR_TYPE_CONFIGURATION, // bDescriptorType
|
||||
USB_WORD(32), // wTotalLength
|
||||
0x01, // bNumInterfaces
|
||||
0x01, // bConfigurationValue
|
||||
0x03, // iConfiguration
|
||||
0x80, // bmAttributes: USB-powered
|
||||
250, // bMaxPower: 500mA
|
||||
|
||||
9, // bLength
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, // bDescriptorType
|
||||
0x00, // bInterfaceNumber
|
||||
0x00, // bAlternateSetting
|
||||
0x02, // bNumEndpoints
|
||||
0xFF, // bInterfaceClass: vendor-specific
|
||||
0xFF, // bInterfaceSubClass
|
||||
0xFF, // bInterfaceProtocol: vendor-specific
|
||||
0x00, // iInterface
|
||||
|
||||
7, // bLength
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, // bDescriptorType
|
||||
USB_BULK_IN_EP_ADDR, // bEndpointAddress
|
||||
0x02, // bmAttributes: BULK
|
||||
USB_WORD(USB_MAX_PACKET_BULK_FS), // wMaxPacketSize
|
||||
0x00, // bInterval: no NAK
|
||||
|
||||
7, // bLength
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, // bDescriptorType
|
||||
USB_BULK_OUT_EP_ADDR, // bEndpointAddress
|
||||
0x02, // bmAttributes: BULK
|
||||
USB_WORD(USB_MAX_PACKET_BULK_FS), // wMaxPacketSize
|
||||
0x00, // bInterval: no NAK
|
||||
|
||||
0, // TERMINATOR
|
||||
};
|
||||
|
||||
uint8_t usb_descriptor_configuration_high_speed[] = {
|
||||
9, // bLength
|
||||
USB_DESCRIPTOR_TYPE_CONFIGURATION, // bDescriptorType
|
||||
USB_WORD(32), // wTotalLength
|
||||
0x01, // bNumInterfaces
|
||||
0x01, // bConfigurationValue
|
||||
0x00, // iConfiguration
|
||||
0x80, // bmAttributes: USB-powered
|
||||
250, // bMaxPower: 500mA
|
||||
|
||||
9, // bLength
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, // bDescriptorType
|
||||
0x00, // bInterfaceNumber
|
||||
0x00, // bAlternateSetting
|
||||
0x02, // bNumEndpoints
|
||||
0xFF, // bInterfaceClass: vendor-specific
|
||||
0xFF, // bInterfaceSubClass
|
||||
0xFF, // bInterfaceProtocol: vendor-specific
|
||||
0x00, // iInterface
|
||||
|
||||
7, // bLength
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, // bDescriptorType
|
||||
USB_BULK_IN_EP_ADDR, // bEndpointAddress
|
||||
0x02, // bmAttributes: BULK
|
||||
USB_WORD(USB_MAX_PACKET_BULK_HS), // wMaxPacketSize
|
||||
0x00, // bInterval: no NAK
|
||||
|
||||
7, // bLength
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, // bDescriptorType
|
||||
USB_BULK_OUT_EP_ADDR, // bEndpointAddress
|
||||
0x02, // bmAttributes: BULK
|
||||
USB_WORD(USB_MAX_PACKET_BULK_HS), // wMaxPacketSize
|
||||
0x00, // bInterval: no NAK
|
||||
9, // bLength
|
||||
USB_DESCRIPTOR_TYPE_CONFIGURATION, // bDescriptorType
|
||||
USB_WORD(32), // wTotalLength
|
||||
0x01, // bNumInterfaces
|
||||
0x01, // bConfigurationValue
|
||||
0x03, // iConfiguration
|
||||
0x80, // bmAttributes: USB-powered
|
||||
250, // bMaxPower: 500mA
|
||||
|
||||
9, // bLength
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, // bDescriptorType
|
||||
0x00, // bInterfaceNumber
|
||||
0x00, // bAlternateSetting
|
||||
0x02, // bNumEndpoints
|
||||
0xFF, // bInterfaceClass: vendor-specific
|
||||
0xFF, // bInterfaceSubClass
|
||||
0xFF, // bInterfaceProtocol: vendor-specific
|
||||
0x00, // iInterface
|
||||
|
||||
7, // bLength
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, // bDescriptorType
|
||||
USB_BULK_IN_EP_ADDR, // bEndpointAddress
|
||||
0x02, // bmAttributes: BULK
|
||||
USB_WORD(USB_MAX_PACKET_BULK_HS), // wMaxPacketSize
|
||||
0x00, // bInterval: no NAK
|
||||
|
||||
7, // bLength
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, // bDescriptorType
|
||||
USB_BULK_OUT_EP_ADDR, // bEndpointAddress
|
||||
0x02, // bmAttributes: BULK
|
||||
USB_WORD(USB_MAX_PACKET_BULK_HS), // wMaxPacketSize
|
||||
0x00, // bInterval: no NAK
|
||||
|
||||
0, // TERMINATOR
|
||||
};
|
||||
|
||||
uint8_t usb_descriptor_configuration_cpld_update_full_speed[] = {
|
||||
9, // bLength
|
||||
USB_DESCRIPTOR_TYPE_CONFIGURATION, // bDescriptorType
|
||||
USB_WORD(32), // wTotalLength
|
||||
0x01, // bNumInterfaces
|
||||
0x02, // bConfigurationValue
|
||||
0x04, // iConfiguration
|
||||
0x80, // bmAttributes: USB-powered
|
||||
250, // bMaxPower: 500mA
|
||||
|
||||
9, // bLength
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, // bDescriptorType
|
||||
0x00, // bInterfaceNumber
|
||||
0x00, // bAlternateSetting
|
||||
0x02, // bNumEndpoints
|
||||
0xFF, // bInterfaceClass: vendor-specific
|
||||
0xFF, // bInterfaceSubClass
|
||||
0xFF, // bInterfaceProtocol: vendor-specific
|
||||
0x00, // iInterface
|
||||
|
||||
7, // bLength
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, // bDescriptorType
|
||||
USB_BULK_IN_EP_ADDR, // bEndpointAddress
|
||||
0x02, // bmAttributes: BULK
|
||||
USB_WORD(USB_MAX_PACKET_BULK_FS), // wMaxPacketSize
|
||||
0x00, // bInterval: no NAK
|
||||
|
||||
7, // bLength
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, // bDescriptorType
|
||||
USB_BULK_OUT_EP_ADDR, // bEndpointAddress
|
||||
0x02, // bmAttributes: BULK
|
||||
USB_WORD(USB_MAX_PACKET_BULK_FS), // wMaxPacketSize
|
||||
0x00, // bInterval: no NAK
|
||||
|
||||
0, // TERMINATOR
|
||||
};
|
||||
|
||||
uint8_t usb_descriptor_configuration_cpld_update_high_speed[] = {
|
||||
9, // bLength
|
||||
USB_DESCRIPTOR_TYPE_CONFIGURATION, // bDescriptorType
|
||||
USB_WORD(32), // wTotalLength
|
||||
0x01, // bNumInterfaces
|
||||
0x02, // bConfigurationValue
|
||||
0x04, // iConfiguration
|
||||
0x80, // bmAttributes: USB-powered
|
||||
250, // bMaxPower: 500mA
|
||||
|
||||
9, // bLength
|
||||
USB_DESCRIPTOR_TYPE_INTERFACE, // bDescriptorType
|
||||
0x00, // bInterfaceNumber
|
||||
0x00, // bAlternateSetting
|
||||
0x02, // bNumEndpoints
|
||||
0xFF, // bInterfaceClass: vendor-specific
|
||||
0xFF, // bInterfaceSubClass
|
||||
0xFF, // bInterfaceProtocol: vendor-specific
|
||||
0x00, // iInterface
|
||||
|
||||
7, // bLength
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, // bDescriptorType
|
||||
USB_BULK_IN_EP_ADDR, // bEndpointAddress
|
||||
0x02, // bmAttributes: BULK
|
||||
USB_WORD(USB_MAX_PACKET_BULK_HS), // wMaxPacketSize
|
||||
0x00, // bInterval: no NAK
|
||||
|
||||
7, // bLength
|
||||
USB_DESCRIPTOR_TYPE_ENDPOINT, // bDescriptorType
|
||||
USB_BULK_OUT_EP_ADDR, // bEndpointAddress
|
||||
0x02, // bmAttributes: BULK
|
||||
USB_WORD(USB_MAX_PACKET_BULK_HS), // wMaxPacketSize
|
||||
0x00, // bInterval: no NAK
|
||||
|
||||
0, // TERMINATOR
|
||||
};
|
||||
|
||||
uint8_t usb_descriptor_string_languages[] = {
|
||||
0x04, // bLength
|
||||
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
|
||||
USB_WORD(USB_STRING_LANGID), // wLANGID
|
||||
0x04, // bLength
|
||||
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
|
||||
USB_WORD(USB_STRING_LANGID), // wLANGID
|
||||
};
|
||||
|
||||
uint8_t usb_descriptor_string_manufacturer[] = {
|
||||
40, // bLength
|
||||
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
|
||||
40, // bLength
|
||||
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
|
||||
'G', 0x00,
|
||||
'r', 0x00,
|
||||
'e', 0x00,
|
||||
@ -171,8 +245,8 @@ uint8_t usb_descriptor_string_manufacturer[] = {
|
||||
};
|
||||
|
||||
uint8_t usb_descriptor_string_product[] = {
|
||||
14, // bLength
|
||||
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
|
||||
14, // bLength
|
||||
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
|
||||
'H', 0x00,
|
||||
'a', 0x00,
|
||||
'c', 0x00,
|
||||
@ -181,10 +255,44 @@ uint8_t usb_descriptor_string_product[] = {
|
||||
'F', 0x00,
|
||||
};
|
||||
|
||||
uint8_t usb_descriptor_string_config1_description[] = {
|
||||
24, // bLength
|
||||
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
|
||||
'T', 0x00,
|
||||
'r', 0x00,
|
||||
'a', 0x00,
|
||||
'n', 0x00,
|
||||
's', 0x00,
|
||||
'c', 0x00,
|
||||
'e', 0x00,
|
||||
'i', 0x00,
|
||||
'v', 0x00,
|
||||
'e', 0x00,
|
||||
'r', 0x00,
|
||||
};
|
||||
|
||||
uint8_t usb_descriptor_string_config2_description[] = {
|
||||
24, // bLength
|
||||
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
|
||||
'C', 0x00,
|
||||
'P', 0x00,
|
||||
'L', 0x00,
|
||||
'D', 0x00,
|
||||
' ', 0x00,
|
||||
'u', 0x00,
|
||||
'p', 0x00,
|
||||
'd', 0x00,
|
||||
'a', 0x00,
|
||||
't', 0x00,
|
||||
'e', 0x00,
|
||||
};
|
||||
|
||||
uint8_t* const usb_descriptor_strings[] = {
|
||||
usb_descriptor_string_languages,
|
||||
usb_descriptor_string_manufacturer,
|
||||
usb_descriptor_string_product,
|
||||
usb_descriptor_string_config1_description,
|
||||
usb_descriptor_string_config2_description,
|
||||
|
||||
0, // TERMINATOR
|
||||
};
|
||||
|
@ -25,6 +25,8 @@ extern uint8_t usb_descriptor_device[];
|
||||
extern uint8_t usb_descriptor_device_qualifier[];
|
||||
extern uint8_t usb_descriptor_configuration_full_speed[];
|
||||
extern uint8_t usb_descriptor_configuration_high_speed[];
|
||||
extern uint8_t usb_descriptor_configuration_cpld_update_full_speed[];
|
||||
extern uint8_t usb_descriptor_configuration_cpld_update_high_speed[];
|
||||
extern uint8_t usb_descriptor_string_languages[];
|
||||
extern uint8_t usb_descriptor_string_manufacturer[];
|
||||
extern uint8_t usb_descriptor_string_product[];
|
||||
|
67
firmware/hackrf_usb/usb_device.c
Normal file
67
firmware/hackrf_usb/usb_device.c
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2012 Jared Boone
|
||||
* Copyright 2013 Benjamin Vernoux
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "usb_device.h"
|
||||
|
||||
#include <usb_type.h>
|
||||
|
||||
#include "usb_descriptor.h"
|
||||
|
||||
usb_configuration_t usb_configuration_high_speed = {
|
||||
.number = 1,
|
||||
.speed = USB_SPEED_HIGH,
|
||||
.descriptor = usb_descriptor_configuration_high_speed,
|
||||
};
|
||||
|
||||
usb_configuration_t usb_configuration_full_speed = {
|
||||
.number = 1,
|
||||
.speed = USB_SPEED_FULL,
|
||||
.descriptor = usb_descriptor_configuration_full_speed,
|
||||
};
|
||||
|
||||
usb_configuration_t usb_configuration_cpld_update_full_speed = {
|
||||
.number = 2,
|
||||
.speed = USB_SPEED_FULL,
|
||||
.descriptor = usb_descriptor_configuration_cpld_update_full_speed,
|
||||
};
|
||||
|
||||
usb_configuration_t usb_configuration_cpld_update_high_speed = {
|
||||
.number = 2,
|
||||
.speed = USB_SPEED_HIGH,
|
||||
.descriptor = usb_descriptor_configuration_cpld_update_high_speed,
|
||||
};
|
||||
|
||||
usb_configuration_t* usb_configurations[] = {
|
||||
&usb_configuration_high_speed,
|
||||
&usb_configuration_full_speed,
|
||||
&usb_configuration_cpld_update_full_speed,
|
||||
&usb_configuration_cpld_update_high_speed,
|
||||
0,
|
||||
};
|
||||
|
||||
usb_device_t usb_device = {
|
||||
.descriptor = usb_descriptor_device,
|
||||
.descriptor_strings = usb_descriptor_strings,
|
||||
.qualifier_descriptor = usb_descriptor_device_qualifier,
|
||||
.configurations = &usb_configurations,
|
||||
.configuration = 0,
|
||||
};
|
30
firmware/hackrf_usb/usb_device.h
Normal file
30
firmware/hackrf_usb/usb_device.h
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2012 Jared Boone
|
||||
* Copyright 2013 Benjamin Vernoux
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __USB_DEVICE_H__
|
||||
#define __USB_DEVICE_H__
|
||||
|
||||
#include <usb_type.h>
|
||||
|
||||
extern usb_device_t usb_device;
|
||||
|
||||
#endif /* end of include guard: __USB_DEVICE_H__ */
|
73
firmware/hackrf_usb/usb_endpoint.c
Normal file
73
firmware/hackrf_usb/usb_endpoint.c
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2012 Jared Boone
|
||||
* Copyright 2013 Benjamin Vernoux
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "usb_endpoint.h"
|
||||
|
||||
#include <usb_request.h>
|
||||
|
||||
#include "usb_device.h"
|
||||
|
||||
usb_endpoint_t usb_endpoint_control_out = {
|
||||
.address = 0x00,
|
||||
.device = &usb_device,
|
||||
.in = &usb_endpoint_control_in,
|
||||
.out = &usb_endpoint_control_out,
|
||||
.setup_complete = usb_setup_complete,
|
||||
.transfer_complete = usb_control_out_complete,
|
||||
};
|
||||
USB_DEFINE_QUEUE(usb_endpoint_control_out, 4);
|
||||
|
||||
usb_endpoint_t usb_endpoint_control_in = {
|
||||
.address = 0x80,
|
||||
.device = &usb_device,
|
||||
.in = &usb_endpoint_control_in,
|
||||
.out = &usb_endpoint_control_out,
|
||||
.setup_complete = 0,
|
||||
.transfer_complete = usb_control_in_complete,
|
||||
};
|
||||
static USB_DEFINE_QUEUE(usb_endpoint_control_in, 4);
|
||||
|
||||
// NOTE: Endpoint number for IN and OUT are different. I wish I had some
|
||||
// evidence that having BULK IN and OUT on separate endpoint numbers was
|
||||
// actually a good idea. Seems like everybody does it that way, but why?
|
||||
|
||||
usb_endpoint_t usb_endpoint_bulk_in = {
|
||||
.address = 0x81,
|
||||
.device = &usb_device,
|
||||
.in = &usb_endpoint_bulk_in,
|
||||
.out = 0,
|
||||
.setup_complete = 0,
|
||||
.transfer_complete = usb_queue_transfer_complete
|
||||
};
|
||||
static USB_DEFINE_QUEUE(usb_endpoint_bulk_in, 1);
|
||||
|
||||
usb_endpoint_t usb_endpoint_bulk_out = {
|
||||
.address = 0x02,
|
||||
.device = &usb_device,
|
||||
.in = 0,
|
||||
.out = &usb_endpoint_bulk_out,
|
||||
.setup_complete = 0,
|
||||
.transfer_complete = usb_queue_transfer_complete
|
||||
};
|
||||
static USB_DEFINE_QUEUE(usb_endpoint_bulk_out, 1);
|
||||
|
||||
|
41
firmware/hackrf_usb/usb_endpoint.h
Normal file
41
firmware/hackrf_usb/usb_endpoint.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2012 Jared Boone
|
||||
* Copyright 2013 Benjamin Vernoux
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __USB_ENDPOINT_H__
|
||||
#define __USB_ENDPOINT_H__
|
||||
|
||||
#include <usb_type.h>
|
||||
#include <usb_queue.h>
|
||||
|
||||
extern usb_endpoint_t usb_endpoint_control_out;
|
||||
extern USB_DECLARE_QUEUE(usb_endpoint_control_out);
|
||||
|
||||
extern usb_endpoint_t usb_endpoint_control_in;
|
||||
extern USB_DECLARE_QUEUE(usb_endpoint_control_in);
|
||||
|
||||
extern usb_endpoint_t usb_endpoint_bulk_in;
|
||||
extern USB_DECLARE_QUEUE(usb_endpoint_bulk_in);
|
||||
|
||||
extern usb_endpoint_t usb_endpoint_bulk_out;
|
||||
extern USB_DECLARE_QUEUE(usb_endpoint_bulk_out);
|
||||
|
||||
#endif /* end of include guard: __USB_ENDPOINT_H__ */
|
@ -1,53 +0,0 @@
|
||||
# Hey Emacs, this is a -*- makefile -*-
|
||||
#
|
||||
# Copyright 2013 Benjamin Vernoux <titanmkd@gmail.com>
|
||||
#
|
||||
# This file is part of HackRF.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
# the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
# Boston, MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
BINARY = hackrf_usb_rom_to_ram
|
||||
|
||||
SRC_DIR = hackrf_usb
|
||||
|
||||
SRC = hackrf_usb.c \
|
||||
usb.c \
|
||||
usb_request.c \
|
||||
usb_standard_request.c \
|
||||
usb_descriptor.c \
|
||||
../common/fault_handler.c \
|
||||
../common/hackrf_core.c \
|
||||
../common/sgpio.c \
|
||||
../common/si5351c.c \
|
||||
../common/max2837.c \
|
||||
../common/max5864.c \
|
||||
../common/rffc5071.c \
|
||||
../common/w25q80bv.c \
|
||||
../common/cpld_jtag.c \
|
||||
../common/xapp058/lenval.c \
|
||||
../common/xapp058/micro.c \
|
||||
../common/xapp058/ports.c \
|
||||
../common/rom_iap.c
|
||||
|
||||
LDSCRIPT = ../common/LPC4330_M4_rom_to_ram.ld
|
||||
|
||||
%.o: ../$(SRC_DIR)/%.c Makefile
|
||||
@printf " CC $(subst $(shell pwd)/,,$(@))\n"
|
||||
$(Q)$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
include ../common/Makefile_inc.mk
|
||||
|
Submodule firmware/libopencm3 updated: d7fdcefbd7...854c112a0e
@ -4,8 +4,11 @@ BINARY = mixertx
|
||||
|
||||
SRC = $(BINARY).c \
|
||||
../common/hackrf_core.c \
|
||||
../common/rf_path.c \
|
||||
../common/sgpio.c \
|
||||
../common/si5351c.c \
|
||||
../common/max2837.c \
|
||||
../common/max5864.c \
|
||||
../common/rffc5071.c
|
||||
|
||||
include ../common/Makefile_inc.mk
|
||||
|
@ -24,6 +24,8 @@ BINARY = sgpio-rx
|
||||
|
||||
SRC = $(BINARY).c \
|
||||
../common/hackrf_core.c \
|
||||
../common/tuning.c \
|
||||
../common/rf_path.c \
|
||||
../common/sgpio.c \
|
||||
../common/si5351c.c \
|
||||
../common/max2837.c \
|
||||
|
@ -21,19 +21,16 @@
|
||||
*/
|
||||
|
||||
#include <libopencm3/lpc43xx/gpio.h>
|
||||
#include <libopencm3/lpc43xx/scu.h>
|
||||
#include <libopencm3/lpc43xx/sgpio.h>
|
||||
#include <libopencm3/lpc43xx/cgu.h>
|
||||
#include <libopencm3/cm3/scs.h>
|
||||
|
||||
#include <hackrf_core.h>
|
||||
#include <max5864.h>
|
||||
#include <max2837.h>
|
||||
#include <rffc5071.h>
|
||||
#include <rf_path.h>
|
||||
#include <sgpio.h>
|
||||
#include <tuning.h>
|
||||
|
||||
void tx_test() {
|
||||
sgpio_configure(TRANSCEIVER_MODE_TX, false);
|
||||
sgpio_set_slice_mode(false);
|
||||
sgpio_configure(TRANSCEIVER_MODE_TX);
|
||||
|
||||
// LSB goes out first, samples are 0x<Q1><I1><Q0><I0>
|
||||
volatile uint32_t buffer[] = {
|
||||
@ -54,7 +51,8 @@ void tx_test() {
|
||||
}
|
||||
|
||||
void rx_test() {
|
||||
sgpio_configure(TRANSCEIVER_MODE_RX, false);
|
||||
sgpio_set_slice_mode(false);
|
||||
sgpio_configure(TRANSCEIVER_MODE_RX);
|
||||
|
||||
volatile uint32_t buffer[4096];
|
||||
uint32_t i = 0;
|
||||
@ -90,28 +88,17 @@ void rx_test() {
|
||||
|
||||
int main(void) {
|
||||
|
||||
const uint32_t freq = 2700000000U;
|
||||
uint8_t switchctrl = 0;
|
||||
const uint64_t freq = 2700000000U;
|
||||
|
||||
pin_setup();
|
||||
enable_1v8_power();
|
||||
cpu_clock_init();
|
||||
ssp1_init();
|
||||
ssp1_set_mode_max2837();
|
||||
max2837_setup();
|
||||
rffc5071_setup();
|
||||
#ifdef JAWBREAKER
|
||||
switchctrl = (SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_HP);
|
||||
#endif
|
||||
rffc5071_rx(switchctrl);
|
||||
rffc5071_set_frequency(500); // 500 MHz
|
||||
rf_path_init();
|
||||
rf_path_set_direction(RF_PATH_DIRECTION_RX);
|
||||
|
||||
max2837_set_frequency(freq);
|
||||
max2837_start();
|
||||
max2837_rx();
|
||||
set_freq(freq);
|
||||
|
||||
ssp1_set_mode_max5864();
|
||||
max5864_xcvr();
|
||||
rx_test();
|
||||
gpio_set(PORT_LED1_3, (PIN_LED2)); /* LED2 on */
|
||||
|
||||
|
@ -20,13 +20,15 @@
|
||||
# Boston, MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
BINARY = sgpio
|
||||
BINARY = sgpio_test
|
||||
|
||||
SRC = $(BINARY).c \
|
||||
../common/hackrf_core.c \
|
||||
../common/rf_path.c \
|
||||
../common/sgpio.c \
|
||||
../common/si5351c.c \
|
||||
../common/max2837.c \
|
||||
../common/max5864.c
|
||||
../common/max5864.c \
|
||||
../common/rffc5071.c
|
||||
|
||||
include ../common/Makefile_inc.mk
|
||||
|
@ -31,7 +31,8 @@
|
||||
#include <sgpio.h>
|
||||
|
||||
void tx_test() {
|
||||
sgpio_configure(TRANSCEIVER_MODE_TX, false);
|
||||
sgpio_set_slice_mode(false);
|
||||
sgpio_configure(TRANSCEIVER_MODE_TX);
|
||||
|
||||
// LSB goes out first, samples are 0x<Q1><I1><Q0><I0>
|
||||
volatile uint32_t buffer[] = {
|
||||
@ -52,7 +53,8 @@ void tx_test() {
|
||||
}
|
||||
|
||||
void rx_test() {
|
||||
sgpio_configure(TRANSCEIVER_MODE_RX, false);
|
||||
sgpio_set_slice_mode(false);
|
||||
sgpio_configure(TRANSCEIVER_MODE_RX);
|
||||
|
||||
volatile uint32_t buffer[4096];
|
||||
uint32_t i = 0;
|
@ -25,8 +25,8 @@ BINARY = sgpio_passthrough
|
||||
|
||||
SRC = $(BINARY).c \
|
||||
../common/hackrf_core.c \
|
||||
../common/sgpio.c \
|
||||
../common/si5351c.c \
|
||||
../common/max2837.c
|
||||
|
||||
LDSCRIPT = ../common/LPC4330_M4_rom_to_ram.ld
|
||||
include ../common/Makefile_inc.mk
|
@ -169,7 +169,7 @@ void test_sgpio_sliceA_D(void)
|
||||
/* SGPIO pin 14 outputs slice H bit 0. */
|
||||
/* SGPIO pin 15 outputs slice P bit 0. */
|
||||
/*******************************************************************************/
|
||||
const u8 slice_preset_tab[16] =
|
||||
const uint8_t slice_preset_tab[16] =
|
||||
{
|
||||
0, /* Idx00 = Slice A => SGPIO0 Freq Div by 1=0 */
|
||||
8, /* Idx01 = Slice B => SGPIO8 Freq Div by 9=8 */
|
@ -4,7 +4,11 @@ BINARY = simpletx
|
||||
|
||||
SRC = $(BINARY).c \
|
||||
../common/hackrf_core.c \
|
||||
../common/rf_path.c \
|
||||
../common/sgpio.c \
|
||||
../common/si5351c.c \
|
||||
../common/max2837.c
|
||||
../common/max2837.c \
|
||||
../common/max5864.c \
|
||||
../common/rffc5071.c
|
||||
|
||||
include ../common/Makefile_inc.mk
|
||||
|
@ -25,6 +25,7 @@ BINARY = spiflash
|
||||
|
||||
SRC = $(BINARY).c \
|
||||
../common/hackrf_core.c \
|
||||
../common/sgpio.c \
|
||||
../common/si5351c.c \
|
||||
../common/max2837.c \
|
||||
../common/w25q80bv.c
|
||||
|
@ -4,7 +4,11 @@ BINARY = startup
|
||||
|
||||
SRC = $(BINARY).c \
|
||||
../common/hackrf_core.c \
|
||||
../common/rf_path.c \
|
||||
../common/sgpio.c \
|
||||
../common/si5351c.c \
|
||||
../common/max2837.c
|
||||
../common/max2837.c \
|
||||
../common/max5864.c \
|
||||
../common/rffc5071.c
|
||||
|
||||
include ../common/Makefile_inc.mk
|
||||
|
@ -4,7 +4,11 @@ BINARY = startup_systick
|
||||
|
||||
SRC = $(BINARY).c \
|
||||
../common/hackrf_core.c \
|
||||
../common/rf_path.c \
|
||||
../common/sgpio.c \
|
||||
../common/si5351c.c \
|
||||
../common/max2837.c
|
||||
../common/max2837.c \
|
||||
../common/max5864.c \
|
||||
../common/rffc5071.c
|
||||
|
||||
include ../common/Makefile_inc.mk
|
||||
|
@ -5,7 +5,11 @@ BINARY = startup_systick_perfo_SPIFI
|
||||
SRC = startup_systick.c \
|
||||
perf_mips.c \
|
||||
../common/hackrf_core.c \
|
||||
../common/rf_path.c \
|
||||
../common/sgpio.c \
|
||||
../common/si5351c.c \
|
||||
../common/max2837.c
|
||||
../common/max2837.c \
|
||||
../common/max5864.c \
|
||||
../common/rffc5071.c
|
||||
|
||||
include ../common/Makefile_inc.mk
|
||||
|
@ -4,6 +4,9 @@ Test number of instruction per second (MIPS) slow blink ON 1s, OFF 1s
|
||||
Then after 16s (the 16tests) it blink LED1/2/3 ON/OFF each 250ms.
|
||||
This example compute the number of instructions per second executed called also MIPS (Millions of Instructions Per Second)
|
||||
|
||||
This example code run from SRAM so maximum performance expected is 204MIPS.
|
||||
See result details in result_exec_from_SRAM.txt
|
||||
|
||||
This example code run from SPIFI (SPI Quad mode) and the tests check different loop size to compute the cache size used with SPIFI and estimated to less than 256Bytes (about 128 instructions in best case and in Thumb2).
|
||||
See result_exec_from_SPIFI.txt for more details.
|
||||
|
||||
|
@ -1,38 +0,0 @@
|
||||
# Hey Emacs, this is a -*- makefile -*-
|
||||
#
|
||||
# Copyright 2013 Benjamin Vernoux <titanmkd@gmail.com>
|
||||
#
|
||||
# This file is part of HackRF.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
# the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
# Boston, MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
BINARY = startup_systick_perfo_rom_to_ram
|
||||
|
||||
SRC_DIR = startup_systick_perfo
|
||||
|
||||
SRC = startup_systick.c \
|
||||
perf_mips.c \
|
||||
../common/hackrf_core.c \
|
||||
../common/si5351c.c \
|
||||
../common/max2837.c
|
||||
LDSCRIPT = ../common/LPC4330_M4_rom_to_ram.ld
|
||||
|
||||
%.o: ../$(SRC_DIR)/%.c Makefile
|
||||
@printf " CC $(subst $(shell pwd)/,,$(@))\n"
|
||||
$(Q)$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
include ../common/Makefile_inc.mk
|
@ -1,17 +0,0 @@
|
||||
This program is an example of the startup sequence for HackRF (Jellybean with
|
||||
Lemondrop attached).
|
||||
Test number of instruction per second (MIPS) slow blink ON 1s, OFF 1s
|
||||
Then after 16s (the 16tests) it blink LED1/2/3 ON/OFF each 250ms.
|
||||
This example compute the number of instructions per second executed called also MIPS (Millions of Instructions Per Second)
|
||||
|
||||
This example code run from SRAM so maximum performance expected is 204MIPS.
|
||||
See result details in result_exec_from_SRAM.txt
|
||||
|
||||
Required Lemondrop -> Jellybean connections:
|
||||
|
||||
SCL: Lemondrop P7 pin 3 -> Jellybean P6 pin 3
|
||||
SDA: Lemondrop P7 pin 5 -> Jellybean P6 pin 5
|
||||
SDA: Lemondrop P7 pin 6 -> Jellybean P6 pin 6
|
||||
VCC: Lemondrop P4 pin 2, 4, or 6 -> Jellybean P17 pin 2, 4, or 6
|
||||
1V8: Lemondrop P11 pin 2, 4, or 6 -> Jellybean P16 pin 2, 4, or 6
|
||||
GND: Lemondrop P5 -> Jellybean P13
|
73
firmware/tools/check_clock.py
Executable file
73
firmware/tools/check_clock.py
Executable file
@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Copyright 2013 Jared Boone
|
||||
#
|
||||
# Interpret the LPC43xx Clock Generation Unit (CGU) FREQ_MON register
|
||||
# and display the estimated clock frequency.
|
||||
#
|
||||
# This file is part of HackRF.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
# the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
# Boston, MA 02110-1301, USA.
|
||||
|
||||
"""
|
||||
Inside GDB:
|
||||
(gdb) set {int}0x40050014 = 0x09800000
|
||||
(gdb) x 0x40050014
|
||||
0x40050014: 0x091bd000
|
||||
This script:
|
||||
./check_clock.py 0x<register value> 0x<RCNT initial value>
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
clock_source_names = {
|
||||
0x00: '32 kHz oscillator',
|
||||
0x01: 'IRC',
|
||||
0x02: 'ENET_RX_CLK',
|
||||
0x03: 'ENET_TX_CLK',
|
||||
0x04: 'GP_CLKIN',
|
||||
0x06: 'Crystal oscillator',
|
||||
0x07: 'PLL0USB',
|
||||
0x08: 'PLL0AUDIO',
|
||||
0x09: 'PLL1',
|
||||
0x0c: 'IDIVA',
|
||||
0x0d: 'IDIVB',
|
||||
0x0e: 'IDIVC',
|
||||
0x0f: 'IDIVD',
|
||||
0x10: 'IDIVE',
|
||||
}
|
||||
|
||||
reg_value = int(sys.argv[1], 16)
|
||||
rcnt = int(sys.argv[2], 16)
|
||||
|
||||
print('0x%08x' % reg_value)
|
||||
|
||||
rcnt_final = reg_value & 0x1ff
|
||||
fcnt = (reg_value >> 9) & 0x3fff
|
||||
clock_source = (reg_value >> 24) & 0x1f
|
||||
fref = 12e6
|
||||
|
||||
if rcnt_final != 0:
|
||||
raise RuntimeError('RCNT did not reach 0')
|
||||
|
||||
print('RCNT: %d' % rcnt)
|
||||
print('FCNT: %d' % fcnt)
|
||||
print('Fref: %d' % fref)
|
||||
|
||||
clock_hz = fcnt / float(rcnt) * fref
|
||||
clock_mhz = clock_hz / 1e6
|
||||
clock_name = clock_source_names[clock_source] if clock_source in clock_source_names else 'Reserved'
|
||||
print('%s: %.3f MHz' % (clock_name, clock_mhz))
|
382
firmware/tools/dump_cgu.py
Executable file
382
firmware/tools/dump_cgu.py
Executable file
@ -0,0 +1,382 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Copyright 2013 Jared Boone
|
||||
#
|
||||
# Display the LPC43xx Clock Generation Unit (CGU) registers in an
|
||||
# easy-to-read format.
|
||||
#
|
||||
# This file is part of HackRF.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, 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; see the file COPYING. If not, write to
|
||||
# the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
# Boston, MA 02110-1301, USA.
|
||||
|
||||
"""
|
||||
In GDB:
|
||||
dump binary memory cgu.bin 0x40050014 0x400500cc
|
||||
"""
|
||||
|
||||
import sys
|
||||
from struct import unpack
|
||||
|
||||
address = 0x40050014
|
||||
|
||||
f = open(sys.argv[1], 'read')
|
||||
d = '\x00' * 20 + f.read()
|
||||
length = len(d)
|
||||
f.close()
|
||||
|
||||
def print_data(d):
|
||||
for i in range(0, length, 16):
|
||||
values = unpack('<IIII', d[i:i+16])
|
||||
values = ['%08x' % v for v in values]
|
||||
values_str = ' '.join(values)
|
||||
line = '%08x: %s' % (address + i, values_str)
|
||||
print(line)
|
||||
|
||||
#print_data(d)
|
||||
#sys.exit(0)
|
||||
|
||||
data = {}
|
||||
for i in range(0, length, 4):
|
||||
data[i] = unpack('<I', d[i:i+4])[0]
|
||||
|
||||
registers = {
|
||||
0x14: {
|
||||
'name': 'FREQ_MON',
|
||||
'fields': (
|
||||
('RCNT', 0, 9),
|
||||
('FCNT', 9, 14),
|
||||
('MEAS', 23, 1),
|
||||
('CLK_SEL', 24, 5),
|
||||
),
|
||||
},
|
||||
0x18: {
|
||||
'name': 'XTAL_OSC_CONTROL',
|
||||
'fields': (
|
||||
('ENABLE', 0, 1),
|
||||
('BYPASS', 1, 1),
|
||||
('HF', 2, 1)
|
||||
),
|
||||
},
|
||||
0x1c: {
|
||||
'name': 'PLL0USB_STAT',
|
||||
'fields': (
|
||||
('LOCK', 0, 1),
|
||||
('FR', 1, 1),
|
||||
),
|
||||
},
|
||||
0x20: {
|
||||
'name': 'PLL0USB_CTRL',
|
||||
'fields': (
|
||||
('PD', 0, 1),
|
||||
('BYPASS', 1, 1),
|
||||
('DIRECTI', 2, 1),
|
||||
('DIRECTO', 3, 1),
|
||||
('CLKEN', 4, 1),
|
||||
('FRM', 6, 1),
|
||||
('AUTOBLOCK', 11, 1),
|
||||
('CLK_SEL', 24, 5),
|
||||
),
|
||||
},
|
||||
0x24: {
|
||||
'name': 'PLL0USB_MDIV',
|
||||
'fields': (
|
||||
('MDEC', 0, 17),
|
||||
('SELP', 17, 5),
|
||||
('SELI', 22, 6),
|
||||
('SELR', 28, 4),
|
||||
),
|
||||
},
|
||||
0x28: {
|
||||
'name': 'PLL0USB_NP_DIV',
|
||||
'fields': (
|
||||
('PDEC', 0, 7),
|
||||
('NDEC', 12, 10),
|
||||
),
|
||||
},
|
||||
0x40: {
|
||||
'name': 'PLL1_STAT',
|
||||
'fields': (
|
||||
('LOCK', 0, 1),
|
||||
),
|
||||
},
|
||||
0x44: {
|
||||
'name': 'PLL1_CTRL',
|
||||
'fields': (
|
||||
('PD', 0, 1),
|
||||
('BYPASS', 1, 1),
|
||||
('FBSEL', 6, 1),
|
||||
('DIRECT', 7, 1),
|
||||
('PSEL', 8, 2),
|
||||
('AUTOBLOCK', 11, 1),
|
||||
('NSEL', 12, 2),
|
||||
('MSEL', 16, 8),
|
||||
('CLK_SEL', 24, 5),
|
||||
),
|
||||
},
|
||||
0x48: {
|
||||
'name': 'IDIVA_CTRL',
|
||||
'fields': (
|
||||
('PD', 0, 1),
|
||||
('IDIV', 2, 2),
|
||||
('AUTOBLOCK', 11, 1),
|
||||
('CLK_SEL', 24, 5),
|
||||
),
|
||||
},
|
||||
0x4C: {
|
||||
'name': 'IDIVB_CTRL',
|
||||
'fields': (
|
||||
('PD', 0, 1),
|
||||
('IDIV', 2, 4),
|
||||
('AUTOBLOCK', 11, 1),
|
||||
('CLK_SEL', 24, 5),
|
||||
),
|
||||
},
|
||||
0x50: {
|
||||
'name': 'IDIVC_CTRL',
|
||||
'fields': (
|
||||
('PD', 0, 1),
|
||||
('IDIV', 2, 4),
|
||||
('AUTOBLOCK', 11, 1),
|
||||
('CLK_SEL', 24, 5),
|
||||
),
|
||||
},
|
||||
0x54: {
|
||||
'name': 'IDIVD_CTRL',
|
||||
'fields': (
|
||||
('PD', 0, 1),
|
||||
('IDIV', 2, 4),
|
||||
('AUTOBLOCK', 11, 1),
|
||||
('CLK_SEL', 24, 5),
|
||||
),
|
||||
},
|
||||
0x58: {
|
||||
'name': 'IDIVE_CTRL',
|
||||
'fields': (
|
||||
('PD', 0, 1),
|
||||
('IDIV', 2, 8),
|
||||
('AUTOBLOCK', 11, 1),
|
||||
('CLK_SEL', 24, 5),
|
||||
),
|
||||
},
|
||||
0x5C: {
|
||||
'name': 'BASE_SAFE_CLK',
|
||||
'fields': (
|
||||
('PD', 0, 1),
|
||||
('AUTOBLOCK', 11, 1),
|
||||
('CLK_SEL', 24, 5),
|
||||
),
|
||||
},
|
||||
0x60: {
|
||||
'name': 'BASE_USB0_CLK',
|
||||
'fields': (
|
||||
('PD', 0, 1),
|
||||
('AUTOBLOCK', 11, 1),
|
||||
('CLK_SEL', 24, 5),
|
||||
),
|
||||
},
|
||||
0x64: {
|
||||
'name': 'BASE_PERIPH_CLK',
|
||||
'fields': (
|
||||
('PD', 0, 1),
|
||||
('AUTOBLOCK', 11, 1),
|
||||
('CLK_SEL', 24, 5),
|
||||
),
|
||||
},
|
||||
0x68: {
|
||||
'name': 'BASE_USB1_CLK',
|
||||
'fields': (
|
||||
('PD', 0, 1),
|
||||
('AUTOBLOCK', 11, 1),
|
||||
('CLK_SEL', 24, 5),
|
||||
),
|
||||
},
|
||||
0x6C: {
|
||||
'name': 'BASE_M4_CLK',
|
||||
'fields': (
|
||||
('PD', 0, 1),
|
||||
('AUTOBLOCK', 11, 1),
|
||||
('CLK_SEL', 24, 5),
|
||||
),
|
||||
},
|
||||
0x70: {
|
||||
'name': 'BASE_SPIFI_CLK',
|
||||
'fields': (
|
||||
('PD', 0, 1),
|
||||
('AUTOBLOCK', 11, 1),
|
||||
('CLK_SEL', 24, 5),
|
||||
),
|
||||
},
|
||||
0x74: {
|
||||
'name': 'BASE_SPI_CLK',
|
||||
'fields': (
|
||||
('PD', 0, 1),
|
||||
('AUTOBLOCK', 11, 1),
|
||||
('CLK_SEL', 24, 5),
|
||||
),
|
||||
},
|
||||
0x78: {
|
||||
'name': 'BASE_PHY_RX_CLK',
|
||||
'fields': (
|
||||
('PD', 0, 1),
|
||||
('AUTOBLOCK', 11, 1),
|
||||
('CLK_SEL', 24, 5),
|
||||
),
|
||||
},
|
||||
0x7C: {
|
||||
'name': 'BASE_PHY_TX_CLK',
|
||||
'fields': (
|
||||
('PD', 0, 1),
|
||||
('AUTOBLOCK', 11, 1),
|
||||
('CLK_SEL', 24, 5),
|
||||
),
|
||||
},
|
||||
0x80: {
|
||||
'name': 'BASE_APB1_CLK',
|
||||
'fields': (
|
||||
('PD', 0, 1),
|
||||
('AUTOBLOCK', 11, 1),
|
||||
('CLK_SEL', 24, 5),
|
||||
),
|
||||
},
|
||||
0x84: {
|
||||
'name': 'BASE_APB3_CLK',
|
||||
'fields': (
|
||||
('PD', 0, 1),
|
||||
('AUTOBLOCK', 11, 1),
|
||||
('CLK_SEL', 24, 5),
|
||||
),
|
||||
},
|
||||
0x88: {
|
||||
'name': 'BASE_LCD_CLK',
|
||||
'fields': (
|
||||
('PD', 0, 1),
|
||||
('AUTOBLOCK', 11, 1),
|
||||
('CLK_SEL', 24, 5),
|
||||
),
|
||||
},
|
||||
0x8C: {
|
||||
'name': 'BASE_VADC_CLK',
|
||||
'fields': (
|
||||
('PD', 0, 1),
|
||||
('AUTOBLOCK', 11, 1),
|
||||
('CLK_SEL', 24, 5),
|
||||
),
|
||||
},
|
||||
0x90: {
|
||||
'name': 'BASE_SDIO_CLK',
|
||||
'fields': (
|
||||
('PD', 0, 1),
|
||||
('AUTOBLOCK', 11, 1),
|
||||
('CLK_SEL', 24, 5),
|
||||
),
|
||||
},
|
||||
0x94: {
|
||||
'name': 'BASE_SSP0_CLK',
|
||||
'fields': (
|
||||
('PD', 0, 1),
|
||||
('AUTOBLOCK', 11, 1),
|
||||
('CLK_SEL', 24, 5),
|
||||
),
|
||||
},
|
||||
0x98: {
|
||||
'name': 'BASE_SSP1_CLK',
|
||||
'fields': (
|
||||
('PD', 0, 1),
|
||||
('AUTOBLOCK', 11, 1),
|
||||
('CLK_SEL', 24, 5),
|
||||
),
|
||||
},
|
||||
0x9C: {
|
||||
'name': 'BASE_UART0_CLK',
|
||||
'fields': (
|
||||
('PD', 0, 1),
|
||||
('AUTOBLOCK', 11, 1),
|
||||
('CLK_SEL', 24, 5),
|
||||
),
|
||||
},
|
||||
0xA0: {
|
||||
'name': 'BASE_UART1_CLK',
|
||||
'fields': (
|
||||
('PD', 0, 1),
|
||||
('AUTOBLOCK', 11, 1),
|
||||
('CLK_SEL', 24, 5),
|
||||
),
|
||||
},
|
||||
0xA4: {
|
||||
'name': 'BASE_UART2_CLK',
|
||||
'fields': (
|
||||
('PD', 0, 1),
|
||||
('AUTOBLOCK', 11, 1),
|
||||
('CLK_SEL', 24, 5),
|
||||
),
|
||||
},
|
||||
0xA8: {
|
||||
'name': 'BASE_UART3_CLK',
|
||||
'fields': (
|
||||
('PD', 0, 1),
|
||||
('AUTOBLOCK', 11, 1),
|
||||
('CLK_SEL', 24, 5),
|
||||
),
|
||||
},
|
||||
0xAC: {
|
||||
'name': 'BASE_OUT_CLK',
|
||||
'fields': (
|
||||
('PD', 0, 1),
|
||||
('AUTOBLOCK', 11, 1),
|
||||
('CLK_SEL', 24, 5),
|
||||
),
|
||||
},
|
||||
0xC0: {
|
||||
'name': 'BASE_APLL_CLK',
|
||||
'fields': (
|
||||
('PD', 0, 1),
|
||||
('AUTOBLOCK', 11, 1),
|
||||
('CLK_SEL', 24, 5),
|
||||
),
|
||||
},
|
||||
0xC4: {
|
||||
'name': 'BASE_CGU_OUT0_CLK',
|
||||
'fields': (
|
||||
('PD', 0, 1),
|
||||
('AUTOBLOCK', 11, 1),
|
||||
('CLK_SEL', 24, 5),
|
||||
),
|
||||
},
|
||||
0xC8: {
|
||||
'name': 'BASE_CGU_OUT1_CLK',
|
||||
'fields': (
|
||||
('PD', 0, 1),
|
||||
('AUTOBLOCK', 11, 1),
|
||||
('CLK_SEL', 24, 5),
|
||||
),
|
||||
},
|
||||
# TODO: Add other CGU registers. I did the ones that were
|
||||
# valuable to me to debug CPU clock issues.
|
||||
}
|
||||
|
||||
for address in sorted(registers):
|
||||
register = registers[address]
|
||||
name = register['name']
|
||||
fields = register['fields']
|
||||
value = data[address]
|
||||
bits = bin(value)[2:].zfill(32)
|
||||
print('%03x %20s %s = %08x' % (address, name, bits, value))
|
||||
for field in fields:
|
||||
name, low_bit, count = field
|
||||
field_value = (value >> low_bit) & ((1 << count) - 1)
|
||||
field_bits = bin(field_value)[2:].zfill(count) + ' ' * low_bit
|
||||
field_bits = field_bits.rjust(32)
|
||||
print('%03s %20s %s = %8x %s' % ('', '', field_bits, field_value, name))
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user