Initial commit of files
This commit is contained in:
9
SoftwareDefined/HackRF/hackrf-2015.07.2/firmware/.gitignore
vendored
Normal file
9
SoftwareDefined/HackRF/hackrf-2015.07.2/firmware/.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
*.bin
|
||||
*.d
|
||||
*.elf
|
||||
*.hex
|
||||
*.list
|
||||
*.map
|
||||
*.o
|
||||
*.srec
|
||||
*.dfu
|
||||
@ -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)
|
||||
56
SoftwareDefined/HackRF/hackrf-2015.07.2/firmware/README
Normal file
56
SoftwareDefined/HackRF/hackrf-2015.07.2/firmware/README
Normal 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
|
||||
@ -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()
|
||||
@ -0,0 +1 @@
|
||||
This is the simplest example firmware for HackRF. It flashes three LEDs.
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
@ -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);
|
||||
@ -0,0 +1,2 @@
|
||||
This directory contains things shared by multiple HackRF firmware
|
||||
implementations.
|
||||
@ -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;
|
||||
}
|
||||
@ -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__
|
||||
@ -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;
|
||||
}
|
||||
@ -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__
|
||||
@ -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);
|
||||
}
|
||||
@ -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__
|
||||
@ -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;
|
||||
}
|
||||
@ -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__*/
|
||||
@ -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
|
||||
@ -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 */
|
||||
@ -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"
|
||||
@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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);
|
||||
}
|
||||
@ -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
|
||||
@ -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);
|
||||
}
|
||||
@ -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__*/
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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__
|
||||
312
SoftwareDefined/HackRF/hackrf-2015.07.2/firmware/common/sgpio.c
Normal file
312
SoftwareDefined/HackRF/hackrf-2015.07.2/firmware/common/sgpio.c
Normal 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;
|
||||
}
|
||||
}
|
||||
@ -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__
|
||||
@ -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;
|
||||
}
|
||||
@ -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__*/
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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 */
|
||||
@ -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);
|
||||
}
|
||||
@ -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__*/
|
||||
142
SoftwareDefined/HackRF/hackrf-2015.07.2/firmware/common/tuning.c
Normal file
142
SoftwareDefined/HackRF/hackrf-2015.07.2/firmware/common/tuning.c
Normal 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;
|
||||
}
|
||||
@ -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__*/
|
||||
660
SoftwareDefined/HackRF/hackrf-2015.07.2/firmware/common/usb.c
Normal file
660
SoftwareDefined/HackRF/hackrf-2015.07.2/firmware/common/usb.c
Normal 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.
|
||||
}
|
||||
}
|
||||
@ -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__
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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__
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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__
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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__
|
||||
@ -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__
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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__
|
||||
@ -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.
|
||||
@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
@ -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 */
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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.
|
||||
Binary file not shown.
@ -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
|
||||
@ -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="<>" 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 & 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>
|
||||
@ -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
|
||||
@ -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";
|
||||
@ -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;
|
||||
@ -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;
|
||||
@ -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]
|
||||
@ -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
|
||||
File diff suppressed because it is too large
Load Diff
@ -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="<>" 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 & 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>
|
||||
@ -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;
|
||||
@ -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;
|
||||
@ -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()
|
||||
@ -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()
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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__*/
|
||||
@ -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;
|
||||
}
|
||||
@ -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__ */
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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__ */
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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__ */
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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__ */
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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__*/
|
||||
@ -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;
|
||||
@ -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__*/
|
||||
@ -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
|
||||
};
|
||||
@ -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[];
|
||||
@ -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,
|
||||
};
|
||||
@ -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
Reference in New Issue
Block a user