Initial commit of files

This commit is contained in:
2021-01-22 10:11:21 -05:00
parent d46bf141a3
commit a9cbd4dac0
418 changed files with 548003 additions and 0 deletions

View File

@ -0,0 +1,9 @@
*.bin
*.d
*.elf
*.hex
*.list
*.map
*.o
*.srec
*.dfu

View File

@ -0,0 +1,36 @@
# 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.
#
# Top directory CMake project for HackRF firmware
cmake_minimum_required(VERSION 2.8.9)
set(CMAKE_TOOLCHAIN_FILE toolchain-arm-cortex-m.cmake)
project (hackrf_firmware_all)
add_subdirectory(blinky)
add_subdirectory(mixertx)
add_subdirectory(sgpio)
add_subdirectory(sgpio-rx)
add_subdirectory(simpletx)
add_subdirectory(startup)
add_subdirectory(startup_systick)
add_subdirectory(startup_systick_perfo)
add_subdirectory(hackrf_usb)

View File

@ -0,0 +1,56 @@
The primary firmware source code for USB HackRF devices is hackrf_usb. Most of
the other directories contain firmware source code for test and development.
The common directory contains source code shared by multiple HackRF firmware
projects. The cpld directory contains HDL source for the CPLD.
The firmware is set up for compilation with the GCC toolchain available here:
https://code.launchpad.net/gcc-arm-embedded
Required dependency:
https://github.com/mossmann/libopencm3
If you are using git, the preferred way to install libopencm3 is to use the
submodule:
$ cd ..
$ git submodule init
$ git submodule update
$ cd firmware/libopencm3
$ make
To build and install a standard firmware image for HackRF One:
$ cd hackrf_usb
$ mkdir build
$ cd build
$ cmake .. -DBOARD=HACKRF_ONE
$ make
$ hackrf_spiflash -w hackrf_usb.bin
If you have a Jawbreaker, use -DBOARD=JAWBREAKER instead.
For loading firmware into RAM with DFU you will also need:
http://dfu-util.gnumonks.org/
To start up HackRF One in DFU mode, hold down the DFU button while powering it
on or while pressing and releasing the RESET button. Release the DFU button
after the 3V3 LED illuminates.
With dfu-util and dfu-suffix (from the dfu-util package) installed and with the
HackRF operating in DFU mode, you can build firmware for RAM and load it with:
$ cd hackrf_usb
$ mkdir build
$ cd build
$ cmake .. -DRUN_FROM=RAM
$ make hackrf_usb-program
Alternatively you can load a .dfu file from a release package with:
$ dfu-util --device 1fc9:000c --alt 0 --download hackrf_usb_ram.dfu

View File

@ -0,0 +1,33 @@
# 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.
#
cmake_minimum_required(VERSION 2.8.9)
set(CMAKE_TOOLCHAIN_FILE ../toolchain-arm-cortex-m.cmake)
project(blinky)
include(../hackrf-common.cmake)
set(SRC_M4
blinky.c
)
DeclareTargets()

View File

@ -0,0 +1 @@
This is the simplest example firmware for HackRF. It flashes three LEDs.

View File

@ -0,0 +1,54 @@
/*
* Copyright 2010 - 2012 Michael Ossmann
*
* 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 <libopencm3/lpc43xx/gpio.h>
#include <libopencm3/lpc43xx/scu.h>
#include "hackrf_core.h"
uint32_t boot0, boot1, boot2, boot3;
int main(void)
{
int i;
pin_setup();
/* enable all power supplies */
enable_1v8_power();
/* Blink LED1/2/3 on the board and Read BOOT0/1/2/3 pins. */
while (1)
{
boot0 = BOOT0_STATE;
boot1 = BOOT1_STATE;
boot2 = BOOT2_STATE;
boot3 = BOOT3_STATE;
gpio_set(PORT_LED1_3, (PIN_LED1|PIN_LED2|PIN_LED3)); /* LEDs on */
for (i = 0; i < 2000000; i++) /* Wait a bit. */
__asm__("nop");
gpio_clear(PORT_LED1_3, (PIN_LED1|PIN_LED2|PIN_LED3)); /* LED off */
for (i = 0; i < 2000000; i++) /* Wait a bit. */
__asm__("nop");
}
return 0;
}

View 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

View 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 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 = 128K
ram_local1 (rwx) : ORIGIN = 0x10000000, LENGTH = 128K
ram_local2 (rwx) : ORIGIN = 0x10080000, LENGTH = 64K
ram_sleep (rwx) : ORIGIN = 0x10090000, LENGTH = 8K
}
INCLUDE LPC43xx_M4_memory.ld

View 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
}

View 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
}

View File

@ -0,0 +1,36 @@
/*
* 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
{
/* Physical address in Flash used to copy Code from Flash to RAM */
rom_flash (rx) : ORIGIN = 0x80000000, LENGTH = 1M
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)
*/
}
usb_bulk_buffer = ORIGIN(ram_usb);

View File

@ -0,0 +1,2 @@
This directory contains things shared by multiple HackRF firmware
implementations.

View File

@ -0,0 +1,45 @@
/*
* 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.
*/
#include "bitband.h"
volatile uint32_t* peripheral_bitband_address(volatile void* const address, const uint_fast8_t bit_number) {
const uint32_t bit_band_base = 0x42000000;
const uint32_t byte_offset = (uint32_t)address - 0x40000000;
const uint32_t bit_word_offset = (byte_offset * 32) + (bit_number * 4);
const uint32_t bit_word_address = bit_band_base + bit_word_offset;
return (volatile uint32_t*)bit_word_address;
}
void peripheral_bitband_set(volatile void* const peripheral_address, const uint_fast8_t bit_number) {
volatile uint32_t* const bitband_address = peripheral_bitband_address(peripheral_address, bit_number);
*bitband_address = 1;
}
void peripheral_bitband_clear(volatile void* const peripheral_address, const uint_fast8_t bit_number) {
volatile uint32_t* const bitband_address = peripheral_bitband_address(peripheral_address, bit_number);
*bitband_address = 0;
}
uint32_t peripheral_bitband_get(volatile void* const peripheral_address, const uint_fast8_t bit_number) {
volatile uint32_t* const bitband_address = peripheral_bitband_address(peripheral_address, bit_number);
return *bitband_address;
}

View File

@ -0,0 +1,32 @@
/*
* 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.
*/
#ifndef __BITBAND_H__
#define __BITBAND_H__
#include <stdint.h>
volatile uint32_t* peripheral_bitband_address(volatile void* const address, const uint_fast8_t bit_number);
void peripheral_bitband_set(volatile void* const peripheral_address, const uint_fast8_t bit_number);
void peripheral_bitband_clear(volatile void* const peripheral_address, const uint_fast8_t bit_number);
uint32_t peripheral_bitband_get(volatile void* const peripheral_address, const uint_fast8_t bit_number);
#endif//__BITBAND_H__

View File

@ -0,0 +1,88 @@
/*
* Copyright 2013 Michael Ossmann <mike@ossmann.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 "cpld_jtag.h"
#include "hackrf_core.h"
#include "xapp058/micro.h"
#include <libopencm3/lpc43xx/gpio.h>
#include <libopencm3/lpc43xx/scu.h>
#include <stdint.h>
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);
scu_pinmux(SCU_PINMUX_CPLD_TCK, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_PINMUX_CPLD_TMS, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_PINMUX_CPLD_TDI, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0);
/* TDO is an input */
GPIO_DIR(PORT_CPLD_TDO) &= ~PIN_CPLD_TDO;
/* the rest are outputs */
GPIO_DIR(PORT_CPLD_TCK) |= PIN_CPLD_TCK;
GPIO_DIR(PORT_CPLD_TMS) |= PIN_CPLD_TMS;
GPIO_DIR(PORT_CPLD_TDI) |= PIN_CPLD_TDI;
}
/* set pins as inputs so we don't interfere with an external JTAG device */
void cpld_jtag_release(void) {
scu_pinmux(SCU_PINMUX_CPLD_TDO, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION4);
scu_pinmux(SCU_PINMUX_CPLD_TCK, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_PINMUX_CPLD_TMS, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_PINMUX_CPLD_TDI, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0);
GPIO_DIR(PORT_CPLD_TDO) &= ~PIN_CPLD_TDO;
GPIO_DIR(PORT_CPLD_TCK) &= ~PIN_CPLD_TCK;
GPIO_DIR(PORT_CPLD_TMS) &= ~PIN_CPLD_TMS;
GPIO_DIR(PORT_CPLD_TDI) &= ~PIN_CPLD_TDI;
}
/* return 0 if success else return error code see xsvfExecute() */
int cpld_jtag_program(
const uint32_t buffer_length,
unsigned char* const buffer,
refill_buffer_cb refill
) {
int error;
cpld_jtag_setup();
xsvf_buffer = buffer;
xsvf_buffer_len = buffer_length;
refill_buffer = refill;
error = xsvfExecute();
cpld_jtag_release();
return error;
}
/* this gets called by the XAPP058 code */
unsigned char cpld_jtag_get_next_byte(void) {
if (xsvf_pos == xsvf_buffer_len) {
refill_buffer();
xsvf_pos = 0;
}
unsigned char byte = xsvf_buffer[xsvf_pos];
xsvf_pos++;
return byte;
}

View File

@ -0,0 +1,43 @@
/*
* Copyright 2013 Michael Ossmann <mike@ossmann.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 __CPLD_JTAG_H__
#define __CPLD_JTAG_H__
#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.
*
* 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__

View File

@ -0,0 +1,86 @@
/*
* Copyright 2012 Jared Boone <jared@sharebrained.com>
* 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.
*/
#include <stdint.h>
#include "fault_handler.h"
typedef struct
{
uint32_t r0;
uint32_t r1;
uint32_t r2;
uint32_t r3;
uint32_t r12;
uint32_t lr; /* Link Register. */
uint32_t pc; /* Program Counter. */
uint32_t psr;/* Program Status Register. */
} hard_fault_stack_t;
__attribute__((naked))
void hard_fault_handler(void) {
__asm__("TST LR, #4");
__asm__("ITE EQ");
__asm__("MRSEQ R0, MSP");
__asm__("MRSNE R0, PSP");
__asm__("B hard_fault_handler_c");
}
volatile hard_fault_stack_t* hard_fault_stack_pt;
__attribute__((used)) void hard_fault_handler_c(uint32_t* args)
{
/* hard_fault_stack_pt contains registers saved before the hard fault */
hard_fault_stack_pt = (hard_fault_stack_t*)args;
// args[0-7]: r0, r1, r2, r3, r12, lr, pc, psr
// Other interesting registers to examine:
// CFSR: Configurable Fault Status Register
// HFSR: Hard Fault Status Register
// DFSR: Debug Fault Status Register
// AFSR: Auxiliary Fault Status Register
// MMAR: MemManage Fault Address Register
// BFAR: Bus Fault Address Register
/*
if( SCB->HFSR & SCB_HFSR_FORCED ) {
if( SCB->CFSR & SCB_CFSR_BFSR_BFARVALID ) {
SCB->BFAR;
if( SCB->CFSR & CSCB_CFSR_BFSR_PRECISERR ) {
}
}
}
*/
while(1);
}
void mem_manage_handler() {
while(1);
}
void bus_fault_handler() {
while(1);
}
void usage_fault_handler() {
while(1);
}

View File

@ -0,0 +1,73 @@
/*
* 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.
*/
#ifndef __FAULT_HANDLER__
#define __FAULT_HANDLER__
#include <stdint.h>
#include <libopencm3/cm3/memorymap.h>
// TODO: Move all this to a Cortex-M(?) include file, since these
// structures are supposedly the same between processors (to an
// undetermined extent).
typedef struct armv7m_scb_t armv7m_scb_t;
struct armv7m_scb_t {
volatile const uint32_t CPUID;
volatile uint32_t ICSR;
volatile uint32_t VTOR;
volatile uint32_t AIRCR;
volatile uint32_t SCR;
volatile uint32_t CCR;
volatile uint32_t SHPR1;
volatile uint32_t SHPR2;
volatile uint32_t SHPR3;
volatile uint32_t SHCSR;
volatile uint32_t CFSR;
volatile uint32_t HFSR;
volatile uint32_t DFSR;
volatile uint32_t MMFAR;
volatile uint32_t BFAR;
volatile uint32_t AFSR;
volatile const uint32_t ID_PFR0;
volatile const uint32_t ID_PFR1;
volatile const uint32_t ID_DFR0;
volatile const uint32_t ID_AFR0;
volatile const uint32_t ID_MMFR0;
volatile const uint32_t ID_MMFR1;
volatile const uint32_t ID_MMFR2;
volatile const uint32_t ID_MMFR3;
volatile const uint32_t ID_ISAR0;
volatile const uint32_t ID_ISAR1;
volatile const uint32_t ID_ISAR2;
volatile const uint32_t ID_ISAR3;
volatile const uint32_t ID_ISAR4;
volatile const uint32_t __reserved_0x74_0x87[5];
volatile uint32_t CPACR;
} __attribute__((packed));
static armv7m_scb_t* const SCB = (armv7m_scb_t*)SCB_BASE;
#define SCB_HFSR_DEBUGEVT (1 << 31)
#define SCB_HFSR_FORCED (1 << 30)
#define SCB_HFSR_VECTTBL (1 << 1)
#endif//__FAULT_HANDLER__

View 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;
}

View 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__*/

View File

@ -0,0 +1,644 @@
/*
* Copyright 2012 Michael Ossmann <mike@ossmann.com>
* Copyright 2012 Jared Boone <jared@sharebrained.com>
* 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.
*/
#include "hackrf_core.h"
#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;
for (i = 0; i < duration; i++)
__asm__("nop");
}
/* GCD algo from wikipedia */
/* http://en.wikipedia.org/wiki/Greatest_common_divisor */
static uint32_t
gcd(uint32_t u, uint32_t v)
{
int s;
if (!u || !v)
return u | v;
for (s=0; !((u|v)&1); s++) {
u >>= 1;
v >>= 1;
}
while (!(u&1))
u >>= 1;
do {
while (!(v&1))
v >>= 1;
if (u>v) {
uint32_t t;
t = v;
v = u;
u = t;
}
v = v - u;
}
while (v);
return u << s;
}
bool sample_rate_frac_set(uint32_t rate_num, uint32_t rate_denom)
{
const uint64_t VCO_FREQ = 800 * 1000 * 1000; /* 800 MHz */
uint32_t MSx_P1,MSx_P2,MSx_P3;
uint32_t a, b, c;
uint32_t rem;
/* Find best config */
a = (VCO_FREQ * rate_denom) / rate_num;
rem = (VCO_FREQ * rate_denom) - (a * rate_num);
if (!rem) {
/* Integer mode */
b = 0;
c = 1;
} else {
/* Fractional */
uint32_t g = gcd(rem, rate_num);
rem /= g;
rate_num /= g;
if (rate_num < (1<<20)) {
/* Perfect match */
b = rem;
c = rate_num;
} else {
/* Approximate */
c = (1<<20) - 1;
b = ((uint64_t)c * (uint64_t)rem) / rate_num;
g = gcd(b, c);
b /= g;
c /= g;
}
}
/* Can we enable integer mode ? */
if (a & 0x1 || b)
si5351c_set_int_mode(0, 0);
else
si5351c_set_int_mode(0, 1);
/* Final MS values */
MSx_P1 = 128*a + (128 * b/c) - 512;
MSx_P2 = (128*b) % c;
MSx_P3 = c;
/* MS0/CLK0 is the source for the MAX5864/CPLD (CODEC_CLK). */
si5351c_configure_multisynth(0, MSx_P1, MSx_P2, MSx_P3, 1);
/* MS0/CLK1 is the source for the CPLD (CODEC_X2_CLK). */
si5351c_configure_multisynth(1, 0, 0, 0, 0);//p1 doesn't matter
/* MS0/CLK2 is the source for SGPIO (CODEC_X2_CLK) */
si5351c_configure_multisynth(2, 0, 0, 0, 0);//p1 doesn't matter
return true;
}
bool sample_rate_set(const uint32_t sample_rate_hz) {
#ifdef JELLYBEAN
/* Due to design issues, Jellybean/Lemondrop frequency plan is limited.
* Long version of the story: The MAX2837 reference frequency
* originates from the same PLL as the sample clocks, and in order to
* keep the sample clocks in phase and keep jitter noise down, the MAX2837
* and sample clocks must be integer-related.
*/
uint32_t r_div_sample = 2;
uint32_t r_div_sgpio = 1;
switch( sample_rate_hz ) {
case 5000000:
r_div_sample = 3; /* 800 MHz / 20 / 8 = 5 MHz */
r_div_sgpio = 2; /* 800 MHz / 20 / 4 = 10 MHz */
break;
case 10000000:
r_div_sample = 2; /* 800 MHz / 20 / 4 = 10 MHz */
r_div_sgpio = 1; /* 800 MHz / 20 / 2 = 20 MHz */
break;
case 20000000:
r_div_sample = 1; /* 800 MHz / 20 / 2 = 20 MHz */
r_div_sgpio = 0; /* 800 MHz / 20 / 1 = 40 MHz */
break;
default:
return false;
}
/* NOTE: Because MS1, 2, 3 outputs are slaved to PLLA, the p1, p2, p3
* values are irrelevant. */
/* MS0/CLK1 is the source for the MAX5864 codec. */
si5351c_configure_multisynth(1, 4608, 0, 1, r_div_sample);
/* MS0/CLK2 is the source for the CPLD codec clock (same as CLK1). */
si5351c_configure_multisynth(2, 4608, 0, 1, r_div_sample);
/* MS0/CLK3 is the source for the SGPIO clock. */
si5351c_configure_multisynth(3, 4608, 0, 1, r_div_sgpio);
return true;
#endif
#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;
case 16000000:
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;
default:
return false;
}
/* MS0/CLK0 is the source for the MAX5864/CPLD (CODEC_CLK). */
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
/* MS0/CLK2 is the source for SGPIO (CODEC_X2_CLK) */
si5351c_configure_multisynth(2, p1, 0, 1, 0);//p1 doesn't matter
return true;
#endif
}
bool baseband_filter_bandwidth_set(const uint32_t bandwidth_hz) {
return max2837_set_lpf_bandwidth(bandwidth_hz);
}
/* 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) */
CGU_BASE_APB1_CLK = CGU_BASE_APB1_CLK_CLK_SEL(CGU_SRC_IRC);
/* use IRC as clock source for APB3 */
CGU_BASE_APB3_CLK = CGU_BASE_APB3_CLK_CLK_SEL(CGU_SRC_IRC);
i2c0_init(15);
si5351c_disable_all_outputs();
si5351c_disable_oeb_pin_control();
si5351c_power_down_all_clocks();
si5351c_set_crystal_configuration();
si5351c_enable_xo_and_ms_fanout();
si5351c_configure_pll_sources();
si5351c_configure_pll_multisynth();
#ifdef JELLYBEAN
/*
* Jellybean/Lemondrop clocks:
* CLK0 -> MAX2837
* CLK1 -> MAX5864/CPLD.GCLK0
* CLK2 -> CPLD.GCLK1
* CLK3 -> CPLD.GCLK2
* CLK4 -> LPC4330
* CLK5 -> RFFC5072
* CLK6 -> extra
* CLK7 -> extra
*/
/* MS0/CLK0 is the source for the MAX2837 clock input. */
si5351c_configure_multisynth(0, 2048, 0, 1, 0); /* 40MHz */
/* MS4/CLK4 is the source for the LPC43xx microcontroller. */
si5351c_configure_multisynth(4, 8021, 0, 3, 0); /* 12MHz */
/* MS5/CLK5 is the source for the RFFC5071 mixer. */
si5351c_configure_multisynth(5, 1536, 0, 1, 0); /* 50MHz */
#endif
#if (defined JAWBREAKER || defined HACKRF_ONE)
/*
* Jawbreaker clocks:
* CLK0 -> MAX5864/CPLD
* CLK1 -> CPLD
* CLK2 -> SGPIO
* CLK3 -> external clock output
* CLK4 -> RFFC5072
* CLK5 -> MAX2837
* CLK6 -> none
* CLK7 -> LPC4330 (but LPC4330 starts up on its own crystal)
*/
/* MS3/CLK3 is the source for the external clock output. */
si5351c_configure_multisynth(3, 80*128-512, 0, 1, 0); /* 800/80 = 10MHz */
/* MS4/CLK4 is the source for the RFFC5071 mixer. */
si5351c_configure_multisynth(4, 16*128-512, 0, 1, 0); /* 800/16 = 50MHz */
/* 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[] = { 90, 255, 20, 0 };
si5351c_write(ms7data, sizeof(ms7data));
#endif
/* Set to 10 MHz, the common rate between Jellybean and Jawbreaker. */
sample_rate_set(10000000);
si5351c_set_clock_source(PLL_SOURCE_XTAL);
// soft reset
uint8_t resetdata[] = { 177, 0xac };
si5351c_write(resetdata, sizeof(resetdata));
si5351c_enable_clock_outputs();
//FIXME disable I2C
/* Kick I2C0 down to 400kHz when we switch over to APB1 clock = 204MHz */
i2c0_init(255);
/*
* 12MHz clock is entering LPC XTAL1/OSC input now. On
* Jellybean/Lemondrop, this is a signal from the clock generator. On
* Jawbreaker, there is a 12 MHz crystal at the LPC.
* Set up PLL1 to run from XTAL1 input.
*/
//FIXME a lot of the details here should be in a CGU driver
#ifdef JELLYBEAN
/* configure xtal oscillator for external clock input signal */
CGU_XTAL_OSC_CTRL |= CGU_XTAL_OSC_CTRL_BYPASS;
#endif
/* set xtal oscillator to low frequency mode */
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_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_AUTOBLOCK(1));
/* use XTAL_OSC as clock source for APB1 */
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 APB3 */
CGU_BASE_APB3_CLK = CGU_BASE_APB3_CLK_AUTOBLOCK(1)
| CGU_BASE_APB3_CLK_CLK_SEL(CGU_SRC_XTAL);
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) | CGU_BASE_M4_CLK_AUTOBLOCK(1));
/* use XTAL_OSC as clock source for PLL0USB */
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_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(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_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(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(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(1)
| CGU_BASE_APB1_CLK_CLK_SEL(CGU_SRC_PLL1);
/* Switch APB3 clock over to use PLL1 (204MHz) */
CGU_BASE_APB3_CLK = CGU_BASE_APB3_CLK_AUTOBLOCK(1)
| CGU_BASE_APB3_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)
{
/*
* Configure CS_AD pin to keep the MAX5864 SPI disabled while we use the
* SPI bus for the MAX2837. FIXME: this should probably be somewhere else.
*/
scu_pinmux(SCU_AD_CS, SCU_GPIO_FAST);
GPIO_SET(PORT_AD_CS) = PIN_AD_CS;
GPIO_DIR(PORT_AD_CS) |= PIN_AD_CS;
scu_pinmux(SCU_XCVR_CS, SCU_GPIO_FAST);
GPIO_SET(PORT_XCVR_CS) = PIN_XCVR_CS;
GPIO_DIR(PORT_XCVR_CS) |= PIN_XCVR_CS;
/* 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));
scu_pinmux(SCU_SSP1_SCK, (SCU_SSP_IO | SCU_CONF_FUNCTION1));
}
void ssp1_set_mode_max2837(void)
{
/* FIXME speed up once everything is working reliably */
/*
// Freq About 0.0498MHz / 49.8KHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz
const uint8_t serial_clock_rate = 32;
const uint8_t clock_prescale_rate = 128;
*/
// Freq About 4.857MHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz
const uint8_t serial_clock_rate = 21;
const uint8_t clock_prescale_rate = 2;
ssp_init(SSP1_NUM,
SSP_DATA_16BITS,
SSP_FRAME_SPI,
SSP_CPOL_0_CPHA_0,
serial_clock_rate,
clock_prescale_rate,
SSP_MODE_NORMAL,
SSP_MASTER,
SSP_SLAVE_OUT_ENABLE);
}
void ssp1_set_mode_max5864(void)
{
/* FIXME speed up once everything is working reliably */
/*
// Freq About 0.0498MHz / 49.8KHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz
const uint8_t serial_clock_rate = 32;
const uint8_t clock_prescale_rate = 128;
*/
// Freq About 4.857MHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz
const uint8_t serial_clock_rate = 21;
const uint8_t clock_prescale_rate = 2;
ssp_init(SSP1_NUM,
SSP_DATA_8BITS,
SSP_FRAME_SPI,
SSP_CPOL_0_CPHA_0,
serial_clock_rate,
clock_prescale_rate,
SSP_MODE_NORMAL,
SSP_MASTER,
SSP_SLAVE_OUT_ENABLE);
}
void pin_setup(void) {
/* Release CPLD JTAG pins */
scu_pinmux(SCU_PINMUX_CPLD_TDO, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION4);
scu_pinmux(SCU_PINMUX_CPLD_TCK, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_PINMUX_CPLD_TMS, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_PINMUX_CPLD_TDI, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0);
GPIO_DIR(PORT_CPLD_TDO) &= ~PIN_CPLD_TDO;
GPIO_DIR(PORT_CPLD_TCK) &= ~PIN_CPLD_TCK;
GPIO_DIR(PORT_CPLD_TMS) &= ~PIN_CPLD_TMS;
GPIO_DIR(PORT_CPLD_TDI) &= ~PIN_CPLD_TDI;
/* Configure SCU Pin Mux as GPIO */
scu_pinmux(SCU_PINMUX_LED1, SCU_GPIO_NOPULL);
scu_pinmux(SCU_PINMUX_LED2, SCU_GPIO_NOPULL);
scu_pinmux(SCU_PINMUX_LED3, SCU_GPIO_NOPULL);
scu_pinmux(SCU_PINMUX_EN1V8, SCU_GPIO_NOPULL);
/* Configure USB indicators */
#if (defined JELLYBEAN || defined JAWBREAKER)
scu_pinmux(SCU_PINMUX_USB_LED0, SCU_CONF_FUNCTION3);
scu_pinmux(SCU_PINMUX_USB_LED1, SCU_CONF_FUNCTION3);
#endif
/* Configure all GPIO as Input (safe state) */
GPIO0_DIR = 0;
GPIO1_DIR = 0;
GPIO2_DIR = 0;
GPIO3_DIR = 0;
GPIO4_DIR = 0;
GPIO5_DIR = 0;
GPIO6_DIR = 0;
GPIO7_DIR = 0;
/* Configure GPIO2[1/2/8] (P4_1/2 P6_12) as output. */
GPIO2_DIR |= (PIN_LED1 | PIN_LED2 | PIN_LED3);
/* GPIO3[6] on P6_10 as output. */
GPIO3_DIR |= PIN_EN1V8;
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));
scu_pinmux(SCU_SSP1_SCK, (SCU_SSP_IO | SCU_CONF_FUNCTION1));
scu_pinmux(SCU_SSP1_SSEL, (SCU_SSP_IO | SCU_CONF_FUNCTION1));
/* Configure external clock in */
scu_pinmux(SCU_PINMUX_GP_CLKIN, SCU_CLK_IN | SCU_CONF_FUNCTION1);
sgpio_configure_pin_functions();
}
void enable_1v8_power(void) {
gpio_set(PORT_EN1V8, PIN_EN1V8);
}
void disable_1v8_power(void) {
gpio_clear(PORT_EN1V8, PIN_EN1V8);
}
#ifdef HACKRF_ONE
void enable_rf_power(void) {
gpio_clear(PORT_NO_VAA_ENABLE, PIN_NO_VAA_ENABLE);
}
void disable_rf_power(void) {
gpio_set(PORT_NO_VAA_ENABLE, PIN_NO_VAA_ENABLE);
}
#endif

View File

@ -0,0 +1,380 @@
/*
* Copyright 2012 Michael Ossmann <mike@ossmann.com>
* Copyright 2012 Benjamin Vernoux <titanmkd@gmail.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.
*/
#ifndef __HACKRF_CORE_H
#define __HACKRF_CORE_H
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h>
#include <stdbool.h>
/* hardware identification number */
#define BOARD_ID_JELLYBEAN 0
#define BOARD_ID_JAWBREAKER 1
#define BOARD_ID_HACKRF_ONE 2
#ifdef JELLYBEAN
#define BOARD_ID BOARD_ID_JELLYBEAN
#endif
#ifdef JAWBREAKER
#define BOARD_ID BOARD_ID_JAWBREAKER
#endif
#ifdef HACKRF_ONE
#define BOARD_ID BOARD_ID_HACKRF_ONE
#endif
/*
* SCU PinMux
*/
/* GPIO Output PinMux */
#define SCU_PINMUX_LED1 (P4_1) /* GPIO2[1] on P4_1 */
#define SCU_PINMUX_LED2 (P4_2) /* GPIO2[2] on P4_2 */
#define SCU_PINMUX_LED3 (P6_12) /* GPIO2[8] on P6_12 */
#define SCU_PINMUX_EN1V8 (P6_10) /* GPIO3[6] on P6_10 */
/* GPIO Input PinMux */
#define SCU_PINMUX_BOOT0 (P1_1) /* GPIO0[8] on P1_1 */
#define SCU_PINMUX_BOOT1 (P1_2) /* GPIO0[9] on P1_2 */
#define SCU_PINMUX_BOOT2 (P2_8) /* GPIO5[7] on P2_8 */
#define SCU_PINMUX_BOOT3 (P2_9) /* GPIO1[10] on P2_9 */
/* USB peripheral */
#if (defined JELLYBEAN || defined JAWBREAKER)
#define SCU_PINMUX_USB_LED0 (P6_8)
#define SCU_PINMUX_USB_LED1 (P6_7)
#endif
/* SSP1 Peripheral PinMux */
#define SCU_SSP1_MISO (P1_3) /* P1_3 */
#define SCU_SSP1_MOSI (P1_4) /* P1_4 */
#define SCU_SSP1_SCK (P1_19) /* P1_19 */
#define SCU_SSP1_SSEL (P1_20) /* P1_20 */
/* 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)
#define SCU_PINMUX_SGPIO1 (P0_1)
#define SCU_PINMUX_SGPIO2 (P1_15)
#define SCU_PINMUX_SGPIO3 (P1_16)
#define SCU_PINMUX_SGPIO4 (P6_3)
#define SCU_PINMUX_SGPIO5 (P6_6)
#define SCU_PINMUX_SGPIO6 (P2_2)
#define SCU_PINMUX_SGPIO7 (P1_0)
#ifdef JELLYBEAN
#define SCU_PINMUX_SGPIO8 (P1_12)
#endif
#if (defined JAWBREAKER || defined HACKRF_ONE)
#define SCU_PINMUX_SGPIO8 (P9_6)
#endif
#define SCU_PINMUX_SGPIO9 (P4_3)
#define SCU_PINMUX_SGPIO10 (P1_14)
#define SCU_PINMUX_SGPIO11 (P1_17)
#define SCU_PINMUX_SGPIO12 (P1_18)
#define SCU_PINMUX_SGPIO13 (P4_8)
#define SCU_PINMUX_SGPIO14 (P4_9)
#define SCU_PINMUX_SGPIO15 (P4_10)
/* MAX2837 GPIO (XCVR_CTL) PinMux */
#ifdef JELLYBEAN
#define SCU_XCVR_RXHP (P4_0) /* GPIO2[0] on P4_0 */
#define SCU_XCVR_B1 (P5_0) /* GPIO2[9] on P5_0 */
#define SCU_XCVR_B2 (P5_1) /* GPIO2[10] on P5_1 */
#define SCU_XCVR_B3 (P5_2) /* GPIO2[11] on P5_2 */
#define SCU_XCVR_B4 (P5_3) /* GPIO2[12] on P5_3 */
#define SCU_XCVR_B5 (P5_4) /* GPIO2[13] on P5_4 */
#define SCU_XCVR_B6 (P5_5) /* GPIO2[14] on P5_5 */
#define SCU_XCVR_B7 (P5_6) /* GPIO2[15] on P5_6 */
#endif
#define SCU_XCVR_ENABLE (P4_6) /* GPIO2[6] on P4_6 */
#define SCU_XCVR_RXENABLE (P4_5) /* GPIO2[5] on P4_5 */
#define SCU_XCVR_TXENABLE (P4_4) /* GPIO2[4] on P4_4 */
#define SCU_XCVR_CS (P1_20) /* GPIO0[15] on P1_20 */
/* MAX5864 SPI chip select (AD_CS) GPIO PinMux */
#define SCU_AD_CS (P5_7) /* GPIO2[7] on P5_7 */
/* RFFC5071 GPIO serial interface PinMux */
#ifdef JELLYBEAN
#define SCU_MIXER_ENX (P7_0) /* GPIO3[8] on P7_0 */
#define SCU_MIXER_SCLK (P7_1) /* GPIO3[9] on P7_1 */
#define SCU_MIXER_SDATA (P7_2) /* GPIO3[10] on P7_2 */
#define SCU_MIXER_RESETX (P7_3) /* GPIO3[11] on P7_3 */
#endif
#if (defined JAWBREAKER || defined HACKRF_ONE)
#define SCU_MIXER_ENX (P5_4) /* GPIO2[13] on P5_4 */
#define SCU_MIXER_SCLK (P2_6) /* GPIO5[6] on P2_6 */
#define SCU_MIXER_SDATA (P6_4) /* GPIO3[3] on P6_4 */
#define SCU_MIXER_RESETX (P5_5) /* GPIO2[14] on P5_5 */
#endif
/* RF LDO control */
#ifdef JAWBREAKER
#define SCU_RF_LDO_ENABLE (P5_0) /* GPIO2[9] on P5_0 */
#endif
/* RF supply (VAA) control */
#ifdef HACKRF_ONE
#define SCU_NO_VAA_ENABLE (P5_0) /* GPIO2[9] on P5_0 */
#endif
/* SPI flash */
#define SCU_SSP0_MISO (P3_6)
#define SCU_SSP0_MOSI (P3_7)
#define SCU_SSP0_SCK (P3_3)
#define SCU_SSP0_SSEL (P3_8) /* GPIO5[11] on P3_8 */
#define SCU_FLASH_HOLD (P3_4) /* GPIO1[14] on P3_4 */
#define SCU_FLASH_WP (P3_5) /* GPIO1[15] on P3_5 */
/* RF switch control */
#ifdef HACKRF_ONE
#define SCU_HP (P4_0) /* GPIO2[0] on P4_0 */
#define SCU_LP (P5_1) /* GPIO2[10] on P5_1 */
#define SCU_TX_MIX_BP (P5_2) /* GPIO2[11] on P5_2 */
#define SCU_NO_MIX_BYPASS (P1_7) /* GPIO1[0] on P1_7 */
#define SCU_RX_MIX_BP (P5_3) /* GPIO2[12] on P5_3 */
#define SCU_TX_AMP (P5_6) /* GPIO2[15] on P5_6 */
#define SCU_TX (P6_7) /* GPIO5[15] on P6_7 */
#define SCU_MIX_BYPASS (P6_8) /* GPIO5[16] on P6_8 */
#define SCU_RX (P2_5) /* GPIO5[5] on P2_5 */
#define SCU_NO_TX_AMP_PWR (P6_9) /* GPIO3[5] on P6_9 */
#define SCU_AMP_BYPASS (P2_10) /* GPIO0[14] on P2_10 */
#define SCU_RX_AMP (P2_11) /* GPIO1[11] on P2_11 */
#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
*/
/* GPIO Output */
#define PIN_LED1 (BIT1) /* GPIO2[1] on P4_1 */
#define PIN_LED2 (BIT2) /* GPIO2[2] on P4_2 */
#define PIN_LED3 (BIT8) /* GPIO2[8] on P6_12 */
#define PORT_LED1_3 (GPIO2) /* PORT for LED1, 2 & 3 */
#define PIN_EN1V8 (BIT6) /* GPIO3[6] on P6_10 */
#define PORT_EN1V8 (GPIO3)
#define PIN_XCVR_CS (BIT15) /* GPIO0[15] on P1_20 */
#define PORT_XCVR_CS (GPIO0) /* PORT for CS */
#define PIN_XCVR_ENABLE (BIT6) /* GPIO2[6] on P4_6 */
#define PIN_XCVR_RXENABLE (BIT5) /* GPIO2[5] on P4_5 */
#define PIN_XCVR_TXENABLE (BIT4) /* GPIO2[4] on P4_4 */
#define PORT_XCVR_ENABLE (GPIO2) /* PORT for ENABLE, TXENABLE, RXENABLE */
#ifdef JELLYBEAN
#define PIN_XCVR_RXHP (BIT0) /* GPIO2[0] on P4_0 */
#define PORT_XCVR_RXHP (GPIO2)
#define PIN_XCVR_B1 (BIT9) /* GPIO2[9] on P5_0 */
#define PIN_XCVR_B2 (BIT10) /* GPIO2[10] on P5_1 */
#define PIN_XCVR_B3 (BIT11) /* GPIO2[11] on P5_2 */
#define PIN_XCVR_B4 (BIT12) /* GPIO2[12] on P5_3 */
#define PIN_XCVR_B5 (BIT13) /* GPIO2[13] on P5_4 */
#define PIN_XCVR_B6 (BIT14) /* GPIO2[14] on P5_5 */
#define PIN_XCVR_B7 (BIT15) /* GPIO2[15] on P5_6 */
#define PORT_XCVR_B (GPIO2)
#endif
#define PIN_AD_CS (BIT7) /* GPIO2[7] on P5_7 */
#define PORT_AD_CS (GPIO2) /* PORT for AD_CS */
#ifdef JELLYBEAN
#define PIN_MIXER_ENX (BIT8) /* GPIO3[8] on P7_0 */
#define PORT_MIXER_ENX (GPIO3)
#define PIN_MIXER_SCLK (BIT9) /* GPIO3[9] on P7_1 */
#define PORT_MIXER_SCLK (GPIO3)
#define PIN_MIXER_SDATA (BIT10) /* GPIO3[10] on P7_2 */
#define PORT_MIXER_SDATA (GPIO3)
#define PIN_MIXER_RESETX (BIT11) /* GPIO3[11] on P7_3 */
#define PORT_MIXER_RESETX (GPIO3)
#endif
#if (defined JAWBREAKER || defined HACKRF_ONE)
#define PIN_MIXER_ENX (BIT13) /* GPIO2[13] on P5_4 */
#define PORT_MIXER_ENX (GPIO2)
#define PIN_MIXER_SCLK (BIT6) /* GPIO5[6] on P2_6 */
#define PORT_MIXER_SCLK (GPIO5)
#define PIN_MIXER_SDATA (BIT3) /* GPIO3[3] on P6_4 */
#define PORT_MIXER_SDATA (GPIO3)
#define PIN_MIXER_RESETX (BIT14) /* GPIO2[14] on P5_5 */
#define PORT_MIXER_RESETX (GPIO2)
#endif
#ifdef JAWBREAKER
#define PIN_RF_LDO_ENABLE (BIT9) /* GPIO2[9] on P5_0 */
#define PORT_RF_LDO_ENABLE (GPIO2) /* PORT for RF_LDO_ENABLE */
#endif
#ifdef HACKRF_ONE
#define PIN_NO_VAA_ENABLE (BIT9) /* GPIO2[9] on P5_0 */
#define PORT_NO_VAA_ENABLE (GPIO2) /* PORT for NO_VAA_ENABLE */
#endif
#define PIN_FLASH_HOLD (BIT14) /* GPIO1[14] on P3_4 */
#define PIN_FLASH_WP (BIT15) /* GPIO1[15] on P3_5 */
#define PORT_FLASH (GPIO1)
#define PIN_SSP0_SSEL (BIT11) /* GPIO5[11] on P3_8 */
#define PORT_SSP0_SSEL (GPIO5)
/* RF switch control */
#ifdef HACKRF_ONE
#define PIN_HP (GPIOPIN0) /* GPIO2[0] on P4_0 */
#define PORT_HP (GPIO2)
#define PIN_LP (GPIOPIN10) /* GPIO2[10] on P5_1 */
#define PORT_LP (GPIO2)
#define PIN_TX_MIX_BP (GPIOPIN11) /* GPIO2[11] on P5_2 */
#define PORT_TX_MIX_BP (GPIO2)
#define PIN_NO_MIX_BYPASS (GPIOPIN0) /* GPIO1[0] on P1_7 */
#define PORT_NO_MIX_BYPASS (GPIO1)
#define PIN_RX_MIX_BP (GPIOPIN12) /* GPIO2[12] on P5_3 */
#define PORT_RX_MIX_BP (GPIO2)
#define PIN_TX_AMP (GPIOPIN15) /* GPIO2[15] on P5_6 */
#define PORT_TX_AMP (GPIO2)
#define PIN_TX (GPIOPIN15) /* GPIO5[15] on P6_7 */
#define PORT_TX (GPIO5)
#define PIN_MIX_BYPASS (GPIOPIN16) /* GPIO5[16] on P6_8 */
#define PORT_MIX_BYPASS (GPIO5)
#define PIN_RX (GPIOPIN5) /* GPIO5[5] on P2_5 */
#define PORT_RX (GPIO5)
#define PIN_NO_TX_AMP_PWR (GPIOPIN5) /* GPIO3[5] on P6_9 */
#define PORT_NO_TX_AMP_PWR (GPIO3)
#define PIN_AMP_BYPASS (GPIOPIN14) /* GPIO0[14] on P2_10 */
#define PORT_AMP_BYPASS (GPIO0)
#define PIN_RX_AMP (GPIOPIN11) /* GPIO1[11] on P2_11 */
#define PORT_RX_AMP (GPIO1)
#define PIN_NO_RX_AMP_PWR (GPIOPIN12) /* GPIO1[12] on P2_12 */
#define PORT_NO_RX_AMP_PWR (GPIO1)
#endif
/* GPIO Input */
#define PIN_BOOT0 (BIT8) /* GPIO0[8] on P1_1 */
#define PIN_BOOT1 (BIT9) /* GPIO0[9] on P1_2 */
#define PIN_BOOT2 (BIT7) /* GPIO5[7] on P2_8 */
#define PIN_BOOT3 (BIT10) /* GPIO1[10] on P2_9 */
/* CPLD JTAG interface GPIO pins */
#define PIN_CPLD_TDO (GPIOPIN18)
#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)
#define BOOT1_STATE GPIO_STATE(GPIO0, PIN_BOOT1)
#define BOOT2_STATE GPIO_STATE(GPIO5, PIN_BOOT2)
#define BOOT3_STATE GPIO_STATE(GPIO1, PIN_BOOT3)
#define MIXER_SDATA_STATE GPIO_STATE(PORT_MIXER_SDATA, PIN_MIXER_SDATA)
#define CPLD_TDO_STATE GPIO_STATE(PORT_CPLD_TDO, PIN_CPLD_TDO)
/* TODO add other Pins */
typedef enum {
TRANSCEIVER_MODE_OFF = 0,
TRANSCEIVER_MODE_RX = 1,
TRANSCEIVER_MODE_TX = 2,
TRANSCEIVER_MODE_SS = 3,
TRANSCEIVER_MODE_CPLD_UPDATE = 4
} transceiver_mode_t;
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);
void pin_setup(void);
void enable_1v8_power(void);
void disable_1v8_power(void);
bool sample_rate_frac_set(uint32_t rate_num, uint32_t rate_denom);
bool sample_rate_set(const uint32_t sampling_rate_hz);
bool baseband_filter_bandwidth_set(const uint32_t bandwidth_hz);
#ifdef HACKRF_ONE
void enable_rf_power(void);
void disable_rf_power(void);
#endif
#ifdef __cplusplus
}
#endif
#endif /* __HACKRF_CORE_H */

View File

@ -0,0 +1,23 @@
# 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.
.data
.section .m0_bin, "ax"
.incbin "${PROJECT_NAME}_m0.bin"

View 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) {
}
}

View File

@ -0,0 +1,507 @@
/*
* 'gcc -DTEST -DDEBUG -O2 -o test max2837.c' prints out what test
* program would do if it had a real spi library
*
* 'gcc -DTEST -DBUS_PIRATE -O2 -o test max2837.c' prints out bus
* pirate commands to do the same thing.
*/
#include <stdint.h>
#include <string.h>
#include "max2837.h"
#include "max2837_regs.def" // private register def macros
#if (defined DEBUG || defined BUS_PIRATE)
#include <stdio.h>
#define LOG printf
#else
#define LOG(x,...)
#include <libopencm3/lpc43xx/ssp.h>
#include <libopencm3/lpc43xx/scu.h>
#include <libopencm3/lpc43xx/gpio.h>
#include "hackrf_core.h"
#endif
/* Default register values. */
static uint16_t max2837_regs_default[MAX2837_NUM_REGS] = {
0x150, /* 0 */
0x002, /* 1 */
0x1f4, /* 2 */
0x1b9, /* 3 */
0x00a, /* 4 */
0x080, /* 5 */
0x006, /* 6 */
0x000, /* 7 */
0x080, /* 8 */
0x018, /* 9 */
0x058, /* 10 */
0x016, /* 11 */
0x24f, /* 12 */
0x150, /* 13 */
0x1c5, /* 14 */
0x081, /* 15 */
0x01c, /* 16 */
0x155, /* 17 */
0x155, /* 18 */
0x153, /* 19 */
0x241, /* 20 */
/*
* Charge Pump Common Mode Enable bit (0) of register 21 must be set or TX
* does not work. Page 1 of the SPI doc says not to set it (0x02c), but
* page 21 says it should be set by default (0x02d).
*/
0x02d, /* 21 */
0x1a9, /* 22 */
0x24f, /* 23 */
0x180, /* 24 */
0x100, /* 25 */
0x3ca, /* 26 */
0x3e3, /* 27 */
0x0c0, /* 28 */
0x3f0, /* 29 */
0x080, /* 30 */
0x000 }; /* 31 */
uint16_t max2837_regs[MAX2837_NUM_REGS];
/* Mark all regsisters dirty so all will be written at init. */
uint32_t max2837_regs_dirty = 0xffffffff;
/* Set up all registers according to defaults specified in docs. */
void max2837_init(void)
{
LOG("# max2837_init\n");
memcpy(max2837_regs, max2837_regs_default, sizeof(max2837_regs));
max2837_regs_dirty = 0xffffffff;
/* Write default register values to chip. */
max2837_regs_commit();
}
/*
* Set up pins for GPIO and SPI control, configure SSP peripheral for SPI, and
* set our own default register configuration.
*/
void max2837_setup(void)
{
LOG("# max2837_setup\n");
#if !defined TEST
/* Configure XCVR_CTL GPIO pins. */
#ifdef JELLYBEAN
scu_pinmux(SCU_XCVR_RXHP, SCU_GPIO_FAST);
scu_pinmux(SCU_XCVR_B1, SCU_GPIO_FAST);
scu_pinmux(SCU_XCVR_B2, SCU_GPIO_FAST);
scu_pinmux(SCU_XCVR_B3, SCU_GPIO_FAST);
scu_pinmux(SCU_XCVR_B4, SCU_GPIO_FAST);
scu_pinmux(SCU_XCVR_B5, SCU_GPIO_FAST);
scu_pinmux(SCU_XCVR_B6, SCU_GPIO_FAST);
scu_pinmux(SCU_XCVR_B7, SCU_GPIO_FAST);
#endif
scu_pinmux(SCU_XCVR_ENABLE, SCU_GPIO_FAST);
scu_pinmux(SCU_XCVR_RXENABLE, SCU_GPIO_FAST);
scu_pinmux(SCU_XCVR_TXENABLE, SCU_GPIO_FAST);
/* Set GPIO pins as outputs. */
GPIO2_DIR |= (PIN_XCVR_ENABLE | PIN_XCVR_RXENABLE | PIN_XCVR_TXENABLE);
#ifdef JELLYBEAN
GPIO_DIR(PORT_XCVR_RXHP) |= PIN_XCVR_RXHP;
GPIO_DIR(PORT_XCVR_B) |=
PIN_XCVR_B1
| PIN_XCVR_B2
| PIN_XCVR_B3
| PIN_XCVR_B4
| PIN_XCVR_B5
| PIN_XCVR_B6
| PIN_XCVR_B7
;
#endif
max2837_mode_shutdown();
#ifdef JELLYBEAN
gpio_set(PORT_XCVR_RXHP, PIN_XCVR_RXHP);
gpio_set(PORT_XCVR_B,
PIN_XCVR_B1
| PIN_XCVR_B2
| PIN_XCVR_B3
| PIN_XCVR_B4
| PIN_XCVR_B5
| PIN_XCVR_B6
| PIN_XCVR_B7
);
#endif
#endif
max2837_init();
LOG("# max2837_init done\n");
/* Use SPI control instead of B1-B7 pins for gain settings. */
set_MAX2837_TXVGA_GAIN_SPI_EN(1);
set_MAX2837_TXVGA_GAIN_MSB_SPI_EN(1);
//set_MAX2837_TXVGA_GAIN(0x3f); /* maximum attenuation */
set_MAX2837_TXVGA_GAIN(0x00); /* minimum attenuation */
set_MAX2837_VGAMUX_enable(1);
set_MAX2837_VGA_EN(1);
set_MAX2837_HPC_RXGAIN_EN(0);
set_MAX2837_HPC_STOP(MAX2837_STOP_1K);
set_MAX2837_LNAgain_SPI_EN(1);
set_MAX2837_LNAgain(MAX2837_LNAgain_MAX); /* maximum gain */
set_MAX2837_VGAgain_SPI_EN(1);
set_MAX2837_VGA(0x18); /* reasonable gain for noisy 2.4GHz environment */
/* maximum rx output common-mode voltage */
set_MAX2837_BUFF_VCM(MAX2837_BUFF_VCM_1_25);
/* configure baseband filter for 8 MHz TX */
set_MAX2837_LPF_EN(1);
set_MAX2837_ModeCtrl(MAX2837_ModeCtrl_RxLPF);
set_MAX2837_FT(MAX2837_FT_5M);
max2837_regs_commit();
}
/* SPI register read. */
uint16_t max2837_spi_read(uint8_t r) {
gpio_clear(PORT_XCVR_CS, PIN_XCVR_CS);
const uint16_t value = ssp_transfer(SSP1_NUM, (uint16_t)((1 << 15) | (r << 10)));
gpio_set(PORT_XCVR_CS, PIN_XCVR_CS);
return value & 0x3ff;
}
/* SPI register write */
void max2837_spi_write(uint8_t r, uint16_t v) {
#ifdef BUS_PIRATE
LOG("{0x%02x 0x%02x]\n", 0x00 | ((uint16_t)r<<2) | ((v>>8) & 0x3),
v & 0xff);
#elif DEBUG
LOG("0x%03x -> reg%d\n", v, r);
#else
gpio_clear(PORT_XCVR_CS, PIN_XCVR_CS);
ssp_transfer(SSP1_NUM, (uint16_t)((r << 10) | (v & 0x3ff)));
gpio_set(PORT_XCVR_CS, PIN_XCVR_CS);
#endif
}
uint16_t max2837_reg_read(uint8_t r)
{
if ((max2837_regs_dirty >> r) & 0x1) {
max2837_regs[r] = max2837_spi_read(r);
};
return max2837_regs[r];
}
void max2837_reg_write(uint8_t r, uint16_t v)
{
max2837_regs[r] = v;
max2837_spi_write(r, v);
MAX2837_REG_SET_CLEAN(r);
}
/* This functions should not be needed, and might be confusing. DELETE. */
void max2837_regs_read(void)
{
;
}
static inline void max2837_reg_commit(uint8_t r)
{
max2837_reg_write(r,max2837_regs[r]);
}
void max2837_regs_commit(void)
{
int r;
for(r = 0; r < MAX2837_NUM_REGS; r++) {
if ((max2837_regs_dirty >> r) & 0x1) {
max2837_reg_commit(r);
}
}
}
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
max2837_mode_standby();
#endif
}
void max2837_tx(void)
{
LOG("# max2837_tx\n");
#if !defined TEST
set_MAX2837_ModeCtrl(MAX2837_ModeCtrl_TxLPF);
max2837_regs_commit();
max2837_mode_tx();
#endif
}
void max2837_rx(void)
{
LOG("# max2837_rx\n");
set_MAX2837_ModeCtrl(MAX2837_ModeCtrl_RxLPF);
max2837_regs_commit();
#if !defined TEST
max2837_mode_rx();
#endif
}
void max2837_stop(void)
{
LOG("# max2837_stop\n");
set_MAX2837_EN_SPI(0);
max2837_regs_commit();
#if !defined TEST
max2837_mode_shutdown();
#endif
}
void max2837_set_frequency(uint32_t freq)
{
uint8_t band;
uint8_t lna_band;
uint32_t div_frac;
uint32_t div_int;
uint32_t div_rem;
uint32_t div_cmp;
int i;
/* Select band. Allow tuning outside specified bands. */
if (freq < 2400000000U) {
band = MAX2837_LOGEN_BSW_2_3;
lna_band = MAX2837_LNAband_2_4;
}
else if (freq < 2500000000U) {
band = MAX2837_LOGEN_BSW_2_4;
lna_band = MAX2837_LNAband_2_4;
}
else if (freq < 2600000000U) {
band = MAX2837_LOGEN_BSW_2_5;
lna_band = MAX2837_LNAband_2_6;
}
else {
band = MAX2837_LOGEN_BSW_2_6;
lna_band = MAX2837_LNAband_2_6;
}
LOG("# max2837_set_frequency %ld, band %d, lna band %d\n",
freq, band, lna_band);
/* ASSUME 40MHz PLL. Ratio = F*(4/3)/40,000,000 = F/30,000,000 */
div_int = freq / 30000000;
div_rem = freq % 30000000;
div_frac = 0;
div_cmp = 30000000;
for( i = 0; i < 20; i++) {
div_frac <<= 1;
div_cmp >>= 1;
if (div_rem > div_cmp) {
div_frac |= 0x1;
div_rem -= div_cmp;
}
}
LOG("# int %ld, frac %ld\n", div_int, div_frac);
/* Band settings */
set_MAX2837_LOGEN_BSW(band);
set_MAX2837_LNAband(lna_band);
/* Write order matters here, so commit INT and FRAC_HI before
* committing FRAC_LO, which is the trigger for VCO
* auto-select. TODO - it's cleaner this way, but it would be
* faster to explicitly commit the registers explicitly so the
* dirty bits aren't scanned twice. */
set_MAX2837_SYN_INT(div_int);
set_MAX2837_SYN_FRAC_HI((div_frac >> 10) & 0x3ff);
max2837_regs_commit();
set_MAX2837_SYN_FRAC_LO(div_frac & 0x3ff);
max2837_regs_commit();
}
typedef struct {
uint32_t bandwidth_hz;
uint32_t ft;
} max2837_ft_t;
static const max2837_ft_t max2837_ft[] = {
{ 1750000, MAX2837_FT_1_75M },
{ 2500000, MAX2837_FT_2_5M },
{ 3500000, MAX2837_FT_3_5M },
{ 5000000, MAX2837_FT_5M },
{ 5500000, MAX2837_FT_5_5M },
{ 6000000, MAX2837_FT_6M },
{ 7000000, MAX2837_FT_7M },
{ 8000000, MAX2837_FT_8M },
{ 9000000, MAX2837_FT_9M },
{ 10000000, MAX2837_FT_10M },
{ 12000000, MAX2837_FT_12M },
{ 14000000, MAX2837_FT_14M },
{ 15000000, MAX2837_FT_15M },
{ 20000000, MAX2837_FT_20M },
{ 24000000, MAX2837_FT_24M },
{ 28000000, MAX2837_FT_28M },
{ 0, 0 },
};
bool max2837_set_lpf_bandwidth(const uint32_t bandwidth_hz) {
const max2837_ft_t* p = max2837_ft;
while( p->bandwidth_hz != 0 ) {
if( p->bandwidth_hz >= bandwidth_hz ) {
break;
}
p++;
}
if( p->bandwidth_hz != 0 ) {
set_MAX2837_FT(p->ft);
max2837_regs_commit();
return true;
} else {
return false;
}
}
bool max2837_set_lna_gain(const uint32_t gain_db) {
uint16_t val;
switch(gain_db){
case 40:
val = MAX2837_LNAgain_MAX;
break;
case 32:
val = MAX2837_LNAgain_M8;
break;
case 24:
val = MAX2837_LNAgain_M16;
break;
case 16:
val = MAX2837_LNAgain_M24;
break;
case 8:
val = MAX2837_LNAgain_M32;
break;
case 0:
val = MAX2837_LNAgain_M40;
break;
default:
return false;
}
set_MAX2837_LNAgain(val);
max2837_reg_commit(1);
return true;
}
bool max2837_set_vga_gain(const uint32_t gain_db) {
if( (gain_db & 0x1) || gain_db > 62)/* 0b11111*2 */
return false;
set_MAX2837_VGA( 31-(gain_db >> 1) );
max2837_reg_commit(5);
return true;
}
bool max2837_set_txvga_gain(const uint32_t gain_db) {
uint16_t val=0;
if(gain_db <16){
val = 31-gain_db;
val |= (1 << 5); // bit6: 16db
} else{
val = 31-(gain_db-16);
}
set_MAX2837_TXVGA_GAIN(val);
max2837_reg_commit(29);
return true;
}
#ifdef TEST
int main(int ac, char **av)
{
max2837_setup();
max2837_set_frequency(2441000000);
max2837_start();
max2837_tx();
max2837_stop();
}
#endif //TEST

View File

@ -0,0 +1,70 @@
#ifndef __MAX2837_H
#define __MAX2837_H
#include <stdint.h>
#include <stdbool.h>
/* TODO - make this a private header for max2837.c only, make new max2837.h */
/* 32 registers, each containing 10 bits of data. */
#define MAX2837_NUM_REGS 32
#define MAX2837_DATA_REGS_MAX_VALUE 1024
/* TODO - these externs will be local to max2837.c ... don't define here? */
extern uint16_t max2837_regs[MAX2837_NUM_REGS];
extern uint32_t max2837_regs_dirty;
#define MAX2837_REG_SET_CLEAN(r) max2837_regs_dirty &= ~(1UL<<r)
#define MAX2837_REG_SET_DIRTY(r) max2837_regs_dirty |= (1UL<<r)
/* Initialize chip. */
extern void max2837_init(void);
extern void max2837_setup(void);
/* Read a register via SPI. Save a copy to memory and return
* value. Mark clean. */
extern uint16_t max2837_reg_read(uint8_t r);
/* Write value to register via SPI and save a copy to memory. Mark
* clean. */
extern void max2837_reg_write(uint8_t r, uint16_t v);
/* Read all registers from chip and copy to memory. Mark all clean. */
extern void max2837_regs_read(void);
/* Write all dirty registers via SPI from memory. Mark all clean. Some
* operations require registers to be written in a certain order. Use
* 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);
/* Set frequency in Hz. Frequency setting is a multi-step function
* where order of register writes matters. */
extern void max2837_set_frequency(uint32_t freq);
bool max2837_set_lpf_bandwidth(const uint32_t bandwidth_hz);
bool max2837_set_lna_gain(const uint32_t gain_db);
bool max2837_set_vga_gain(const uint32_t gain_db);
bool max2837_set_txvga_gain(const uint32_t gain_db);
extern void max2837_tx(void);
extern void max2837_rx(void);
#endif // __MAX2837_H

View File

@ -0,0 +1,405 @@
/* -*- mode: c -*- */
#ifndef __MAX2837_REGS_DEF
#define __MAX2837_REGS_DEF
/* Generate static inline accessors that operate on the global
* regs. Done this way to (1) allow defs to be scraped out and used
* elsewhere, e.g. in scripts, (2) to avoid dealing with endian
* (structs). This may be used in firmware, or on host predefined
* register loads. */
/* On set_, register is always set dirty, even if nothing
* changed. This makes sure that write that have side effects,
* e.g. frequency setting, are not skipped. */
/* n=name, r=regnum, o=offset (bits from LSB), l=length (bits) */
#define __MREG__(n,r,o,l) \
static inline uint16_t get_##n(void) { \
return (max2837_regs[r] >> (o-l+1)) & ((1<<l)-1); \
} \
static inline void set_##n(uint16_t v) { \
max2837_regs[r] &= ~(((1<<l)-1)<<(o-l+1)); \
max2837_regs[r] |= ((v&((1<<l)-1))<<(o-l+1)); \
MAX2837_REG_SET_DIRTY(r); \
}
/* REG 0 */
__MREG__(MAX2837_LNA_EN, 0,0,1)
__MREG__(MAX2837_Mixer_EN, 0,1,1)
__MREG__(MAX2837_RxLO_EN, 0,2,1)
__MREG__(MAX2837_Lbias, 0,4,2)
#define MAX2837_Lbias_LOWEST 0
#define MAX2837_Lbias_NOMINAL 2
#define MAX2837_Lbias_HIGHEST 3
__MREG__(MAX2837_Mbias, 0,6,2)
#define MAX2837_Mbias_LOWEST 0
#define MAX2837_Mbias_NOMINAL 2
#define MAX2837_Mbias_HIGHEST 3
__MREG__(MAX2837_buf, 0,8,2)
#define MAX2837_buf_LOWEST 0
#define MAX2837_buf_NOMINAL 2
#define MAX2837_buf_HIGHEST 3
__MREG__(MAX2837_LNAband, 0,9,1)
#define MAX2837_LNAband_2_4 0 // 2.3-2.5 GHz
#define MAX2837_LNAband_2_6 1 // 2.5-2.7 GHz
/* REG 1 */
__MREG__(MAX2837_LNAtune, 1,0,1)
#define MAX2837_LNAtune_NOMINAL 0
#define MAX2837_LNAtune_DOWN 1
__MREG__(MAX2837_LNAde_Q,1,1,1)
#define MAX2837_LNAde_Q_NOMINAL 0
#define MAX2837_LNAde_Q_2DB 1
__MREG__(MAX2837_LNAgain,1,4,3)
#define MAX2837_LNAgain_MAX 0b000 // Pad in 8dB steps, bits reversed
#define MAX2837_LNAgain_M8 0b100
#define MAX2837_LNAgain_M16 0b010
#define MAX2837_LNAgain_M24 0b110
#define MAX2837_LNAgain_M32 0b011
#define MAX2837_LNAgain_M40 0b111
__MREG__(MAX2837_iqerr_trim,1,9,5)
// 0b00000 = +4.0 degree phase error
// 0b01111 = 0.0
// 0b11111 = -4.0
/* REG 2 */
__MREG__(MAX2837_LPF_EN,2,0,1)
__MREG__(MAX2837_TxBB_EN,2,1,1)
__MREG__(MAX2837_ModeCtrl,2,3,2)
#define MAX2837_ModeCtrl_RxCalibration 0
#define MAX2837_ModeCtrl_RxLPF 1
#define MAX2837_ModeCtrl_TxLPF 2
#define MAX2837_ModeCtrl_LPFTrim 3
__MREG__(MAX2837_FT,2,7,4)
#define MAX2837_FT_1_75M 0
#define MAX2837_FT_2_5M 1
#define MAX2837_FT_3_5M 2
#define MAX2837_FT_5M 3
#define MAX2837_FT_5_5M 4
#define MAX2837_FT_6M 5
#define MAX2837_FT_7M 6
#define MAX2837_FT_8M 7
#define MAX2837_FT_9M 8
#define MAX2837_FT_10M 9
#define MAX2837_FT_12M 10
#define MAX2837_FT_14M 11
#define MAX2837_FT_15M 12
#define MAX2837_FT_20M 13
#define MAX2837_FT_24M 14
#define MAX2837_FT_28M 15
__MREG__(MAX2837_dF,2,9,2)
#define MAX2837_dF_M10 0b00 // -10%
#define MAX2837_dF_NOMINAL 0b01
#define MAX2837_dF_10 0b11 // +10%
/* REG 3 */
__MREG__(MAX2837_PT_SPI,3,3,4) // slowest=1111 fastest=0000 nom=1001
__MREG__(MAX2837_Bqd,3,6,3) // MSB doubles bias current, lower 2 25% each
__MREG__(MAX2837_TxRPCM,3,9,3) // 000=1.00V, 0.05V steps, 111 not allowed
/* REG 4 */
__MREG__(MAX2837_RP,4,1,2) // 20% steps, 00=lowest, 11=highest
__MREG__(MAX2837_TxBuff,4,3,2) // 25% steps, 00=lowest, 11=highest
__MREG__(MAX2837_VGA_EN,4,4,1)
__MREG__(MAX2837_VGAMUX_enable,4,5,1)
__MREG__(MAX2837_BUFF_Curr,4,7,2) // 250uA + 125uA steps
__MREG__(MAX2837_BUFF_VCM,4,9,2) // VGA common mode
#define MAX2837_BUFF_VCM_0_9 0 // 0.9V
#define MAX2837_BUFF_VCM_1_0 1 // 1.0V
#define MAX2837_BUFF_VCM_1_1 2 // 1.1V
#define MAX2837_BUFF_VCM_1_25 3 // 1.25V
/* REG 5 */
__MREG__(MAX2837_VGA,5,4,5) // max=00000, attenuation in 2dB steps
__MREG__(MAX2837_sel_In1_In2,5,5,1)
#define MAX2837_sel_In1_In2_RXVGA 0
#define MAX2837_sel_In1_In2_TXAM 1
__MREG__(MAX2837_turbo15n20,5,6,1)
__MREG__(MAX2837_VGA_Curr,5,8,2) // 01=default, 00=-33%, 10=+33%, 11=+67%
__MREG__(MAX2837_fuse_arm,5,9,1)
/* REG 6 */
__MREG__(MAX2837_RSSI_EN,6,6,1) // enable RSSI
__MREG__(MAX2837_RSSI_MUX,6,7,1)
#define MAX2837_RSSI_MUX_RSSI 0
#define MAX2837_RSSI_MUX_TEMP 1
__MREG__(MAX2837_RSSI_MODE,6,8,1) // set to override RXHP pin
__MREG__(MAX2837_LPF_MODE_SEL,6,9,1) // set to enable mode in reg 2 ModeCtrl
/* REG 7 is R/O */
// D4:0 ts_adc (temp sensor)
// D9:5 zeros or test outputs
/* REG 8 */
__MREG__(MAX2837_LNAgain_SPI_EN,8,0,1) // set to override pin control of LNA
__MREG__(MAX2837_VGAgain_SPI_EN,8,1,1) // set to override pin control of VGA
__MREG__(MAX2837_EN_Bias_Trim,8,2,1) // route bias current to bondpad
__MREG__(MAX2837_BIAS_TRIM_SPI,8,7,5) // down=00000, up=11111, nom=10000
__MREG__(MAX2837_BIAS_TRIM_CNTRL,8,8,1) // enable BIAS_TRIM_SPI value
__MREG__(MAX2837_RX_IQERR_SPI_EN,8,9,1) // ???
/* REG 9 */
__MREG__(MAX2837_ts_adc_trigger,9,0,1) // temp sensor trigger (one shot)
__MREG__(MAX2837_ts_en,9,1,1) // temp sensor enable (before trigger)
__MREG__(MAX2837_LPFtrim_SPI_EN,9,2,1)
__MREG__(MAX2837_DOUT_DRVH,9,3,1)
#define MAX2837_DOUT_DRVH_1X 0
#define MAX2837_DOUT_DRVH_4X 1
__MREG__(MAX2837_DOUT_PU,9,4,1) // set to enable CMOS PU (default), else OD
__MREG__(MAX2837_DOUT_SEL,9,7,3)
#define MAX2837_DOUT_SEL_SPI 0 // default, SPI comm
#define MAX2837_DOUT_SEL_PLL_LOCK_DETECT 1
#define MAX2837_DOUT_SEL_VAS_TEST_OUT 2
#define MAX2837_DOUT_SEL_HPFSM_TEST_OUT 3
#define MAX2837_DOUT_SEL_LOGEN_TRIM_OUT 4
#define MAX2837_DOUT_SEL_RX_FUSE_GASKET 5
#define MAX2837_DOUT_SEL_TX_FUSE_GASKET 6
#define MAX2837_DOUT_SEL_ZERO 7
__MREG__(MAX2837_fuse_sh,9,8,1) // ???
__MREG__(MAX2837_fuse_burn_gkt,9,9,1) // enable (don't)
/* REG 10 */
__MREG__(MAX2837_TXCAL_GAIN,10,2,2) // 00=default, steps of +10dB
__MREG__(MAX2837_TXCAL_V2I_FILT,10,5,3) // 000=+12%, 111=-16%, 011=default
__MREG__(MAX2837_TX_BIAS_ADJ,10,7,2) // 00=-10%, 01=default, 10=+10%, 11=+20%
/* REG 11 */
__MREG__(MAX2837_AMD_SPI_EN,11,0,1) // enable AM detector
__MREG__(MAX2837_TXMXR_V2I_GAIN,11,4,4) // 0000=max, steps of -0.5dB
/* REG 12 */
__MREG__(MAX2837_HPC_10M,12,1,2) // steps of 0.4uS (0.0-1.2)
__MREG__(MAX2837_HPC_10M_GAIN,12,3,2) // steps of 0.4uS (0.0-1.2)
__MREG__(MAX2837_HPC_600K,12,6,3) // steps of 0.8uS (0.0-4.8), 7=stay 1
__MREG__(MAX2837_HPC_600K_GAIN,12,9,3) // steps of 0.8uS (0.0-4.8), 7=stay 1
/* REG 13 */
__MREG__(MAX2837_HPC_100K,13,1,2) // steps of 3.2uS (0.0-9.6)
__MREG__(MAX2837_HPC_100K_GAIN,13,3,2) // steps of 3.2uS (0.0-9.6)
__MREG__(MAX2837_HPC_30K,13,5,2) // steps of 3.2uS (0.0-9.6)
__MREG__(MAX2837_HPC_30K_GAIN,13,7,2) // steps of 3.2uS (0.0-9.6)
__MREG__(MAX2837_HPC_1K,13,9,2) // steps of 3.2uS (0.0-9.6)
/* REG 14 */
__MREG__(MAX2837_HPC_1K_GAIN,14,1,2) // steps of 3.2uS (0.0-9.6)
__MREG__(MAX2837_HPC_DELAY,14,3,2) // steps of 0.2uS (0.0-0.6)
__MREG__(MAX2837_HPC_STOP,14,5,2)
#define MAX2837_STOP_100 0
#define MAX2837_STOP_1K 1
#define MAX2837_STOP_30K 2
#define MAX2837_STOP_100K 3
__MREG__(MAX2837_HPC_STOP_M2,14,7,2)
#define MAX2837_STOP_M2_1K 0
#define MAX2837_STOP_M2_30K 1
#define MAX2837_STOP_M2_100K 2
#define MAX2837_STOP_M2_600K 3
__MREG__(MAX2837_HPC_RXGAIN_EN,14,8,1) // RXVGA HPFSM re-triggered by B7 & B6
__MREG__(MAX2837_HPC_MODE,14,9,1) // use RXHP
/* REG 15 */
__MREG__(MAX2837_HPC_DIVH,15,0,1)
#define MAX2837_HPC_DIVH_20M 0
#define MAX2837_HPC_DIVH_40M 1
__MREG__(MAX2837_HPC_TST,15,5,5) // filter test modes ... see doc
__MREG__(MAX2837_HPC_SEQ_BYP,15,6,1) // set to bypass programmed sequence
__MREG__(MAX2837_DOUT_CSB_SEL,15,7,1) // set to tri state DOUT when CSB high
/* REG 16 */
__MREG__(MAX2837_EN_SPI,16,0,1) // enable overall chip
__MREG__(MAX2837_CAL_SPI,16,1,1) // enable calibration mode
__MREG__(MAX2837_LOGEN_SPI_EN,16,2,1) // ???
__MREG__(MAX2837_SYN_SPI_EN,16,3,1) // enable synthesizer
__MREG__(MAX2837_VAS_SPI_EN,16,4,1) // enable VCO autoselect
__MREG__(MAX2837_PADRV_SPI_EN,16,5,1) // enable power amp
__MREG__(MAX2837_PADAC_SPI_EN,16,6,1) // enable power amp bias DAC always
__MREG__(MAX2837_PADAC_TX_EN,16,7,1) // enable power amp bias only if TX pin
__MREG__(MAX2837_TXMX_SPI_EN,16,8,1) // enable TX mixer
__MREG__(MAX2837_TXLO_SPI_EN,16,9,1) // enable TX LO
/* REG 17 */
__MREG__(MAX2837_SYN_FRAC_LO,17,9,10)
/* REG 18 */
__MREG__(MAX2837_SYN_FRAC_HI,18,9,10)
/* REG 19 */
__MREG__(MAX2837_SYN_INT,19,7,8)
__MREG__(MAX2837_LOGEN_BSW,19,9,2)
#define MAX2837_LOGEN_BSW_2_3 0 // 2300 - <2400 MHz
#define MAX2837_LOGEN_BSW_2_4 1 // 2400 - <2500 MHz
#define MAX2837_LOGEN_BSW_2_5 2 // 2500 - <2600 MHz
#define MAX2837_LOGEN_BSW_2_6 3 // 2600 - <2700 MHz
/* REG 20 */
__MREG__(MAX2837_SYN_MODE,20,0,1)
#define MAX2837_SYN_MODE_INTEGER 0
#define MAX2837_SYN_MODE_FRACTIONAL 1
__MREG__(MAX2837_SYN_REF_DIV,20,2,2)
#define MAX2837_SYN_REF_DIV_1 0
#define MAX2837_SYN_REF_DIV_2 1
#define MAX2837_SYN_REF_DIV_4 2
#define MAX2837_SYN_REF_DIV_8 3
__MREG__(MAX2837_SYN_CURRENT_,20,4,2)
#define MAX2837_SYN_CURRENT_3_2_DIFF 0 // 3.2mA differential
#define MAX2837_SYN_CURRENT_1_6_DIFF 1 // 1.6mA differential
#define MAX2837_SYN_CURRENT_1_6_SINGLE 2 // 1.6mA single-ended
#define MAX2837_SYN_CURRENT_0_8_SINGLE 3 // 0.8mA single-ended
__MREG__(MAX2837_SYN_CLOCKOUT_DRIVE,20,5,1)
#define MAX2837_SYN_CLOCKOUT_DRIVE_1X 0
#define MAX2837_SYN_CLOCKOUT_DRIVE_4X 1
__MREG__(MAX2837_SYN_TURBO_EN,20,6,1) // ???
__MREG__(MAX2837_SYN_BIAS_SPI,20,7,1) // Use trim value below
__MREG__(MAX2837_SYN_BIAS_TRIM,20,9,2) // 00=max 10=default 11=min
/* REG 21 */
__MREG__(MAX2837_SYN_CP_COMMON_MODE_EN,21,0,1)
__MREG__(MAX2837_SYN_PRESCALER_BIAS_BOOST,21,1,1) // 0=default 1=+20%
__MREG__(MAX2837_SYN_CP_BETA_EN,21,2,1)
__MREG__(MAX2837_SYN_SD_CLOCK_SEL,21,3,1)
#define MAX2837_SYN_SD_CLOCK_PFD 0 // from PFD reset
#define MAX2837_SYN_SD_CLOCK_PRE 1 // from prescaler
__MREG__(MAX2837_SYN_CP_PULSE_WIDTH_ADJ,21,4,1) // 0=default 1=-20%
__MREG__(MAX2837_SYN_CP_LIN_CUR,21,6,2) // +3% per step
__MREG__(MAX2837_SYN_TEST_OUT,21,9,3) // high bit locks CP in test mode
#define MAX2837_SYN_TEST_LOCK_DETECT 0b000
#define MAX2837_SYN_TEST_SD 0b001
#define MAX2837_SYN_TEST_REF_DIV 0b010
#define MAX2837_SYN_TEST_MAIN_DIV 0b011
#define MAX2837_SYN_TEST_CP_LO_Z_LOCK_DETECT 0b100
#define MAX2837_SYN_TEST_CP_SOURCE_SD 0b101
#define MAX2837_SYN_TEST_CP_SINK_REF_DIV 0b110
#define MAX2837_SYN_TEST_CP_HI_Z_MAIN_DIV 0b111
/* REG 22 */
__MREG__(MAX2837_VAS_EN,22,0,1) // select VCO subband by VAS, vs. reg
__MREG__(MAX2837_VAS_RELOCK_SEL,22,1,1)
#define MAX2837_VAS_RELOCK_SELECTED 0
#define MAX2837_VAS_RELOCK_PRESENT 1
__MREG__(MAX2837_VAS_DIV,22,4,3)
#define MAX2837_VAS_CLK_DIV_8 0
#define MAX2837_VAS_CLK_DIV_9 1
#define MAX2837_VAS_CLK_DIV_10 2
#define MAX2837_VAS_CLK_DIV_11 3
#define MAX2837_VAS_CLK_DIV_12 4
#define MAX2837_VAS_CLK_DIV_13 5
#define MAX2837_VAS_CLK_DIV_14 6
#define MAX2837_VAS_CLK_DIV_2 7
__MREG__(MAX2837_VAS_DLY,22,6,2) // Delay = Txtal * VAS_DIV * VAS_DLY * 7
#define MAX2837_VAS_DLY_16
#define MAX2837_VAS_DLY_32
#define MAX2837_VAS_DLY_64
#define MAX2837_VAS_DLY_128
__MREG__(MAX2837_VAS_TRIG_EN,22,7,1)
__MREG__(MAX2837_VAS_ADE,22,8,1)
__MREG__(MAX2837_VAS_ADL_SPI,22,9,1)
/* REG 23 */
__MREG__(MAX2837_VAS_SPI,23,4,5) // subband selection default is center (15)
__MREG__(MAX2837_XTAL_BIAS,23,6,2)
#define MAX2837_XTAL_BIAS_240_20 0 // 240uA for 20MHz
#define MAX2837_XTAL_BIAS_420_20 1
#define MAX2837_XTAL_BIAS_600_40 2
#define MAX2837_XTAL_BIAS_780_40 3
__MREG__(MAX2837_XTAL_E2C_BIAS,23,7,1)
#define MAX2837_XTAL_E2C_BIAS_360 0 // uA
#define MAX2837_XTAL_E2C_BIAS_540 1
__MREG__(MAX2837_VAS_SE,23,8,1)
#define MAX2837_VAS_SE_DIFF 0
#define MAX2837_VAS_SE_SINGLE 1
__MREG__(MAX2837_VCO_SPI_EN,23,9,1) // set to override mode
/* REG 24 */
__MREG__(MAX2837_XTAL_TUNE,24,6,7) // 0=max 127=min freq
__MREG__(MAX2837_CLKOUT_PIN_EN,24,7,1)
__MREG__(MAX2837_CLKOUT_DIV,24,8,1)
#define MAX2837_CLKOUT_DIV_1 0
#define MAX2837_CLKOUT_DIV_2 1
__MREG__(MAX2837_XTAL_CORE_EN,24,9,1) // set to override mode
/* REG 25 */
__MREG__(MAX2837_VCO_BIAS_SPI_EN,25,0,1) // enable override of vco bias trim
__MREG__(MAX2837_VCO_BIAS,25,4,4) // 0b1000 nominal
__MREG__(MAX2837_VCO_CMEN,25,5,1) // enable Miller capacitor
__MREG__(MAX2837_VCO_PDET_TST,25,7,2) // peak detector test output select
#define MAX2837_VCO_PDET_TST_NORMAL 0
#define MAX2837_VCO_PDET_TST_PDOUT 1 // peak detector output
#define MAX2837_VCO_PDET_TST_PDREF 2 // peak detector reference
#define MAX2837_VCO_PDET_TST_TEMP 3 // VCO temperature sensor
__MREG__(MAX2837_VCO_BUF_BIAS,25,9,2) // VCO buffer bias
#define MAX2837_VCO_BUF_BIAS_800uA 0
#define MAX2837_VCO_BUF_BIAS_1200uA 1 // default
#define MAX2837_VCO_BUF_BIAS_1600uA 2
#define MAX2837_VCO_BUF_BIAS_2000uA 3
/* REG 26 */
__MREG__(MAX2837_LOGEN_BIAS1,26,1,2) // LOGEN emitter follower bias
#define MAX2837_LOGEN_BIAS1_400u 0
#define MAX2837_LOGEN_BIAS1_600u 1
#define MAX2837_LOGEN_BIAS1_800u 2
#define MAX2837_LOGEN_BIAS1_1000u 3
__MREG__(MAX2837_LOGEN_BIAS2,26,2,1) // LOGEN RX/TX Gm bias
#define MAX2837_LOGEN_BIAS2_DEFAULT 0 // default
#define MAX2837_LOGEN_BIAS2_PLUS25 1 // +25%
__MREG__(MAX2837_LOGEN_2GM,26,3,1) //
__MREG__(MAX2837_LOGEN_TRIM1,26,4,1) // mixer tank trim enable
__MREG__(MAX2837_LOGEN_TRIM2,26,5,1) // bandpass filter trim enable
__MREG__(MAX2837_VAS_TST,26,9,4) // DOUT test signal select
#define MAX2837_VAS_TST_VCO_BSW0 0 // VAS band select output (5 bits)
#define MAX2837_VAS_TST_VCO_BSW1 1
#define MAX2837_VAS_TST_VCO_BSW2 2
#define MAX2837_VAS_TST_VCO_BSW3 3
#define MAX2837_VAS_TST_VCO_BSW4 4
#define MAX2837_VAS_TST_Vtune_ADC0 5 // VCO Vtune ADC output (3 bits)
#define MAX2837_VAS_TST_Vtune_ADC1 6
#define MAX2837_VAS_TST_Vtune_ADC2 7
#define MAX2837_VAS_TST_VASA 8 // VAS accomplish (success)
#define MAX2837_VAS_TST_VASE 9 // VAS end (success or gave up)
#define MAX2837_VAS_TST_ZERO 15 // default
/* REG 27 */
__MREG__(MAX2837_PADRV_BIAS,27,2,3) // PA driver bias (0-7), default 3
__MREG__(MAX2837_PADRV_DOWN_SPI_EN,27,3,1) // PA drv down process select enable
__MREG__(MAX2837_PADRV_DOWN,27,4,1) // PA driver down select
#define MAX2837_PADRV_DOWN_DOWN 0
#define MAX2837_PADRV_DOWN_UP 1 // default
__MREG__(MAX2837_PADAC_IV,27,5,1) // PA DAC I/V output select
#define MAX2837_PADAC_IV_VOLTAGE 0
#define MAX2837_PADAC_IV_CURRENT 1 // default
__MREG__(MAX2837_PADAC_VMODE,27,6,1) // set logic 0 or 1 for PADAC_IV out
__MREG__(MAX2837_PADAC_DIV,27,7,1) // PA DAC clock divide ratio
#define MAX2837_PADAC_DIV_20MHz 0
#define MAX2837_PADAC_DIV_40MHz 1
__MREG__(MAX2837_TXGATE_EN,27,8,1) // set to relock when TXOOL=1 or LD=0
__MREG__(MAX2837_TXDCCORR_EN,27,9,1) // TX DC offset correction enable
/* REG 28 */
__MREG__(MAX2837_PADAC_BIAS,28,5,6) // PADAC output current control, 5uA step
__MREG__(MAX2837_PADAC_DLY,28,9,4) // PADAC turn-on delay control
// 0,1 are both 0us
// then 0.5us steps to 7.0us
/* REG 29 */
__MREG__(MAX2837_TXVGA_GAIN_SPI_EN,29,0,1) // Enable SPI control of TXVGA gain
__MREG__(MAX2837_TXVGA_GAIN_MSB_SPI_EN,29,1,1)
__MREG__(MAX2837_TX_DCCORR_SPI_EN,29,2,1)
__MREG__(MAX2837_FUSE_ARM,29,3,1) // Fuse burn enable
__MREG__(MAX2837_TXVGA_GAIN,29,9,6) // 0 = min atten, 63 = max atten
/* REG 30 */
__MREG__(MAX2837_TXLO_IQ,30,4,5)
__MREG__(MAX2837_TXLO_IQ_SPI_EN,30,5,1)
__MREG__(MAX2837_TXLO_BUFF_BIAS,30,7,2)
#define MAX2837_TXLO_BUFF_BIAS_1_0mA 0
#define MAX2837_TXLO_BUFF_BIAS_1_5mA 1
#define MAX2837_TXLO_BUFF_BIAS_2_0mA 2 // default
#define MAX2837_TXLO_BUFF_BIAS_2_5mA 3
__MREG__(MAX2837_FUSE_GKT,30,8,1)
__MREG__(MAX2837_FUSE_RTH,30,9,1)
/* REG 31 */
// 0 -> 992/0uA correction, 15 -> 0/992uA correction ... if TX_DCCORR_SPI_EN
__MREG__(MAX2837_TX_DCCORR_I,31,4,5)
__MREG__(MAX2837_TX_DCCORR_Q,31,9,5)
#endif // __MAX2837_REGS_DEF

View File

@ -0,0 +1,100 @@
/*
* 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.
*/
#include <stdint.h>
#include <libopencm3/lpc43xx/gpio.h>
#include <libopencm3/lpc43xx/ssp.h>
#include "hackrf_core.h"
#include "max5864.h"
void max5864_spi_write(uint_fast8_t value) {
gpio_clear(PORT_AD_CS, PIN_AD_CS);
ssp_transfer(SSP1_NUM, value);
gpio_set(PORT_AD_CS, PIN_AD_CS);
}
/* Set MAX5864 operation mode to "Shutdown":
* REF: off
* CLK: off
* ADCs: off (bus is tri-stated)
* DACs: off (set input bus to zero or OVdd)
*/
void max5864_shutdown()
{
max5864_spi_write(0x00);
}
/* Set MAX5864 operation mode to "Standby":
* REF: on
* CLK: off?
* ADCs: off (bus is tri-stated)
* DACs: off (set input bus to zero or OVdd)
*/
void max5864_standby()
{
max5864_spi_write(0x05);
}
/* Set MAX5864 operation mode to "Idle":
* REF: on
* CLK: on
* ADCs: off (bus is tri-stated)
* DACs: off (set input bus to zero or OVdd)
*/
void max5864_idle()
{
max5864_spi_write(0x01);
}
/* Set MAX5864 operation mode to "Rx":
* REF: on
* CLK: on
* ADCs: on
* DACs: off (set input bus to zero or OVdd)
*/
void max5864_rx()
{
max5864_spi_write(0x02);
}
/* Set MAX5864 operation mode to "Tx":
* REF: on
* CLK: on
* ADCs: off (bus is tri-stated)
* DACs: on
*/
void max5864_tx()
{
max5864_spi_write(0x03);
}
/* Set MAX5864 operation mode to "Xcvr":
* REF: on
* CLK: on
* ADCs: on
* DACs: on
*/
void max5864_xcvr()
{
max5864_spi_write(0x04);
}

View File

@ -0,0 +1,32 @@
/*
* 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.
*/
#ifndef __MAX5864_H
#define __MAX5864_H
void max5864_shutdown();
void max5864_standby();
void max5864_idle();
void max5864_rx();
void max5864_tx();
void max5864_xcvr();
#endif // __MAX5864_H

View File

@ -0,0 +1,335 @@
/*
* 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;
/*
* Antenna port power on HackRF One is controlled by GPO1 on the RFFC5072.
* This is the only thing we use RFFC5072 GPO for on HackRF One. The value of
* SWITCHCTRL_NO_ANT_PWR does not correspond to the GPO1 bit in the gpo
* register.
*/
#define SWITCHCTRL_ANT_PWR (1 << 6) /* turn on antenna port power */
#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);
if (ctrl & SWITCHCTRL_ANT_PWR) {
rffc5071_set_gpo(0x00); /* turn on antenna power by clearing GPO1 */
} else {
rffc5071_set_gpo(0x01); /* turn off antenna power by setting GPO1 */
}
}
#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 antenna port
* power 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:
#ifdef HACKRF_ONE
rf_path_set_antenna(0);
#endif
rf_path_set_lna(0);
/* 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);
}
/* antenna port power control */
void rf_path_set_antenna(const uint_fast8_t enable) {
if (enable) {
switchctrl |= SWITCHCTRL_ANT_PWR;
} else {
switchctrl &= ~(SWITCHCTRL_ANT_PWR);
}
switchctrl_set(switchctrl);
}

View File

@ -0,0 +1,50 @@
/*
* 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 = 0,
RF_PATH_FILTER_LOW_PASS = 1,
RF_PATH_FILTER_HIGH_PASS = 2,
} 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);
void rf_path_set_antenna(const uint_fast8_t enable);
#endif/*__RFPATH_H__*/

View File

@ -0,0 +1,514 @@
/*
* Copyright 2012 Michael Ossmann
* Copyright 2014 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.
*/
/*
* 'gcc -DTEST -DDEBUG -O2 -o test rffc5071.c' prints out what test
* program would do if it had a real spi library
*/
/*
* The actual part on Jawbreaker is the RFFC5072, not the RFFC5071, but the
* RFFC5071 may be installed instead. The only difference between the parts is
* that the RFFC5071 includes a second mixer.
*/
#include <stdint.h>
#include <string.h>
#include "rffc5071.h"
#include "rffc5071_regs.def" // private register def macros
#if (defined DEBUG)
#include <stdio.h>
#define LOG printf
#else
#define LOG(x,...)
#include <libopencm3/lpc43xx/ssp.h>
#include <libopencm3/lpc43xx/scu.h>
#include <libopencm3/lpc43xx/gpio.h>
#include "hackrf_core.h"
#endif
/* Default register values. */
static uint16_t rffc5071_regs_default[RFFC5071_NUM_REGS] = {
0xbefa, /* 00 */
0x4064, /* 01 */
0x9055, /* 02 */
0x2d02, /* 03 */
0xacbf, /* 04 */
0xacbf, /* 05 */
0x0028, /* 06 */
0x0028, /* 07 */
0xff00, /* 08 */
0x8220, /* 09 */
0x0202, /* 0A */
0x4800, /* 0B */
0x1a94, /* 0C */
0xd89d, /* 0D */
0x8900, /* 0E */
0x1e84, /* 0F */
0x89d8, /* 10 */
0x9d00, /* 11 */
0x2a20, /* 12 */
0x0000, /* 13 */
0x0000, /* 14 */
0x0000, /* 15 */
0x0000, /* 16 */
0x4900, /* 17 */
0x0281, /* 18 */
0xf00f, /* 19 */
0x0000, /* 1A */
0x0000, /* 1B */
0xc840, /* 1C */
0x1000, /* 1D */
0x0005, /* 1E */ };
uint16_t rffc5071_regs[RFFC5071_NUM_REGS];
/* Mark all regsisters dirty so all will be written at init. */
uint32_t rffc5071_regs_dirty = 0x7fffffff;
/* Set up all registers according to defaults specified in docs. */
void rffc5071_init(void)
{
LOG("# rffc5071_init\n");
memcpy(rffc5071_regs, rffc5071_regs_default, sizeof(rffc5071_regs));
rffc5071_regs_dirty = 0x7fffffff;
/* Write default register values to chip. */
rffc5071_regs_commit();
}
/*
* Set up pins for GPIO and SPI control, configure SSP peripheral for SPI, and
* set our own default register configuration.
*/
void rffc5071_setup(void)
{
rffc5071_init();
LOG("# rffc5071_setup\n");
#if !defined TEST
/* Configure GPIO pins. */
scu_pinmux(SCU_MIXER_ENX, SCU_GPIO_FAST);
scu_pinmux(SCU_MIXER_SCLK, SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
scu_pinmux(SCU_MIXER_SDATA, SCU_GPIO_FAST);
scu_pinmux(SCU_MIXER_RESETX, SCU_GPIO_FAST);
/* Set GPIO pins as outputs. */
GPIO_DIR(PORT_MIXER_ENX) |= PIN_MIXER_ENX;
GPIO_DIR(PORT_MIXER_SCLK) |= PIN_MIXER_SCLK;
GPIO_DIR(PORT_MIXER_SDATA) |= PIN_MIXER_SDATA;
GPIO_DIR(PORT_MIXER_RESETX) |= PIN_MIXER_RESETX;
/* set to known state */
gpio_set(PORT_MIXER_ENX, PIN_MIXER_ENX); /* active low */
gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK);
gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA);
gpio_set(PORT_MIXER_RESETX, PIN_MIXER_RESETX); /* active low */
#endif
/* initial setup */
/* put zeros in freq contol registers */
set_RFFC5071_P2N(0);
set_RFFC5071_P2LODIV(0);
set_RFFC5071_P2PRESC(0);
set_RFFC5071_P2VCOSEL(0);
set_RFFC5071_P2N(0);
set_RFFC5071_P2LODIV(0);
set_RFFC5071_P2PRESC(0);
set_RFFC5071_P2VCOSEL(0);
set_RFFC5071_P2N(0);
set_RFFC5071_P2LODIV(0);
set_RFFC5071_P2PRESC(0);
set_RFFC5071_P2VCOSEL(0);
/* set ENBL and MODE to be configured via 3-wire interface,
* not control pins. */
set_RFFC5071_SIPIN(1);
/* GPOs are active at all times */
set_RFFC5071_GATE(1);
rffc5071_regs_commit();
}
void serial_delay(void)
{
uint32_t i;
for (i = 0; i < 2; i++)
__asm__("nop");
}
/* SPI register read.
*
* Send 9 bits:
* first bit is ignored,
* second bit is one for read operation,
* next 7 bits are register address.
* Then receive 16 bits (register value).
*/
uint16_t rffc5071_spi_read(uint8_t r) {
int bits = 9;
int msb = 1 << (bits -1);
uint32_t data = 0x80 | (r & 0x7f);
#if DEBUG
LOG("reg%d = 0\n", r);
return 0;
#else
/* make sure everything is starting in the correct state */
gpio_set(PORT_MIXER_ENX, PIN_MIXER_ENX);
gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK);
gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA);
/*
* The device requires two clocks while ENX is high before a serial
* transaction. This is not clearly documented.
*/
serial_delay();
gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK);
serial_delay();
gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK);
serial_delay();
gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK);
serial_delay();
gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK);
/* start transaction by bringing ENX low */
gpio_clear(PORT_MIXER_ENX, PIN_MIXER_ENX);
while (bits--) {
if (data & msb)
gpio_set(PORT_MIXER_SDATA, PIN_MIXER_SDATA);
else
gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA);
data <<= 1;
serial_delay();
gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK);
serial_delay();
gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK);
}
serial_delay();
gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK);
serial_delay();
gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK);
bits = 16;
data = 0;
/* set SDATA line as input */
GPIO_DIR(PORT_MIXER_SDATA) &= ~PIN_MIXER_SDATA;
while (bits--) {
data <<= 1;
serial_delay();
gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK);
serial_delay();
gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK);
if (MIXER_SDATA_STATE)
data |= 1;
}
/* set SDATA line as output */
GPIO_DIR(PORT_MIXER_SDATA) |= PIN_MIXER_SDATA;
serial_delay();
gpio_set(PORT_MIXER_ENX, PIN_MIXER_ENX);
/*
* The device requires a clock while ENX is high after a serial
* transaction. This is not clearly documented.
*/
gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK);
serial_delay();
gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK);
return data;
#endif /* DEBUG */
}
/* SPI register write
*
* Send 25 bits:
* first bit is ignored,
* second bit is zero for write operation,
* next 7 bits are register address,
* next 16 bits are register value.
*/
void rffc5071_spi_write(uint8_t r, uint16_t v) {
#if DEBUG
LOG("0x%04x -> reg%d\n", v, r);
#else
int bits = 25;
int msb = 1 << (bits -1);
uint32_t data = ((r & 0x7f) << 16) | v;
/* make sure everything is starting in the correct state */
gpio_set(PORT_MIXER_ENX, PIN_MIXER_ENX);
gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK);
gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA);
/*
* The device requires two clocks while ENX is high before a serial
* transaction. This is not clearly documented.
*/
serial_delay();
gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK);
serial_delay();
gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK);
serial_delay();
gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK);
serial_delay();
gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK);
/* start transaction by bringing ENX low */
gpio_clear(PORT_MIXER_ENX, PIN_MIXER_ENX);
while (bits--) {
if (data & msb)
gpio_set(PORT_MIXER_SDATA, PIN_MIXER_SDATA);
else
gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA);
data <<= 1;
serial_delay();
gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK);
serial_delay();
gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK);
}
gpio_set(PORT_MIXER_ENX, PIN_MIXER_ENX);
/*
* The device requires a clock while ENX is high after a serial
* transaction. This is not clearly documented.
*/
serial_delay();
gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK);
serial_delay();
gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK);
#endif
}
uint16_t rffc5071_reg_read(uint8_t r)
{
/* Readback register is not cached. */
if (r == RFFC5071_READBACK_REG)
return rffc5071_spi_read(r);
/* Discard uncommited write when reading. This shouldn't
* happen, and probably has not been tested. */
if ((rffc5071_regs_dirty >> r) & 0x1) {
rffc5071_regs[r] = rffc5071_spi_read(r);
};
return rffc5071_regs[r];
}
void rffc5071_reg_write(uint8_t r, uint16_t v)
{
rffc5071_regs[r] = v;
rffc5071_spi_write(r, v);
RFFC5071_REG_SET_CLEAN(r);
}
static inline void rffc5071_reg_commit(uint8_t r)
{
rffc5071_reg_write(r,rffc5071_regs[r]);
}
void rffc5071_regs_commit(void)
{
int r;
for(r = 0; r < RFFC5071_NUM_REGS; r++) {
if ((rffc5071_regs_dirty >> r) & 0x1) {
rffc5071_reg_commit(r);
}
}
}
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 */
rffc5071_regs_commit();
}
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 */
rffc5071_regs_commit();
}
/*
* This function turns on both mixer (full-duplex) on the RFFC5071, but our
* current hardware designs do not support full-duplex operation.
*/
void rffc5071_rxtx(void) {
LOG("# rfc5071_rxtx\n");
set_RFFC5071_ENBL(0);
set_RFFC5071_FULLD(1); /* mixer 1 and mixer 2 (RXTX) */
rffc5071_regs_commit();
rffc5071_enable();
}
void rffc5071_disable(void) {
LOG("# rfc5071_disable\n");
set_RFFC5071_ENBL(0);
rffc5071_regs_commit();
}
void rffc5071_enable(void) {
LOG("# rfc5071_enable\n");
set_RFFC5071_ENBL(1);
rffc5071_regs_commit();
}
#define LO_MAX 5400
#define REF_FREQ 50
#define FREQ_ONE_MHZ (1000*1000)
/* configure frequency synthesizer in integer mode (lo in MHz) */
uint64_t rffc5071_config_synth_int(uint16_t lo) {
uint8_t lodiv;
uint16_t fvco;
uint8_t fbkdiv;
uint16_t n;
uint64_t tune_freq_hz;
uint16_t p1nmsb;
uint8_t p1nlsb;
LOG("# config_synth_int\n");
/* Calculate n_lo */
uint8_t n_lo = 0;
uint16_t x = LO_MAX / lo;
while ((x > 1) && (n_lo < 5)) {
n_lo++;
x >>= 1;
}
lodiv = 1 << n_lo;
fvco = lodiv * lo;
/* higher divider and charge pump current required above
* 3.2GHz. Programming guide says these values (fbkdiv, n,
* maybe pump?) can be changed back after enable in order to
* improve phase noise, since the VCO will already be stable
* and will be unaffected. */
if (fvco > 3200) {
fbkdiv = 4;
set_RFFC5071_PLLCPL(3);
} else {
fbkdiv = 2;
set_RFFC5071_PLLCPL(2);
}
uint64_t tmp_n = ((uint64_t)fvco << 29ULL) / (fbkdiv*REF_FREQ) ;
n = tmp_n >> 29ULL;
p1nmsb = (tmp_n >> 13ULL) & 0xffff;
p1nlsb = (tmp_n >> 5ULL) & 0xff;
tune_freq_hz = (REF_FREQ * (tmp_n >> 5ULL) * fbkdiv * FREQ_ONE_MHZ)
/ (lodiv * (1 << 24ULL));
LOG("# lo=%d n_lo=%d lodiv=%d fvco=%d fbkdiv=%d n=%d tune_freq_hz=%d\n",
lo, n_lo, lodiv, fvco, fbkdiv, n, tune_freq);
/* Path 1 */
set_RFFC5071_P1LODIV(n_lo);
set_RFFC5071_P1N(n);
set_RFFC5071_P1PRESC(fbkdiv >> 1);
set_RFFC5071_P1NMSB(p1nmsb);
set_RFFC5071_P1NLSB(p1nlsb);
/* Path 2 */
set_RFFC5071_P2LODIV(n_lo);
set_RFFC5071_P2N(n);
set_RFFC5071_P2PRESC(fbkdiv >> 1);
set_RFFC5071_P2NMSB(p1nmsb);
set_RFFC5071_P2NLSB(p1nlsb);
rffc5071_regs_commit();
return tune_freq_hz;
}
/* !!!!!!!!!!! hz is currently ignored !!!!!!!!!!! */
uint64_t rffc5071_set_frequency(uint16_t mhz) {
uint32_t tune_freq;
rffc5071_disable();
tune_freq = rffc5071_config_synth_int(mhz);
rffc5071_enable();
return tune_freq;
}
void rffc5071_set_gpo(uint8_t gpo)
{
/* We set GPO for both paths just in case. */
set_RFFC5071_P1GPO(gpo);
set_RFFC5071_P2GPO(gpo);
rffc5071_regs_commit();
}
#ifdef TEST
int main(int ac, char **av)
{
rffc5071_setup();
rffc5071_tx(0);
rffc5071_set_frequency(500, 0);
rffc5071_set_frequency(525, 0);
rffc5071_set_frequency(550, 0);
rffc5071_set_frequency(1500, 0);
rffc5071_set_frequency(1525, 0);
rffc5071_set_frequency(1550, 0);
rffc5071_disable();
rffc5071_rx(0);
rffc5071_disable();
rffc5071_rxtx();
rffc5071_disable();
}
#endif //TEST

View File

@ -0,0 +1,65 @@
/*
* Copyright 2012 Michael Ossmann
* Copyright 2014 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 __RFFC5071_H
#define __RFFC5071_H
/* 31 registers, each containing 16 bits of data. */
#define RFFC5071_NUM_REGS 31
extern uint16_t rffc5071_regs[RFFC5071_NUM_REGS];
extern uint32_t rffc5071_regs_dirty;
#define RFFC5071_REG_SET_CLEAN(r) rffc5071_regs_dirty &= ~(1UL<<r)
#define RFFC5071_REG_SET_DIRTY(r) rffc5071_regs_dirty |= (1UL<<r)
/* Initialize chip. Call _setup() externally, as it calls _init(). */
extern void rffc5071_init(void);
extern void rffc5071_setup(void);
/* Read a register via SPI. Save a copy to memory and return
* value. Discard any uncommited changes and mark CLEAN. */
extern uint16_t rffc5071_reg_read(uint8_t r);
/* Write value to register via SPI and save a copy to memory. Mark
* CLEAN. */
extern void rffc5071_reg_write(uint8_t r, uint16_t v);
/* Write all dirty registers via SPI from memory. Mark all clean. Some
* operations require registers to be written in a certain order. Use
* provided routines for those operations. */
extern void rffc5071_regs_commit(void);
/* Set frequency (MHz). */
extern uint64_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(void);
extern void rffc5071_rx(void);
extern void rffc5071_rxtx(void);
extern void rffc5071_enable(void);
extern void rffc5071_disable(void);
extern void rffc5071_set_gpo(uint8_t);
#endif // __RFFC5071_H

View File

@ -0,0 +1,257 @@
/* -*- mode: c -*-
*
* Copyright 2012 Michael Ossmann
*
* 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 __RFFC5071_REGS_DEF
#define __RFFC5071_REGS_DEF
#define RFFC5071_READBACK_REG 31
/* Generate static inline accessors that operate on the global
* regs. Done this way to (1) allow defs to be scraped out and used
* elsewhere, e.g. in scripts, (2) to avoid dealing with endian
* (structs). This may be used in firmware, or on host predefined
* register loads. */
/* On set_, register is always set dirty, even if nothing
* changed. This makes sure that writes that have side effects,
* e.g. frequency setting, are not skipped. */
/* n=name, r=regnum, o=offset (bits from LSB) of LSB of field,
* l=length (bits) */
#define __MREG__(n,r,o,l) \
static inline uint16_t get_##n(void) { \
return (rffc5071_regs[r] >> o) & ((1L<<l)-1); \
} \
static inline void set_##n(uint16_t v) { \
rffc5071_regs[r] &= (uint16_t)(~(((1L<<l)-1)<<o)); \
rffc5071_regs[r] |= (uint16_t)(((v&((1L<<l)-1))<<o)); \
RFFC5071_REG_SET_DIRTY(r); \
}
/* REG 00 (0): LF */
__MREG__(RFFC5071_PLLCPL,0,0,3)
__MREG__(RFFC5071_P1CPDEF,0,3,6)
__MREG__(RFFC5071_P2CPDEF,0,9,6)
__MREG__(RFFC5071_IFACT,0,15,1)
#define RFFC5071_
/* REG 01 (1): XO */
__MREG__(RFFC5071_SUWAIT,1,0,10)
__MREG__(RFFC5071_XOCF,1,10,1)
__MREG__(RFFC5071_XOC,1,11,4)
__MREG__(RFFC5071_XOCH,1,15,1)
/* REG 02 (2): CAL_TIME */
__MREG__(RFFC5071_TKV2,2,0,4)
__MREG__(RFFC5071_TKV1,2,4,4)
__MREG__(RFFC5071_TCT,2,10,5)
__MREG__(RFFC5071_WAIT,2,15,1)
/* REG 03 (3): VCO_CTRL */
__MREG__(RFFC5071_ICPUP,3,1,2)
__MREG__(RFFC5071_REFST,3,3,1)
__MREG__(RFFC5071_XOI3,3,4,1)
__MREG__(RFFC5071_XOI2,3,5,1)
__MREG__(RFFC5071_XOI1,3,6,1)
__MREG__(RFFC5071_KVPOL,3,7,1)
__MREG__(RFFC5071_KVRNG,3,8,1)
__MREG__(RFFC5071_KVAVG,3,9,2)
__MREG__(RFFC5071_CLKPL,3,1,1)
__MREG__(RFFC5071_CTPOL,3,12,1)
__MREG__(RFFC5071_CTAVG,3,13,2)
__MREG__(RFFC5071_XTVCO,3,15,1)
/* REG 04 (4): CT_CAL1 */
__MREG__(RFFC5071_P1CTDEF,4,0,7)
__MREG__(RFFC5071_P1CT,4,7,1)
__MREG__(RFFC5071_P1CTV,4,8,5)
__MREG__(RFFC5071_P1CTGAIN,4,13,3)
/* REG 05 (5): CT_CAL2 */
__MREG__(RFFC5071_P2CTDEF,5,0,7)
__MREG__(RFFC5071_P2CT,5,7,1)
__MREG__(RFFC5071_P2CTV,5,8,5)
__MREG__(RFFC5071_P2CTGAIN,5,13,3)
/* REG 06 (6): PLL_CAL1 */
__MREG__(RFFC5071_P1SGN,6,2,1)
__MREG__(RFFC5071_P1KVGAIN,6,3,3)
__MREG__(RFFC5071_P1DN,6,6,9)
__MREG__(RFFC5071_P1KV,6,15,1)
/* REG 07 (7): PLL_CAL2 */
__MREG__(RFFC5071_P2SGN,7,2,1)
__MREG__(RFFC5071_P2KVGAIN,7,3,3)
__MREG__(RFFC5071_P2DB,7,6,9)
__MREG__(RFFC5071_P2KV,7,15,1)
/* REG 08 (8): VCO_AUTO */
__MREG__(RFFC5071_CTMIN,8,1,7)
__MREG__(RFFC5071_CTMAX,8,8,7)
__MREG__(RFFC5071_AUTO,8,15,1)
/* REG 09 (9): PLL_CTRL */
__MREG__(RFFC5071_PLLDY,9,0,2)
__MREG__(RFFC5071_ALOI,9,2,1)
__MREG__(RFFC5071_RELOK,9,3,1)
__MREG__(RFFC5071_LDLEV,9,4,1)
__MREG__(RFFC5071_LDEN,9,5,1)
__MREG__(RFFC5071_TVCO,9,6,5)
__MREG__(RFFC5071_PLLST,9,11,1)
__MREG__(RFFC5071_CLKDIV,9,12,3)
__MREG__(RFFC5071_DIVBY,9,15,1)
/* REG 0A (10): PLL_BIAS */
__MREG__(RFFC5071_P2VCOI,10,0,3)
__MREG__(RFFC5071_P2LOI,10,3,4)
__MREG__(RFFC5071_P1VCOI,10,8,3)
__MREG__(RFFC5071_P1LOI,10,11,4)
/* REG 0B (11): MIX_CONT */
__MREG__(RFFC5071_P2MIXIDD,11,9,3)
__MREG__(RFFC5071_P1MIXIDD,11,12,3)
__MREG__(RFFC5071_FULLD,11,15,1)
/* REG 0C (12): P1_FREQ1 */
__MREG__(RFFC5071_P1VCOSEL,12,0,2)
__MREG__(RFFC5071_P1PRESC,12,2,2)
__MREG__(RFFC5071_P1LODIV,12,4,3)
__MREG__(RFFC5071_P1N,12,7,9)
/* REG 0D (13): P1_FREQ2 */ /* !!!!! CHECK FOR OVERFLOW !!!!! */
__MREG__(RFFC5071_P1NMSB,13,0,16)
/* REG 0E (14): P1_FREQ3 */
__MREG__(RFFC5071_P1NLSB,14,8,8)
/* REG 0F (15): P2_FREQ1 */
__MREG__(RFFC5071_P2VCOSEL,15,0,2)
__MREG__(RFFC5071_P2PRESC,15,2,2)
__MREG__(RFFC5071_P2LODIV,15,4,3)
__MREG__(RFFC5071_P2N,15,7,9)
/* REG 10 (16): P2_FREQ2 */ /* !!!!! CHECK FOR OVERFLOW !!!!! */
__MREG__(RFFC5071_P2NMSB,16,0,16)
/* REG 11 (17): P2_FREQ3 */
__MREG__(RFFC5071_P2NLSB,17,8,8)
/* REG 12 (18): FN_CTRL */
__MREG__(RFFC5071_TZPS,18,1,1)
__MREG__(RFFC5071_DMODE,18,2,1)
__MREG__(RFFC5071_FM,18,3,1)
__MREG__(RFFC5071_DITH,18,4,1)
__MREG__(RFFC5071_DSM_MODE,18,5,1)
__MREG__(RFFC5071_PHSALNDLY,18,6,2)
__MREG__(RFFC5071_PHSALNGAIN,18,8,3)
__MREG__(RFFC5071_PHALN,18,11,1)
__MREG__(RFFC5071_SDM,18,12,2)
__MREG__(RFFC5071_DITHR,18,14,1)
__MREG__(RFFC5071_FNZ,18,15,1)
/* REG 13 (19): EXT_MOD */
__MREG__(RFFC5071_MODSTEP,19,10,4)
__MREG__(RFFC5071_MODSETUP,19,14,2)
/* REG 14 (20): FMOD */ /* !!!!! CHECK FOR OVERFLOW !!!!! */
__MREG__(RFFC5071_MODULATION,20,0,16)
/* REG 15 (21): SDI_CTRL */
__MREG__(RFFC5071_RESET,21,1,1)
__MREG__(RFFC5071_ADDR,21,11,1)
__MREG__(RFFC5071_4WIRE,21,12,1)
__MREG__(RFFC5071_MODE,21,13,1)
__MREG__(RFFC5071_ENBL,21,14,1)
__MREG__(RFFC5071_SIPIN,21,15,1)
/* REG 16 (22): GPO */
__MREG__(RFFC5071_LOCK,22,0,1)
__MREG__(RFFC5071_GATE,22,1,1)
__MREG__(RFFC5071_P1GPO,22,2,7)
__MREG__(RFFC5071_P2GPO,22,9,7)
/* REG 17 (23): T_VCO */
__MREG__(RFFC5071_CURVE_VCO3,23,7,3)
__MREG__(RFFC5071_CURVE_VCO2,23,10,3)
__MREG__(RFFC5071_CURVE_VCO1,23,13,3)
/* REG 18 (24): IQMOD1 */
__MREG__(RFFC5071_BUFDC,24,0,2)
__MREG__(RFFC5071_DIVBIAS,24,2,1)
__MREG__(RFFC5071_CALBLK,24,3,1)
__MREG__(RFFC5071_CALNUL,24,4,1)
__MREG__(RFFC5071_CALON,24,5,1)
__MREG__(RFFC5071_LOBIAS,24,6,2)
__MREG__(RFFC5071_MODBIAS,24,8,3)
__MREG__(RFFC5071_CTRL,24,11,5) /* shown as 5 fields in reg overview */
/* REG 19 (25): IQMOD2 */
__MREG__(RFFC5071_MODBUF,25,0,2)
__MREG__(RFFC5071_MOD,25,2,2)
__MREG__(RFFC5071_CALATTEN,25,4,2)
__MREG__(RFFC5071_RCTUNE,25,6,6)
__MREG__(RFFC5071_BBATTEN,25,12,4)
/* REG 1A (26): IQMOD3 */
__MREG__(RFFC5071_DACEN,26,3,1)
__MREG__(RFFC5071_BUFDACQ,26,4,6)
__MREG__(RFFC5071_BUFDACI,26,10,6)
/* REG 1B (27): IQMOD4 */
__MREG__(RFFC5071_BUFBIAS2,27,2,2)
__MREG__(RFFC5071_BUFBIAS1,27,4,2)
__MREG__(RFFC5071_MODDACQ,27,6,6)
__MREG__(RFFC5071_MODDACI,27,12,6)
/* REG 1C (28): T_CTRL */
__MREG__(RFFC5071_V_TEST,28,5,1)
__MREG__(RFFC5071_LDO_BY,28,6,1)
__MREG__(RFFC5071_EXT_FILT,28,7,1)
__MREG__(RFFC5071_REF_SEL,28,8,1)
__MREG__(RFFC5071_FILT_CTRL,28,9,2)
__MREG__(RFFC5071_FC_EN,28,11,1)
__MREG__(RFFC5071_TBL_SEL,28,12,2)
__MREG__(RFFC5071_TC_EN,28,14,2)
/* REG 1D (29): DEV_CTRL */
__MREG__(RFFC5071_BYPAS,29,1,1)
__MREG__(RFFC5071_CTCLK,29,2,1)
__MREG__(RFFC5071_DAC,29,3,1)
__MREG__(RFFC5071_CPD,29,4,1)
__MREG__(RFFC5071_CPU,29,5,1)
__MREG__(RFFC5071_RSMSTOPST,29,6,5)
__MREG__(RFFC5071_RSMST,29,11,1)
__MREG__(RFFC5071_READSEL,29,12,4)
/* REG 1E (30): TEST */
__MREG__(RFFC5071_LFSRD,30,0,1) /* n/a in reg overview */
__MREG__(RFFC5071_RCBYP,30,1,1)
__MREG__(RFFC5071_RGBYP,30,2,1)
__MREG__(RFFC5071_LFSRT,30,3,1)
__MREG__(RFFC5071_LFSRGATET,30,4,4)
__MREG__(RFFC5071_LFSRP,30,8,1)
__MREG__(RFFC5071_LFSR,30,9,1)
__MREG__(RFFC5071_TSEL,30,10,2)
__MREG__(RFFC5071_TMUX,30,12,3)
__MREG__(RFFC5071_TEN,30,15,1)
#endif // __RFFC5071_REGS_DEF

View File

@ -0,0 +1,105 @@
/*
* 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.
*/
#include "hackrf_core.h"
#include <stdint.h>
#include "rom_iap.h"
#include "w25q80bv.h"
#define ROM_IAP_ADDR (0x10400100)
#define ROM_IAP_UNDEF_ADDR (0x12345678)
#define ROM_OTP_PART_ID_ADDR (0x40045000)
typedef void (* IAP_t)(uint32_t [],uint32_t[]);
typedef struct {
const IAP_t IAP; /* If equal to 0x12345678 IAP not implemented */
/* Other TBD */
} *pENTRY_ROM_API_t;
#define pROM_API ((pENTRY_ROM_API_t)ROM_IAP_ADDR)
/*
See Errata sheet ES_LPC43X0_A.pdf (LPC4350/30/20/10 Rev A)
3.5 IAP.1: In-Application Programming API not present on flashless parts
Introduction:
The LPC43x0 microcontrollers contain an APIfor In-Application Programming of flash
memory. This API also allows identification of the part.
Problem:
On the LPC43x0 microcontrollers, the IAP API is not present. The ISP interface is present
which allows the part to be identified externally (via the UART) but part identification is not
possible internally using the IAP call because it is not implemented.
The first word of the Part ID can be read directly from OTP at 0x40045000. The second word of the Part ID is always
'0' on flashless parts. */
bool iap_is_implemented(void)
{
bool res;
if( *((uint32_t*)ROM_IAP_ADDR) != ROM_IAP_UNDEF_ADDR )
{
res = true;
}else
{
res = false;
}
return res;
}
isp_iap_ret_code_t iap_cmd_call(iap_cmd_res_t* iap_cmd_res)
{
uint32_t* p_u32_data;
if( iap_is_implemented() )
{
pROM_API->IAP( (uint32_t*)&iap_cmd_res->cmd_param, (uint32_t*)&iap_cmd_res->status_res);
}else
{
/*
Alternative way to retrieve Part Id on MCU with no IAP
Read Serial No => Read Unique ID in SPIFI (only compatible with W25Q80BV
*/
w25q80bv_setup();
switch(iap_cmd_res->cmd_param.command_code)
{
case IAP_CMD_READ_PART_ID_NO:
p_u32_data = (uint32_t*)ROM_OTP_PART_ID_ADDR;
iap_cmd_res->status_res.iap_result[0] = p_u32_data[0];
iap_cmd_res->status_res.iap_result[1] = p_u32_data[1];
iap_cmd_res->status_res.status_ret = CMD_SUCCESS;
break;
case IAP_CMD_READ_SERIAL_NO:
/* Only 64bits used */
iap_cmd_res->status_res.iap_result[0] = 0;
iap_cmd_res->status_res.iap_result[1] = 0;
w25q80bv_get_unique_id( (w25q80bv_unique_id_t*)&iap_cmd_res->status_res.iap_result[2] );
iap_cmd_res->status_res.status_ret = CMD_SUCCESS;
break;
default:
iap_cmd_res->status_res.status_ret = ERROR_IAP_NOT_IMPLEMENTED;
break;
}
}
return iap_cmd_res->status_res.status_ret;
}

View File

@ -0,0 +1,121 @@
/*
* 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.
*/
#ifndef __ROM_IAP__
#define __ROM_IAP__
#include <stdint.h>
typedef enum
{
/* TODO define other commands */
IAP_CMD_INIT_IAP = 49,
/* Command Init IAP
Input Command code: 49 (decimal)
Return Code CMD_SUCCESS
Result None
Description Initializes and prepares the flash for erase and write operations.
Stack usage 88 B */
IAP_CMD_READ_PART_ID_NO = 54,
/* Read part identification number
Command Read part identification number
Input Command code: 54 (decimal)
Parameters:None
Return Code CMD_SUCCESS |
Result Result0:Part Identification Number.
Result1:Part Identification Number.
Description This command is used to read the part identification number. See Table 1082
<09>LPC43xx part identification numbers<72>.
The command returns two words: word0 followed by word1. Word 0 corresponds
to the part id and word1 indicates the flash configuration or contains 0x0 for
flashless parts.
Stack usage 8 B */
IAP_CMD_READ_SERIAL_NO = 58
/* Read device serial number
Input Command code: 58 (decimal)
Parameters: None
Return Code CMD_SUCCESS
Result Result0:First 32-bit word of Device Identification Number (at the lowest address)
Result1:Second 32-bit word of Device Identification Number
Result2:Third 32-bit word of Device Identification Number
Result3:Fourth 32-bit word of Device Identification Number
Description This command is used to read the device identification number. The serial number
may be used to uniquely identify a single unit among all LPC43xx devices.
Stack usage 8 B */
} iap_cmd_code_t;
/* ISP/IAP Return Code */
typedef enum
{
CMD_SUCCESS = 0x00000000, /* CMD_SUCCESS Command is executed successfully. Sent by ISP handler only when command given by the host has been completely and successfully executed. */
INVALID_COMMAND = 0x00000001, /* Invalid command. */
SRC_ADDR_ERROR = 0x00000002, /* Source address is not on word boundary. */
DST_ADDR_ERROR = 0x00000003, /* Destination address not on word or 256 byte boundary. */
SRC_ADDR_NOT_MAPPED = 0x00000004, /* Source address is not mapped in the memory map. Count value is taken into consideration where applicable. */
DST_ADDR_NOT_MAPPED = 0x00000005, /* Destination address is not mapped in the memory map. Count value is taken into consideration where applicable.*/
COUNT_ERROR = 0x00000006, /* Byte count is not multiple of 4 or is not a permitted value. */
INVALID_SECTOR = 0x00000007, /* Sector number is invalid or end sector number is greater than start sector number. */
SECTOR_NOT_BLANK = 0x00000008, /* Sector is not blank. */
SECTOR_NOT_PREP_WRITE_OP = 0x00000009, /* Command to prepare sector for write operation was not executed. */
COMPARE_ERROR = 0x0000000A, /* Source and destination data not equal. */
BUSY = 0x0000000B, /* Flash programming hardware interface is busy. */
PARAM_ERROR = 0x0000000C, /* Insufficient number of parameters or invalid parameter. */
ADDR_ERROR = 0x0000000D, /* Address is not on word boundary. */
ADDR_NOT_MAPPED = 0x0000000E, /* Address is not mapped in the memory map. Count value is taken in to consideration where applicable. */
CMD_LOCKED = 0x0000000F, /* Command is locked. */
INVALID_CODE = 0x00000010, /* Unlock code is invalid. */
INVALID_BAUD_RATE = 0x00000011, /* Invalid baud rate setting. */
INVALID_STOP_BIT = 0x00000012, /* Invalid stop bit setting. */
CODE_READ_PROTECTION_ENABLED = 0x00000013, /* Code read protection enabled. */
INVALID_FLASH_UNIT = 0x00000014, /* Invalid flash unit. */
USER_CODE_CHECKSUM = 0x00000015,
ERROR_SETTING_ACTIVE_PARTITION = 0x00000016,
/* Special Error */
ERROR_IAP_NOT_IMPLEMENTED = 0x00000100 /* IAP is not implemented in this part */
} isp_iap_ret_code_t;
typedef struct
{
/* Input Command/Param */
struct
{
iap_cmd_code_t command_code;
uint32_t iap_param[5];
} cmd_param;
/* Output Status/Result */
struct
{
isp_iap_ret_code_t status_ret;
uint32_t iap_result[4];
} status_res;
} iap_cmd_res_t;
/* Check if IAP is implemented */
bool iap_is_implemented(void);
isp_iap_ret_code_t iap_cmd_call(iap_cmd_res_t* iap_cmd_res);
#endif//__ROM_IAP__

View File

@ -0,0 +1,312 @@
/*
* Copyright 2012 Jared Boone <jared@sharebrained.com>
* 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.
*/
#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);
scu_pinmux(SCU_PINMUX_SGPIO2, SCU_GPIO_FAST | SCU_CONF_FUNCTION2);
scu_pinmux(SCU_PINMUX_SGPIO3, SCU_GPIO_FAST | SCU_CONF_FUNCTION2);
scu_pinmux(SCU_PINMUX_SGPIO4, SCU_GPIO_FAST | SCU_CONF_FUNCTION2);
scu_pinmux(SCU_PINMUX_SGPIO5, SCU_GPIO_FAST | SCU_CONF_FUNCTION2);
scu_pinmux(SCU_PINMUX_SGPIO6, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_PINMUX_SGPIO7, SCU_GPIO_FAST | SCU_CONF_FUNCTION6);
scu_pinmux(SCU_PINMUX_SGPIO8, SCU_GPIO_FAST | SCU_CONF_FUNCTION6);
scu_pinmux(SCU_PINMUX_SGPIO9, SCU_GPIO_FAST | SCU_CONF_FUNCTION7);
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_FUNCTION0); /* GPIO0[13] */
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(1);
sgpio_cpld_stream_rx_set_q_invert(0);
GPIO_DIR(GPIO0) |= GPIOPIN13;
GPIO_DIR(GPIO5) |= GPIOPIN14 | GPIOPIN13 | GPIOPIN12;
}
void sgpio_test_interface() {
const uint_fast8_t host_clock_sgpio_pin = 8; // Input
const uint_fast8_t host_capture_sgpio_pin = 9; // Input
const uint_fast8_t host_disable_sgpio_pin = 10; // Output
const uint_fast8_t host_direction_sgpio_pin = 11; // Output
SGPIO_GPIO_OENREG = 0; // All inputs for the moment.
// Disable all counters during configuration
SGPIO_CTRL_ENABLE = 0;
// Make all SGPIO controlled by SGPIO's "GPIO" registers
for (uint_fast8_t i = 0; i < 16; i++) {
SGPIO_OUT_MUX_CFG(i) =
SGPIO_OUT_MUX_CFG_P_OE_CFG(0)
| SGPIO_OUT_MUX_CFG_P_OUT_CFG(4);
}
// Set SGPIO output values.
SGPIO_GPIO_OUTREG =
(1L << host_direction_sgpio_pin)
| (1L << host_disable_sgpio_pin);
// Enable SGPIO pin outputs.
SGPIO_GPIO_OENREG =
(1L << host_direction_sgpio_pin)
| (1L << host_disable_sgpio_pin)
| (0L << host_capture_sgpio_pin)
| (0L << host_clock_sgpio_pin)
| (0xFF << 0);
// Configure SGPIO slices.
// Enable codec data stream.
SGPIO_GPIO_OUTREG &= ~(1L << host_disable_sgpio_pin);
while (1) {
for (uint_fast8_t i = 0; i < 8; i++) {
SGPIO_GPIO_OUTREG ^= (1L << i);
}
}
}
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)
ADC=> CLK x 2=CLKx2 with CLKx2(0)rising=D0Q, CLKx2(1)rising=D1I (corresponds to CLK(0)falling+tD0Q=>D0Q, CLK(1)rising+tDOI=>D1I, CLK(1)falling+tD0Q=>D1Q, CLK(1)rising+tDOI=>D2I ...)
tDOI(CLK Rise to I-ADC Channel-I Output Data Valid)=7.4 to 9ns, tD0Q(CLK Fall to Q-ADC Channel-Q Output Data Valid)=6.9 to 9ns
DAC=> CLK x 2=CLKx2 with CLKx2(0)rising=Q:N-2, CLKx2(1)rising=I:N-1(corresponds to CLK(0)rising=>Q:N-2, CLK(0)falling I:N-1, CLK(1)rising=>Q:N-1, CLK(1)falling I:N ...)
tDSI(I-DAC Data to CLK Fall Setup Time)=min 10ns, tDSQ(Q-DAC Data to CLK Rise Setup Time)=min 10ns
SGPIO8 Clock Input (External Clock)
SGPIO9 Capture Input (Capture/ChipSelect, 1=Enable Capture, 0=Disable capture)
SGPIO10 Disable Output (1/High=Disable codec data stream, 0/Low=Enable codec data stream)
SGPIO11 Direction Output (1/High=TX mode LPC43xx=>CPLD=>DAC, 0/Low=RX mode LPC43xx<=CPLD<=ADC)
*/
void sgpio_configure(
const sgpio_direction_t direction
) {
// Disable all counters during configuration
SGPIO_CTRL_ENABLE = 0;
// Set SGPIO output values.
const uint_fast8_t cpld_direction =
(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)
;
// Enable SGPIO pin outputs.
const uint_fast16_t sgpio_gpio_data_direction =
(direction == SGPIO_DIRECTION_TX)
? (0xFF << 0)
: (0x00 << 0);
SGPIO_GPIO_OENREG =
(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)
| sgpio_gpio_data_direction // 0xFF=Output all SGPIO High(TX mode), 0x00=Output all SPGIO Low(RX mode)
;
SGPIO_OUT_MUX_CFG( 8) = // SGPIO8: Input: clock
SGPIO_OUT_MUX_CFG_P_OE_CFG(0) /* 0x0 gpio_oe (state set by GPIO_OEREG) */
| SGPIO_OUT_MUX_CFG_P_OUT_CFG(0) /* 0x0 dout_doutm1 (1-bit mode) */
;
SGPIO_OUT_MUX_CFG( 9) = // SGPIO9: Input: qualifier
SGPIO_OUT_MUX_CFG_P_OE_CFG(0) /* 0x0 gpio_oe (state set by GPIO_OEREG) */
| SGPIO_OUT_MUX_CFG_P_OUT_CFG(0) /* 0x0 dout_doutm1 (1-bit mode) */
;
SGPIO_OUT_MUX_CFG(10) = // GPIO10: Output: disable
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(11) = // GPIO11: Output: direction
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 =
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".
SGPIO_OUT_MUX_CFG(i) =
SGPIO_OUT_MUX_CFG_P_OE_CFG(0)
| SGPIO_OUT_MUX_CFG_P_OUT_CFG(output_multiplexing_mode) /* 11/0xB=dout_doutm8c (8-bit mode 8c)(multislice L0/7, N0/7), 9=dout_doutm8a (8-bit mode 8a)(A0/7,B0/7) */
;
}
const uint_fast8_t slice_indices[] = {
SGPIO_SLICE_A,
SGPIO_SLICE_I,
SGPIO_SLICE_E,
SGPIO_SLICE_J,
SGPIO_SLICE_C,
SGPIO_SLICE_K,
SGPIO_SLICE_F,
SGPIO_SLICE_L,
};
const uint_fast8_t slice_gpdma = SGPIO_SLICE_H;
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 (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) && (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 */
SGPIO_MUX_CFG(slice_index) =
SGPIO_MUX_CFG_CONCAT_ORDER(concat_order)
| SGPIO_MUX_CFG_CONCAT_ENABLE(concat_enable)
| 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_index) =
SGPIO_SLICE_MUX_CFG_INV_QUALIFIER(0) /* 0x0=Use normal qualifier. */
| SGPIO_SLICE_MUX_CFG_PARALLEL_MODE(3) /* 0x3=Shift 1 byte(8bits) 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_index) = 0; // External clock, don't care
SGPIO_COUNT(slice_index) = 0; // External clock, don't care
SGPIO_POS(slice_index) =
SGPIO_POS_POS_RESET(pos)
| SGPIO_POS_POS(pos)
;
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;
}
void sgpio_cpld_stream_enable() {
// Enable codec data stream.
SGPIO_GPIO_OUTREG &= ~(1L << 10); /* SGPIO10 */
}
void sgpio_cpld_stream_disable() {
// Disable codec data stream.
SGPIO_GPIO_OUTREG |= (1L << 10); /* SGPIO10 */
}
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 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)
*/
const uint_fast8_t skip_n = n - 1;
GPIO_SET(GPIO5) = GPIOPIN14 | GPIOPIN13 | GPIOPIN12;
GPIO_CLR(GPIO5) = (skip_n & 7) << 12;
return (skip_n < 8);
}
void sgpio_cpld_stream_rx_set_q_invert(const uint_fast8_t invert) {
if( invert ) {
GPIO_SET(GPIO0) = GPIOPIN13;
} else {
GPIO_CLR(GPIO0) = GPIOPIN13;
}
}

View File

@ -0,0 +1,47 @@
/*
* 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.
*/
#ifndef __SGPIO_H__
#define __SGPIO_H__
#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_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 n);
void sgpio_cpld_stream_rx_set_q_invert(const uint_fast8_t invert);
#endif//__SGPIO_H__

View 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;
}

View 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__*/

View File

@ -0,0 +1,314 @@
/*
* 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.
*/
#include "si5351c.h"
#include <libopencm3/lpc43xx/i2c.h>
enum pll_sources active_clock_source;
/* FIXME return i2c0 status from each function */
/* write to single register */
void si5351c_write_single(uint8_t reg, uint8_t val)
{
i2c0_tx_start();
i2c0_tx_byte(SI5351C_I2C_ADDR | I2C_WRITE);
i2c0_tx_byte(reg);
i2c0_tx_byte(val);
i2c0_stop();
}
/* read single register */
uint8_t si5351c_read_single(uint8_t reg)
{
uint8_t val;
/* set register address with write */
i2c0_tx_start();
i2c0_tx_byte(SI5351C_I2C_ADDR | I2C_WRITE);
i2c0_tx_byte(reg);
/* read the value */
i2c0_tx_start();
i2c0_tx_byte(SI5351C_I2C_ADDR | I2C_READ);
val = i2c0_rx_byte();
i2c0_stop();
return val;
}
/*
* Write to one or more contiguous registers. data[0] should be the first
* register number, one or more values follow.
*/
void si5351c_write(uint8_t* const data, const uint_fast8_t data_count)
{
uint_fast8_t i;
i2c0_tx_start();
i2c0_tx_byte(SI5351C_I2C_ADDR | I2C_WRITE);
for (i = 0; i < data_count; i++)
i2c0_tx_byte(data[i]);
i2c0_stop();
}
/* Disable all CLKx outputs. */
void si5351c_disable_all_outputs()
{
uint8_t data[] = { 3, 0xFF };
si5351c_write(data, sizeof(data));
}
/* Turn off OEB pin control for all CLKx */
void si5351c_disable_oeb_pin_control()
{
uint8_t data[] = { 9, 0xFF };
si5351c_write(data, sizeof(data));
}
/* Power down all CLKx */
void si5351c_power_down_all_clocks()
{
uint8_t data[] = { 16
, SI5351C_CLK_POWERDOWN
, SI5351C_CLK_POWERDOWN
, SI5351C_CLK_POWERDOWN
, SI5351C_CLK_POWERDOWN
, SI5351C_CLK_POWERDOWN
, SI5351C_CLK_POWERDOWN
, SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE
, SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE
};
si5351c_write(data, sizeof(data));
}
/*
* Register 183: Crystal Internal Load Capacitance
* Reads as 0xE4 on power-up
* Set to 8pF based on crystal specs and HackRF One testing
*/
void si5351c_set_crystal_configuration()
{
uint8_t data[] = { 183, 0x80 };
si5351c_write(data, sizeof(data));
}
/*
* Register 187: Fanout Enable
* Turn on XO and MultiSynth fanout only.
*/
void si5351c_enable_xo_and_ms_fanout()
{
uint8_t data[] = { 187, 0xD0 };
si5351c_write(data, sizeof(data));
}
/*
* Register 15: PLL Input Source
* CLKIN_DIV=0 (Divide by 1)
* PLLA_SRC=0 (XTAL)
* PLLB_SRC=1 (CLKIN)
*/
void si5351c_configure_pll_sources(void)
{
uint8_t data[] = { 15, 0x08 };
si5351c_write(data, sizeof(data));
}
/* MultiSynth NA (PLLA) and NB (PLLB) */
void si5351c_configure_pll_multisynth(void)
{
//init plla to (0x0e00+512)/128*25mhz xtal = 800mhz -> int mode
uint8_t data[] = { 26, 0x00, 0x01, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00 };
si5351c_write(data, sizeof(data));
/* 10 MHz input on CLKIN for PLLB */
data[0] = 34;
data[4] = 0x26;
si5351c_write(data, sizeof(data));
}
void si5351c_reset_pll(void)
{
/* reset PLLA and PLLB */
uint8_t data[] = { 177, 0xA0 };
si5351c_write(data, sizeof(data));
}
void si5351c_configure_multisynth(const uint_fast8_t ms_number,
const uint32_t p1, const uint32_t p2, const uint32_t p3,
const uint_fast8_t r_div)
{
/*
* TODO: Check for p3 > 0? 0 has no meaning in fractional mode?
* And it makes for more jitter in integer mode.
*/
/*
* r is the r divider value encoded:
* 0 means divide by 1
* 1 means divide by 2
* 2 means divide by 4
* ...
* 7 means divide by 128
*/
const uint_fast8_t register_number = 42 + (ms_number * 8);
uint8_t data[] = {
register_number,
(p3 >> 8) & 0xFF,
(p3 >> 0) & 0xFF,
(r_div << 4) | (0 << 2) | ((p1 >> 16) & 0x3),
(p1 >> 8) & 0xFF,
(p1 >> 0) & 0xFF,
(((p3 >> 16) & 0xF) << 4) | (((p2 >> 16) & 0xF) << 0),
(p2 >> 8) & 0xFF,
(p2 >> 0) & 0xFF };
si5351c_write(data, sizeof(data));
}
#ifdef JELLYBEAN
/*
* Registers 16 through 23: CLKx Control
* CLK0:
* CLK0_PDN=0 (powered up)
* MS0_INT=1 (integer mode)
* MS0_SRC=0 (PLLA as source for MultiSynth 0)
* CLK0_INV=0 (not inverted)
* CLK0_SRC=3 (MS0 as input source)
* CLK0_IDRV=3 (8mA)
* CLK1:
* CLK1_PDN=0 (powered up)
* MS1_INT=1 (integer mode)
* MS1_SRC=0 (PLLA as source for MultiSynth 1)
* CLK1_INV=0 (not inverted)
* CLK1_SRC=2 (MS0 as input source)
* CLK1_IDRV=3 (8mA)
* CLK2:
* CLK2_PDN=0 (powered up)
* MS2_INT=1 (integer mode)
* MS2_SRC=0 (PLLA as source for MultiSynth 2)
* CLK2_INV=0 (not inverted)
* CLK2_SRC=2 (MS0 as input source)
* CLK2_IDRV=3 (8mA)
* CLK3:
* CLK3_PDN=0 (powered up)
* MS3_INT=1 (integer mode)
* MS3_SRC=0 (PLLA as source for MultiSynth 3)
* CLK3_INV=0 (inverted)
* CLK3_SRC=2 (MS0 as input source)
* CLK3_IDRV=3 (8mA)
* CLK4:
* CLK4_PDN=0 (powered up)
* MS4_INT=0 (fractional mode -- to support 12MHz to LPC for USB DFU)
* MS4_SRC=0 (PLLA as source for MultiSynth 4)
* CLK4_INV=0 (not inverted)
* CLK4_SRC=3 (MS4 as input source)
* CLK4_IDRV=3 (8mA)
* CLK5:
* CLK5_PDN=0 (powered up)
* MS5_INT=1 (integer mode)
* MS5_SRC=0 (PLLA as source for MultiSynth 5)
* CLK5_INV=0 (not inverted)
* CLK5_SRC=3 (MS5 as input source)
* CLK5_IDRV=3 (8mA)
*/
void si5351c_configure_clock_control()
{
uint8_t data[] = { 16, 0x4F, 0x4B, 0x4B, 0x4B, 0x0F, 0x4F, 0xC0, 0xC0 };
si5351c_write(data, sizeof(data));
}
#endif
#if (defined JAWBREAKER || defined HACKRF_ONE)
void si5351c_configure_clock_control(const enum pll_sources source)
{
uint8_t pll;
if (source == PLL_SOURCE_CLKIN) {
/* PLLB on CLKIN */
pll = SI5351C_CLK_PLL_SRC_B;
} else {
/* PLLA on XTAL */
pll = SI5351C_CLK_PLL_SRC_A;
}
uint8_t data[] = {16
,SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(pll) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA)
,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_0_4) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA)
,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_0_4) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA)
,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA)
,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_6MA)
,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) | 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_INT_MODE | SI5351C_CLK_PLL_SRC(pll) | 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, 3, 4, 5, 7 only. */
void si5351c_enable_clock_outputs()
{
uint8_t data[] = { 3, 0x40 };
si5351c_write(data, sizeof(data));
}
void si5351c_set_int_mode(const uint_fast8_t ms_number, const uint_fast8_t on){
uint8_t data[] = {16, 0};
if(ms_number < 8){
data[0] = 16 + ms_number;
data[1] = si5351c_read_single(data[0]);
if(on)
data[1] |= SI5351C_CLK_INT_MODE;
else
data[1] &= ~(SI5351C_CLK_INT_MODE);
si5351c_write(data, 2);
}
}
void si5351c_set_clock_source(const enum pll_sources source)
{
si5351c_configure_clock_control(source);
active_clock_source = source;
}
void si5351c_activate_best_clock_source(void)
{
uint8_t device_status = si5351c_read_single(0);
if (device_status & SI5351C_LOS) {
/* CLKIN not detected */
if (active_clock_source == PLL_SOURCE_CLKIN) {
si5351c_set_clock_source(PLL_SOURCE_XTAL);
}
} else {
/* CLKIN detected */
if (active_clock_source == PLL_SOURCE_XTAL) {
si5351c_set_clock_source(PLL_SOURCE_CLKIN);
}
}
}

View File

@ -0,0 +1,90 @@
/*
* 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.
*/
#ifndef __SI5351C_H
#define __SI5351C_H
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h>
#define SI_INTDIV(x) (x*128-512)
#define SI5351C_I2C_ADDR (0x60 << 1)
#define SI5351C_CLK_POWERDOWN (1<<7)
#define SI5351C_CLK_INT_MODE (1<<6)
#define SI5351C_CLK_FRAC_MODE (0<<6)
#define SI5351C_CLK_PLL_SRC(x) (x<<5)
#define SI5351C_CLK_PLL_SRC_A 0
#define SI5351C_CLK_PLL_SRC_B 1
#define SI5351C_CLK_INV (1<<4)
#define SI5351C_CLK_SRC(x) (x<<2)
#define SI5351C_CLK_SRC_XTAL 0
#define SI5351C_CLK_SRC_CLKIN 1
#define SI5351C_CLK_SRC_MULTISYNTH_0_4 2
#define SI5351C_CLK_SRC_MULTISYNTH_SELF 3
#define SI5351C_CLK_IDRV(x) (x<<0)
#define SI5351C_CLK_IDRV_2MA 0
#define SI5351C_CLK_IDRV_4MA 1
#define SI5351C_CLK_IDRV_6MA 2
#define SI5351C_CLK_IDRV_8MA 3
#define SI5351C_LOS (1<<4)
enum pll_sources {
PLL_SOURCE_XTAL = 0,
PLL_SOURCE_CLKIN = 1,
};
void si5351c_disable_all_outputs();
void si5351c_disable_oeb_pin_control();
void si5351c_power_down_all_clocks();
void si5351c_set_crystal_configuration();
void si5351c_enable_xo_and_ms_fanout();
void si5351c_configure_pll_sources(void);
void si5351c_configure_pll_multisynth(void);
void si5351c_reset_pll(void);
void si5351c_configure_multisynth(const uint_fast8_t ms_number,
const uint32_t p1, const uint32_t p2, const uint32_t p3,
const uint_fast8_t r_div);
void si5351c_configure_clock_control(const enum pll_sources source);
void si5351c_enable_clock_outputs();
void si5351c_set_int_mode(const uint_fast8_t ms_number, const uint_fast8_t on);
void si5351c_write_single(uint8_t reg, uint8_t val);
uint8_t si5351c_read_single(uint8_t reg);
void si5351c_write(uint8_t* const data, const uint_fast8_t data_count);
void si5351c_set_clock_source(const enum pll_sources source);
void si5351c_activate_best_clock_source(void);
#ifdef __cplusplus
}
#endif
#endif /* __SI5351C_H */

View 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);
}

View 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__*/

View File

@ -0,0 +1,142 @@
/*
* 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 <sgpio.h>
#define FREQ_ONE_MHZ (1000*1000)
#define MIN_LP_FREQ_MHZ (0)
#define MAX_LP_FREQ_MHZ (2150)
#define MIN_BYPASS_FREQ_MHZ (2150)
#define MAX_BYPASS_FREQ_MHZ (2750)
#define MIN_HP_FREQ_MHZ (2750)
#define MID1_HP_FREQ_MHZ (3600)
#define MID2_HP_FREQ_MHZ (5100)
#define MAX_HP_FREQ_MHZ (7250)
#define MIN_LO_FREQ_HZ (84375000)
#define MAX_LO_FREQ_HZ (5400000000ULL)
static uint32_t max2837_freq_nominal_hz=2560000000;
uint64_t freq_cache = 100000000;
/*
* Set freq/tuning between 0MHz to 7250 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;
uint64_t real_RFFC5071_freq_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 < MAX_LP_FREQ_MHZ)
{
rf_path_set_filter(RF_PATH_FILTER_LOW_PASS);
/* IF is graduated from 2650 MHz to 2343 MHz */
max2837_freq_nominal_hz = 2650000000 - (freq / 7);
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);
max2837_set_frequency(real_RFFC5071_freq_hz - freq);
sgpio_cpld_stream_rx_set_q_invert(1);
}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);
sgpio_cpld_stream_rx_set_q_invert(0);
}else if( (freq_mhz >= MIN_HP_FREQ_MHZ) && (freq_mhz <= MAX_HP_FREQ_MHZ) )
{
if (freq_mhz < MID1_HP_FREQ_MHZ) {
/* IF is graduated from 2150 MHz to 2750 MHz */
max2837_freq_nominal_hz = 2150000000 + (((freq - 2750000000) * 60) / 85);
} else if (freq_mhz < MID2_HP_FREQ_MHZ) {
/* IF is graduated from 2350 MHz to 2650 MHz */
max2837_freq_nominal_hz = 2350000000 + ((freq - 3600000000) / 5);
} else {
/* IF is graduated from 2500 MHz to 2738 MHz */
max2837_freq_nominal_hz = 2500000000 + ((freq - 5100000000) / 9);
}
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);
max2837_set_frequency(freq - real_RFFC5071_freq_hz);
sgpio_cpld_stream_rx_set_q_invert(0);
}else
{
/* Error freq_mhz too high */
success = false;
}
max2837_set_mode(prior_max2837_mode);
if( success ) {
freq_cache = freq;
}
return success;
}
bool set_freq_explicit(const uint64_t if_freq_hz, const uint64_t lo_freq_hz,
const rf_path_filter_t path)
{
if ((if_freq_hz < ((uint64_t)MIN_BYPASS_FREQ_MHZ * FREQ_ONE_MHZ))
|| (if_freq_hz > ((uint64_t)MAX_BYPASS_FREQ_MHZ * FREQ_ONE_MHZ))) {
return false;
}
if ((path != RF_PATH_FILTER_BYPASS) &&
((lo_freq_hz < MIN_LO_FREQ_HZ) || (lo_freq_hz > MAX_LO_FREQ_HZ))) {
return false;
}
if (path > 2) {
return false;
}
rf_path_set_filter(path);
max2837_set_frequency(if_freq_hz);
if (lo_freq_hz > if_freq_hz) {
sgpio_cpld_stream_rx_set_q_invert(1);
} else {
sgpio_cpld_stream_rx_set_q_invert(0);
}
if (path != RF_PATH_FILTER_BYPASS) {
(void)rffc5071_set_frequency(lo_freq_hz / FREQ_ONE_MHZ);
}
return true;
}

View File

@ -0,0 +1,35 @@
/*
* 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 "rf_path.h"
#include <stdint.h>
#include <stdbool.h>
bool set_freq(const uint64_t freq);
bool set_freq_explicit(const uint64_t if_freq_hz, const uint64_t lo_freq_hz,
const rf_path_filter_t path);
#endif/*__TUNING_H__*/

View File

@ -0,0 +1,660 @@
/*
* 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.
*/
#include <stdint.h>
#include <stdbool.h>
#include "usb.h"
#include "usb_type.h"
#include "usb_queue.h"
#include "usb_standard_request.h"
#include <libopencm3/lpc43xx/creg.h>
#include <libopencm3/lpc43xx/m4/nvic.h>
#include <libopencm3/lpc43xx/rgu.h>
#include <libopencm3/lpc43xx/usb.h>
usb_device_t* usb_device_usb0 = 0;
usb_queue_head_t usb_qh[12] ATTR_ALIGNED(2048);
#define USB_QH_INDEX(endpoint_address) (((endpoint_address & 0xF) * 2) + ((endpoint_address >> 7) & 1))
usb_queue_head_t* usb_queue_head(
const uint_fast8_t endpoint_address
) {
return &usb_qh[USB_QH_INDEX(endpoint_address)];
}
static usb_endpoint_t* usb_endpoint_from_address(
const uint_fast8_t endpoint_address
) {
return (usb_endpoint_t*)usb_queue_head(endpoint_address)->_reserved_0;
}
static uint_fast8_t usb_endpoint_address(
const usb_transfer_direction_t direction,
const uint_fast8_t number
) {
return ((direction == USB_TRANSFER_DIRECTION_IN) ? 0x80 : 0x00) + number;
}
static bool usb_endpoint_is_in(const uint_fast8_t endpoint_address) {
return (endpoint_address & 0x80) ? true : false;
}
static uint_fast8_t usb_endpoint_number(const uint_fast8_t endpoint_address) {
return (endpoint_address & 0xF);
}
void usb_peripheral_reset() {
RESET_CTRL0 = RESET_CTRL0_USB0_RST;
RESET_CTRL0 = 0;
while( (RESET_ACTIVE_STATUS0 & RESET_CTRL0_USB0_RST) == 0 );
}
static void usb_phy_enable() {
CREG_CREG0 &= ~CREG_CREG0_USB0PHY;
}
static void usb_clear_pending_interrupts(const uint32_t mask) {
USB0_ENDPTNAK = mask;
USB0_ENDPTNAKEN = mask;
USB0_USBSTS_D = mask;
USB0_ENDPTSETUPSTAT = USB0_ENDPTSETUPSTAT & mask;
USB0_ENDPTCOMPLETE = USB0_ENDPTCOMPLETE & mask;
}
static void usb_clear_all_pending_interrupts() {
usb_clear_pending_interrupts(0xFFFFFFFF);
}
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 );
}
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;
}
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 );
}
static void usb_flush_primed_endpoints(const uint32_t mask) {
usb_wait_for_endpoint_priming_to_finish(mask);
usb_flush_endpoints(mask);
usb_wait_for_endpoint_flushing_to_finish(mask);
}
static void usb_flush_all_primed_endpoints() {
usb_flush_primed_endpoints(0xFFFFFFFF);
}
static void usb_endpoint_set_type(
const usb_endpoint_t* const endpoint,
const usb_transfer_type_t transfer_type
) {
// NOTE: UM10503 section 23.6.24 "Endpoint 1 to 5 control registers" says
// that the disabled side of an endpoint must be set to a non-control type
// (e.g. bulk, interrupt, or iso).
const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
USB0_ENDPTCTRL(endpoint_number)
= ( USB0_ENDPTCTRL(endpoint_number)
& ~(USB0_ENDPTCTRL_TXT1_0_MASK | USB0_ENDPTCTRL_RXT_MASK)
)
| ( USB0_ENDPTCTRL_TXT1_0(transfer_type)
| USB0_ENDPTCTRL_RXT(transfer_type)
);
}
static void usb_endpoint_enable(
const usb_endpoint_t* const endpoint
) {
const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
if( usb_endpoint_is_in(endpoint->address) ) {
USB0_ENDPTCTRL(endpoint_number) |= (USB0_ENDPTCTRL_TXE | USB0_ENDPTCTRL_TXR);
} else {
USB0_ENDPTCTRL(endpoint_number) |= (USB0_ENDPTCTRL_RXE | USB0_ENDPTCTRL_RXR);
}
}
static void usb_endpoint_clear_pending_interrupts(
const usb_endpoint_t* const endpoint
) {
const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
if( usb_endpoint_is_in(endpoint->address) ) {
usb_clear_pending_interrupts(USB0_ENDPTCOMPLETE_ETCE(1 << endpoint_number));
} else {
usb_clear_pending_interrupts(USB0_ENDPTCOMPLETE_ERCE(1 << endpoint_number));
}
}
void usb_endpoint_disable(
const usb_endpoint_t* const endpoint
) {
const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
if( usb_endpoint_is_in(endpoint->address) ) {
USB0_ENDPTCTRL(endpoint_number) &= ~(USB0_ENDPTCTRL_TXE);
} else {
USB0_ENDPTCTRL(endpoint_number) &= ~(USB0_ENDPTCTRL_RXE);
}
usb_queue_flush_endpoint(endpoint);
usb_endpoint_clear_pending_interrupts(endpoint);
usb_endpoint_flush(endpoint);
}
void usb_endpoint_prime(
const usb_endpoint_t* const endpoint,
usb_transfer_descriptor_t* const first_td
) {
usb_queue_head_t* const qh = usb_queue_head(endpoint->address);
qh->next_dtd_pointer = first_td;
qh->total_bytes
&= ~( USB_TD_DTD_TOKEN_STATUS_ACTIVE
| USB_TD_DTD_TOKEN_STATUS_HALTED
)
;
const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
if( usb_endpoint_is_in(endpoint->address) ) {
USB0_ENDPTPRIME = USB0_ENDPTPRIME_PETB(1 << endpoint_number);
} else {
USB0_ENDPTPRIME = USB0_ENDPTPRIME_PERB(1 << endpoint_number);
}
}
static bool usb_endpoint_is_priming(
const usb_endpoint_t* const endpoint
) {
const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
if( usb_endpoint_is_in(endpoint->address) ) {
return USB0_ENDPTPRIME & USB0_ENDPTPRIME_PETB(1 << endpoint_number);
} else {
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 {
usb_flush_primed_endpoints(USB0_ENDPTFLUSH_FERB(1 << endpoint_number));
}
}
/*
static bool usb_endpoint_is_flushing(
const usb_endpoint_t* const endpoint
) {
const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
if( usb_endpoint_is_in(endpoint->address) ) {
return USB0_ENDPTFLUSH & USB0_ENDPTFLUSH_FETB(1 << endpoint_number);
} else {
return USB0_ENDPTFLUSH & USB0_ENDPTFLUSH_FERB(1 << endpoint_number);
}
}
*/
bool usb_endpoint_is_ready(
const usb_endpoint_t* const endpoint
) {
const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
if( usb_endpoint_is_in(endpoint->address) ) {
return USB0_ENDPTSTAT & USB0_ENDPTSTAT_ETBR(1 << endpoint_number);
} else {
return USB0_ENDPTSTAT & USB0_ENDPTSTAT_ERBR(1 << endpoint_number);
}
}
bool usb_endpoint_is_complete(
const usb_endpoint_t* const endpoint
) {
const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
if( usb_endpoint_is_in(endpoint->address) ) {
return USB0_ENDPTCOMPLETE & USB0_ENDPTCOMPLETE_ETCE(1 << endpoint_number);
} else {
return USB0_ENDPTCOMPLETE & USB0_ENDPTCOMPLETE_ERCE(1 << endpoint_number);
}
}
void usb_endpoint_stall(
const usb_endpoint_t* const endpoint
) {
// Endpoint is to be stalled as a pair -- both OUT and IN.
// See UM10503 section 23.10.5.2 "Stalling"
const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
USB0_ENDPTCTRL(endpoint_number) |= (USB0_ENDPTCTRL_RXS | USB0_ENDPTCTRL_TXS);
// TODO: Also need to reset data toggle in both directions?
}
static void usb_controller_run() {
USB0_USBCMD_D |= USB0_USBCMD_D_RS;
}
static void usb_controller_stop() {
USB0_USBCMD_D &= ~USB0_USBCMD_D_RS;
}
static uint_fast8_t usb_controller_is_resetting() {
return (USB0_USBCMD_D & USB0_USBCMD_D_RST) != 0;
}
static void usb_controller_set_device_mode() {
// Set USB0 peripheral mode
USB0_USBMODE_D = USB0_USBMODE_D_CM1_0(2);
// Set device-related OTG flags
// OTG termination: controls pull-down on USB_DM
// VBUS_Discharge: VBUS discharges through resistor
USB0_OTGSC = USB0_OTGSC_OT | USB0_OTGSC_VD;
}
usb_speed_t usb_speed(
const usb_device_t* const device
) {
if( device == usb_device_usb0 ) {
switch( USB0_PORTSC1_D & USB0_PORTSC1_D_PSPD_MASK ) {
case USB0_PORTSC1_D_PSPD(0):
return USB_SPEED_FULL;
case USB0_PORTSC1_D_PSPD(2):
return USB_SPEED_HIGH;
default:
// TODO: What to do/return here? Is this even possible?
return USB_SPEED_FULL;
}
} else {
// TODO: This should not be possible with a more class-like
// implementation.
return USB_SPEED_FULL;
}
}
static void usb_clear_status(const uint32_t status) {
USB0_USBSTS_D = status;
}
static uint32_t usb_get_status() {
// Mask status flags with enabled flag interrupts.
const uint32_t status = USB0_USBSTS_D & USB0_USBINTR_D;
// Clear flags that were just read, leaving alone any flags that
// were just set (after the read). It's important to read and
// reset flags atomically! :-)
usb_clear_status(status);
return status;
}
static void usb_clear_endpoint_setup_status(const uint32_t endpoint_setup_status) {
USB0_ENDPTSETUPSTAT = endpoint_setup_status;
}
static uint32_t usb_get_endpoint_setup_status() {
return USB0_ENDPTSETUPSTAT;
}
static void usb_clear_endpoint_complete(const uint32_t endpoint_complete) {
USB0_ENDPTCOMPLETE = endpoint_complete;
}
static uint32_t usb_get_endpoint_complete() {
return USB0_ENDPTCOMPLETE;
}
static void usb_disable_all_endpoints() {
// Endpoint 0 is always enabled. TODO: So why set ENDPTCTRL0?
USB0_ENDPTCTRL0 &= ~(USB0_ENDPTCTRL0_RXE | USB0_ENDPTCTRL0_TXE);
USB0_ENDPTCTRL1 &= ~(USB0_ENDPTCTRL1_RXE | USB0_ENDPTCTRL1_TXE);
USB0_ENDPTCTRL2 &= ~(USB0_ENDPTCTRL2_RXE | USB0_ENDPTCTRL2_TXE);
USB0_ENDPTCTRL3 &= ~(USB0_ENDPTCTRL3_RXE | USB0_ENDPTCTRL3_TXE);
USB0_ENDPTCTRL4 &= ~(USB0_ENDPTCTRL4_RXE | USB0_ENDPTCTRL4_TXE);
USB0_ENDPTCTRL5 &= ~(USB0_ENDPTCTRL5_RXE | USB0_ENDPTCTRL5_TXE);
}
void usb_set_address_immediate(
const usb_device_t* const device,
const uint_fast8_t address
) {
if( device == usb_device_usb0 ) {
USB0_DEVICEADDR = USB0_DEVICEADDR_USBADR(address);
}
}
void usb_set_address_deferred(
const usb_device_t* const device,
const uint_fast8_t address
) {
if( device == usb_device_usb0 ) {
USB0_DEVICEADDR
= USB0_DEVICEADDR_USBADR(address)
| USB0_DEVICEADDR_USBADRA
;
}
}
static void usb_reset_all_endpoints() {
usb_disable_all_endpoints();
usb_clear_all_pending_interrupts();
usb_flush_all_primed_endpoints();
}
static void usb_controller_reset() {
// TODO: Good to disable some USB interrupts to avoid priming new
// new endpoints before the controller is reset?
usb_reset_all_endpoints();
usb_controller_stop();
// Reset controller. Resets internal pipelines, timers, counters, state
// machines to initial values. Not recommended when device is in attached
// state -- effect on attached host is undefined. Detach first by flushing
// all primed endpoints and stopping controller.
USB0_USBCMD_D = USB0_USBCMD_D_RST;
while( usb_controller_is_resetting() );
}
static void usb_bus_reset(usb_device_t* const device) {
// According to UM10503 v1.4 section 23.10.3 "Bus reset":
usb_reset_all_endpoints();
usb_set_address_immediate(device, 0);
usb_set_configuration(device, 0);
// TODO: Enable endpoint 0, which might not actually be necessary,
// as the datasheet claims it can't be disabled.
//wait_ms(3);
//
//if( USB0_PORTSC1 & USB0_PORTSC1_PR ) {
// // Port still is in the reset state.
//} else {
// usb_hardware_reset();
//}
}
static void usb_interrupt_enable(
usb_device_t* const device
) {
if( device == usb_device_usb0 ) {
nvic_enable_irq(NVIC_USB0_IRQ);
}
}
void usb_device_init(
const uint_fast8_t device_ordinal,
usb_device_t* const device
) {
if( device_ordinal == 0 ) {
usb_device_usb0 = device;
usb_phy_enable();
usb_controller_reset();
usb_controller_set_device_mode();
// Set interrupt threshold interval to 0
USB0_USBCMD_D &= ~USB0_USBCMD_D_ITC_MASK;
// Configure endpoint list address
USB0_ENDPOINTLISTADDR = (uint32_t)usb_qh;
// Enable interrupts
USB0_USBINTR_D =
USB0_USBINTR_D_UE
| USB0_USBINTR_D_UEE
| USB0_USBINTR_D_PCE
| USB0_USBINTR_D_URE
//| USB0_USBINTR_D_SRE
| USB0_USBINTR_D_SLE
//| USB0_USBINTR_D_NAKE
;
}
}
void usb_run(
usb_device_t* const device
) {
usb_interrupt_enable(device);
usb_controller_run(device);
}
static void copy_setup(usb_setup_t* const dst, const volatile uint8_t* const src) {
dst->request_type = src[0];
dst->request = src[1];
dst->value_l = src[2];
dst->value_h = src[3];
dst->index_l = src[4];
dst->index_h = src[5];
dst->length_l = src[6];
dst->length_h = src[7];
}
void usb_endpoint_init(
const usb_endpoint_t* const endpoint
) {
usb_endpoint_flush(endpoint);
uint_fast16_t max_packet_size = endpoint->device->descriptor[7];
usb_transfer_type_t transfer_type = USB_TRANSFER_TYPE_CONTROL;
const uint8_t* const endpoint_descriptor = usb_endpoint_descriptor(endpoint);
if( endpoint_descriptor ) {
max_packet_size = usb_endpoint_descriptor_max_packet_size(endpoint_descriptor);
transfer_type = usb_endpoint_descriptor_transfer_type(endpoint_descriptor);
}
// TODO: There are more capabilities to adjust based on the endpoint
// descriptor.
usb_queue_head_t* const qh = usb_queue_head(endpoint->address);
qh->capabilities
= USB_QH_CAPABILITIES_MULT(0)
| USB_QH_CAPABILITIES_ZLT
| USB_QH_CAPABILITIES_MPL(max_packet_size)
| ((transfer_type == USB_TRANSFER_TYPE_CONTROL) ? USB_QH_CAPABILITIES_IOS : 0)
;
qh->current_dtd_pointer = 0;
qh->next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE;
qh->total_bytes
= USB_TD_DTD_TOKEN_TOTAL_BYTES(0)
| USB_TD_DTD_TOKEN_MULTO(0)
;
qh->buffer_pointer_page[0] = 0;
qh->buffer_pointer_page[1] = 0;
qh->buffer_pointer_page[2] = 0;
qh->buffer_pointer_page[3] = 0;
qh->buffer_pointer_page[4] = 0;
// This is how we look up an endpoint structure from an endpoint address:
qh->_reserved_0 = (uint32_t)endpoint;
// TODO: Should NAK be enabled? I'm kinda squishy on this...
//USB0_ENDPTNAKEN |=
// USB0_ENDPTNAKEN_EPRNE(1 << endpoint_out->number);
usb_endpoint_set_type(endpoint, transfer_type);
usb_endpoint_enable(endpoint);
}
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_from_address(
usb_endpoint_address(USB_TRANSFER_DIRECTION_OUT, i)
);
if( endpoint && endpoint->setup_complete ) {
copy_setup(&endpoint->setup, usb_queue_head(endpoint->address)->setup);
// TODO: Clean up this duplicated effort by providing
// a cleaner way to get the SETUP data.
copy_setup(&endpoint->in->setup, usb_queue_head(endpoint->address)->setup);
usb_clear_endpoint_setup_status(endptsetupstat_bit);
endpoint->setup_complete(endpoint);
} else {
usb_clear_endpoint_setup_status(endptsetupstat_bit);
}
}
}
}
}
static void usb_check_for_transfer_events() {
const uint32_t endptcomplete = usb_get_endpoint_complete();
if( endptcomplete ) {
for( uint_fast8_t i=0; i<6; i++ ) {
const uint32_t endptcomplete_out_bit = USB0_ENDPTCOMPLETE_ERCE(1 << i);
if( endptcomplete & endptcomplete_out_bit ) {
usb_clear_endpoint_complete(endptcomplete_out_bit);
usb_endpoint_t* const endpoint =
usb_endpoint_from_address(
usb_endpoint_address(USB_TRANSFER_DIRECTION_OUT, i)
);
if( endpoint && endpoint->transfer_complete ) {
endpoint->transfer_complete(endpoint);
}
}
const uint32_t endptcomplete_in_bit = USB0_ENDPTCOMPLETE_ETCE(1 << i);
if( endptcomplete & endptcomplete_in_bit ) {
usb_clear_endpoint_complete(endptcomplete_in_bit);
usb_endpoint_t* const endpoint =
usb_endpoint_from_address(
usb_endpoint_address(USB_TRANSFER_DIRECTION_IN, i)
);
if( endpoint && endpoint->transfer_complete ) {
endpoint->transfer_complete(endpoint);
}
}
}
}
}
void usb0_isr() {
const uint32_t status = usb_get_status();
if( status == 0 ) {
// Nothing to do.
return;
}
if( status & USB0_USBSTS_D_UI ) {
// USB:
// - Completed transaction transfer descriptor has IOC set.
// - Short packet detected.
// - SETUP packet received.
usb_check_for_setup_events();
usb_check_for_transfer_events();
// TODO: Reset ignored ENDPTSETUPSTAT and ENDPTCOMPLETE flags?
}
if( status & USB0_USBSTS_D_SRI ) {
// Start Of Frame received.
}
if( status & USB0_USBSTS_D_PCI ) {
// Port change detect:
// Port controller entered full- or high-speed operational state.
}
if( status & USB0_USBSTS_D_SLI ) {
// Device controller suspend.
}
if( status & USB0_USBSTS_D_URI ) {
// USB reset received.
usb_bus_reset(usb_device_usb0);
}
if( status & USB0_USBSTS_D_UEI ) {
// USB error:
// Completion of a USB transaction resulted in an error condition.
// Set along with USBINT if the TD on which the error interrupt
// occurred also had its interrupt on complete (IOC) bit set.
// The device controller detects resume signalling only.
}
if( status & USB0_USBSTS_D_NAKI ) {
// Both the TX/RX endpoint NAK bit and corresponding TX/RX endpoint
// NAK enable bit are set.
}
}

View File

@ -0,0 +1,96 @@
/*
* 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.
*/
#ifndef __USB_H__
#define __USB_H__
// TODO: Refactor to support high performance operations without having to
// expose usb_transfer_descriptor_t. Or usb_endpoint_prime(). Or, or, or...
#include <libopencm3/lpc43xx/usb.h>
#include "usb_type.h"
void usb_peripheral_reset();
void usb_device_init(
const uint_fast8_t device_ordinal,
usb_device_t* const device
);
void usb_run(
usb_device_t* const device
);
void usb_run_tasks(
const usb_device_t* const device
);
usb_speed_t usb_speed(
const usb_device_t* const device
);
void usb_set_address_immediate(
const usb_device_t* const device,
const uint_fast8_t address
);
void usb_set_address_deferred(
const usb_device_t* const device,
const uint_fast8_t address
);
void usb_endpoint_init(
const usb_endpoint_t* const endpoint
);
void usb_endpoint_stall(
const usb_endpoint_t* const endpoint
);
void usb_endpoint_disable(
const usb_endpoint_t* const endpoint
);
void usb_endpoint_flush(
const usb_endpoint_t* const endpoint
);
bool usb_endpoint_is_ready(
const usb_endpoint_t* const endpoint
);
void usb_endpoint_prime(
const usb_endpoint_t* const endpoint,
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__

View 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;
}
}

View 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__

View File

@ -0,0 +1,94 @@
/*
* 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.
*/
#include "usb.h"
#include "usb_request.h"
#include "usb_queue.h"
#include <stdbool.h>
static void usb_request(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage
) {
usb_request_status_t status = USB_REQUEST_STATUS_STALL;
usb_request_handler_fn handler = 0;
switch( endpoint->setup.request_type & USB_SETUP_REQUEST_TYPE_mask ) {
case USB_SETUP_REQUEST_TYPE_STANDARD:
handler = usb_request_handlers.standard;
break;
case USB_SETUP_REQUEST_TYPE_CLASS:
handler = usb_request_handlers.class;
break;
case USB_SETUP_REQUEST_TYPE_VENDOR:
handler = usb_request_handlers.vendor;
break;
case USB_SETUP_REQUEST_TYPE_RESERVED:
handler = usb_request_handlers.reserved;
break;
}
if( handler ) {
status = handler(endpoint, stage);
}
if( status != USB_REQUEST_STATUS_OK ) {
// USB 2.0 section 9.2.7 "Request Error"
usb_endpoint_stall(endpoint);
}
}
void usb_setup_complete(
usb_endpoint_t* const endpoint
) {
usb_request(endpoint, USB_TRANSFER_STAGE_SETUP);
}
void usb_control_out_complete(
usb_endpoint_t* const endpoint
) {
const bool device_to_host =
endpoint->setup.request_type >> USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_shift;
if( device_to_host ) {
usb_request(endpoint, USB_TRANSFER_STAGE_STATUS);
} else {
usb_request(endpoint, USB_TRANSFER_STAGE_DATA);
}
usb_queue_transfer_complete(endpoint);
}
void usb_control_in_complete(
usb_endpoint_t* const endpoint
) {
const bool device_to_host =
endpoint->setup.request_type >> USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_shift;
if( device_to_host ) {
usb_request(endpoint, USB_TRANSFER_STAGE_DATA);
} else {
usb_request(endpoint, USB_TRANSFER_STAGE_STATUS);
}
usb_queue_transfer_complete(endpoint);
}

View File

@ -0,0 +1,71 @@
/*
* 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.
*/
#ifndef __USB_REQUEST_H__
#define __USB_REQUEST_H__
#include "usb_type.h"
typedef enum {
USB_RESPONSE_NONE,
USB_RESPONSE_IN,
USB_RESPONSE_OUT,
USB_RESPONSE_STALL,
} usb_endpoint_type_t;
typedef enum {
USB_TRANSFER_STAGE_SETUP,
USB_TRANSFER_STAGE_DATA,
USB_TRANSFER_STAGE_STATUS,
} usb_transfer_stage_t;
typedef enum {
USB_REQUEST_STATUS_OK = 0,
USB_REQUEST_STATUS_STALL = 1,
} usb_request_status_t;
typedef usb_request_status_t (*usb_request_handler_fn)(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage
);
typedef struct {
usb_request_handler_fn standard;
usb_request_handler_fn class;
usb_request_handler_fn vendor;
usb_request_handler_fn reserved;
} usb_request_handlers_t;
extern const usb_request_handlers_t usb_request_handlers;
void usb_setup_complete(
usb_endpoint_t* const endpoint
);
void usb_control_in_complete(
usb_endpoint_t* const endpoint
);
void usb_control_out_complete(
usb_endpoint_t* const endpoint
);
#endif//__USB_REQUEST_H__

View File

@ -0,0 +1,338 @@
/*
* 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.
*/
#include <stdint.h>
#include <stddef.h>
#include "usb_standard_request.h"
#include "usb.h"
#include "usb_type.h"
#include "usb_queue.h"
const uint8_t* usb_endpoint_descriptor(
const usb_endpoint_t* const endpoint
) {
const usb_configuration_t* const configuration = endpoint->device->configuration;
if( configuration ) {
const uint8_t* descriptor = configuration->descriptor;
while( descriptor[0] != 0 ) {
if( descriptor[1] == USB_DESCRIPTOR_TYPE_ENDPOINT ) {
if( descriptor[2] == endpoint->address ) {
return descriptor;
}
}
descriptor += descriptor[0];
}
}
return 0;
}
uint_fast16_t usb_endpoint_descriptor_max_packet_size(
const uint8_t* const endpoint_descriptor
) {
return (endpoint_descriptor[5] << 8) | endpoint_descriptor[4];
}
usb_transfer_type_t usb_endpoint_descriptor_transfer_type(
const uint8_t* const endpoint_descriptor
) {
return (endpoint_descriptor[3] & 0x3);
}
void (*usb_configuration_changed_cb)(usb_device_t* const) = NULL;
void usb_set_configuration_changed_cb(
void (*callback)(usb_device_t* const)
) {
usb_configuration_changed_cb = callback;
}
bool usb_set_configuration(
usb_device_t* const device,
const uint_fast8_t configuration_number
) {
const usb_configuration_t* new_configuration = 0;
if( configuration_number != 0 ) {
// Locate requested configuration.
if( device->configurations ) {
usb_configuration_t** configurations = *(device->configurations);
uint32_t i = 0;
const usb_speed_t usb_speed_current = usb_speed(device);
while( configurations[i] ) {
if( (configurations[i]->speed == usb_speed_current) &&
(configurations[i]->number == configuration_number) ) {
new_configuration = configurations[i];
break;
}
i++;
}
}
// Requested configuration not found: request error.
if( new_configuration == 0 ) {
return false;
}
}
if( new_configuration != device->configuration ) {
// Configuration changed.
device->configuration = new_configuration;
}
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,
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];
}
// We cast the const away but this shouldn't be a problem as this is a write transfer
usb_transfer_schedule_block(
endpoint->in,
(uint8_t* const) descriptor_data,
(setup_length > descriptor_length) ? descriptor_length : setup_length,
NULL, NULL
);
usb_transfer_schedule_ack(endpoint->out);
return USB_REQUEST_STATUS_OK;
}
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; endpoint->device->descriptor_strings[i] != 0; i++ ) {
if( i == index ) {
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, endpoint->device->descriptor);
case USB_DESCRIPTOR_TYPE_CONFIGURATION:
// TODO: Duplicated code. Refactor.
if( usb_speed(endpoint->device) == USB_SPEED_HIGH ) {
return usb_send_descriptor_config(endpoint, USB_SPEED_HIGH, endpoint->setup.value_l);
} else {
return usb_send_descriptor_config(endpoint, USB_SPEED_FULL, endpoint->setup.value_l);
}
case USB_DESCRIPTOR_TYPE_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_config(endpoint, USB_SPEED_FULL, endpoint->setup.value_l);
} else {
return usb_send_descriptor_config(endpoint, USB_SPEED_HIGH, endpoint->setup.value_l);
}
case USB_DESCRIPTOR_TYPE_STRING:
return usb_send_descriptor_string(endpoint);
case USB_DESCRIPTOR_TYPE_INTERFACE:
case USB_DESCRIPTOR_TYPE_ENDPOINT:
default:
return USB_REQUEST_STATUS_STALL;
}
}
static usb_request_status_t usb_standard_request_get_descriptor(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage
) {
switch( stage ) {
case USB_TRANSFER_STAGE_SETUP:
return usb_standard_request_get_descriptor_setup(endpoint);
case USB_TRANSFER_STAGE_DATA:
case USB_TRANSFER_STAGE_STATUS:
return USB_REQUEST_STATUS_OK;
default:
return USB_REQUEST_STATUS_STALL;
}
}
/*********************************************************************/
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_transfer_schedule_ack(endpoint->in);
return USB_REQUEST_STATUS_OK;
}
static usb_request_status_t usb_standard_request_set_address(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage
) {
switch( stage ) {
case USB_TRANSFER_STAGE_SETUP:
return usb_standard_request_set_address_setup(endpoint);
case USB_TRANSFER_STAGE_DATA:
case USB_TRANSFER_STAGE_STATUS:
/* NOTE: Not necessary to set address here, as DEVICEADR.USBADRA bit
* will cause controller to automatically perform set address
* operation on IN ACK.
*/
return USB_REQUEST_STATUS_OK;
default:
return USB_REQUEST_STATUS_STALL;
}
}
/*********************************************************************/
static usb_request_status_t usb_standard_request_set_configuration_setup(
usb_endpoint_t* const endpoint
) {
const uint8_t usb_configuration = endpoint->setup.value_l;
if( usb_set_configuration(endpoint->device, usb_configuration) ) {
if( usb_configuration == 0 ) {
// TODO: Should this be done immediately?
usb_set_address_immediate(endpoint->device, 0);
}
usb_transfer_schedule_ack(endpoint->in);
return USB_REQUEST_STATUS_OK;
} else {
return USB_REQUEST_STATUS_STALL;
}
}
static usb_request_status_t usb_standard_request_set_configuration(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage
) {
switch( stage ) {
case USB_TRANSFER_STAGE_SETUP:
return usb_standard_request_set_configuration_setup(endpoint);
case USB_TRANSFER_STAGE_DATA:
case USB_TRANSFER_STAGE_STATUS:
return USB_REQUEST_STATUS_OK;
default:
return USB_REQUEST_STATUS_STALL;
}
}
/*********************************************************************/
static usb_request_status_t usb_standard_request_get_configuration_setup(
usb_endpoint_t* const endpoint
) {
if( endpoint->setup.length == 1 ) {
endpoint->buffer[0] = 0;
if( endpoint->device->configuration ) {
endpoint->buffer[0] = endpoint->device->configuration->number;
}
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;
}
}
static usb_request_status_t usb_standard_request_get_configuration(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage
) {
switch( stage ) {
case USB_TRANSFER_STAGE_SETUP:
return usb_standard_request_get_configuration_setup(endpoint);
case USB_TRANSFER_STAGE_DATA:
case USB_TRANSFER_STAGE_STATUS:
return USB_REQUEST_STATUS_OK;
default:
return USB_REQUEST_STATUS_STALL;
}
}
/*********************************************************************/
usb_request_status_t usb_standard_request(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage
) {
switch( endpoint->setup.request ) {
case USB_STANDARD_REQUEST_GET_DESCRIPTOR:
return usb_standard_request_get_descriptor(endpoint, stage);
case USB_STANDARD_REQUEST_SET_ADDRESS:
return usb_standard_request_set_address(endpoint, stage);
case USB_STANDARD_REQUEST_SET_CONFIGURATION:
return usb_standard_request_set_configuration(endpoint, stage);
case USB_STANDARD_REQUEST_GET_CONFIGURATION:
return usb_standard_request_get_configuration(endpoint, stage);
default:
return USB_REQUEST_STATUS_STALL;
}
}

View File

@ -0,0 +1,54 @@
/*
* 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.
*/
#ifndef __USB_STANDARD_REQUEST_H__
#define __USB_STANDARD_REQUEST_H__
#include "usb_type.h"
#include "usb_request.h"
void usb_set_configuration_changed_cb(
void (*callback)(usb_device_t* const)
);
usb_request_status_t usb_standard_request(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage
);
const uint8_t* usb_endpoint_descriptor(
const usb_endpoint_t* const endpoint
);
uint_fast16_t usb_endpoint_descriptor_max_packet_size(
const uint8_t* const endpoint_descriptor
);
usb_transfer_type_t usb_endpoint_descriptor_transfer_type(
const uint8_t* const endpoint_descriptor
);
bool usb_set_configuration(
usb_device_t* const device,
const uint_fast8_t configuration_number
);
#endif//__USB_STANDARD_REQUEST_H__

View File

@ -0,0 +1,144 @@
/*
* 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.
*/
#ifndef __USB_TYPE_H__
#define __USB_TYPE_H__
#include <stdint.h>
#include <stdbool.h>
// TODO: Move this to some common compiler-tricks location.
#define ATTR_PACKED __attribute__((packed))
#define ATTR_ALIGNED(x) __attribute__ ((aligned(x)))
#define ATTR_SECTION(x) __attribute__ ((section(x)))
typedef struct ATTR_PACKED {
uint8_t request_type;
uint8_t request;
union {
struct {
uint8_t value_l;
uint8_t value_h;
};
uint16_t value;
};
union {
struct {
uint8_t index_l;
uint8_t index_h;
};
uint16_t index;
};
union {
struct {
uint8_t length_l;
uint8_t length_h;
};
uint16_t length;
};
} usb_setup_t;
typedef enum {
USB_STANDARD_REQUEST_GET_STATUS = 0,
USB_STANDARD_REQUEST_CLEAR_FEATURE = 1,
USB_STANDARD_REQUEST_SET_FEATURE = 3,
USB_STANDARD_REQUEST_SET_ADDRESS = 5,
USB_STANDARD_REQUEST_GET_DESCRIPTOR = 6,
USB_STANDARD_REQUEST_SET_DESCRIPTOR = 7,
USB_STANDARD_REQUEST_GET_CONFIGURATION = 8,
USB_STANDARD_REQUEST_SET_CONFIGURATION = 9,
USB_STANDARD_REQUEST_GET_INTERFACE = 10,
USB_STANDARD_REQUEST_SET_INTERFACE = 11,
USB_STANDARD_REQUEST_SYNCH_FRAME = 12,
} usb_standard_request_t;
typedef enum {
USB_SETUP_REQUEST_TYPE_shift = 5,
USB_SETUP_REQUEST_TYPE_mask = 3 << USB_SETUP_REQUEST_TYPE_shift,
USB_SETUP_REQUEST_TYPE_STANDARD = 0 << USB_SETUP_REQUEST_TYPE_shift,
USB_SETUP_REQUEST_TYPE_CLASS = 1 << USB_SETUP_REQUEST_TYPE_shift,
USB_SETUP_REQUEST_TYPE_VENDOR = 2 << USB_SETUP_REQUEST_TYPE_shift,
USB_SETUP_REQUEST_TYPE_RESERVED = 3 << USB_SETUP_REQUEST_TYPE_shift,
USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_shift = 7,
USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_mask = 1 << USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_shift,
USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_HOST_TO_DEVICE = 0 << USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_shift,
USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_DEVICE_TO_HOST = 1 << USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_shift,
} usb_setup_request_type_t;
typedef enum {
USB_TRANSFER_DIRECTION_OUT = 0,
USB_TRANSFER_DIRECTION_IN = 1,
} usb_transfer_direction_t;
typedef enum {
USB_DESCRIPTOR_TYPE_DEVICE = 1,
USB_DESCRIPTOR_TYPE_CONFIGURATION = 2,
USB_DESCRIPTOR_TYPE_STRING = 3,
USB_DESCRIPTOR_TYPE_INTERFACE = 4,
USB_DESCRIPTOR_TYPE_ENDPOINT = 5,
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER = 6,
USB_DESCRIPTOR_TYPE_OTHER_SPEED_CONFIGURATION = 7,
USB_DESCRIPTOR_TYPE_INTERFACE_POWER = 8,
} usb_descriptor_type_t;
typedef enum {
USB_TRANSFER_TYPE_CONTROL = 0,
USB_TRANSFER_TYPE_ISOCHRONOUS = 1,
USB_TRANSFER_TYPE_BULK = 2,
USB_TRANSFER_TYPE_INTERRUPT = 3,
} usb_transfer_type_t;
typedef enum {
USB_SPEED_LOW = 0,
USB_SPEED_FULL = 1,
USB_SPEED_HIGH = 2,
USB_SPEED_SUPER = 3,
} usb_speed_t;
typedef struct {
const uint8_t* const descriptor;
const uint32_t number;
const usb_speed_t speed;
} usb_configuration_t;
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;
typedef struct usb_endpoint_t usb_endpoint_t;
struct usb_endpoint_t {
usb_setup_t setup;
uint8_t buffer[8]; // Buffer for use during IN stage.
const uint_fast8_t address;
usb_device_t* const device;
usb_endpoint_t* const in;
usb_endpoint_t* const out;
void (*setup_complete)(usb_endpoint_t* const endpoint);
void (*transfer_complete)(usb_endpoint_t* const endpoint);
};
#endif//__USB_TYPE_H__

View File

@ -0,0 +1,245 @@
/*
* Copyright 2013 Michael Ossmann
* 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.
*/
/*
* This is a rudimentary driver for the W25Q80BV SPI Flash IC using the
* LPC43xx's SSP0 peripheral (not quad SPIFI). The only goal here is to allow
* programming the flash.
*/
#include <stdint.h>
#include "w25q80bv.h"
#include "hackrf_core.h"
#include <libopencm3/lpc43xx/ssp.h>
#include <libopencm3/lpc43xx/scu.h>
#include <libopencm3/lpc43xx/gpio.h>
#include <libopencm3/lpc43xx/rgu.h>
/*
* Set up pins for GPIO and SPI control, configure SSP0 peripheral for SPI.
* SSP0_SSEL is controlled by GPIO in order to handle various transfer lengths.
*/
void w25q80bv_setup(void)
{
uint8_t device_id;
const uint8_t serial_clock_rate = 2;
const uint8_t clock_prescale_rate = 2;
/* Reset SPIFI peripheral before to Erase/Write SPIFI memory through SPI */
RESET_CTRL1 = RESET_CTRL1_SPIFI_RST;
/* Init SPIFI GPIO to Normal GPIO */
scu_pinmux(P3_3, (SCU_SSP_IO | SCU_CONF_FUNCTION2)); // P3_3 SPIFI_SCK => SSP0_SCK
scu_pinmux(P3_4, (SCU_GPIO_FAST | SCU_CONF_FUNCTION0)); // P3_4 SPIFI SPIFI_SIO3 IO3 => GPIO1[14]
scu_pinmux(P3_5, (SCU_GPIO_FAST | SCU_CONF_FUNCTION0)); // P3_5 SPIFI SPIFI_SIO2 IO2 => GPIO1[15]
scu_pinmux(P3_6, (SCU_GPIO_FAST | SCU_CONF_FUNCTION0)); // P3_6 SPIFI SPIFI_MISO IO1 => GPIO0[6]
scu_pinmux(P3_7, (SCU_GPIO_FAST | SCU_CONF_FUNCTION4)); // P3_7 SPIFI SPIFI_MOSI IO0 => GPIO5[10]
scu_pinmux(P3_8, (SCU_GPIO_FAST | SCU_CONF_FUNCTION4)); // P3_8 SPIFI SPIFI_CS => GPIO5[11]
/* configure SSP pins */
scu_pinmux(SCU_SSP0_MISO, (SCU_SSP_IO | SCU_CONF_FUNCTION5));
scu_pinmux(SCU_SSP0_MOSI, (SCU_SSP_IO | SCU_CONF_FUNCTION5));
scu_pinmux(SCU_SSP0_SCK, (SCU_SSP_IO | SCU_CONF_FUNCTION2));
/* configure GPIO pins */
scu_pinmux(SCU_FLASH_HOLD, SCU_GPIO_FAST);
scu_pinmux(SCU_FLASH_WP, SCU_GPIO_FAST);
scu_pinmux(SCU_SSP0_SSEL, (SCU_GPIO_FAST | SCU_CONF_FUNCTION4));
/* drive SSEL, HOLD, and WP pins high */
gpio_set(PORT_FLASH, (PIN_FLASH_HOLD | PIN_FLASH_WP));
gpio_set(PORT_SSP0_SSEL, PIN_SSP0_SSEL);
/* Set GPIO pins as outputs. */
GPIO1_DIR |= (PIN_FLASH_HOLD | PIN_FLASH_WP);
GPIO5_DIR |= PIN_SSP0_SSEL;
/* initialize SSP0 */
ssp_init(SSP0_NUM,
SSP_DATA_8BITS,
SSP_FRAME_SPI,
SSP_CPOL_0_CPHA_0,
serial_clock_rate,
clock_prescale_rate,
SSP_MODE_NORMAL,
SSP_MASTER,
SSP_SLAVE_OUT_ENABLE);
device_id = 0;
while(device_id != W25Q80BV_DEVICE_ID_RES)
{
device_id = w25q80bv_get_device_id();
}
}
uint8_t w25q80bv_get_status(void)
{
uint8_t value;
gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL);
ssp_transfer(SSP0_NUM, W25Q80BV_READ_STATUS1);
value = ssp_transfer(SSP0_NUM, 0xFF);
gpio_set(PORT_SSP0_SSEL, PIN_SSP0_SSEL);
return value;
}
/* Release power down / Device ID */
uint8_t w25q80bv_get_device_id(void)
{
uint8_t value;
gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL);
ssp_transfer(SSP0_NUM, W25Q80BV_DEVICE_ID);
/* Read 3 dummy bytes */
value = ssp_transfer(SSP0_NUM, 0xFF);
value = ssp_transfer(SSP0_NUM, 0xFF);
value = ssp_transfer(SSP0_NUM, 0xFF);
/* Read Device ID shall return 0x13 for W25Q80BV */
value = ssp_transfer(SSP0_NUM, 0xFF);
gpio_set(PORT_SSP0_SSEL, PIN_SSP0_SSEL);
return value;
}
void w25q80bv_get_unique_id(w25q80bv_unique_id_t* unique_id)
{
int i;
uint8_t value;
gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL);
ssp_transfer(SSP0_NUM, W25Q80BV_UNIQUE_ID);
/* Read 4 dummy bytes */
for(i=0; i<4; i++)
value = ssp_transfer(SSP0_NUM, 0xFF);
/* Read Unique ID 64bits (8*8) */
for(i=0; i<8; i++)
{
value = ssp_transfer(SSP0_NUM, 0xFF);
unique_id->id_8b[i] = value;
}
gpio_set(PORT_SSP0_SSEL, PIN_SSP0_SSEL);
}
void w25q80bv_wait_while_busy(void)
{
while (w25q80bv_get_status() & W25Q80BV_STATUS_BUSY);
}
void w25q80bv_write_enable(void)
{
w25q80bv_wait_while_busy();
gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL);
ssp_transfer(SSP0_NUM, W25Q80BV_WRITE_ENABLE);
gpio_set(PORT_SSP0_SSEL, PIN_SSP0_SSEL);
}
void w25q80bv_chip_erase(void)
{
uint8_t device_id;
device_id = 0;
while(device_id != W25Q80BV_DEVICE_ID_RES)
{
device_id = w25q80bv_get_device_id();
}
w25q80bv_write_enable();
w25q80bv_wait_while_busy();
gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL);
ssp_transfer(SSP0_NUM, W25Q80BV_CHIP_ERASE);
gpio_set(PORT_SSP0_SSEL, PIN_SSP0_SSEL);
}
/* write up a 256 byte page or partial page */
void w25q80bv_page_program(const uint32_t addr, const uint16_t len, const uint8_t* data)
{
int i;
/* do nothing if asked to write beyond a page boundary */
if (((addr & 0xFF) + len) > W25Q80BV_PAGE_LEN)
return;
/* do nothing if we would overflow the flash */
if (addr > (W25Q80BV_NUM_BYTES - len))
return;
w25q80bv_write_enable();
w25q80bv_wait_while_busy();
gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL);
ssp_transfer(SSP0_NUM, W25Q80BV_PAGE_PROGRAM);
ssp_transfer(SSP0_NUM, (addr & 0xFF0000) >> 16);
ssp_transfer(SSP0_NUM, (addr & 0xFF00) >> 8);
ssp_transfer(SSP0_NUM, addr & 0xFF);
for (i = 0; i < len; i++)
ssp_transfer(SSP0_NUM, data[i]);
gpio_set(PORT_SSP0_SSEL, PIN_SSP0_SSEL);
}
/* write an arbitrary number of bytes */
void w25q80bv_program(uint32_t addr, uint32_t len, const uint8_t* data)
{
uint16_t first_block_len;
uint8_t device_id;
device_id = 0;
while(device_id != W25Q80BV_DEVICE_ID_RES)
{
device_id = w25q80bv_get_device_id();
}
/* do nothing if we would overflow the flash */
if ((len > W25Q80BV_NUM_BYTES) || (addr > W25Q80BV_NUM_BYTES)
|| ((addr + len) > W25Q80BV_NUM_BYTES))
return;
/* handle start not at page boundary */
first_block_len = W25Q80BV_PAGE_LEN - (addr % W25Q80BV_PAGE_LEN);
if (len < first_block_len)
first_block_len = len;
if (first_block_len) {
w25q80bv_page_program(addr, first_block_len, data);
addr += first_block_len;
data += first_block_len;
len -= first_block_len;
}
/* one page at a time on boundaries */
while (len >= W25Q80BV_PAGE_LEN) {
w25q80bv_page_program(addr, W25Q80BV_PAGE_LEN, data);
addr += W25Q80BV_PAGE_LEN;
data += W25Q80BV_PAGE_LEN;
len -= W25Q80BV_PAGE_LEN;
}
/* handle end not at page boundary */
if (len) {
w25q80bv_page_program(addr, len, data);
}
}

View File

@ -0,0 +1,55 @@
/*
* Copyright 2013 Michael Ossmann
* 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 __W25Q80BV_H__
#define __W25Q80BV_H__
#define W25Q80BV_PAGE_LEN 256U
#define W25Q80BV_NUM_PAGES 4096U
#define W25Q80BV_NUM_BYTES 1048576U
#define W25Q80BV_WRITE_ENABLE 0x06
#define W25Q80BV_CHIP_ERASE 0xC7
#define W25Q80BV_READ_STATUS1 0x05
#define W25Q80BV_PAGE_PROGRAM 0x02
#define W25Q80BV_DEVICE_ID 0xAB
#define W25Q80BV_UNIQUE_ID 0x4B
#define W25Q80BV_STATUS_BUSY 0x01
#define W25Q80BV_DEVICE_ID_RES 0x13 /* Expected device_id for W25Q80BV */
typedef union
{
uint64_t id_64b;
uint32_t id_32b[2]; /* 2*32bits 64bits Unique ID */
uint8_t id_8b[8]; /* 8*8bits 64bits Unique ID */
} w25q80bv_unique_id_t;
void w25q80bv_setup(void);
void w25q80bv_chip_erase(void);
void w25q80bv_program(uint32_t addr, uint32_t len, const uint8_t* data);
uint8_t w25q80bv_get_device_id(void);
void w25q80bv_get_unique_id(w25q80bv_unique_id_t* unique_id);
#endif//__W25Q80BV_H__

View File

@ -0,0 +1,12 @@
The code in this directory was originally is taken from:
http://www.xilinx.com/support/documentation/application_notes/xapp058.zip
(v.5.01)
Ian Lesnet wrote: "I contacted Xilinx support and they said the license is do
what you want, no warranty. (BSD I guess...)"
(http://dangerousprototypes.com/forum/viewtopic.php?f=51&t=2239#p21257)
Refer to XAPP058 for more information:
http://www.xilinx.com/support/documentation/application_notes/xapp058.pdf
This software has been modified for HackRF.

View File

@ -0,0 +1,190 @@
/*******************************************************/
/* file: lenval.c */
/* abstract: This file contains routines for using */
/* the lenVal data structure. */
/*******************************************************/
#include "lenval.h"
#include "ports.h"
/*****************************************************************************
* Function: value
* Description: Extract the long value from the lenval array.
* Parameters: plvValue - ptr to lenval.
* Returns: long - the extracted value.
*****************************************************************************/
long value( lenVal* plvValue )
{
long lValue; /* result to hold the accumulated result */
short sIndex;
lValue = 0;
for ( sIndex = 0; sIndex < plvValue->len ; ++sIndex )
{
lValue <<= 8; /* shift the accumulated result */
lValue |= plvValue->val[ sIndex]; /* get the last byte first */
}
return( lValue );
}
/*****************************************************************************
* Function: initLenVal
* Description: Initialize the lenval array with the given value.
* Assumes lValue is less than 256.
* Parameters: plv - ptr to lenval.
* lValue - the value to set.
* Returns: void.
*****************************************************************************/
void initLenVal( lenVal* plv,
long lValue )
{
plv->len = 1;
plv->val[0] = (unsigned char)lValue;
}
/*****************************************************************************
* Function: EqualLenVal
* Description: Compare two lenval arrays with an optional mask.
* Parameters: plvTdoExpected - ptr to lenval #1.
* plvTdoCaptured - ptr to lenval #2.
* plvTdoMask - optional ptr to mask (=0 if no mask).
* Returns: short - 0 = mismatch; 1 = equal.
*****************************************************************************/
short EqualLenVal( lenVal* plvTdoExpected,
lenVal* plvTdoCaptured,
lenVal* plvTdoMask )
{
short sEqual;
short sIndex;
unsigned char ucByteVal1;
unsigned char ucByteVal2;
unsigned char ucByteMask;
sEqual = 1;
sIndex = plvTdoExpected->len;
while ( sEqual && sIndex-- )
{
ucByteVal1 = plvTdoExpected->val[ sIndex ];
ucByteVal2 = plvTdoCaptured->val[ sIndex ];
if ( plvTdoMask )
{
ucByteMask = plvTdoMask->val[ sIndex ];
ucByteVal1 &= ucByteMask;
ucByteVal2 &= ucByteMask;
}
if ( ucByteVal1 != ucByteVal2 )
{
sEqual = 0;
}
}
return( sEqual );
}
/*****************************************************************************
* Function: RetBit
* Description: return the (byte, bit) of lv (reading from left to right).
* Parameters: plv - ptr to lenval.
* iByte - the byte to get the bit from.
* iBit - the bit number (0=msb)
* Returns: short - the bit value.
*****************************************************************************/
short RetBit( lenVal* plv,
int iByte,
int iBit )
{
/* assert( ( iByte >= 0 ) && ( iByte < plv->len ) ); */
/* assert( ( iBit >= 0 ) && ( iBit < 8 ) ); */
return( (short)( ( plv->val[ iByte ] >> ( 7 - iBit ) ) & 0x1 ) );
}
/*****************************************************************************
* Function: SetBit
* Description: set the (byte, bit) of lv equal to val
* Example: SetBit("00000000",byte, 1) equals "01000000".
* Parameters: plv - ptr to lenval.
* iByte - the byte to get the bit from.
* iBit - the bit number (0=msb).
* sVal - the bit value to set.
* Returns: void.
*****************************************************************************/
void SetBit( lenVal* plv,
int iByte,
int iBit,
short sVal )
{
unsigned char ucByteVal;
unsigned char ucBitMask;
ucBitMask = (unsigned char)(1 << ( 7 - iBit ));
ucByteVal = (unsigned char)(plv->val[ iByte ] & (~ucBitMask));
if ( sVal )
{
ucByteVal |= ucBitMask;
}
plv->val[ iByte ] = ucByteVal;
}
/*****************************************************************************
* Function: AddVal
* Description: add val1 to val2 and store in resVal;
* assumes val1 and val2 are of equal length.
* Parameters: plvResVal - ptr to result.
* plvVal1 - ptr of addendum.
* plvVal2 - ptr of addendum.
* Returns: void.
*****************************************************************************/
void addVal( lenVal* plvResVal,
lenVal* plvVal1,
lenVal* plvVal2 )
{
unsigned char ucCarry;
unsigned short usSum;
unsigned short usVal1;
unsigned short usVal2;
short sIndex;
plvResVal->len = plvVal1->len; /* set up length of result */
/* start at least significant bit and add bytes */
ucCarry = 0;
sIndex = plvVal1->len;
while ( sIndex-- )
{
usVal1 = plvVal1->val[ sIndex ]; /* i'th byte of val1 */
usVal2 = plvVal2->val[ sIndex ]; /* i'th byte of val2 */
/* add the two bytes plus carry from previous addition */
usSum = (unsigned short)( usVal1 + usVal2 + ucCarry );
/* set up carry for next byte */
ucCarry = (unsigned char)( ( usSum > 255 ) ? 1 : 0 );
/* set the i'th byte of the result */
plvResVal->val[ sIndex ] = (unsigned char)usSum;
}
}
/*****************************************************************************
* Function: readVal
* Description: read from XSVF numBytes bytes of data into x.
* Parameters: plv - ptr to lenval in which to put the bytes read.
* sNumBytes - the number of bytes to read.
* Returns: void.
*****************************************************************************/
void readVal( lenVal* plv,
short sNumBytes )
{
unsigned char* pucVal;
plv->len = sNumBytes; /* set the length of the lenVal */
for ( pucVal = plv->val; sNumBytes; --sNumBytes, ++pucVal )
{
/* read a byte of data into the lenVal */
readByte( pucVal );
}
}

View File

@ -0,0 +1,93 @@
/*******************************************************/
/* file: lenval.h */
/* abstract: This file contains a description of the */
/* data structure "lenval". */
/*******************************************************/
#ifndef lenval_dot_h
#define lenval_dot_h
/* the lenVal structure is a byte oriented type used to store an */
/* arbitrary length binary value. As an example, the hex value */
/* 0x0e3d is represented as a lenVal with len=2 (since 2 bytes */
/* and val[0]=0e and val[1]=3d. val[2-MAX_LEN] are undefined */
/* maximum length (in bytes) of value to read in */
/* this needs to be at least 4, and longer than the */
/* length of the longest SDR instruction. If there is, */
/* only 1 device in the chain, MAX_LEN must be at least */
/* ceil(27/8) == 4. For 6 devices in a chain, MAX_LEN */
/* must be 5, for 14 devices MAX_LEN must be 6, for 20 */
/* devices MAX_LEN must be 7, etc.. */
/* You can safely set MAX_LEN to a smaller number if you*/
/* know how many devices will be in your chain. */
/* #define MAX_LEN (Actual #define is below this comment block)
This #define defines the maximum length (in bytes) of predefined
buffers in which the XSVF player stores the current shift data.
This length must be greater than the longest shift length (in bytes)
in the XSVF files that will be processed. 7000 is a very conservative
number. The buffers are stored on the stack and if you have limited
stack space, you may decrease the MAX_LEN value.
How to find the "shift length" in bits?
Look at the ASCII version of the XSVF (generated with the -a option
for the SVF2XSVF translator) and search for the XSDRSIZE command
with the biggest parameter. XSDRSIZE is equivalent to the SVF's
SDR length plus the lengths of applicable HDR and TDR commands.
Remember that the MAX_LEN is defined in bytes. Therefore, the
minimum MAX_LEN = ceil( max( XSDRSIZE ) / 8 );
The following MAX_LEN values have been tested and provide relatively
good margin for the corresponding devices:
DEVICE MAX_LEN Resulting Shift Length Max (in bits)
--------- ------- ----------------------------------------------
XC9500/XL/XV 32 256
CoolRunner/II 256 2048 - actual max 1 device = 1035 bits
FPGA 128 1024 - svf2xsvf -rlen 1024
XC18V00/XCF00
1100 8800 - no blank check performed (default)
- actual max 1 device = 8192 bits verify
- max 1 device = 4096 bits program-only
XC18V00/XCF00 when using the optional Blank Check operation
2500 20000 - required for blank check
- blank check max 1 device = 16384 bits
*/
#define MAX_LEN 256
typedef struct var_len_byte
{
short len; /* number of chars in this value */
unsigned char val[MAX_LEN+1]; /* bytes of data */
} lenVal;
/* return the long representation of a lenVal */
extern long value(lenVal *x);
/* set lenVal equal to value */
extern void initLenVal(lenVal *x, long value);
/* check if expected equals actual (taking the mask into account) */
extern short EqualLenVal(lenVal *expected, lenVal *actual, lenVal *mask);
/* add val1+val2 and put the result in resVal */
extern void addVal(lenVal *resVal, lenVal *val1, lenVal *val2);
/* return the (byte, bit) of lv (reading from left to right) */
extern short RetBit(lenVal *lv, int byte, int bit);
/* set the (byte, bit) of lv equal to val (e.g. SetBit("00000000",byte, 1)
equals "01000000" */
extern void SetBit(lenVal *lv, int byte, int bit, short val);
/* read from XSVF numBytes bytes of data into x */
extern void readVal(lenVal *x, short numBytes);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,42 @@
/*****************************************************************************
* File: micro.h
* Description: This header file contains the function prototype to the
* primary interface function for the XSVF player.
* Usage: FIRST - PORTS.C
* Customize the ports.c function implementations to establish
* the correct protocol for communicating with your JTAG ports
* (setPort() and readTDOBit()) and tune the waitTime() delay
* function. Also, establish access to the XSVF data source
* in the readByte() function.
* FINALLY - Call xsvfExecute().
*****************************************************************************/
#ifndef XSVF_MICRO_H
#define XSVF_MICRO_H
/* Legacy error codes for xsvfExecute from original XSVF player v2.0 */
#define XSVF_LEGACY_SUCCESS 1
#define XSVF_LEGACY_ERROR 0
/* 4.04 [NEW] Error codes for xsvfExecute. */
/* Must #define XSVF_SUPPORT_ERRORCODES in micro.c to get these codes */
#define XSVF_ERROR_NONE 0
#define XSVF_ERROR_UNKNOWN 1
#define XSVF_ERROR_TDOMISMATCH 2
#define XSVF_ERROR_MAXRETRIES 3 /* TDO mismatch after max retries */
#define XSVF_ERROR_ILLEGALCMD 4
#define XSVF_ERROR_ILLEGALSTATE 5
#define XSVF_ERROR_DATAOVERFLOW 6 /* Data > lenVal MAX_LEN buffer size*/
/* Insert new errors here */
#define XSVF_ERROR_LAST 7
/*****************************************************************************
* Function: xsvfExecute
* Description: Process, interpret, and apply the XSVF commands.
* See port.c:readByte for source of XSVF data.
* Parameters: none.
* Returns: int - For error codes see above.
*****************************************************************************/
extern int xsvfExecute();
#endif /* XSVF_MICRO_H */

View File

@ -0,0 +1,113 @@
/*******************************************************/
/* file: ports.c */
/* abstract: This file contains the routines to */
/* output values on the JTAG ports, to read */
/* the TDO bit, and to read a byte of data */
/* from the prom */
/* Revisions: */
/* 12/01/2008: Same code as before (original v5.01). */
/* Updated comments to clarify instructions.*/
/* Add print in setPort for xapp058_example.exe.*/
/*******************************************************/
#include "ports.h"
#include "hackrf_core.h"
#include "cpld_jtag.h"
#include <libopencm3/lpc43xx/gpio.h>
void delay_jtag(uint32_t duration)
{
#define DIVISOR (1024)
#define MIN_NOP (8)
uint32_t i;
uint32_t delay_nop;
/* @204Mhz duration of about 400ns for delay_nop=20 */
if(duration < DIVISOR)
{
delay_nop = MIN_NOP;
}else
{
delay_nop = (duration / DIVISOR) + MIN_NOP;
}
for (i = 0; i < delay_nop; i++)
__asm__("nop");
}
/* 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)
{
if (p==TMS) {
if (val)
gpio_set(PORT_CPLD_TMS, PIN_CPLD_TMS);
else
gpio_clear(PORT_CPLD_TMS, PIN_CPLD_TMS);
} if (p==TDI) {
if (val)
gpio_set(PORT_CPLD_TDI, PIN_CPLD_TDI);
else
gpio_clear(PORT_CPLD_TDI, PIN_CPLD_TDI);
} if (p==TCK) {
if (val)
gpio_set(PORT_CPLD_TCK, PIN_CPLD_TCK);
else
gpio_clear(PORT_CPLD_TCK, PIN_CPLD_TCK);
}
/* conservative delay */
delay_jtag(20000);
}
/* toggle tck LH. No need to modify this code. It is output via setPort. */
void pulseClock()
{
setPort(TCK,0); /* set the TCK port to low */
delay_jtag(200);
setPort(TCK,1); /* set the TCK port to high */
delay_jtag(200);
}
/* readByte: Implement to source the next byte from your XSVF file location */
/* read in a byte of data from the prom */
void readByte(unsigned char *data)
{
*data = cpld_jtag_get_next_byte();
}
/* readTDOBit: Implement to return the current value of the JTAG TDO signal.*/
/* read the TDO bit from port */
unsigned char readTDOBit()
{
delay_jtag(2000);
return CPLD_TDO_STATE;
}
/* waitTime: Implement as follows: */
/* REQUIRED: This function must consume/wait at least the specified number */
/* of microsec, interpreting microsec as a number of microseconds.*/
/* REQUIRED FOR SPARTAN/VIRTEX FPGAs and indirect flash programming: */
/* This function must pulse TCK for at least microsec times, */
/* interpreting microsec as an integer value. */
/* RECOMMENDED IMPLEMENTATION: Pulse TCK at least microsec times AND */
/* continue pulsing TCK until the microsec wait */
/* requirement is also satisfied. */
void waitTime(long microsec)
{
static long tckCyclesPerMicrosec = 1; /* must be at least 1 */
long tckCycles = microsec * tckCyclesPerMicrosec;
long i;
/* This implementation is highly recommended!!! */
/* This implementation requires you to tune the tckCyclesPerMicrosec
variable (above) to match the performance of your embedded system
in order to satisfy the microsec wait time requirement. */
for ( i = 0; i < tckCycles; ++i )
{
pulseClock();
}
}

View File

@ -0,0 +1,31 @@
/*******************************************************/
/* file: ports.h */
/* abstract: This file contains extern declarations */
/* for providing stimulus to the JTAG ports.*/
/*******************************************************/
#ifndef ports_dot_h
#define ports_dot_h
/* these constants are used to send the appropriate ports to setPort */
/* they should be enumerated types, but some of the microcontroller */
/* compilers don't like enumerated types */
#define TCK (short) 0
#define TMS (short) 1
#define TDI (short) 2
/* set the port "p" (TCK, TMS, or TDI) to val (0 or 1) */
extern void setPort(short p, short val);
/* read the TDO bit and store it in val */
extern unsigned char readTDOBit();
/* make clock go down->up->down*/
extern void pulseClock();
/* read the next byte of data from the xsvf file */
extern void readByte(unsigned char *data);
extern void waitTime(long microsec);
#endif

View File

@ -0,0 +1,9 @@
The primary CPLD image is: sgpio_if/default.xsvf
This is a binary file built from HDL source in sgpio_if. You do not need
Xilinx tools unless you want to make your own modifications.
To update the CPLD, first update the firmware, libhackrf, and hackrf-tools.
Then:
$ hackrf_cpldjtag -x sgpio_if/default.xsvf

View File

@ -0,0 +1,51 @@
CPLD interface between LPC43xx microcontroller SGPIO peripheral and MAX5864
RF codec.
Requirements
============
To build this VHDL project and produce an SVF file for flashing the CPLD:
* Xilinx WebPACK 13.4 for Windows or Linux.
To program the SVF file into the CPLD:
* Dangerous Prototypes Bus Blaster v2:
* Configured with [JTAGKey buffers](http://dangerousprototypes.com/docs/Bus_Blaster_v2_buffer_logic).
* Connected to CPLD JTAG signals on Jellybean.
* urJTAG built with libftdi support.
* BSDL model files for Xilinx CoolRunner-II XC264A, available at xilinx.com,
in the "Device Models" Support Resources section of the CoolRunner-II
Product Support & Documentation page. Only one file from the BSDL package is
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
==========
./program
...which connects to the Bus Blaster interface 0, sets the BSDL directory,
detects devices on the JTAG chain, and writes the sgpio_if.svf file to the
CPLD.

View File

@ -0,0 +1,10 @@
#!/bin/sh
echo Program Xilinx CoolRunner-II CPLD on Jellybean, using Bus Blaster v2
jtag <<COMMANDSEND
cable jtagkey vid=0x0403 pid=0x6010 interface=0 driver=ftdi-mpsse
bsdl path bsdl/xc2c
detect
svf default.svf progress stop
COMMANDSEND

View File

@ -0,0 +1,246 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<project xmlns="http://www.xilinx.com/XMLSchema" xmlns:xil_pn="http://www.xilinx.com/XMLSchema">
<header>
<!-- ISE source project file created by Project Navigator. -->
<!-- -->
<!-- This file contains project source information including a list of -->
<!-- project source files, project and process properties. This file, -->
<!-- along with the project source files, is sufficient to open and -->
<!-- implement in ISE Project Navigator. -->
<!-- -->
<!-- Copyright (c) 1995-2013 Xilinx, Inc. All rights reserved. -->
</header>
<version xil_pn:ise_version="14.7" xil_pn:schema_version="2"/>
<files>
<file xil_pn:name="top.vhd" xil_pn:type="FILE_VHDL">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="1"/>
<association xil_pn:name="Implementation" xil_pn:seqID="1"/>
</file>
<file xil_pn:name="top_tb.vhd" xil_pn:type="FILE_VHDL">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="2"/>
<association xil_pn:name="PostRouteSimulation" xil_pn:seqID="2"/>
</file>
<file xil_pn:name="top.ucf" xil_pn:type="FILE_UCF">
<association xil_pn:name="Implementation" xil_pn:seqID="0"/>
</file>
</files>
<properties>
<property xil_pn:name="Add I/O Buffers" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Allow Unmatched LOC Constraints" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Allow Unmatched Timing Group Constraints" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Analysis Effort Level" xil_pn:value="Standard" xil_pn:valueState="default"/>
<property xil_pn:name="Auto Implementation Compile Order" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Auto Implementation Top" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Automatically Insert glbl Module in the Netlist" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Bring Out Global Set/Reset Net as a Port" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Bring Out Global Tristate Net as a Port" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Bus Delimiter" xil_pn:value="&lt;>" xil_pn:valueState="default"/>
<property xil_pn:name="Case" xil_pn:value="Maintain" xil_pn:valueState="default"/>
<property xil_pn:name="Case Implementation Style" xil_pn:value="None" xil_pn:valueState="default"/>
<property xil_pn:name="Clock Enable" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Collapsing Input Limit (4-40)" xil_pn:value="32" xil_pn:valueState="default"/>
<property xil_pn:name="Collapsing Pterm Limit (3-56)" xil_pn:value="28" xil_pn:valueState="default"/>
<property xil_pn:name="Compile CPLD Simulation Library" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Compile SIMPRIM (Timing) Simulation Library" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Compile UNISIM (Functional) Simulation Library" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Compile for HDL Debugging" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Compile uni9000 (Functional) Simulation Library" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Create IEEE 1532 Configuration File" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Custom Waveform Configuration File Behav" xil_pn:value="Default.wcfg" xil_pn:valueState="non-default"/>
<property xil_pn:name="Default Powerup Value of Registers" xil_pn:value="Low" xil_pn:valueState="default"/>
<property xil_pn:name="Delay Values To Be Read from SDF" xil_pn:value="Setup Time" xil_pn:valueState="default"/>
<property xil_pn:name="Device" xil_pn:value="xc2c64a" xil_pn:valueState="non-default"/>
<property xil_pn:name="Device Family" xil_pn:value="CoolRunner2 CPLDs" xil_pn:valueState="non-default"/>
<property xil_pn:name="Device Speed Grade/Select ABS Minimum" xil_pn:value="-7" xil_pn:valueState="default"/>
<property xil_pn:name="Do Not Escape Signal and Instance Names in Netlist" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Enable Hardware Co-Simulation" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Enable Message Filtering" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Equivalent Register Removal XST" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Evaluation Development Board" xil_pn:value="None Specified" xil_pn:valueState="default"/>
<property xil_pn:name="Exhaustive Fit Mode" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="FSM Encoding Algorithm" xil_pn:value="Auto" xil_pn:valueState="default"/>
<property xil_pn:name="Filter Files From Compile Order" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Function Block Input Limit (4-40)" xil_pn:value="38" xil_pn:valueState="default"/>
<property xil_pn:name="Functional Model Target Language ArchWiz" xil_pn:value="VHDL" xil_pn:valueState="default"/>
<property xil_pn:name="Functional Model Target Language Coregen" xil_pn:value="VHDL" xil_pn:valueState="default"/>
<property xil_pn:name="Functional Model Target Language Schematic" xil_pn:value="VHDL" xil_pn:valueState="default"/>
<property xil_pn:name="Generate Architecture Only (No Entity Declaration)" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Generate Multiple Hierarchical Netlist Files" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Generate Post-Fit Power Data" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Generate Post-Fit Simulation Model" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Generate RTL Schematic" xil_pn:value="Yes" xil_pn:valueState="default"/>
<property xil_pn:name="Generate SAIF File for Power Optimization/Estimation Par" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Generate Testbench File" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Generics, Parameters" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Global Set/Reset Port Name" xil_pn:value="GSR_PORT" xil_pn:valueState="default"/>
<property xil_pn:name="Global Tristate Port Name" xil_pn:value="GTS_PORT" xil_pn:valueState="default"/>
<property xil_pn:name="HDL Equations Style" xil_pn:value="Source" xil_pn:valueState="default"/>
<property xil_pn:name="Hierarchy Separator" xil_pn:value="/" xil_pn:valueState="default"/>
<property xil_pn:name="I/O Voltage Standard" xil_pn:value="LVCMOS18" xil_pn:valueState="default"/>
<property xil_pn:name="ISim UUT Instance Name" xil_pn:value="UUT" xil_pn:valueState="default"/>
<property xil_pn:name="Implementation Template" xil_pn:value="Optimize Density" xil_pn:valueState="default"/>
<property xil_pn:name="Implementation Top" xil_pn:value="Architecture|top|Behavioral" xil_pn:valueState="non-default"/>
<property xil_pn:name="Implementation Top File" xil_pn:value="top.vhd" xil_pn:valueState="non-default"/>
<property xil_pn:name="Implementation Top Instance Path" xil_pn:value="/top" xil_pn:valueState="non-default"/>
<property xil_pn:name="Include 'uselib Directive in Verilog File" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Include SIMPRIM Models in Verilog File" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Include UNISIM Models in Verilog File" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Include sdf_annotate task in Verilog File" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Incremental Compilation" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Input and tristate I/O Termination Mode" xil_pn:value="Keeper" xil_pn:valueState="default"/>
<property xil_pn:name="Insert Buffers to Prevent Pulse Swallowing" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Instantiation Template Target Language Xps" xil_pn:value="VHDL" xil_pn:valueState="default"/>
<property xil_pn:name="Keep Hierarchy" xil_pn:value="No" xil_pn:valueState="default"/>
<property xil_pn:name="Keep Hierarchy CPLD" xil_pn:value="Yes" xil_pn:valueState="default"/>
<property xil_pn:name="Language" xil_pn:value="VHDL" xil_pn:valueState="default"/>
<property xil_pn:name="Last Applied Goal" xil_pn:value="Balanced" xil_pn:valueState="default"/>
<property xil_pn:name="Last Applied Strategy" xil_pn:value="Xilinx Default (unlocked)" xil_pn:valueState="default"/>
<property xil_pn:name="Last Unlock Status" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Launch SDK after Export" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Library for Verilog Sources" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Load glbl" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Logic Optimization" xil_pn:value="Density" xil_pn:valueState="default"/>
<property xil_pn:name="Macro Preserve" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Manual Implementation Compile Order" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Max Fanout" xil_pn:value="100000" xil_pn:valueState="non-default"/>
<property xil_pn:name="Maximum Number of Lines in Report" xil_pn:value="1000" xil_pn:valueState="default"/>
<property xil_pn:name="Maximum Signal Name Length" xil_pn:value="20" xil_pn:valueState="default"/>
<property xil_pn:name="Mux Extraction" xil_pn:value="Yes" xil_pn:valueState="default"/>
<property xil_pn:name="Netlist Hierarchy" xil_pn:value="As Optimized" xil_pn:valueState="default"/>
<property xil_pn:name="Number of Clock Buffers" xil_pn:value="4" xil_pn:valueState="default"/>
<property xil_pn:name="Optimization Effort" xil_pn:value="Normal" xil_pn:valueState="default"/>
<property xil_pn:name="Optimization Goal" xil_pn:value="Speed" xil_pn:valueState="default"/>
<property xil_pn:name="Other CPLD Fitter Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other Compiler Options" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other Compiler Options Fit" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other Compiler Options Map" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other Compiler Options Par" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other Compiler Options Translate" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other Compxlib Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other NETGEN Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other Ngdbuild Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other Programming Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other Simulator Commands Behavioral" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other Simulator Commands Fit" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other Timing Report Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other XPWR Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other XST Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Output Extended Identifiers" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Output File Name" xil_pn:value="top" xil_pn:valueState="default"/>
<property xil_pn:name="Output Slew Rate" xil_pn:value="Fast" xil_pn:valueState="default"/>
<property xil_pn:name="Overwrite Compiled Libraries" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Package" xil_pn:value="VQ100" xil_pn:valueState="non-default"/>
<property xil_pn:name="Port to be used" xil_pn:value="Auto - default" xil_pn:valueState="default"/>
<property xil_pn:name="Post Map Simulation Model Name" xil_pn:value="top_map.vhd" xil_pn:valueState="default"/>
<property xil_pn:name="Post Place &amp; Route Simulation Model Name" xil_pn:value="top_timesim.vhd" xil_pn:valueState="default"/>
<property xil_pn:name="Post Synthesis Simulation Model Name" xil_pn:value="top_synthesis.vhd" xil_pn:valueState="default"/>
<property xil_pn:name="Post Translate Simulation Model Name" xil_pn:value="top_translate.vhd" xil_pn:valueState="default"/>
<property xil_pn:name="Preferred Language" xil_pn:value="VHDL" xil_pn:valueState="non-default"/>
<property xil_pn:name="Preserve Unused Inputs" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Produce Verbose Report" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Project Description" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Property Specification in Project File" xil_pn:value="Store all values" xil_pn:valueState="default"/>
<property xil_pn:name="Regenerate Core" xil_pn:value="Under Current Project Setting" xil_pn:valueState="default"/>
<property xil_pn:name="Rename Design Instance in Testbench File to" xil_pn:value="UUT" xil_pn:valueState="default"/>
<property xil_pn:name="Rename Top Level Architecture To" xil_pn:value="Structure" xil_pn:valueState="default"/>
<property xil_pn:name="Rename Top Level Entity to" xil_pn:value="top" xil_pn:valueState="default"/>
<property xil_pn:name="Rename Top Level Module To" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Reset On Configuration Pulse Width" xil_pn:value="100" xil_pn:valueState="default"/>
<property xil_pn:name="Resource Sharing" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Retain Hierarchy" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Run for Specified Time" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Run for Specified Time Map" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Run for Specified Time Par" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Run for Specified Time Translate" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Safe Implementation" xil_pn:value="No" xil_pn:valueState="default"/>
<property xil_pn:name="Selected Module Instance Name" xil_pn:value="/top_tb" xil_pn:valueState="non-default"/>
<property xil_pn:name="Selected Simulation Root Source Node Behavioral" xil_pn:value="work.top_tb" xil_pn:valueState="non-default"/>
<property xil_pn:name="Selected Simulation Root Source Node Post-Map" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Selected Simulation Root Source Node Post-Route" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Selected Simulation Root Source Node Post-Translate" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Selected Simulation Source Node" xil_pn:value="UUT" xil_pn:valueState="default"/>
<property xil_pn:name="Show All Models" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Simulation Model Target" xil_pn:value="VHDL" xil_pn:valueState="default"/>
<property xil_pn:name="Simulation Run Time ISim" xil_pn:value="1000 ns" xil_pn:valueState="default"/>
<property xil_pn:name="Simulation Run Time Map" xil_pn:value="1000 ns" xil_pn:valueState="default"/>
<property xil_pn:name="Simulation Run Time Par" xil_pn:value="1000 ns" xil_pn:valueState="default"/>
<property xil_pn:name="Simulation Run Time Translate" xil_pn:value="1000 ns" xil_pn:valueState="default"/>
<property xil_pn:name="Simulator" xil_pn:value="ISim (VHDL/Verilog)" xil_pn:valueState="default"/>
<property xil_pn:name="Specify 'define Macro Name and Value" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Specify Top Level Instance Names Behavioral" xil_pn:value="work.top_tb" xil_pn:valueState="default"/>
<property xil_pn:name="Specify Top Level Instance Names Fit" xil_pn:value="Default" xil_pn:valueState="default"/>
<property xil_pn:name="Speed Grade" xil_pn:value="-7" xil_pn:valueState="non-default"/>
<property xil_pn:name="Synthesis Tool" xil_pn:value="XST (VHDL/Verilog)" xil_pn:valueState="default"/>
<property xil_pn:name="Target Simulator" xil_pn:value="Please Specify" xil_pn:valueState="default"/>
<property xil_pn:name="Target UCF File Name" xil_pn:value="top.ucf" xil_pn:valueState="non-default"/>
<property xil_pn:name="Timing Report Format" xil_pn:value="Summary" xil_pn:valueState="default"/>
<property xil_pn:name="Top-Level Source Type" xil_pn:value="HDL" xil_pn:valueState="default"/>
<property xil_pn:name="Tristate On Configuration Pulse Width" xil_pn:value="0" xil_pn:valueState="default"/>
<property xil_pn:name="Unused I/O Pad Termination Mode" xil_pn:value="Keeper" xil_pn:valueState="default"/>
<property xil_pn:name="Use 64-bit PlanAhead on 64-bit Systems" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Use Custom Project File Behavioral" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Use Custom Project File Fit" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Use Custom Simulation Command File Behavioral" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Use Custom Simulation Command File Map" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Use Custom Simulation Command File Par" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Use Custom Simulation Command File Translate" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Use Custom Waveform Configuration File Behav" xil_pn:value="true" xil_pn:valueState="non-default"/>
<property xil_pn:name="Use Custom Waveform Configuration File Fit" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Use Custom Waveform Configuration File Map" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Use Custom Waveform Configuration File Par" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Use Custom Waveform Configuration File Translate" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Use Data Gate" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Use Direct Input for Input Registers" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Use Global Clocks" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Use Global Output Enables" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Use Global Set/Reset" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Use Location Constraints" xil_pn:value="Always" xil_pn:valueState="default"/>
<property xil_pn:name="Use Multi-level Logic Optimization" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Use Smart Guide" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Use Synthesis Constraints File" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Use Timing Constraints" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="User Browsed Strategy Files" xil_pn:value="E:/Xilinx/14.1/ISE_DS/ISE/data/default.xds" xil_pn:valueState="non-default"/>
<property xil_pn:name="VHDL Source Analysis Standard" xil_pn:value="VHDL-93" xil_pn:valueState="default"/>
<property xil_pn:name="Value Range Check" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Verilog 2001 Xst" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Verilog Macros" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="WYSIWYG" xil_pn:value="None" xil_pn:valueState="default"/>
<property xil_pn:name="Working Directory" xil_pn:value="." xil_pn:valueState="non-default"/>
<property xil_pn:name="XOR Preserve" xil_pn:value="true" xil_pn:valueState="default"/>
<!-- -->
<!-- The following properties are for internal use only. These should not be modified.-->
<!-- -->
<property xil_pn:name="PROP_BehavioralSimTop" xil_pn:value="Architecture|top_tb|behavior" xil_pn:valueState="non-default"/>
<property xil_pn:name="PROP_DesignName" xil_pn:value="sgpio_test" xil_pn:valueState="non-default"/>
<property xil_pn:name="PROP_DevFamilyPMName" xil_pn:value="xbr" xil_pn:valueState="default"/>
<property xil_pn:name="PROP_FPGAConfiguration" xil_pn:value="FPGAConfiguration" xil_pn:valueState="default"/>
<property xil_pn:name="PROP_PostFitSimTop" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="PROP_PostMapSimTop" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="PROP_PostParSimTop" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="PROP_PostSynthSimTop" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="PROP_PostXlateSimTop" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="PROP_PreSynthesis" xil_pn:value="PreSynthesis" xil_pn:valueState="default"/>
<property xil_pn:name="PROP_intProjectCreationTimestamp" xil_pn:value="2012-04-29T12:49:49" xil_pn:valueState="non-default"/>
<property xil_pn:name="PROP_intWbtProjectID" xil_pn:value="8998E598855F452AB5BAE34A005D4FD5" xil_pn:valueState="non-default"/>
<property xil_pn:name="PROP_intWorkingDirLocWRTProjDir" xil_pn:value="Same" xil_pn:valueState="non-default"/>
<property xil_pn:name="PROP_intWorkingDirUsed" xil_pn:value="No" xil_pn:valueState="non-default"/>
</properties>
<bindings/>
<libraries/>
<autoManagedFiles>
<!-- The following files are identified by `include statements in verilog -->
<!-- source files and are automatically managed by Project Navigator. -->
<!-- -->
<!-- Do not hand-edit this section, as it will be overwritten when the -->
<!-- project is analyzed based on files automatically identified as -->
<!-- include files. -->
</autoManagedFiles>
</project>

View File

@ -0,0 +1,757 @@
Programmer Jedec Bit Map
Date Extracted: Wed Aug 20 08:36:47 2014
QF25812*
QP100*
QV0*
F0*
X0*
J0 0*
N VERSION P.20131013*
N DEVICE XC2C64A-7-VQ100*
Note Block 0 *
Note Block 0 ZIA *
L000000 1111111011100111*
L000016 1110101011111111*
L000032 1111111011110011*
L000048 1111111111111111*
L000064 1111111111111111*
L000080 1111111011010111*
L000096 1110101011111111*
L000112 1111111111111111*
L000128 1110101011111111*
L000144 1111111111111111*
L000160 1111111111111111*
L000176 1111111011100111*
L000192 1111111111111111*
L000208 1111111011100111*
L000224 1111111111111111*
L000240 1111111111111111*
L000256 1111111111111111*
L000272 1111111111111111*
L000288 1111111011010111*
L000304 1111111111111111*
L000320 1111111111111111*
L000336 1111111011100111*
L000352 1111111111111111*
L000368 1111111111111111*
L000384 1111111111111111*
L000400 1111111111111111*
L000416 1111111111111111*
L000432 1111111111111111*
L000448 1111111111111111*
L000464 1111111111111111*
L000480 1111111111111111*
L000496 1111111111111111*
L000512 1111111111111111*
L000528 1111111111111111*
L000544 1111111111111111*
L000560 1111111111111111*
L000576 1111111111111111*
L000592 1111111111111111*
L000608 1111111111111111*
L000624 1111111111111111*
Note Block 0 PLA AND array *
L000640 11110111111111111111110111011111111111111111111111111111111111111111111111111111*
L000720 11011011111111111111111111111111111111111111111111111111111111111111111111111111*
L000800 11011111111111111011111011111111111111111111111111111111111111111111111111111111*
L000880 11100111111111110111111011111111111111111111111111111111111111111111111111111111*
L000960 11011111111101111111111111011111111111111111111111111111111111111111111111111111*
L001040 11111011111111111111111111111111111111111111111111111111111111111111111111111111*
L001120 01111111111111110111110111111111111111111111111111111111111111111111111111111111*
L001200 10111111111111111011110111111111111111111111111111111111111111111111111111111111*
L001280 01011111111101110111111111111111111111111111111111111111111111111111111111111111*
L001360 11110111111101111111110111111111111111111110111111111111111111111111111111111111*
L001440 11010111111101110111111111111111111111111110111111111111111111111111111111111111*
L001520 11110111111110111111110111111111111111111101111111111111111111111111111111111111*
L001600 11010111111110110111111011111111111111111111111111111111111111111111111111111111*
L001680 11111011110111111111111111111111111111111111111111111111111111111111111111111111*
L001760 11111111110111111111111111111111111110111111111111111111111111111111111111111111*
L001840 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L001920 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L002000 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L002080 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L002160 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L002240 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L002320 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L002400 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L002480 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L002560 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L002640 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L002720 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L002800 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L002880 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L002960 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L003040 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L003120 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L003200 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L003280 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L003360 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L003440 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L003520 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L003600 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L003680 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L003760 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L003840 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L003920 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L004000 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L004080 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L004160 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L004240 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L004320 11111011111111111111111111111111111110111111111111111111111111111111111111111111*
L004400 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L004480 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L004560 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L004640 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L004720 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L004800 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L004880 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L004960 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L005040 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
Note Block 0 PLA OR array *
L005120 1111111111111110*
L005136 1111111111111110*
L005152 1111111111111110*
L005168 1111111111111110*
L005184 1111111111111110*
L005200 1111111111111101*
L005216 1111111111111101*
L005232 1111111111111101*
L005248 1111111111111101*
L005264 1111111111111011*
L005280 1111111111111011*
L005296 1111111111111011*
L005312 1111111111111011*
L005328 1111111111101111*
L005344 1111111111101111*
L005360 1111111111111111*
L005376 1111111111111111*
L005392 1111111111111111*
L005408 1111111111111111*
L005424 1111111111111111*
L005440 1111111111111111*
L005456 1111111111111111*
L005472 1111111111111111*
L005488 1111111111111111*
L005504 1111111111111111*
L005520 1111111111111111*
L005536 1111111111111111*
L005552 1111111111111111*
L005568 1111111111111111*
L005584 1111111111111111*
L005600 1111111111111111*
L005616 1111111111111111*
L005632 1111111111111111*
L005648 1111111111111111*
L005664 1111111111111111*
L005680 1111111111111111*
L005696 1111111111111111*
L005712 1111111111111111*
L005728 1111111111111111*
L005744 1111111111111111*
L005760 1111111111111111*
L005776 1111111111111111*
L005792 1111111111111111*
L005808 1111111111111111*
L005824 1111111111111111*
L005840 1111111111111111*
L005856 1111111111111111*
L005872 1111111111111111*
L005888 1111111111111111*
L005904 1111111111111111*
L005920 1111111111111111*
L005936 1111111111111111*
L005952 1111111111111111*
L005968 1111111111111111*
L005984 1111111111111111*
L006000 1111111111111111*
Note Block 0 I/O Macrocell Configuration 27 bits *
N Aclk ClkOp Clk:2 ClkFreq R:2 P:2 RegMod:2 INz:2 FB:2 InReg St XorIn:2 RegCom Oe:4 Tm Slw Pu*
L006016 000001111001111110011111100*
L006043 000001111001111110011111100*
L006070 000001111001111110011111100*
L006097 000001111001111110011111100*
L006124 000001111001111110011111100*
L006151 000001111001111110011111100*
L006178 000001111001111110011111100*
L006205 000001111001111110011111100*
L006232 000001111001111110011111100*
L006259 000001111001111110011111100*
L006286 000001111001111110011111100*
L006313 000001111001100110011111101*
L006340 000001111001100111011111101*
L006367 000101111101110110011111100*
L006394 000101111101110111111111100*
L006421 000101111001110110011111100*
Note Block 1 *
Note Block 1 ZIA *
L006448 1111111111111111*
L006464 1111111011010111*
L006480 1111111011010111*
L006496 1110101011111111*
L006512 1111111011010111*
L006528 1111111011010111*
L006544 1111111111111111*
L006560 1111111111111111*
L006576 1111111011010111*
L006592 1111111011010111*
L006608 1111111011100111*
L006624 1111111111111111*
L006640 1111111111111111*
L006656 1111111111111111*
L006672 1111111011100111*
L006688 1111111011110011*
L006704 1111111011100111*
L006720 1111111111111111*
L006736 1111111111111111*
L006752 1111111111111111*
L006768 1111111111111111*
L006784 1111111011010111*
L006800 1111111111111111*
L006816 1111111111111111*
L006832 1111111111111111*
L006848 1111111111111111*
L006864 1111111111111111*
L006880 1111111111111111*
L006896 1111111111111111*
L006912 1111111111111111*
L006928 1111111111111111*
L006944 1111111111111111*
L006960 1111111111111111*
L006976 1111111111111111*
L006992 1111111111111111*
L007008 1111111111111111*
L007024 1111111111111111*
L007040 1111111111111111*
L007056 1111111111111111*
L007072 1111111111111111*
Note Block 1 PLA AND array *
L007088 11111111110111110111111111111101011111111111111111111111111111111111111111111111*
L007168 11111101111111111111111111111111101111111111111111111111111111111111111111111111*
L007248 11111111110111110111011111111101111111111111111111111111111111111111111111111111*
L007328 11111101111111111111101111111111111111111111111111111111111111111111111111111111*
L007408 11111111110111110101111111111101111111111111111111111111111111111111111111111111*
L007488 11111101111111111110111111111111111111111111111111111111111111111111111111111111*
L007568 11111111110111110111111111111101111111111101111111111111111111111111111111111111*
L007648 11111101111111111111111111111111111111111110111111111111111111111111111111111111*
L007728 11111111010111110111111111111101111111111111111111111111111111111111111111111111*
L007808 11111101101111111111111111111111111111111111111111111111111111111111111111111111*
L007888 11110111110111110111111111111101111111111111111111111111111111111111111111111111*
L007968 11111001111111111111111111111111111111111111111111111111111111111111111111111111*
L008048 11011111110111110111111111111101111111111111111111111111111111111111111111111111*
L008128 11101101111111111111111111111111111111111111111111111111111111111111111111111111*
L008208 11111111110111110111111111110101111111111111111111111111111111111111111111111111*
L008288 11111101111111111111111111111011111111111111111111111111111111111111111111111111*
L008368 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L008448 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L008528 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L008608 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L008688 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L008768 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L008848 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L008928 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L009008 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L009088 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L009168 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L009248 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L009328 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L009408 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L009488 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L009568 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L009648 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L009728 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L009808 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L009888 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L009968 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L010048 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L010128 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L010208 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L010288 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L010368 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L010448 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L010528 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L010608 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L010688 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L010768 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L010848 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L010928 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L011008 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L011088 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L011168 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L011248 11111101111111111111111111111111111111111111111111111111111111111111111111111111*
L011328 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L011408 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L011488 11111101111111111111111111111111111111111111111111111111111111111111111111111111*
Note Block 1 PLA OR array *
L011568 1111111111111011*
L011584 1111111111111011*
L011600 1111111111110111*
L011616 1111111111110111*
L011632 1111111111101111*
L011648 1111111111101111*
L011664 1111111111011111*
L011680 1111111111011111*
L011696 1111111101111111*
L011712 1111111101111111*
L011728 1111101111111111*
L011744 1111101111111111*
L011760 1111011111111111*
L011776 1111011111111111*
L011792 1110111111111111*
L011808 1110111111111111*
L011824 1111111111111111*
L011840 1111111111111111*
L011856 1111111111111111*
L011872 1111111111111111*
L011888 1111111111111111*
L011904 1111111111111111*
L011920 1111111111111111*
L011936 1111111111111111*
L011952 1111111111111111*
L011968 1111111111111111*
L011984 1111111111111111*
L012000 1111111111111111*
L012016 1111111111111111*
L012032 1111111111111111*
L012048 1111111111111111*
L012064 1111111111111111*
L012080 1111111111111111*
L012096 1111111111111111*
L012112 1111111111111111*
L012128 1111111111111111*
L012144 1111111111111111*
L012160 1111111111111111*
L012176 1111111111111111*
L012192 1111111111111111*
L012208 1111111111111111*
L012224 1111111111111111*
L012240 1111111111111111*
L012256 1111111111111111*
L012272 1111111111111111*
L012288 1111111111111111*
L012304 1111111111111111*
L012320 1111111111111111*
L012336 1111111111111111*
L012352 1111111111111111*
L012368 1111111111111111*
L012384 1111111111111111*
L012400 1111111111111111*
L012416 1111111111111111*
L012432 1111111111111111*
L012448 1111111111111111*
Note Block 1 I/O Macrocell Configuration 27 bits *
N Aclk ClkOp Clk:2 ClkFreq R:2 P:2 RegMod:2 INz:2 FB:2 InReg St XorIn:2 RegCom Oe:4 Tm Slw Pu*
L012464 000001111001111110011111100*
L012491 000001111001111110011111100*
L012518 000001111001111110011111100*
L012545 000101111001111100000000011*
L012572 000101111001111101100000011*
L012599 000101111001111101100000011*
L012626 000001111001111110011111100*
L012653 000001111000011100011111100*
L012680 000101111001111101100000011*
L012707 000001111001111100011111100*
L012734 000101111001111101100000011*
L012761 000101111001111101100000011*
L012788 000101111001111101100000011*
L012815 000101111001111101100000011*
L012842 000101111001111100100000011*
L012869 000101111001111100100000011*
Note Block 2 *
Note Block 2 ZIA *
L012896 1111111111111111*
L012912 1110101011111111*
L012928 1111111011110011*
L012944 1111111111111111*
L012960 1111111010110111*
L012976 1111111011010111*
L012992 1110101011111111*
L013008 1100111011111111*
L013024 1110101011111111*
L013040 1111111010110111*
L013056 1110101011111111*
L013072 1111111010110111*
L013088 1111111010110111*
L013104 1111111111111111*
L013120 1111111010110111*
L013136 1111111011010111*
L013152 1111111111111111*
L013168 1111111111111111*
L013184 1111111111111111*
L013200 1111111111111111*
L013216 1111111111111111*
L013232 1111111111111111*
L013248 1111111111111111*
L013264 1111111011010111*
L013280 1111111011010111*
L013296 1111111111111111*
L013312 1111111111111111*
L013328 1111111111111111*
L013344 1111111111111111*
L013360 1111111111111111*
L013376 1111111111111111*
L013392 1111111111111111*
L013408 1111111011100111*
L013424 1111111111111111*
L013440 1111111111111111*
L013456 1111111111111111*
L013472 1111111111111111*
L013488 1111111111111111*
L013504 1111111111111111*
L013520 1111111111111111*
Note Block 2 PLA AND array *
L013536 11110111110111111111111111111111111111111111111111111111111111111011111111111111*
L013616 11011011111001110111111111111111111111111111111111111111111111111011111111111111*
L013696 11110111111011011111111111111111111111111111111111111111111111111111111111111111*
L013776 11111011110111011111111111111111111111111111111111111111111111111111111111111111*
L013856 11111111111111111101011111111111111111111111111111111111111111111111111111111111*
L013936 11111111111111111110101111111111111111111111111111111111111111111111111111111111*
L014016 11111111111111111111011111110111111111111111111111111111111111111111111111111111*
L014096 11111111111011111111111111111111111111111111111111111111111111111111111111111111*
L014176 11111111111111111111101111111011111111111111111111111111111111111111111111111111*
L014256 11111111011111111111011111111111111111111111111111111111111111111111111111111111*
L014336 11111111101111111111101111111111111111111111111111111111111111111111111111111111*
L014416 11111111111111111111011101111111111111111111111111111111111111111111111111111111*
L014496 11111111111111111111101110111111111111111111111111111111111111111111111111111111*
L014576 11111111111111111111010111111111111111111111111111111111111111111111111111111111*
L014656 11111111111111111111101011111111111111111111111111111111111111111111111111111111*
L014736 11111111111111111111011111111111111111111111110111111111111111111111111111111111*
L014816 11111111111111111111101111111111111111111111111011111111111111111111111111111111*
L014896 11111111111111111111011111111101111111111111111111111111111111111111111111111111*
L014976 11111111111111111111101111111110111111111111111111111111111111111111111111111111*
L015056 11111111111111111111011111111111111111111111111110111111111111111111111111111111*
L015136 11111111111111111111101111111111111111111111111101111111111111111111111111111111*
L015216 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L015296 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L015376 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L015456 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L015536 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L015616 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L015696 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L015776 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L015856 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L015936 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L016016 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L016096 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L016176 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L016256 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L016336 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L016416 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L016496 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L016576 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L016656 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L016736 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L016816 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L016896 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L016976 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L017056 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L017136 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L017216 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L017296 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L017376 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L017456 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L017536 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L017616 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L017696 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L017776 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L017856 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L017936 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
Note Block 2 PLA OR array *
L018016 0111111111111111*
L018032 0111111111111111*
L018048 0111111111111111*
L018064 0111111111111111*
L018080 1101111111111111*
L018096 1101111111111111*
L018112 1111011111111111*
L018128 1111111111111111*
L018144 1111011111111111*
L018160 1111111101111111*
L018176 1111111101111111*
L018192 1111111110111111*
L018208 1111111110111111*
L018224 1111111111111011*
L018240 1111111111111011*
L018256 1111111111111101*
L018272 1111111111111101*
L018288 1111111111111110*
L018304 1111111111111110*
L018320 1111110111111111*
L018336 1111110111111111*
L018352 1111111111111111*
L018368 1111111111111111*
L018384 1111111111111111*
L018400 1111111111111111*
L018416 1111111111111111*
L018432 1111111111111111*
L018448 1111111111111111*
L018464 1111111111111111*
L018480 1111111111111111*
L018496 1111111111111111*
L018512 1111111111111111*
L018528 1111111111111111*
L018544 1111111111111111*
L018560 1111111111111111*
L018576 1111111111111111*
L018592 1111111111111111*
L018608 1111111111111111*
L018624 1111111111111111*
L018640 1111111111111111*
L018656 1111111111111111*
L018672 1111111111111111*
L018688 1111111111111111*
L018704 1111111111111111*
L018720 1111111111111111*
L018736 1111111111111111*
L018752 1111111111111111*
L018768 1111111111111111*
L018784 1111111111111111*
L018800 1111111111111111*
L018816 1111111111111111*
L018832 1111111111111111*
L018848 1111111111111111*
L018864 1111111111111111*
L018880 1111111111111111*
L018896 1111111111111111*
Note Block 2 I/O Macrocell Configuration 27 bits *
N Aclk ClkOp Clk:2 ClkFreq R:2 P:2 RegMod:2 INz:2 FB:2 InReg St XorIn:2 RegCom Oe:4 Tm Slw Pu*
L018912 000101111001110100000000011*
L018939 000001111000011100011111100*
L018966 000101111000011101101000111*
L018993 000001111000011100011111100*
L019020 000101111000011101101000111*
L019047 000001111000011100011111100*
L019074 000101111000011101101000111*
L019101 000001111000011100011111100*
L019128 000101111000011101101000111*
L019155 000101111000011101101000111*
L019182 000001111000011100011111100*
L019209 000001111000011100011111100*
L019236 000001111001111110011111100*
L019263 000101111000011101101000111*
L019290 000101111000011101101000111*
L019317 000101111000011101101000111*
Note Block 3 *
Note Block 3 ZIA *
L019344 1111111111111111*
L019360 1111111111111111*
L019376 1111111111111111*
L019392 1111111111111111*
L019408 1111111111111111*
L019424 1111111111111111*
L019440 1111111111111111*
L019456 1111111111111111*
L019472 1111111111111111*
L019488 1111111111111111*
L019504 1111111111111111*
L019520 1111111111111111*
L019536 1111111111111111*
L019552 1111111111111111*
L019568 1111111111111111*
L019584 1111111111111111*
L019600 1111111111111111*
L019616 1111111111111111*
L019632 1111111111111111*
L019648 1111111111111111*
L019664 1111111111111111*
L019680 1111111111111111*
L019696 1111111111111111*
L019712 1111111111111111*
L019728 1111111111111111*
L019744 1111111111111111*
L019760 1111111111111111*
L019776 1111111111111111*
L019792 1111111111111111*
L019808 1111111111111111*
L019824 1111111111111111*
L019840 1111111111111111*
L019856 1111111111111111*
L019872 1111111111111111*
L019888 1111111111111111*
L019904 1111111111111111*
L019920 1111111111111111*
L019936 1111111111111111*
L019952 1111111111111111*
L019968 1111111111111111*
Note Block 3 PLA AND array *
L019984 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L020064 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L020144 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L020224 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L020304 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L020384 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L020464 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L020544 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L020624 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L020704 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L020784 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L020864 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L020944 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L021024 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L021104 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L021184 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L021264 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L021344 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L021424 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L021504 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L021584 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L021664 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L021744 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L021824 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L021904 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L021984 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L022064 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L022144 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L022224 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L022304 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L022384 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L022464 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L022544 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L022624 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L022704 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L022784 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L022864 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L022944 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L023024 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L023104 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L023184 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L023264 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L023344 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L023424 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L023504 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L023584 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L023664 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L023744 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L023824 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L023904 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L023984 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L024064 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L024144 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L024224 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L024304 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
L024384 11111111111111111111111111111111111111111111111111111111111111111111111111111111*
Note Block 3 PLA OR array *
L024464 1111111111111111*
L024480 1111111111111111*
L024496 1111111111111111*
L024512 1111111111111111*
L024528 1111111111111111*
L024544 1111111111111111*
L024560 1111111111111111*
L024576 1111111111111111*
L024592 1111111111111111*
L024608 1111111111111111*
L024624 1111111111111111*
L024640 1111111111111111*
L024656 1111111111111111*
L024672 1111111111111111*
L024688 1111111111111111*
L024704 1111111111111111*
L024720 1111111111111111*
L024736 1111111111111111*
L024752 1111111111111111*
L024768 1111111111111111*
L024784 1111111111111111*
L024800 1111111111111111*
L024816 1111111111111111*
L024832 1111111111111111*
L024848 1111111111111111*
L024864 1111111111111111*
L024880 1111111111111111*
L024896 1111111111111111*
L024912 1111111111111111*
L024928 1111111111111111*
L024944 1111111111111111*
L024960 1111111111111111*
L024976 1111111111111111*
L024992 1111111111111111*
L025008 1111111111111111*
L025024 1111111111111111*
L025040 1111111111111111*
L025056 1111111111111111*
L025072 1111111111111111*
L025088 1111111111111111*
L025104 1111111111111111*
L025120 1111111111111111*
L025136 1111111111111111*
L025152 1111111111111111*
L025168 1111111111111111*
L025184 1111111111111111*
L025200 1111111111111111*
L025216 1111111111111111*
L025232 1111111111111111*
L025248 1111111111111111*
L025264 1111111111111111*
L025280 1111111111111111*
L025296 1111111111111111*
L025312 1111111111111111*
L025328 1111111111111111*
L025344 1111111111111111*
Note Block 3 I/O Macrocell Configuration 27 bits *
N Aclk ClkOp Clk:2 ClkFreq R:2 P:2 RegMod:2 INz:2 FB:2 InReg St XorIn:2 RegCom Oe:4 Tm Slw Pu*
L025360 000001111000011100011111100*
L025387 000001111000011100011111100*
L025414 000001111000011100011111100*
L025441 000001111000011100011111100*
L025468 000001111000011100011111100*
L025495 000001111000011100011111100*
L025522 000001111000011100011111100*
L025549 000001111000011100011111100*
L025576 000001111001111110011111100*
L025603 000001111001111110011111100*
L025630 000001111001111110011111100*
L025657 000001111001111110011111100*
L025684 000001111001111110011111100*
L025711 000001111001111110011111100*
L025738 000001111001111110011111100*
L025765 000001111001111110011111100*
Note Globals *
Note Global Clock Mux *
L025792 001*
Note Global Set/Reset Mux *
L025795 00*
Note Global OE Mux *
L025797 11111111*
Note Global Termination *
L025805 0*
Note Input Voltage Standard for IOB *
L025806 1*
Note Output Voltage Standard for IOB *
L025807 1*
Note I/O Bank 0 Vcci *
L025808 0*
Note I/O Bank 0 Vcco *
L025809 0*
Note I/O Bank 1 Vcci *
L025810 0*
Note I/O Bank 1 Vcco *
L025811 0*
CFB93*
AA7A

View File

@ -0,0 +1,68 @@
#
# 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 | TNM=adc_data;
NET "CODEC_X2_CLK" LOC="27" |IOSTANDARD=LVCMOS33;
NET "CODEC_X2_CLK" TNM_NET = CODEC_X2_CLK;
TIMESPEC TS_codec_x2_data = PERIOD "CODEC_X2_CLK" 25 ns;
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 | 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 "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 "HOST_Q_INVERT" LOC="70" |IOSTANDARD=LVCMOS33;
TIMEGRP "adc_data" OFFSET = IN 16 ns BEFORE "CODEC_X2_CLK";
TIMEGRP "dac_data" OFFSET = OUT 15 ns AFTER "CODEC_X2_CLK";
TIMEGRP "to_host" OFFSET = OUT 20 ns AFTER "CODEC_X2_CLK";

View File

@ -0,0 +1,168 @@
--
-- 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.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;
library UNISIM;
use UNISIM.vcomponents.all;
entity top is
Port(
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_DECIM_SEL : in std_logic_vector(2 downto 0);
HOST_Q_INVERT : in std_logic;
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
);
end top;
architecture Behavioral of top is
signal codec_clk_i : std_logic;
signal adc_data_i : std_logic_vector(7 downto 0);
signal dac_data_o : std_logic_vector(9 downto 0);
signal host_clk_i : std_logic;
type transfer_direction is (from_adc, to_dac);
signal transfer_direction_i : transfer_direction;
signal host_data_enable_i : std_logic;
signal host_data_capture_o : std_logic;
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;
signal q_invert : std_logic;
signal rx_q_invert_mask : std_logic_vector(7 downto 0);
signal tx_q_invert_mask : std_logic_vector(7 downto 0);
begin
------------------------------------------------
-- Codec interface
adc_data_i <= DA(7 downto 0);
DD(9 downto 0) <= dac_data_o;
------------------------------------------------
-- Clocks
codec_clk_i <= CODEC_CLK;
BUFG_host : BUFG
port map (
O => host_clk_i,
I => CODEC_X2_CLK
);
------------------------------------------------
-- SGPIO interface
HOST_DATA <= data_to_host_o when transfer_direction_i = from_adc
else (others => 'Z');
data_from_host_i <= HOST_DATA;
HOST_CAPTURE <= host_data_capture_o;
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;
q_invert <= HOST_Q_INVERT;
rx_q_invert_mask <= X"80" when q_invert = '1' else X"7f";
tx_q_invert_mask <= X"7F" when q_invert = '1' else X"80";
process(host_clk_i)
begin
if rising_edge(host_clk_i) then
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 rx_q_invert_mask;
end if;
end if;
end process;
process(host_clk_i)
begin
if rising_edge(host_clk_i) then
if transfer_direction_i = to_dac then
if codec_clk_i = '1' then
dac_data_o <= (data_from_host_i xor tx_q_invert_mask) & tx_q_invert_mask(0) & tx_q_invert_mask(0);
else
dac_data_o <= (data_from_host_i xor X"80") & "00";
end if;
else
dac_data_o <= (dac_data_o'high => '0', others => '1');
end if;
end if;
end process;
process(host_clk_i)
begin
if rising_edge(host_clk_i) then
if transfer_direction_i = to_dac then
if codec_clk_i = '1' then
host_data_capture_o <= host_data_enable_i;
end if;
else
if codec_clk_i = '0' then
host_data_capture_o <= host_data_enable_i and decimate_en;
end if;
end if;
end if;
end process;
end Behavioral;

View File

@ -0,0 +1,132 @@
--
-- 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;
ENTITY top_tb IS
END top_tb;
ARCHITECTURE behavior OF top_tb IS
COMPONENT top
PORT(
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_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
);
END COMPONENT;
--Inputs
signal DA : std_logic_vector(7 downto 0) := (others => '0');
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_DECIM_SEL : std_logic_vector(2 downto 0) := "010";
--BiDirs
signal HOST_DATA : std_logic_vector(7 downto 0);
--Outputs
signal DD : std_logic_vector(9 downto 0);
signal HOST_CAPTURE : std_logic;
begin
uut: top PORT MAP (
HOST_DATA => HOST_DATA,
HOST_CAPTURE => HOST_CAPTURE,
HOST_DISABLE => HOST_DISABLE,
HOST_DIRECTION => HOST_DIRECTION,
HOST_DECIM_SEL => HOST_DECIM_SEL,
DA => DA,
DD => DD,
CODEC_CLK => CODEC_CLK,
CODEC_X2_CLK => CODEC_X2_CLK
);
clk_process :process
begin
CODEC_CLK <= '1';
CODEC_X2_CLK <= '1';
wait for 12.5 ns;
CODEC_X2_CLK <= '0';
wait for 12.5 ns;
CODEC_CLK <= '0';
CODEC_X2_CLK <= '1';
wait for 12.5 ns;
CODEC_X2_CLK <= '0';
wait for 12.5 ns;
end process;
adc_proc: process
begin
wait until rising_edge(CODEC_CLK);
wait for 9 ns;
DA <= "00000000";
wait until falling_edge(CODEC_CLK);
wait for 9 ns;
DA <= "00000001";
end process;
sgpio_proc: process
begin
HOST_DATA <= (others => 'Z');
HOST_DIRECTION <= '0';
HOST_DISABLE <= '1';
wait for 135 ns;
HOST_DISABLE <= '0';
wait for 1000 ns;
HOST_DISABLE <= '1';
wait for 100 ns;
HOST_DIRECTION <= '1';
wait for 100 ns;
HOST_DISABLE <= '0';
for i in 0 to 10 loop
HOST_DATA <= (others => '0');
wait until rising_edge(CODEC_CLK) and HOST_CAPTURE = '1';
HOST_DATA <= (others => '1');
wait until rising_edge(CODEC_CLK) and HOST_CAPTURE = '1';
end loop;
wait;
end process;
end;

View File

@ -0,0 +1,37 @@
CPLD interface to expose LPC43xx microcontroller SGPIO peripheral, either
as all inputs or all outputs.
Requirements
============
To build this VHDL project and produce an SVF file for flashing the CPLD:
* Xilinx WebPACK 13.4 for Windows or Linux.
* BSDL model files for Xilinx CoolRunner-II XC264A, available at xilinx.com,
in the "Device Models" Support Resources section of the CoolRunner-II
Product Support & Documentation page. Only one file from the BSDL package is
required, and the "program" script below expects it to be at the relative
path "bsdl/xc2c/xc2c64.bsd".
To program the SVF file into the CPLD:
* Dangerous Prototypes Bus Blaster v2:
* Configured with JTAGKey buffers.
* Connected to CPLD JTAG signals on Jellybean.
* urJTAG built with libftdi support.
To Program
==========
./program
...which connects to the Bus Blaster interface 0, sets the BSDL directory,
detects devices on the JTAG chain, and writes the sgpio_if_passthrough.svf
file to the CPLD.
Usage:
B1AUX9=0 control SGPIO0 to 15 as Input. B2AUX[1-16] => SGPIO[0-15]
B1AUX9=1 control SGPIO0 to 15 as Output. SGPIO[0-15] => B2AUX[1-16]

View File

@ -0,0 +1,10 @@
#!/bin/sh
echo Program Xilinx CoolRunner-II CPLD on Jellybean, using Bus Blaster v2
jtag <<COMMANDSEND
cable jtagkey vid=0x0403 pid=0x6010 interface=0 driver=ftdi-mpsse
bsdl path bsdl/xc2c
detect
svf sgpio_if_passthrough.svf progress stop
COMMANDSEND

View File

@ -0,0 +1,242 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<project xmlns="http://www.xilinx.com/XMLSchema" xmlns:xil_pn="http://www.xilinx.com/XMLSchema">
<header>
<!-- ISE source project file created by Project Navigator. -->
<!-- -->
<!-- This file contains project source information including a list of -->
<!-- project source files, project and process properties. This file, -->
<!-- along with the project source files, is sufficient to open and -->
<!-- implement in ISE Project Navigator. -->
<!-- -->
<!-- Copyright (c) 1995-2011 Xilinx, Inc. All rights reserved. -->
</header>
<version xil_pn:ise_version="13.4" xil_pn:schema_version="2"/>
<files>
<file xil_pn:name="top.vhd" xil_pn:type="FILE_VHDL">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="1"/>
<association xil_pn:name="Implementation" xil_pn:seqID="1"/>
</file>
<file xil_pn:name="top.ucf" xil_pn:type="FILE_UCF">
<association xil_pn:name="Implementation" xil_pn:seqID="0"/>
</file>
</files>
<properties>
<property xil_pn:name="Add I/O Buffers" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Allow Unmatched LOC Constraints" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Allow Unmatched Timing Group Constraints" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Analysis Effort Level" xil_pn:value="Standard" xil_pn:valueState="default"/>
<property xil_pn:name="Auto Implementation Compile Order" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Auto Implementation Top" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Automatically Insert glbl Module in the Netlist" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Bring Out Global Set/Reset Net as a Port" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Bring Out Global Tristate Net as a Port" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Bus Delimiter" xil_pn:value="&lt;>" xil_pn:valueState="default"/>
<property xil_pn:name="Case" xil_pn:value="Maintain" xil_pn:valueState="default"/>
<property xil_pn:name="Case Implementation Style" xil_pn:value="None" xil_pn:valueState="default"/>
<property xil_pn:name="Clock Enable" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Collapsing Input Limit (4-40)" xil_pn:value="32" xil_pn:valueState="default"/>
<property xil_pn:name="Collapsing Pterm Limit (3-56)" xil_pn:value="28" xil_pn:valueState="default"/>
<property xil_pn:name="Compile CPLD Simulation Library" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Compile SIMPRIM (Timing) Simulation Library" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Compile UNISIM (Functional) Simulation Library" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Compile for HDL Debugging" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Compile uni9000 (Functional) Simulation Library" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Create IEEE 1532 Configuration File" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Custom Waveform Configuration File Behav" xil_pn:value="Default.wcfg" xil_pn:valueState="non-default"/>
<property xil_pn:name="Default Powerup Value of Registers" xil_pn:value="Low" xil_pn:valueState="default"/>
<property xil_pn:name="Delay Values To Be Read from SDF" xil_pn:value="Setup Time" xil_pn:valueState="default"/>
<property xil_pn:name="Device" xil_pn:value="xc2c64a" xil_pn:valueState="non-default"/>
<property xil_pn:name="Device Family" xil_pn:value="CoolRunner2 CPLDs" xil_pn:valueState="non-default"/>
<property xil_pn:name="Device Speed Grade/Select ABS Minimum" xil_pn:value="-7" xil_pn:valueState="default"/>
<property xil_pn:name="Do Not Escape Signal and Instance Names in Netlist" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Enable Hardware Co-Simulation" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Enable Message Filtering" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Equivalent Register Removal XST" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Evaluation Development Board" xil_pn:value="None Specified" xil_pn:valueState="default"/>
<property xil_pn:name="Exhaustive Fit Mode" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="FSM Encoding Algorithm" xil_pn:value="Auto" xil_pn:valueState="default"/>
<property xil_pn:name="Filter Files From Compile Order" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Function Block Input Limit (4-40)" xil_pn:value="38" xil_pn:valueState="default"/>
<property xil_pn:name="Functional Model Target Language ArchWiz" xil_pn:value="VHDL" xil_pn:valueState="default"/>
<property xil_pn:name="Functional Model Target Language Coregen" xil_pn:value="VHDL" xil_pn:valueState="default"/>
<property xil_pn:name="Functional Model Target Language Schematic" xil_pn:value="VHDL" xil_pn:valueState="default"/>
<property xil_pn:name="Generate Architecture Only (No Entity Declaration)" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Generate Multiple Hierarchical Netlist Files" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Generate Post-Fit Power Data" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Generate Post-Fit Simulation Model" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Generate RTL Schematic" xil_pn:value="Yes" xil_pn:valueState="default"/>
<property xil_pn:name="Generate SAIF File for Power Optimization/Estimation Par" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Generate Testbench File" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Generics, Parameters" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Global Set/Reset Port Name" xil_pn:value="GSR_PORT" xil_pn:valueState="default"/>
<property xil_pn:name="Global Tristate Port Name" xil_pn:value="GTS_PORT" xil_pn:valueState="default"/>
<property xil_pn:name="HDL Equations Style" xil_pn:value="Source" xil_pn:valueState="default"/>
<property xil_pn:name="Hierarchy Separator" xil_pn:value="/" xil_pn:valueState="default"/>
<property xil_pn:name="I/O Voltage Standard" xil_pn:value="LVCMOS18" xil_pn:valueState="default"/>
<property xil_pn:name="ISim UUT Instance Name" xil_pn:value="UUT" xil_pn:valueState="default"/>
<property xil_pn:name="Implementation Template" xil_pn:value="Optimize Density" xil_pn:valueState="default"/>
<property xil_pn:name="Implementation Top" xil_pn:value="Architecture|top|Behavioral" xil_pn:valueState="non-default"/>
<property xil_pn:name="Implementation Top File" xil_pn:value="top.vhd" xil_pn:valueState="non-default"/>
<property xil_pn:name="Implementation Top Instance Path" xil_pn:value="/top" xil_pn:valueState="non-default"/>
<property xil_pn:name="Include 'uselib Directive in Verilog File" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Include SIMPRIM Models in Verilog File" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Include UNISIM Models in Verilog File" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Include sdf_annotate task in Verilog File" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Incremental Compilation" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Input and tristate I/O Termination Mode" xil_pn:value="Keeper" xil_pn:valueState="default"/>
<property xil_pn:name="Insert Buffers to Prevent Pulse Swallowing" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Instantiation Template Target Language Xps" xil_pn:value="VHDL" xil_pn:valueState="default"/>
<property xil_pn:name="Keep Hierarchy" xil_pn:value="No" xil_pn:valueState="default"/>
<property xil_pn:name="Keep Hierarchy CPLD" xil_pn:value="Yes" xil_pn:valueState="default"/>
<property xil_pn:name="Language" xil_pn:value="VHDL" xil_pn:valueState="default"/>
<property xil_pn:name="Last Applied Goal" xil_pn:value="Balanced" xil_pn:valueState="default"/>
<property xil_pn:name="Last Applied Strategy" xil_pn:value="Xilinx Default (unlocked)" xil_pn:valueState="default"/>
<property xil_pn:name="Last Unlock Status" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Launch SDK after Export" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Library for Verilog Sources" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Load glbl" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Logic Optimization" xil_pn:value="Density" xil_pn:valueState="default"/>
<property xil_pn:name="Macro Preserve" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Manual Implementation Compile Order" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Max Fanout" xil_pn:value="100000" xil_pn:valueState="non-default"/>
<property xil_pn:name="Maximum Number of Lines in Report" xil_pn:value="1000" xil_pn:valueState="default"/>
<property xil_pn:name="Maximum Signal Name Length" xil_pn:value="20" xil_pn:valueState="default"/>
<property xil_pn:name="Mux Extraction" xil_pn:value="Yes" xil_pn:valueState="default"/>
<property xil_pn:name="Netlist Hierarchy" xil_pn:value="As Optimized" xil_pn:valueState="default"/>
<property xil_pn:name="Number of Clock Buffers" xil_pn:value="4" xil_pn:valueState="default"/>
<property xil_pn:name="Optimization Effort" xil_pn:value="Normal" xil_pn:valueState="default"/>
<property xil_pn:name="Optimization Goal" xil_pn:value="Speed" xil_pn:valueState="default"/>
<property xil_pn:name="Other CPLD Fitter Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other Compiler Options" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other Compiler Options Fit" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other Compiler Options Map" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other Compiler Options Par" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other Compiler Options Translate" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other Compxlib Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other NETGEN Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other Ngdbuild Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other Programming Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other Simulator Commands Behavioral" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other Simulator Commands Fit" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other Timing Report Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other XPWR Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Other XST Command Line Options" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Output Extended Identifiers" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Output File Name" xil_pn:value="top" xil_pn:valueState="default"/>
<property xil_pn:name="Output Slew Rate" xil_pn:value="Fast" xil_pn:valueState="default"/>
<property xil_pn:name="Overwrite Compiled Libraries" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Package" xil_pn:value="VQ100" xil_pn:valueState="non-default"/>
<property xil_pn:name="Port to be used" xil_pn:value="Auto - default" xil_pn:valueState="default"/>
<property xil_pn:name="Post Map Simulation Model Name" xil_pn:value="top_map.vhd" xil_pn:valueState="default"/>
<property xil_pn:name="Post Place &amp; Route Simulation Model Name" xil_pn:value="top_timesim.vhd" xil_pn:valueState="default"/>
<property xil_pn:name="Post Synthesis Simulation Model Name" xil_pn:value="top_synthesis.vhd" xil_pn:valueState="default"/>
<property xil_pn:name="Post Translate Simulation Model Name" xil_pn:value="top_translate.vhd" xil_pn:valueState="default"/>
<property xil_pn:name="Preferred Language" xil_pn:value="VHDL" xil_pn:valueState="non-default"/>
<property xil_pn:name="Preserve Unused Inputs" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Produce Verbose Report" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Project Description" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Property Specification in Project File" xil_pn:value="Store all values" xil_pn:valueState="default"/>
<property xil_pn:name="Regenerate Core" xil_pn:value="Under Current Project Setting" xil_pn:valueState="default"/>
<property xil_pn:name="Rename Design Instance in Testbench File to" xil_pn:value="UUT" xil_pn:valueState="default"/>
<property xil_pn:name="Rename Top Level Architecture To" xil_pn:value="Structure" xil_pn:valueState="default"/>
<property xil_pn:name="Rename Top Level Entity to" xil_pn:value="top" xil_pn:valueState="default"/>
<property xil_pn:name="Rename Top Level Module To" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Reset On Configuration Pulse Width" xil_pn:value="100" xil_pn:valueState="default"/>
<property xil_pn:name="Resource Sharing" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Retain Hierarchy" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Run for Specified Time" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Run for Specified Time Map" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Run for Specified Time Par" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Run for Specified Time Translate" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Safe Implementation" xil_pn:value="No" xil_pn:valueState="default"/>
<property xil_pn:name="Selected Module Instance Name" xil_pn:value="/top_tb" xil_pn:valueState="non-default"/>
<property xil_pn:name="Selected Simulation Root Source Node Behavioral" xil_pn:value="work.top_tb" xil_pn:valueState="non-default"/>
<property xil_pn:name="Selected Simulation Root Source Node Post-Map" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Selected Simulation Root Source Node Post-Route" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Selected Simulation Root Source Node Post-Translate" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Selected Simulation Source Node" xil_pn:value="UUT" xil_pn:valueState="default"/>
<property xil_pn:name="Show All Models" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Simulation Model Target" xil_pn:value="VHDL" xil_pn:valueState="default"/>
<property xil_pn:name="Simulation Run Time ISim" xil_pn:value="1000 ns" xil_pn:valueState="default"/>
<property xil_pn:name="Simulation Run Time Map" xil_pn:value="1000 ns" xil_pn:valueState="default"/>
<property xil_pn:name="Simulation Run Time Par" xil_pn:value="1000 ns" xil_pn:valueState="default"/>
<property xil_pn:name="Simulation Run Time Translate" xil_pn:value="1000 ns" xil_pn:valueState="default"/>
<property xil_pn:name="Simulator" xil_pn:value="ISim (VHDL/Verilog)" xil_pn:valueState="default"/>
<property xil_pn:name="Specify 'define Macro Name and Value" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Specify Top Level Instance Names Behavioral" xil_pn:value="work.top_tb" xil_pn:valueState="default"/>
<property xil_pn:name="Specify Top Level Instance Names Fit" xil_pn:value="Default" xil_pn:valueState="default"/>
<property xil_pn:name="Speed Grade" xil_pn:value="-7" xil_pn:valueState="non-default"/>
<property xil_pn:name="Synthesis Tool" xil_pn:value="XST (VHDL/Verilog)" xil_pn:valueState="default"/>
<property xil_pn:name="Target Simulator" xil_pn:value="Please Specify" xil_pn:valueState="default"/>
<property xil_pn:name="Target UCF File Name" xil_pn:value="top.ucf" xil_pn:valueState="non-default"/>
<property xil_pn:name="Timing Report Format" xil_pn:value="Summary" xil_pn:valueState="default"/>
<property xil_pn:name="Top-Level Source Type" xil_pn:value="HDL" xil_pn:valueState="default"/>
<property xil_pn:name="Tristate On Configuration Pulse Width" xil_pn:value="0" xil_pn:valueState="default"/>
<property xil_pn:name="Unused I/O Pad Termination Mode" xil_pn:value="Keeper" xil_pn:valueState="default"/>
<property xil_pn:name="Use 64-bit PlanAhead on 64-bit Systems" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Use Custom Project File Behavioral" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Use Custom Project File Fit" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Use Custom Simulation Command File Behavioral" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Use Custom Simulation Command File Map" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Use Custom Simulation Command File Par" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Use Custom Simulation Command File Translate" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Use Custom Waveform Configuration File Behav" xil_pn:value="true" xil_pn:valueState="non-default"/>
<property xil_pn:name="Use Custom Waveform Configuration File Fit" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Use Custom Waveform Configuration File Map" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Use Custom Waveform Configuration File Par" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Use Custom Waveform Configuration File Translate" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Use Data Gate" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Use Direct Input for Input Registers" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Use Global Clocks" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Use Global Output Enables" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Use Global Set/Reset" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Use Location Constraints" xil_pn:value="Always" xil_pn:valueState="default"/>
<property xil_pn:name="Use Multi-level Logic Optimization" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Use Smart Guide" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Use Synthesis Constraints File" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Use Timing Constraints" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="User Browsed Strategy Files" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="VHDL Source Analysis Standard" xil_pn:value="VHDL-93" xil_pn:valueState="default"/>
<property xil_pn:name="Value Range Check" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Verilog 2001 Xst" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Verilog Macros" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="WYSIWYG" xil_pn:value="None" xil_pn:valueState="default"/>
<property xil_pn:name="Working Directory" xil_pn:value="." xil_pn:valueState="non-default"/>
<property xil_pn:name="XOR Preserve" xil_pn:value="true" xil_pn:valueState="default"/>
<!-- -->
<!-- The following properties are for internal use only. These should not be modified.-->
<!-- -->
<property xil_pn:name="PROP_BehavioralSimTop" xil_pn:value="Architecture|top_tb|behavior" xil_pn:valueState="non-default"/>
<property xil_pn:name="PROP_DesignName" xil_pn:value="sgpio_test" xil_pn:valueState="non-default"/>
<property xil_pn:name="PROP_DevFamilyPMName" xil_pn:value="xbr" xil_pn:valueState="default"/>
<property xil_pn:name="PROP_FPGAConfiguration" xil_pn:value="FPGAConfiguration" xil_pn:valueState="default"/>
<property xil_pn:name="PROP_PostFitSimTop" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="PROP_PostMapSimTop" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="PROP_PostParSimTop" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="PROP_PostSynthSimTop" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="PROP_PostXlateSimTop" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="PROP_PreSynthesis" xil_pn:value="PreSynthesis" xil_pn:valueState="default"/>
<property xil_pn:name="PROP_intProjectCreationTimestamp" xil_pn:value="2012-04-29T12:49:49" xil_pn:valueState="non-default"/>
<property xil_pn:name="PROP_intWbtProjectID" xil_pn:value="8998E598855F452AB5BAE34A005D4FD5" xil_pn:valueState="non-default"/>
<property xil_pn:name="PROP_intWorkingDirLocWRTProjDir" xil_pn:value="Same" xil_pn:valueState="non-default"/>
<property xil_pn:name="PROP_intWorkingDirUsed" xil_pn:value="No" xil_pn:valueState="non-default"/>
</properties>
<bindings/>
<libraries/>
<autoManagedFiles>
<!-- The following files are identified by `include statements in verilog -->
<!-- source files and are automatically managed by Project Navigator. -->
<!-- -->
<!-- Do not hand-edit this section, as it will be overwritten when the -->
<!-- project is analyzed based on files automatically identified as -->
<!-- include files. -->
</autoManagedFiles>
</project>

View File

@ -0,0 +1,89 @@
#
# 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" |FAST |IOSTANDARD=LVCMOS18;
NET "CODEC_X2_CLK" LOC="27" |FAST |IOSTANDARD=LVCMOS18;
#NET "GCLK0" LOC="22" |FAST |IOSTANDARD=LVCMOS18;
NET "CODEC_X2_CLK" TNM_NET = CODEC_X2_CLK;
TIMESPEC TS_codec_x2_data = PERIOD "CODEC_X2_CLK" 50 ns;
NET "DA<7>" LOC="35" |FAST |IOSTANDARD=LVCMOS18;
NET "DA<6>" LOC="36" |FAST |IOSTANDARD=LVCMOS18;
NET "DA<5>" LOC="37" |FAST |IOSTANDARD=LVCMOS18;
NET "DA<4>" LOC="39" |FAST |IOSTANDARD=LVCMOS18;
NET "DA<3>" LOC="40" |FAST |IOSTANDARD=LVCMOS18;
NET "DA<2>" LOC="41" |FAST |IOSTANDARD=LVCMOS18;
NET "DA<1>" LOC="42" |FAST |IOSTANDARD=LVCMOS18;
NET "DA<0>" LOC="43" |FAST |IOSTANDARD=LVCMOS18;
NET "DD<9>" LOC="17" |FAST |IOSTANDARD=LVCMOS18;
NET "DD<8>" LOC="18" |FAST |IOSTANDARD=LVCMOS18;
NET "DD<7>" LOC="19" |FAST |IOSTANDARD=LVCMOS18;
NET "DD<6>" LOC="24" |FAST |IOSTANDARD=LVCMOS18;
NET "DD<5>" LOC="28" |FAST |IOSTANDARD=LVCMOS18;
NET "DD<4>" LOC="29" |FAST |IOSTANDARD=LVCMOS18;
NET "DD<3>" LOC="30" |FAST |IOSTANDARD=LVCMOS18;
NET "DD<2>" LOC="32" |FAST |IOSTANDARD=LVCMOS18;
NET "DD<1>" LOC="33" |FAST |IOSTANDARD=LVCMOS18;
NET "DD<0>" LOC="34" |FAST |IOSTANDARD=LVCMOS18;
NET "B1AUX<16>" LOC="60" |FAST |IOSTANDARD=LVCMOS18;
NET "B1AUX<15>" LOC="58" |FAST |IOSTANDARD=LVCMOS18;
NET "B1AUX<14>" LOC="56" |FAST |IOSTANDARD=LVCMOS18;
NET "B1AUX<13>" LOC="55" |FAST |IOSTANDARD=LVCMOS18;
NET "B1AUX<12>" LOC="53" |FAST |IOSTANDARD=LVCMOS18;
NET "B1AUX<11>" LOC="52" |FAST |IOSTANDARD=LVCMOS18;
NET "B1AUX<10>" LOC="50" |FAST |IOSTANDARD=LVCMOS18;
NET "B1AUX<9>" LOC="49" |FAST |IOSTANDARD=LVCMOS18;
NET "SGPIO<15>" LOC="78" |FAST |IOSTANDARD=LVCMOS33;
NET "SGPIO<14>" LOC="81" |FAST |IOSTANDARD=LVCMOS33;
NET "SGPIO<13>" LOC="90" |FAST |IOSTANDARD=LVCMOS33;
NET "SGPIO<12>" LOC="70" |FAST |IOSTANDARD=LVCMOS33;
NET "SGPIO<11>" LOC="71" |FAST |IOSTANDARD=LVCMOS33;
NET "SGPIO<10>" LOC="76" |FAST |IOSTANDARD=LVCMOS33;
NET "SGPIO<9>" LOC="91" |FAST |IOSTANDARD=LVCMOS33;
NET "SGPIO<8>" LOC="68" |FAST |IOSTANDARD=LVCMOS33;
NET "SGPIO<7>" LOC="77" |FAST |IOSTANDARD=LVCMOS33;
NET "SGPIO<6>" LOC="61" |FAST |IOSTANDARD=LVCMOS33;
NET "SGPIO<5>" LOC="64" |FAST |IOSTANDARD=LVCMOS33;
NET "SGPIO<4>" LOC="67" |FAST |IOSTANDARD=LVCMOS33;
NET "SGPIO<3>" LOC="72" |FAST |IOSTANDARD=LVCMOS33;
NET "SGPIO<2>" LOC="74" |FAST |IOSTANDARD=LVCMOS33;
NET "SGPIO<1>" LOC="79" |FAST |IOSTANDARD=LVCMOS33;
NET "SGPIO<0>" LOC="89" |FAST |IOSTANDARD=LVCMOS33;
NET "B2AUX<16>" LOC="92" |FAST |IOSTANDARD=LVCMOS33;
NET "B2AUX<15>" LOC="94" |FAST |IOSTANDARD=LVCMOS33;
NET "B2AUX<14>" LOC="97" |FAST |IOSTANDARD=LVCMOS33;
NET "B2AUX<13>" LOC="99" |FAST |IOSTANDARD=LVCMOS33;
NET "B2AUX<12>" LOC="1" |FAST |IOSTANDARD=LVCMOS33;
NET "B2AUX<11>" LOC="2" |FAST |IOSTANDARD=LVCMOS33;
NET "B2AUX<10>" LOC="3" |FAST |IOSTANDARD=LVCMOS33;
NET "B2AUX<9>" LOC="4" |FAST |IOSTANDARD=LVCMOS33;
NET "B2AUX<8>" LOC="6" |FAST |IOSTANDARD=LVCMOS33;
NET "B2AUX<7>" LOC="7" |FAST |IOSTANDARD=LVCMOS33;
NET "B2AUX<6>" LOC="8" |FAST |IOSTANDARD=LVCMOS33;
NET "B2AUX<5>" LOC="9" |FAST |IOSTANDARD=LVCMOS33;
NET "B2AUX<4>" LOC="10" |FAST |IOSTANDARD=LVCMOS33;
NET "B2AUX<3>" LOC="11" |FAST |IOSTANDARD=LVCMOS33;
NET "B2AUX<2>" LOC="12" |FAST |IOSTANDARD=LVCMOS33;
NET "B2AUX<1>" LOC="13" |FAST |IOSTANDARD=LVCMOS33;

View File

@ -0,0 +1,60 @@
--
-- 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;
library UNISIM;
use UNISIM.vcomponents.all;
entity top is
Port(
SGPIO : inout std_logic_vector(15 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 : in std_logic_vector(16 downto 9);
B2AUX : inout std_logic_vector(16 downto 1)
);
end top;
architecture Behavioral of top is
type transfer_direction is (to_sgpio, from_sgpio);
signal transfer_direction_i : transfer_direction;
begin
transfer_direction_i <= to_sgpio when B1AUX(9) = '0'
else from_sgpio;
DD <= (DD'high => '1', others => '0');
B2AUX <= SGPIO when transfer_direction_i = from_sgpio
else (others => 'Z');
SGPIO <= B2AUX when transfer_direction_i = to_sgpio
else (others => 'Z');
end Behavioral;

View File

@ -0,0 +1,178 @@
# Copyright 2009 Uwe Hermann <uwe@hermann-uwe.de>
# Copyright 2010 Piotr Esden-Tempski <piotr@esden.net>
# Copyright 2012 Michael Ossmann <mike@ossmann.com>
# Copyright 2012 Benjamin Vernoux <titanmkd@gmail.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.
#
# derived primarily from Makefiles in libopencm3
enable_language(C CXX ASM)
SET(PATH_HACKRF ../..)
SET(PATH_HACKRF_FIRMWARE ${PATH_HACKRF}/firmware)
SET(PATH_HACKRF_FIRMWARE_COMMON ${PATH_HACKRF_FIRMWARE}/common)
SET(LIBOPENCM3 ${PATH_HACKRF_FIRMWARE}/libopencm3)
execute_process(
COMMAND git log -n 1 --format=%h
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
RESULT_VARIABLE GIT_VERSION_FOUND
ERROR_QUIET
OUTPUT_VARIABLE GIT_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if (GIT_VERSION_FOUND)
set(VERSION "unknown")
else (GIT_VERSION_FOUND)
set(VERSION ${GIT_VERSION})
endif (GIT_VERSION_FOUND)
if(NOT DEFINED BOARD)
set(BOARD HACKRF_ONE)
endif()
if(NOT DEFINED RUN_FROM)
set(RUN_FROM SPIFI)
endif()
if(BOARD STREQUAL "HACKRF_ONE")
set(MCU_PARTNO LPC4320)
else()
set(MCU_PARTNO LPC4330)
endif()
if(NOT DEFINED SRC_M0)
set(SRC_M0 "${PATH_HACKRF_FIRMWARE_COMMON}/m0_sleep.c")
endif()
SET(HACKRF_OPTS "-D${BOARD} -DLPC43XX -D${MCU_PARTNO} -DTX_ENABLE -D'VERSION_STRING=\"git-${VERSION}\"' -DRUN_FROM=${RUN_FROM}")
SET(LDSCRIPT_M4 "-T${PATH_HACKRF_FIRMWARE_COMMON}/${MCU_PARTNO}_M4_memory.ld")
if( RUN_FROM STREQUAL "RAM")
SET(LDSCRIPT_M4 "${LDSCRIPT_M4} -Tlibopencm3_lpc43xx.ld")
else()
SET(LDSCRIPT_M4 "${LDSCRIPT_M4} -Tlibopencm3_lpc43xx_rom_to_ram.ld")
endif()
SET(LDSCRIPT_M4 "${LDSCRIPT_M4} -T${PATH_HACKRF_FIRMWARE_COMMON}/LPC43xx_M4_M0_image_from_text.ld")
SET(LDSCRIPT_M0 "-T${PATH_HACKRF_FIRMWARE_COMMON}/LPC43xx_M0_memory.ld -Tlibopencm3_lpc43xx_m0.ld")
SET(CFLAGS_COMMON "-Os -g3 -Wall -Wextra ${HACKRF_OPTS} ${COMMON_FLAGS} -fno-common -MD")
SET(LDFLAGS_COMMON "-nostartfiles -Wl,--gc-sections")
if(V STREQUAL "1")
SET(LDFLAGS_COMMON "${LDFLAGS_COMMON} -Wl,--print-gc-sections")
endif()
SET(CPUFLAGS_M0 "-mthumb -mcpu=cortex-m0 -mfloat-abi=soft")
SET(CFLAGS_M0 "-std=gnu99 ${CFLAGS_COMMON} ${CPUFLAGS_M0} -DLPC43XX_M0")
SET(CXXFLAGS_M0 "-std=gnu++0x ${CFLAGS_COMMON} ${CPUFLAGS_M0} -DLPC43XX_M0")
SET(LDFLAGS_M0 "${LDFLAGS_COMMON} ${CPUFLAGS_M0} ${LDSCRIPT_M0} -Xlinker -Map=m0.map --specs=nano.specs")
SET(CPUFLAGS_M4 "-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16")
SET(CFLAGS_M4 "-std=gnu99 ${CFLAGS_COMMON} ${CPUFLAGS_M4} -DLPC43XX_M4")
SET(CXXFLAGS_M4 "-std=gnu++0x ${CFLAGS_COMMON} ${CPUFLAGS_M4} -DLPC43XX_M4")
SET(LDFLAGS_M4 "${LDFLAGS_COMMON} ${CPUFLAGS_M4} ${LDSCRIPT_M4} -Xlinker -Map=m4.map")
set(BUILD_SHARED_LIBS OFF)
include_directories("${LIBOPENCM3}/include/")
include_directories("${PATH_HACKRF_FIRMWARE_COMMON}")
macro(DeclareTargets)
configure_file(
${PATH_HACKRF_FIRMWARE_COMMON}/m0_bin.s.cmake
m0_bin.s
)
link_directories(
"${PATH_HACKRF_FIRMWARE_COMMON}"
"${LIBOPENCM3}/lib"
"${LIBOPENCM3}/lib/lpc43xx"
"${CMAKE_INSTALL_PREFIX}/lib/armv7e-m/fpu"
)
add_executable(${PROJECT_NAME}_m0.elf ${SRC_M0})
target_link_libraries(
${PROJECT_NAME}_m0.elf
c
nosys
opencm3_lpc43xx_m0
)
set_target_properties(${PROJECT_NAME}_m0.elf PROPERTIES COMPILE_FLAGS "${CFLAGS_M0}")
set_target_properties(${PROJECT_NAME}_m0.elf PROPERTIES LINK_FLAGS "${LDFLAGS_M0}")
add_custom_target(
${PROJECT_NAME}_m0.bin
DEPENDS ${PROJECT_NAME}_m0.elf
COMMAND ${CMAKE_OBJCOPY} -Obinary ${PROJECT_NAME}_m0.elf ${PROJECT_NAME}_m0.bin
)
add_executable(${PROJECT_NAME}.elf
${SRC_M4}
${PATH_HACKRF_FIRMWARE_COMMON}/hackrf_core.c
${PATH_HACKRF_FIRMWARE_COMMON}/sgpio.c
${PATH_HACKRF_FIRMWARE_COMMON}/rf_path.c
${PATH_HACKRF_FIRMWARE_COMMON}/si5351c.c
${PATH_HACKRF_FIRMWARE_COMMON}/max2837.c
${PATH_HACKRF_FIRMWARE_COMMON}/max5864.c
${PATH_HACKRF_FIRMWARE_COMMON}/rffc5071.c
m0_bin.s
)
add_dependencies(${PROJECT_NAME}.elf ${PROJECT_NAME}_m0.bin)
target_link_libraries(
${PROJECT_NAME}.elf
c
nosys
opencm3_lpc43xx
m
)
set_target_properties(${PROJECT_NAME}.elf PROPERTIES COMPILE_FLAGS "${CFLAGS_M4}")
set_target_properties(${PROJECT_NAME}.elf PROPERTIES LINK_FLAGS "${LDFLAGS_M4}")
add_custom_target(
${PROJECT_NAME}.bin
DEPENDS ${PROJECT_NAME}.elf
COMMAND ${CMAKE_OBJCOPY} -Obinary ${PROJECT_NAME}.elf ${PROJECT_NAME}.bin
)
add_custom_target(
${PROJECT_NAME}.dfu ALL
DEPENDS ${PROJECT_NAME}.bin
COMMAND rm -f _tmp.dfu _header.bin
COMMAND cp ${PROJECT_NAME}.bin _tmp.dfu
COMMAND dfu-suffix --vid=0x1fc9 --pid=0x000c --did=0x0 -s 0 -a _tmp.dfu
COMMAND python -c \"import os.path\; import struct\; print\('0000000: da ff ' + ' '.join\(map\(lambda s: '%02x' % ord\(s\), struct.pack\('<H', os.path.getsize\('${PROJECT_NAME}.bin'\) / 512 + 1\)\)\) + ' ff ff ff ff'\)\" | xxd -g1 -r > _header.bin
COMMAND cat _header.bin _tmp.dfu >${PROJECT_NAME}.dfu
COMMAND rm -f _tmp.dfu _header.bin
)
add_custom_target(
${PROJECT_NAME}-program
DEPENDS ${PROJECT_NAME}.dfu
COMMAND dfu-util --device 1fc9:000c --alt 0 --download ${PROJECT_NAME}.dfu
)
endmacro()

View File

@ -0,0 +1,55 @@
# 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.
#
cmake_minimum_required(VERSION 2.8.9)
set(CMAKE_TOOLCHAIN_FILE ../toolchain-arm-cortex-m.cmake)
project(hackrf_usb)
include(../hackrf-common.cmake)
set(SRC_M4
hackrf_usb.c
"${PATH_HACKRF_FIRMWARE_COMMON}/tuning.c"
"${PATH_HACKRF_FIRMWARE_COMMON}/streaming.c"
sgpio_isr.c
usb_bulk_buffer.c
"${PATH_HACKRF_FIRMWARE_COMMON}/usb.c"
"${PATH_HACKRF_FIRMWARE_COMMON}/usb_request.c"
"${PATH_HACKRF_FIRMWARE_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
"${PATH_HACKRF_FIRMWARE_COMMON}/usb_queue.c"
"${PATH_HACKRF_FIRMWARE_COMMON}/fault_handler.c"
"${PATH_HACKRF_FIRMWARE_COMMON}/w25q80bv.c"
"${PATH_HACKRF_FIRMWARE_COMMON}/cpld_jtag.c"
"${PATH_HACKRF_FIRMWARE_COMMON}/xapp058/lenval.c"
"${PATH_HACKRF_FIRMWARE_COMMON}/xapp058/micro.c"
"${PATH_HACKRF_FIRMWARE_COMMON}/xapp058/ports.c"
"${PATH_HACKRF_FIRMWARE_COMMON}/rom_iap.c"
)
DeclareTargets()

View File

@ -0,0 +1,286 @@
/*
* 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 <stddef.h>
#include <libopencm3/cm3/vector.h>
#include <libopencm3/lpc43xx/gpio.h>
#include <libopencm3/lpc43xx/m4/nvic.h>
#include <streaming.h>
#include "usb.h"
#include "usb_standard_request.h"
#include <rom_iap.h>
#include "usb_descriptor.h"
#include "usb_device.h"
#include "usb_endpoint.h"
#include "usb_api_board_info.h"
#include "usb_api_cpld.h"
#include "usb_api_register.h"
#include "usb_api_spiflash.h"
#include "usb_api_transceiver.h"
#include "rf_path.h"
#include "sgpio_isr.h"
#include "usb_bulk_buffer.h"
#include "si5351c.h"
static volatile transceiver_mode_t _transceiver_mode = TRANSCEIVER_MODE_OFF;
void set_transceiver_mode(const transceiver_mode_t new_transceiver_mode) {
baseband_streaming_disable();
usb_endpoint_disable(&usb_endpoint_bulk_in);
usb_endpoint_disable(&usb_endpoint_bulk_out);
_transceiver_mode = new_transceiver_mode;
if( _transceiver_mode == TRANSCEIVER_MODE_RX ) {
gpio_clear(PORT_LED1_3, PIN_LED3);
gpio_set(PORT_LED1_3, PIN_LED2);
usb_endpoint_init(&usb_endpoint_bulk_in);
rf_path_set_direction(RF_PATH_DIRECTION_RX);
vector_table.irq[NVIC_SGPIO_IRQ] = sgpio_isr_rx;
} else if (_transceiver_mode == TRANSCEIVER_MODE_TX) {
gpio_clear(PORT_LED1_3, PIN_LED2);
gpio_set(PORT_LED1_3, PIN_LED3);
usb_endpoint_init(&usb_endpoint_bulk_out);
rf_path_set_direction(RF_PATH_DIRECTION_TX);
vector_table.irq[NVIC_SGPIO_IRQ] = sgpio_isr_tx;
} else {
gpio_clear(PORT_LED1_3, PIN_LED2);
gpio_clear(PORT_LED1_3, PIN_LED3);
rf_path_set_direction(RF_PATH_DIRECTION_OFF);
vector_table.irq[NVIC_SGPIO_IRQ] = sgpio_isr_rx;
}
if( _transceiver_mode != TRANSCEIVER_MODE_OFF ) {
si5351c_activate_best_clock_source();
baseband_streaming_enable();
}
}
transceiver_mode_t transceiver_mode(void) {
return _transceiver_mode;
}
usb_request_status_t usb_vendor_request_set_transceiver_mode(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage
) {
if( stage == USB_TRANSFER_STAGE_SETUP ) {
switch( endpoint->setup.value ) {
case TRANSCEIVER_MODE_OFF:
case TRANSCEIVER_MODE_RX:
case TRANSCEIVER_MODE_TX:
set_transceiver_mode(endpoint->setup.value);
usb_transfer_schedule_ack(endpoint->in);
return USB_REQUEST_STATUS_OK;
case TRANSCEIVER_MODE_CPLD_UPDATE:
usb_endpoint_init(&usb_endpoint_bulk_out);
start_cpld_update = true;
usb_transfer_schedule_ack(endpoint->in);
return USB_REQUEST_STATUS_OK;
default:
return USB_REQUEST_STATUS_STALL;
}
} else {
return USB_REQUEST_STATUS_OK;
}
}
static const usb_request_handler_fn vendor_request_handler[] = {
NULL,
usb_vendor_request_set_transceiver_mode,
usb_vendor_request_write_max2837,
usb_vendor_request_read_max2837,
usb_vendor_request_write_si5351c,
usb_vendor_request_read_si5351c,
usb_vendor_request_set_sample_rate_frac,
usb_vendor_request_set_baseband_filter_bandwidth,
usb_vendor_request_write_rffc5071,
usb_vendor_request_read_rffc5071,
usb_vendor_request_erase_spiflash,
usb_vendor_request_write_spiflash,
usb_vendor_request_read_spiflash,
NULL, // used to be write_cpld
usb_vendor_request_read_board_id,
usb_vendor_request_read_version_string,
usb_vendor_request_set_freq,
usb_vendor_request_set_amp_enable,
usb_vendor_request_read_partid_serialno,
usb_vendor_request_set_lna_gain,
usb_vendor_request_set_vga_gain,
usb_vendor_request_set_txvga_gain,
NULL, // was set_if_freq
#ifdef HACKRF_ONE
usb_vendor_request_set_antenna_enable,
#else
NULL,
#endif
usb_vendor_request_set_freq_explicit,
};
static const uint32_t vendor_request_handler_count =
sizeof(vendor_request_handler) / sizeof(vendor_request_handler[0]);
usb_request_status_t usb_vendor_request(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage
) {
usb_request_status_t status = USB_REQUEST_STATUS_STALL;
if( endpoint->setup.request < vendor_request_handler_count ) {
usb_request_handler_fn handler = vendor_request_handler[endpoint->setup.request];
if( handler ) {
status = handler(endpoint, stage);
}
}
return status;
}
const usb_request_handlers_t usb_request_handlers = {
.standard = usb_standard_request,
.class = 0,
.vendor = usb_vendor_request,
.reserved = 0,
};
void usb_configuration_changed(
usb_device_t* const device
) {
/* Reset transceiver to idle state until other commands are received */
set_transceiver_mode(TRANSCEIVER_MODE_OFF);
if( device->configuration->number == 1 ) {
// transceiver configuration
cpu_clock_pll1_max_speed();
gpio_set(PORT_LED1_3, PIN_LED1);
} else if( device->configuration->number == 2 ) {
// CPLD update configuration
cpu_clock_pll1_max_speed();
usb_endpoint_init(&usb_endpoint_bulk_out);
start_cpld_update = true;
} else {
/* Configuration number equal 0 means usb bus reset. */
cpu_clock_pll1_low_speed();
gpio_clear(PORT_LED1_3, PIN_LED1);
}
}
void usb_set_descriptor_by_serial_number(void)
{
iap_cmd_res_t iap_cmd_res;
/* 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) {
usb_descriptor_string_serial_number[0] = USB_DESCRIPTOR_STRING_SERIAL_BUF_LEN;
usb_descriptor_string_serial_number[1] = USB_DESCRIPTOR_TYPE_STRING;
/* 32 characters of serial number, convert to UTF-16LE */
for (size_t i=0; i<USB_DESCRIPTOR_STRING_SERIAL_LEN; i++) {
const uint_fast8_t nibble = (iap_cmd_res.status_res.iap_result[i >> 3] >> (28 - (i & 7) * 4)) & 0xf;
const char c = (nibble > 9) ? ('a' + nibble - 10) : ('0' + nibble);
usb_descriptor_string_serial_number[2 + i * 2] = c;
usb_descriptor_string_serial_number[3 + i * 2] = 0x00;
}
} else {
usb_descriptor_string_serial_number[0] = 2;
usb_descriptor_string_serial_number[1] = USB_DESCRIPTOR_TYPE_STRING;
}
}
int main(void) {
pin_setup();
enable_1v8_power();
#ifdef HACKRF_ONE
enable_rf_power();
#endif
cpu_clock_init();
usb_set_descriptor_by_serial_number();
usb_set_configuration_changed_cb(usb_configuration_changed);
usb_peripheral_reset();
usb_device_init(0, &usb_device);
usb_queue_init(&usb_endpoint_control_out_queue);
usb_queue_init(&usb_endpoint_control_in_queue);
usb_queue_init(&usb_endpoint_bulk_out_queue);
usb_queue_init(&usb_endpoint_bulk_in_queue);
usb_endpoint_init(&usb_endpoint_control_out);
usb_endpoint_init(&usb_endpoint_control_in);
nvic_set_priority(NVIC_USB0_IRQ, 255);
usb_run(&usb_device);
ssp1_init();
rf_path_init();
unsigned int phase = 0;
while(true) {
// Check whether we need to initiate a CPLD update
if (start_cpld_update)
cpld_update();
// Set up IN transfer of buffer 0.
if ( usb_bulk_buffer_offset >= 16384
&& phase == 1
&& transceiver_mode() != TRANSCEIVER_MODE_OFF) {
usb_transfer_schedule_block(
(transceiver_mode() == TRANSCEIVER_MODE_RX)
? &usb_endpoint_bulk_in : &usb_endpoint_bulk_out,
&usb_bulk_buffer[0x0000],
0x4000,
NULL, NULL
);
phase = 0;
}
// Set up IN transfer of buffer 1.
if ( usb_bulk_buffer_offset < 16384
&& phase == 0
&& transceiver_mode() != TRANSCEIVER_MODE_OFF) {
usb_transfer_schedule_block(
(transceiver_mode() == TRANSCEIVER_MODE_RX)
? &usb_endpoint_bulk_in : &usb_endpoint_bulk_out,
&usb_bulk_buffer[0x4000],
0x4000,
NULL, NULL
);
phase = 1;
}
}
return 0;
}

View 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;
}

View 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__*/

View 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;
}

View 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__ */

View File

@ -0,0 +1,96 @@
/*
* 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)
{
(void)user_data;
(void)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);
}
}

View 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__ */

View 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;
}
}

View 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__ */

View 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;
}
}

View 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__ */

View File

@ -0,0 +1,225 @@
/*
* 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;
struct set_freq_explicit_params {
uint64_t if_freq_hz; /* intermediate frequency */
uint64_t lo_freq_hz; /* front-end local oscillator frequency */
uint8_t path; /* image rejection filter path */
};
struct set_freq_explicit_params explicit_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 * 1000000ULL + 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_antenna_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_antenna(0);
usb_transfer_schedule_ack(endpoint->in);
return USB_REQUEST_STATUS_OK;
case 1:
rf_path_set_antenna(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_freq_explicit(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{
if (stage == USB_TRANSFER_STAGE_SETUP) {
usb_transfer_schedule_block(endpoint->out, &explicit_params,
sizeof(struct set_freq_explicit_params), NULL, NULL);
return USB_REQUEST_STATUS_OK;
} else if (stage == USB_TRANSFER_STAGE_DATA) {
if (set_freq_explicit(explicit_params.if_freq_hz,
explicit_params.lo_freq_hz, explicit_params.path)) {
usb_transfer_schedule_ack(endpoint->in);
return USB_REQUEST_STATUS_OK;
}
return USB_REQUEST_STATUS_STALL;
} else {
return USB_REQUEST_STATUS_OK;
}
}

View File

@ -0,0 +1,56 @@
/*
* 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_antenna_enable(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_set_freq_explicit(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
#endif/*__USB_API_TRANSCEIVER_H__*/

View 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;

View 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__*/

View File

@ -0,0 +1,343 @@
/*
* 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.
*/
#include <stdint.h>
#include "usb_type.h"
#include "usb_descriptor.h"
#define USB_VENDOR_ID (0x1D50)
#ifdef HACKRF_ONE
#define USB_PRODUCT_ID (0x6089)
#elif JAWBREAKER
#define USB_PRODUCT_ID (0x604B)
#else
#define USB_PRODUCT_ID (0xFFFF)
#endif
#define USB_WORD(x) (x & 0xFF), ((x >> 8) & 0xFF)
#define USB_MAX_PACKET0 (64)
#define USB_MAX_PACKET_BULK_FS (64)
#define USB_MAX_PACKET_BULK_HS (512)
#define USB_BULK_IN_EP_ADDR (0x81)
#define USB_BULK_OUT_EP_ADDR (0x02)
#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
0x05, // 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
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
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
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
};
uint8_t usb_descriptor_string_manufacturer[] = {
40, // bLength
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
'G', 0x00,
'r', 0x00,
'e', 0x00,
'a', 0x00,
't', 0x00,
' ', 0x00,
'S', 0x00,
'c', 0x00,
'o', 0x00,
't', 0x00,
't', 0x00,
' ', 0x00,
'G', 0x00,
'a', 0x00,
'd', 0x00,
'g', 0x00,
'e', 0x00,
't', 0x00,
's', 0x00,
};
uint8_t usb_descriptor_string_product[] = {
#ifdef HACKRF_ONE
22, // bLength
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
'H', 0x00,
'a', 0x00,
'c', 0x00,
'k', 0x00,
'R', 0x00,
'F', 0x00,
' ', 0x00,
'O', 0x00,
'n', 0x00,
'e', 0x00,
#elif JAWBREAKER
36, // bLength
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
'H', 0x00,
'a', 0x00,
'c', 0x00,
'k', 0x00,
'R', 0x00,
'F', 0x00,
' ', 0x00,
'J', 0x00,
'a', 0x00,
'w', 0x00,
'b', 0x00,
'r', 0x00,
'e', 0x00,
'a', 0x00,
'k', 0x00,
'e', 0x00,
'r', 0x00,
#else
14, // bLength
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
'H', 0x00,
'a', 0x00,
'c', 0x00,
'k', 0x00,
'R', 0x00,
'F', 0x00,
#endif
};
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 usb_descriptor_string_serial_number[USB_DESCRIPTOR_STRING_SERIAL_BUF_LEN];
uint8_t* 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,
usb_descriptor_string_serial_number,
0, // TERMINATOR
};

View File

@ -0,0 +1,38 @@
/*
* 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.
*/
#include <stdint.h>
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[];
#define USB_DESCRIPTOR_STRING_SERIAL_LEN 32
#define USB_DESCRIPTOR_STRING_SERIAL_BUF_LEN (USB_DESCRIPTOR_STRING_SERIAL_LEN*2 + 2) /* UTF-16LE */
extern uint8_t usb_descriptor_string_serial_number[];
extern uint8_t* usb_descriptor_strings[];

View 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,
};

View 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__ */

Some files were not shown because too many files have changed in this diff Show More