Merge pull request #233 from mossmann/jboone-abstract_buses
Abstract buses
This commit is contained in:
@ -19,13 +19,8 @@
|
|||||||
* Boston, MA 02110-1301, USA.
|
* Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <libopencm3/lpc43xx/gpio.h>
|
|
||||||
#include <libopencm3/lpc43xx/scu.h>
|
|
||||||
|
|
||||||
#include "hackrf_core.h"
|
#include "hackrf_core.h"
|
||||||
|
|
||||||
uint32_t boot0, boot1, boot2, boot3;
|
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -34,18 +29,20 @@ int main(void)
|
|||||||
/* enable all power supplies */
|
/* enable all power supplies */
|
||||||
enable_1v8_power();
|
enable_1v8_power();
|
||||||
|
|
||||||
/* Blink LED1/2/3 on the board and Read BOOT0/1/2/3 pins. */
|
/* Blink LED1/2/3 on the board. */
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
boot0 = BOOT0_STATE;
|
led_on(LED1);
|
||||||
boot1 = BOOT1_STATE;
|
led_on(LED2);
|
||||||
boot2 = BOOT2_STATE;
|
led_on(LED3);
|
||||||
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. */
|
for (i = 0; i < 2000000; i++) /* Wait a bit. */
|
||||||
__asm__("nop");
|
__asm__("nop");
|
||||||
gpio_clear(PORT_LED1_3, (PIN_LED1|PIN_LED2|PIN_LED3)); /* LED off */
|
|
||||||
|
led_off(LED1);
|
||||||
|
led_off(LED2);
|
||||||
|
led_off(LED3);
|
||||||
|
|
||||||
for (i = 0; i < 2000000; i++) /* Wait a bit. */
|
for (i = 0; i < 2000000; i++) /* Wait a bit. */
|
||||||
__asm__("nop");
|
__asm__("nop");
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,6 @@
|
|||||||
#include "cpld_jtag.h"
|
#include "cpld_jtag.h"
|
||||||
#include "hackrf_core.h"
|
#include "hackrf_core.h"
|
||||||
#include "xapp058/micro.h"
|
#include "xapp058/micro.h"
|
||||||
#include <libopencm3/lpc43xx/gpio.h>
|
|
||||||
#include <libopencm3/lpc43xx/scu.h>
|
#include <libopencm3/lpc43xx/scu.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
@ -30,47 +29,45 @@ static refill_buffer_cb refill_buffer;
|
|||||||
static uint32_t xsvf_buffer_len, xsvf_pos;
|
static uint32_t xsvf_buffer_len, xsvf_pos;
|
||||||
static unsigned char* xsvf_buffer;
|
static unsigned char* xsvf_buffer;
|
||||||
|
|
||||||
void cpld_jtag_setup(void) {
|
void cpld_jtag_setup(jtag_t* const jtag) {
|
||||||
scu_pinmux(SCU_PINMUX_CPLD_TDO, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION4);
|
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_TCK, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0);
|
||||||
scu_pinmux(SCU_PINMUX_CPLD_TMS, 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);
|
scu_pinmux(SCU_PINMUX_CPLD_TDI, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0);
|
||||||
|
|
||||||
/* TDO is an input */
|
gpio_input(jtag->gpio->gpio_tdo);
|
||||||
GPIO_DIR(PORT_CPLD_TDO) &= ~PIN_CPLD_TDO;
|
gpio_output(jtag->gpio->gpio_tck);
|
||||||
|
gpio_output(jtag->gpio->gpio_tms);
|
||||||
/* the rest are outputs */
|
gpio_output(jtag->gpio->gpio_tdi);
|
||||||
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 */
|
/* set pins as inputs so we don't interfere with an external JTAG device */
|
||||||
void cpld_jtag_release(void) {
|
void cpld_jtag_release(jtag_t* const jtag) {
|
||||||
scu_pinmux(SCU_PINMUX_CPLD_TDO, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION4);
|
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_TCK, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0);
|
||||||
scu_pinmux(SCU_PINMUX_CPLD_TMS, 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);
|
scu_pinmux(SCU_PINMUX_CPLD_TDI, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0);
|
||||||
|
|
||||||
GPIO_DIR(PORT_CPLD_TDO) &= ~PIN_CPLD_TDO;
|
gpio_input(jtag->gpio->gpio_tdo);
|
||||||
GPIO_DIR(PORT_CPLD_TCK) &= ~PIN_CPLD_TCK;
|
gpio_input(jtag->gpio->gpio_tck);
|
||||||
GPIO_DIR(PORT_CPLD_TMS) &= ~PIN_CPLD_TMS;
|
gpio_input(jtag->gpio->gpio_tms);
|
||||||
GPIO_DIR(PORT_CPLD_TDI) &= ~PIN_CPLD_TDI;
|
gpio_input(jtag->gpio->gpio_tdi);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return 0 if success else return error code see xsvfExecute() */
|
/* return 0 if success else return error code see xsvfExecute() */
|
||||||
int cpld_jtag_program(
|
int cpld_jtag_program(
|
||||||
|
jtag_t* const jtag,
|
||||||
const uint32_t buffer_length,
|
const uint32_t buffer_length,
|
||||||
unsigned char* const buffer,
|
unsigned char* const buffer,
|
||||||
refill_buffer_cb refill
|
refill_buffer_cb refill
|
||||||
) {
|
) {
|
||||||
int error;
|
int error;
|
||||||
cpld_jtag_setup();
|
cpld_jtag_setup(jtag);
|
||||||
xsvf_buffer = buffer;
|
xsvf_buffer = buffer;
|
||||||
xsvf_buffer_len = buffer_length;
|
xsvf_buffer_len = buffer_length;
|
||||||
refill_buffer = refill;
|
refill_buffer = refill;
|
||||||
error = xsvfExecute();
|
error = xsvfExecute(jtag->gpio);
|
||||||
cpld_jtag_release();
|
cpld_jtag_release(jtag);
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -24,9 +24,22 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "gpio.h"
|
||||||
|
|
||||||
|
typedef struct jtag_gpio_t {
|
||||||
|
gpio_t gpio_tms;
|
||||||
|
gpio_t gpio_tck;
|
||||||
|
gpio_t gpio_tdi;
|
||||||
|
gpio_t gpio_tdo;
|
||||||
|
} jtag_gpio_t;
|
||||||
|
|
||||||
|
typedef struct jtag_t {
|
||||||
|
jtag_gpio_t* const gpio;
|
||||||
|
} jtag_t;
|
||||||
|
|
||||||
typedef void (*refill_buffer_cb)(void);
|
typedef void (*refill_buffer_cb)(void);
|
||||||
|
|
||||||
void cpld_jtag_release(void);
|
void cpld_jtag_release(jtag_t* const jtag);
|
||||||
|
|
||||||
/* Return 0 if success else return error code see xsvfExecute() see micro.h.
|
/* Return 0 if success else return error code see xsvfExecute() see micro.h.
|
||||||
*
|
*
|
||||||
@ -34,6 +47,7 @@ void cpld_jtag_release(void);
|
|||||||
* contents of the buffer has been streamed to the CPLD the given
|
* contents of the buffer has been streamed to the CPLD the given
|
||||||
* refill_buffer callback will be called. */
|
* refill_buffer callback will be called. */
|
||||||
int cpld_jtag_program(
|
int cpld_jtag_program(
|
||||||
|
jtag_t* const jtag,
|
||||||
const uint32_t buffer_length,
|
const uint32_t buffer_length,
|
||||||
unsigned char* const buffer,
|
unsigned char* const buffer,
|
||||||
refill_buffer_cb refill
|
refill_buffer_cb refill
|
||||||
|
38
firmware/common/gpio.h
Normal file
38
firmware/common/gpio.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
||||||
|
*
|
||||||
|
* 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 __GPIO_H__
|
||||||
|
#define __GPIO_H__
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
typedef const struct gpio_t* gpio_t;
|
||||||
|
|
||||||
|
void gpio_init();
|
||||||
|
void gpio_set(gpio_t gpio);
|
||||||
|
void gpio_clear(gpio_t gpio);
|
||||||
|
void gpio_toggle(gpio_t gpio);
|
||||||
|
void gpio_output(gpio_t gpio);
|
||||||
|
void gpio_input(gpio_t gpio);
|
||||||
|
void gpio_write(gpio_t gpio, const bool value);
|
||||||
|
bool gpio_read(gpio_t gpio);
|
||||||
|
|
||||||
|
#endif/*__GPIO_H__*/
|
58
firmware/common/gpio_lpc.c
Normal file
58
firmware/common/gpio_lpc.c
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
||||||
|
*
|
||||||
|
* 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 "gpio_lpc.h"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
void gpio_init() {
|
||||||
|
for(size_t i=0; i<8; i++) {
|
||||||
|
GPIO_LPC_PORT(i)->dir = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void gpio_set(gpio_t gpio) {
|
||||||
|
gpio->port->set = gpio->mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gpio_clear(gpio_t gpio) {
|
||||||
|
gpio->port->clr = gpio->mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gpio_toggle(gpio_t gpio) {
|
||||||
|
gpio->port->not = gpio->mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gpio_output(gpio_t gpio) {
|
||||||
|
gpio->port->dir |= gpio->mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gpio_input(gpio_t gpio) {
|
||||||
|
gpio->port->dir &= ~gpio->mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gpio_write(gpio_t gpio, const bool value) {
|
||||||
|
*gpio->gpio_w = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gpio_read(gpio_t gpio) {
|
||||||
|
return *gpio->gpio_w;
|
||||||
|
}
|
70
firmware/common/gpio_lpc.h
Normal file
70
firmware/common/gpio_lpc.h
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
||||||
|
*
|
||||||
|
* 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 __GPIO_LPC_H__
|
||||||
|
#define __GPIO_LPC_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "gpio.h"
|
||||||
|
|
||||||
|
/* NOTE: libopencm3 constants and functions not used here due to naming
|
||||||
|
* conflicts. I'd recommend changes to libopencm3 design to separate
|
||||||
|
* register #defines and API declarations into separate header files.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct gpio_port_t {
|
||||||
|
volatile uint32_t dir; /* +0x000 */
|
||||||
|
uint32_t _reserved0[31];
|
||||||
|
volatile uint32_t mask; /* +0x080 */
|
||||||
|
uint32_t _reserved1[31];
|
||||||
|
volatile uint32_t pin; /* +0x100 */
|
||||||
|
uint32_t _reserved2[31];
|
||||||
|
volatile uint32_t mpin; /* +0x180 */
|
||||||
|
uint32_t _reserved3[31];
|
||||||
|
volatile uint32_t set; /* +0x200 */
|
||||||
|
uint32_t _reserved4[31];
|
||||||
|
volatile uint32_t clr; /* +0x280 */
|
||||||
|
uint32_t _reserved5[31];
|
||||||
|
volatile uint32_t not; /* +0x300 */
|
||||||
|
} gpio_port_t;
|
||||||
|
|
||||||
|
struct gpio_t {
|
||||||
|
const uint32_t mask;
|
||||||
|
gpio_port_t* const port;
|
||||||
|
volatile uint32_t* const gpio_w;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GPIO_LPC_BASE (0x400f4000)
|
||||||
|
#define GPIO_LPC_B_OFFSET (0x0)
|
||||||
|
#define GPIO_LPC_W_OFFSET (0x1000)
|
||||||
|
#define GPIO_LPC_PORT_OFFSET (0x2000)
|
||||||
|
|
||||||
|
#define GPIO_LPC_PORT(_n) ((gpio_port_t*)((GPIO_LPC_BASE + GPIO_LPC_PORT_OFFSET) + (_n) * 4))
|
||||||
|
#define GPIO_LPC_W(_port_num, _pin_num) (volatile uint32_t*)((GPIO_LPC_BASE + GPIO_LPC_W_OFFSET) + ((_port_num) * 0x80) + ((_pin_num) * 4))
|
||||||
|
|
||||||
|
#define GPIO(_port_num, _pin_num) { \
|
||||||
|
.mask = (1UL << (_pin_num)), \
|
||||||
|
.port = GPIO_LPC_PORT(_port_num), \
|
||||||
|
.gpio_w = GPIO_LPC_W(_port_num, _pin_num), \
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif/*__GPIO_LPC_H__*/
|
@ -23,18 +23,295 @@
|
|||||||
|
|
||||||
#include "hackrf_core.h"
|
#include "hackrf_core.h"
|
||||||
#include "si5351c.h"
|
#include "si5351c.h"
|
||||||
|
#include "spi_ssp.h"
|
||||||
#include "max2837.h"
|
#include "max2837.h"
|
||||||
|
#include "max2837_target.h"
|
||||||
|
#include "max5864.h"
|
||||||
|
#include "max5864_target.h"
|
||||||
#include "rffc5071.h"
|
#include "rffc5071.h"
|
||||||
#include "sgpio.h"
|
#include "rffc5071_spi.h"
|
||||||
#include "rf_path.h"
|
#include "w25q80bv.h"
|
||||||
#include <libopencm3/lpc43xx/i2c.h>
|
#include "w25q80bv_target.h"
|
||||||
|
#include "i2c_bus.h"
|
||||||
|
#include "i2c_lpc.h"
|
||||||
#include <libopencm3/lpc43xx/cgu.h>
|
#include <libopencm3/lpc43xx/cgu.h>
|
||||||
#include <libopencm3/lpc43xx/gpio.h>
|
|
||||||
#include <libopencm3/lpc43xx/scu.h>
|
#include <libopencm3/lpc43xx/scu.h>
|
||||||
#include <libopencm3/lpc43xx/ssp.h>
|
#include <libopencm3/lpc43xx/ssp.h>
|
||||||
|
|
||||||
|
#include "gpio_lpc.h"
|
||||||
|
|
||||||
|
/* TODO: Consolidate ARRAY_SIZE declarations */
|
||||||
|
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||||
|
|
||||||
#define WAIT_CPU_CLOCK_INIT_DELAY (10000)
|
#define WAIT_CPU_CLOCK_INIT_DELAY (10000)
|
||||||
|
|
||||||
|
/* GPIO Output PinMux */
|
||||||
|
static struct gpio_t gpio_led[3] = {
|
||||||
|
GPIO(2, 1),
|
||||||
|
GPIO(2, 2),
|
||||||
|
GPIO(2, 8)
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct gpio_t gpio_1v8_enable = GPIO(3, 6);
|
||||||
|
|
||||||
|
/* MAX2837 GPIO (XCVR_CTL) PinMux */
|
||||||
|
static struct gpio_t gpio_max2837_select = GPIO(0, 15);
|
||||||
|
static struct gpio_t gpio_max2837_enable = GPIO(2, 6);
|
||||||
|
static struct gpio_t gpio_max2837_rx_enable = GPIO(2, 5);
|
||||||
|
static struct gpio_t gpio_max2837_tx_enable = GPIO(2, 4);
|
||||||
|
#ifdef JELLYBEAN
|
||||||
|
static struct gpio_t gpio_max2837_rxhp = GPIO(2, 0);
|
||||||
|
static struct gpio_t gpio_max2837_b1 = GPIO(2, 9);
|
||||||
|
static struct gpio_t gpio_max2837_b2 = GPIO(2, 10);
|
||||||
|
static struct gpio_t gpio_max2837_b3 = GPIO(2, 11);
|
||||||
|
static struct gpio_t gpio_max2837_b4 = GPIO(2, 12);
|
||||||
|
static struct gpio_t gpio_max2837_b5 = GPIO(2, 13);
|
||||||
|
static struct gpio_t gpio_max2837_b6 = GPIO(2, 14);
|
||||||
|
static struct gpio_t gpio_max2837_b7 = GPIO(2, 15);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* MAX5864 SPI chip select (AD_CS) GPIO PinMux */
|
||||||
|
static struct gpio_t gpio_max5864_select = GPIO(2, 7);
|
||||||
|
|
||||||
|
/* RFFC5071 GPIO serial interface PinMux */
|
||||||
|
#ifdef JELLYBEAN
|
||||||
|
static struct gpio_t gpio_rffc5072_select = GPIO(3, 8);
|
||||||
|
static struct gpio_t gpio_rffc5072_clock = GPIO(3, 9);
|
||||||
|
static struct gpio_t gpio_rffc5072_data = GPIO(3, 10);
|
||||||
|
static struct gpio_t gpio_rffc5072_reset = GPIO(3, 11);
|
||||||
|
#endif
|
||||||
|
#if (defined JAWBREAKER || defined HACKRF_ONE)
|
||||||
|
static struct gpio_t gpio_rffc5072_select = GPIO(2, 13);
|
||||||
|
static struct gpio_t gpio_rffc5072_clock = GPIO(5, 6);
|
||||||
|
static struct gpio_t gpio_rffc5072_data = GPIO(3, 3);
|
||||||
|
static struct gpio_t gpio_rffc5072_reset = GPIO(2, 14);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* RF LDO control */
|
||||||
|
#ifdef JAWBREAKER
|
||||||
|
static struct gpio_t gpio_rf_ldo_enable = GPIO(2, 9);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* RF supply (VAA) control */
|
||||||
|
#ifdef HACKRF_ONE
|
||||||
|
static struct gpio_t gpio_vaa_disable = GPIO(2, 9);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static struct gpio_t gpio_w25q80bv_hold = GPIO(1, 14);
|
||||||
|
static struct gpio_t gpio_w25q80bv_wp = GPIO(1, 15);
|
||||||
|
static struct gpio_t gpio_w25q80bv_select = GPIO(5, 11);
|
||||||
|
|
||||||
|
/* RF switch control */
|
||||||
|
#ifdef HACKRF_ONE
|
||||||
|
static struct gpio_t gpio_hp = GPIO(2, 0);
|
||||||
|
static struct gpio_t gpio_lp = GPIO(2, 10);
|
||||||
|
static struct gpio_t gpio_tx_mix_bp = GPIO(2, 11);
|
||||||
|
static struct gpio_t gpio_no_mix_bypass = GPIO(1, 0);
|
||||||
|
static struct gpio_t gpio_rx_mix_bp = GPIO(2, 12);
|
||||||
|
static struct gpio_t gpio_tx_amp = GPIO(2, 15);
|
||||||
|
static struct gpio_t gpio_tx = GPIO(5, 15);
|
||||||
|
static struct gpio_t gpio_mix_bypass = GPIO(5, 16);
|
||||||
|
static struct gpio_t gpio_rx = GPIO(5, 5);
|
||||||
|
static struct gpio_t gpio_no_tx_amp_pwr = GPIO(3, 5);
|
||||||
|
static struct gpio_t gpio_amp_bypass = GPIO(0, 14);
|
||||||
|
static struct gpio_t gpio_rx_amp = GPIO(1, 11);
|
||||||
|
static struct gpio_t gpio_no_rx_amp_pwr = GPIO(1, 12);
|
||||||
|
#endif
|
||||||
|
#if 0
|
||||||
|
/* GPIO Input */
|
||||||
|
static struct gpio_t gpio_boot[] = {
|
||||||
|
GPIO(0, 8),
|
||||||
|
GPIO(0, 9),
|
||||||
|
GPIO(5, 7),
|
||||||
|
GPIO(1, 10),
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
/* CPLD JTAG interface GPIO pins */
|
||||||
|
static struct gpio_t gpio_cpld_tdo = GPIO(5, 18);
|
||||||
|
static struct gpio_t gpio_cpld_tck = GPIO(3, 0);
|
||||||
|
#ifdef HACKRF_ONE
|
||||||
|
static struct gpio_t gpio_cpld_tms = GPIO(3, 4);
|
||||||
|
static struct gpio_t gpio_cpld_tdi = GPIO(3, 1);
|
||||||
|
#else
|
||||||
|
static struct gpio_t gpio_cpld_tms = GPIO(3, 1);
|
||||||
|
static struct gpio_t gpio_cpld_tdi = GPIO(3, 4);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static struct gpio_t gpio_rx_decimation[3] = {
|
||||||
|
GPIO(5, 12),
|
||||||
|
GPIO(5, 13),
|
||||||
|
GPIO(5, 14),
|
||||||
|
};
|
||||||
|
static struct gpio_t gpio_rx_q_invert = GPIO(0, 13);
|
||||||
|
|
||||||
|
i2c_bus_t i2c0 = {
|
||||||
|
.obj = (void*)I2C0_BASE,
|
||||||
|
.start = i2c_lpc_start,
|
||||||
|
.stop = i2c_lpc_stop,
|
||||||
|
.transfer = i2c_lpc_transfer,
|
||||||
|
};
|
||||||
|
|
||||||
|
i2c_bus_t i2c1 = {
|
||||||
|
.obj = (void*)I2C1_BASE,
|
||||||
|
.start = i2c_lpc_start,
|
||||||
|
.stop = i2c_lpc_stop,
|
||||||
|
.transfer = i2c_lpc_transfer,
|
||||||
|
};
|
||||||
|
|
||||||
|
const i2c_lpc_config_t i2c_config_si5351c_slow_clock = {
|
||||||
|
.duty_cycle_count = 15,
|
||||||
|
};
|
||||||
|
|
||||||
|
const i2c_lpc_config_t i2c_config_si5351c_fast_clock = {
|
||||||
|
.duty_cycle_count = 255,
|
||||||
|
};
|
||||||
|
|
||||||
|
si5351c_driver_t clock_gen = {
|
||||||
|
.bus = &i2c0,
|
||||||
|
.i2c_address = 0x60,
|
||||||
|
};
|
||||||
|
|
||||||
|
const ssp_config_t ssp_config_max2837 = {
|
||||||
|
/* 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
|
||||||
|
.data_bits = SSP_DATA_16BITS,
|
||||||
|
.serial_clock_rate = 21,
|
||||||
|
.clock_prescale_rate = 2,
|
||||||
|
.gpio_select = &gpio_max2837_select,
|
||||||
|
};
|
||||||
|
|
||||||
|
const ssp_config_t ssp_config_max5864 = {
|
||||||
|
/* 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
|
||||||
|
.data_bits = SSP_DATA_8BITS,
|
||||||
|
.serial_clock_rate = 21,
|
||||||
|
.clock_prescale_rate = 2,
|
||||||
|
.gpio_select = &gpio_max5864_select,
|
||||||
|
};
|
||||||
|
|
||||||
|
spi_bus_t spi_bus_ssp1 = {
|
||||||
|
.obj = (void*)SSP1_BASE,
|
||||||
|
.config = &ssp_config_max2837,
|
||||||
|
.start = spi_ssp_start,
|
||||||
|
.stop = spi_ssp_stop,
|
||||||
|
.transfer = spi_ssp_transfer,
|
||||||
|
.transfer_gather = spi_ssp_transfer_gather,
|
||||||
|
};
|
||||||
|
|
||||||
|
max2837_driver_t max2837 = {
|
||||||
|
.bus = &spi_bus_ssp1,
|
||||||
|
.gpio_enable = &gpio_max2837_enable,
|
||||||
|
.gpio_rx_enable = &gpio_max2837_rx_enable,
|
||||||
|
.gpio_tx_enable = &gpio_max2837_tx_enable,
|
||||||
|
#ifdef JELLYBEAN
|
||||||
|
.gpio_rxhp = &gpio_max2837_rxhp,
|
||||||
|
.gpio_b1 = &gpio_max2837_b1,
|
||||||
|
.gpio_b2 = &gpio_max2837_b2,
|
||||||
|
.gpio_b3 = &gpio_max2837_b3,
|
||||||
|
.gpio_b4 = &gpio_max2837_b4,
|
||||||
|
.gpio_b5 = &gpio_max2837_b5,
|
||||||
|
.gpio_b6 = &gpio_max2837_b6,
|
||||||
|
.gpio_b7 = &gpio_max2837_b7,
|
||||||
|
#endif
|
||||||
|
.target_init = max2837_target_init,
|
||||||
|
.set_mode = max2837_target_set_mode,
|
||||||
|
};
|
||||||
|
|
||||||
|
max5864_driver_t max5864 = {
|
||||||
|
.bus = &spi_bus_ssp1,
|
||||||
|
.target_init = max5864_target_init,
|
||||||
|
};
|
||||||
|
|
||||||
|
const rffc5071_spi_config_t rffc5071_spi_config = {
|
||||||
|
.gpio_select = &gpio_rffc5072_select,
|
||||||
|
.gpio_clock = &gpio_rffc5072_clock,
|
||||||
|
.gpio_data = &gpio_rffc5072_data,
|
||||||
|
};
|
||||||
|
|
||||||
|
spi_bus_t spi_bus_rffc5071 = {
|
||||||
|
.config = &rffc5071_spi_config,
|
||||||
|
.start = rffc5071_spi_start,
|
||||||
|
.stop = rffc5071_spi_stop,
|
||||||
|
.transfer = rffc5071_spi_transfer,
|
||||||
|
.transfer_gather = rffc5071_spi_transfer_gather,
|
||||||
|
};
|
||||||
|
|
||||||
|
rffc5071_driver_t rffc5072 = {
|
||||||
|
.bus = &spi_bus_rffc5071,
|
||||||
|
.gpio_reset = &gpio_rffc5072_reset,
|
||||||
|
};
|
||||||
|
|
||||||
|
const ssp_config_t ssp_config_w25q80bv = {
|
||||||
|
.data_bits = SSP_DATA_8BITS,
|
||||||
|
.serial_clock_rate = 2,
|
||||||
|
.clock_prescale_rate = 2,
|
||||||
|
.gpio_select = &gpio_w25q80bv_select,
|
||||||
|
};
|
||||||
|
|
||||||
|
spi_bus_t spi_bus_ssp0 = {
|
||||||
|
.obj = (void*)SSP0_BASE,
|
||||||
|
.config = &ssp_config_w25q80bv,
|
||||||
|
.start = spi_ssp_start,
|
||||||
|
.stop = spi_ssp_stop,
|
||||||
|
.transfer = spi_ssp_transfer,
|
||||||
|
.transfer_gather = spi_ssp_transfer_gather,
|
||||||
|
};
|
||||||
|
|
||||||
|
w25q80bv_driver_t spi_flash = {
|
||||||
|
.bus = &spi_bus_ssp0,
|
||||||
|
.gpio_hold = &gpio_w25q80bv_hold,
|
||||||
|
.gpio_wp = &gpio_w25q80bv_wp,
|
||||||
|
.target_init = w25q80bv_target_init,
|
||||||
|
};
|
||||||
|
|
||||||
|
sgpio_config_t sgpio_config = {
|
||||||
|
.gpio_rx_q_invert = &gpio_rx_q_invert,
|
||||||
|
.gpio_rx_decimation = {
|
||||||
|
&gpio_rx_decimation[0],
|
||||||
|
&gpio_rx_decimation[1],
|
||||||
|
&gpio_rx_decimation[2],
|
||||||
|
},
|
||||||
|
.slice_mode_multislice = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
rf_path_t rf_path = {
|
||||||
|
.switchctrl = 0,
|
||||||
|
.gpio_hp = &gpio_hp,
|
||||||
|
.gpio_lp = &gpio_lp,
|
||||||
|
.gpio_tx_mix_bp = &gpio_tx_mix_bp,
|
||||||
|
.gpio_no_mix_bypass = &gpio_no_mix_bypass,
|
||||||
|
.gpio_rx_mix_bp = &gpio_rx_mix_bp,
|
||||||
|
.gpio_tx_amp = &gpio_tx_amp,
|
||||||
|
.gpio_tx = &gpio_tx,
|
||||||
|
.gpio_mix_bypass = &gpio_mix_bypass,
|
||||||
|
.gpio_rx = &gpio_rx,
|
||||||
|
.gpio_no_tx_amp_pwr = &gpio_no_tx_amp_pwr,
|
||||||
|
.gpio_amp_bypass = &gpio_amp_bypass,
|
||||||
|
.gpio_rx_amp = &gpio_rx_amp,
|
||||||
|
.gpio_no_rx_amp_pwr = &gpio_no_rx_amp_pwr,
|
||||||
|
};
|
||||||
|
|
||||||
|
jtag_gpio_t jtag_gpio_cpld = {
|
||||||
|
.gpio_tms = &gpio_cpld_tms,
|
||||||
|
.gpio_tck = &gpio_cpld_tck,
|
||||||
|
.gpio_tdi = &gpio_cpld_tdi,
|
||||||
|
.gpio_tdo = &gpio_cpld_tdo,
|
||||||
|
};
|
||||||
|
|
||||||
|
jtag_t jtag_cpld = {
|
||||||
|
.gpio = &jtag_gpio_cpld,
|
||||||
|
};
|
||||||
|
|
||||||
void delay(uint32_t duration)
|
void delay(uint32_t duration)
|
||||||
{
|
{
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
@ -118,9 +395,9 @@ bool sample_rate_frac_set(uint32_t rate_num, uint32_t rate_denom)
|
|||||||
|
|
||||||
/* Can we enable integer mode ? */
|
/* Can we enable integer mode ? */
|
||||||
if (a & 0x1 || b)
|
if (a & 0x1 || b)
|
||||||
si5351c_set_int_mode(0, 0);
|
si5351c_set_int_mode(&clock_gen, 0, 0);
|
||||||
else
|
else
|
||||||
si5351c_set_int_mode(0, 1);
|
si5351c_set_int_mode(&clock_gen, 0, 1);
|
||||||
|
|
||||||
/* Final MS values */
|
/* Final MS values */
|
||||||
MSx_P1 = 128*a + (128 * b/c) - 512;
|
MSx_P1 = 128*a + (128 * b/c) - 512;
|
||||||
@ -128,13 +405,13 @@ bool sample_rate_frac_set(uint32_t rate_num, uint32_t rate_denom)
|
|||||||
MSx_P3 = c;
|
MSx_P3 = c;
|
||||||
|
|
||||||
/* MS0/CLK0 is the source for the MAX5864/CPLD (CODEC_CLK). */
|
/* MS0/CLK0 is the source for the MAX5864/CPLD (CODEC_CLK). */
|
||||||
si5351c_configure_multisynth(0, MSx_P1, MSx_P2, MSx_P3, 1);
|
si5351c_configure_multisynth(&clock_gen, 0, MSx_P1, MSx_P2, MSx_P3, 1);
|
||||||
|
|
||||||
/* MS0/CLK1 is the source for the CPLD (CODEC_X2_CLK). */
|
/* MS0/CLK1 is the source for the CPLD (CODEC_X2_CLK). */
|
||||||
si5351c_configure_multisynth(1, 0, 0, 0, 0);//p1 doesn't matter
|
si5351c_configure_multisynth(&clock_gen, 1, 0, 0, 0, 0);//p1 doesn't matter
|
||||||
|
|
||||||
/* MS0/CLK2 is the source for SGPIO (CODEC_X2_CLK) */
|
/* MS0/CLK2 is the source for SGPIO (CODEC_X2_CLK) */
|
||||||
si5351c_configure_multisynth(2, 0, 0, 0, 0);//p1 doesn't matter
|
si5351c_configure_multisynth(&clock_gen, 2, 0, 0, 0, 0);//p1 doesn't matter
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -174,13 +451,13 @@ bool sample_rate_set(const uint32_t sample_rate_hz) {
|
|||||||
* values are irrelevant. */
|
* values are irrelevant. */
|
||||||
|
|
||||||
/* MS0/CLK1 is the source for the MAX5864 codec. */
|
/* MS0/CLK1 is the source for the MAX5864 codec. */
|
||||||
si5351c_configure_multisynth(1, 4608, 0, 1, r_div_sample);
|
si5351c_configure_multisynth(&clock_gen, 1, 4608, 0, 1, r_div_sample);
|
||||||
|
|
||||||
/* MS0/CLK2 is the source for the CPLD codec clock (same as CLK1). */
|
/* MS0/CLK2 is the source for the CPLD codec clock (same as CLK1). */
|
||||||
si5351c_configure_multisynth(2, 4608, 0, 1, r_div_sample);
|
si5351c_configure_multisynth(&clock_gen, 2, 4608, 0, 1, r_div_sample);
|
||||||
|
|
||||||
/* MS0/CLK3 is the source for the SGPIO clock. */
|
/* MS0/CLK3 is the source for the SGPIO clock. */
|
||||||
si5351c_configure_multisynth(3, 4608, 0, 1, r_div_sgpio);
|
si5351c_configure_multisynth(&clock_gen, 3, 4608, 0, 1, r_div_sgpio);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
@ -237,20 +514,20 @@ bool sample_rate_set(const uint32_t sample_rate_hz) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* MS0/CLK0 is the source for the MAX5864/CPLD (CODEC_CLK). */
|
/* MS0/CLK0 is the source for the MAX5864/CPLD (CODEC_CLK). */
|
||||||
si5351c_configure_multisynth(0, p1, p2, p3, 1);
|
si5351c_configure_multisynth(&clock_gen, 0, p1, p2, p3, 1);
|
||||||
|
|
||||||
/* MS0/CLK1 is the source for the CPLD (CODEC_X2_CLK). */
|
/* MS0/CLK1 is the source for the CPLD (CODEC_X2_CLK). */
|
||||||
si5351c_configure_multisynth(1, p1, 0, 1, 0);//p1 doesn't matter
|
si5351c_configure_multisynth(&clock_gen, 1, p1, 0, 1, 0);//p1 doesn't matter
|
||||||
|
|
||||||
/* MS0/CLK2 is the source for SGPIO (CODEC_X2_CLK) */
|
/* MS0/CLK2 is the source for SGPIO (CODEC_X2_CLK) */
|
||||||
si5351c_configure_multisynth(2, p1, 0, 1, 0);//p1 doesn't matter
|
si5351c_configure_multisynth(&clock_gen, 2, p1, 0, 1, 0);//p1 doesn't matter
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool baseband_filter_bandwidth_set(const uint32_t bandwidth_hz) {
|
bool baseband_filter_bandwidth_set(const uint32_t bandwidth_hz) {
|
||||||
return max2837_set_lpf_bandwidth(bandwidth_hz);
|
return max2837_set_lpf_bandwidth(&max2837, bandwidth_hz);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* clock startup for Jellybean with Lemondrop attached
|
/* clock startup for Jellybean with Lemondrop attached
|
||||||
@ -264,15 +541,15 @@ void cpu_clock_init(void)
|
|||||||
/* use IRC as clock source for APB3 */
|
/* use IRC as clock source for APB3 */
|
||||||
CGU_BASE_APB3_CLK = CGU_BASE_APB3_CLK_CLK_SEL(CGU_SRC_IRC);
|
CGU_BASE_APB3_CLK = CGU_BASE_APB3_CLK_CLK_SEL(CGU_SRC_IRC);
|
||||||
|
|
||||||
i2c0_init(15);
|
i2c_bus_start(clock_gen.bus, &i2c_config_si5351c_slow_clock);
|
||||||
|
|
||||||
si5351c_disable_all_outputs();
|
si5351c_disable_all_outputs(&clock_gen);
|
||||||
si5351c_disable_oeb_pin_control();
|
si5351c_disable_oeb_pin_control(&clock_gen);
|
||||||
si5351c_power_down_all_clocks();
|
si5351c_power_down_all_clocks(&clock_gen);
|
||||||
si5351c_set_crystal_configuration();
|
si5351c_set_crystal_configuration(&clock_gen);
|
||||||
si5351c_enable_xo_and_ms_fanout();
|
si5351c_enable_xo_and_ms_fanout(&clock_gen);
|
||||||
si5351c_configure_pll_sources();
|
si5351c_configure_pll_sources(&clock_gen);
|
||||||
si5351c_configure_pll_multisynth();
|
si5351c_configure_pll_multisynth(&clock_gen);
|
||||||
|
|
||||||
#ifdef JELLYBEAN
|
#ifdef JELLYBEAN
|
||||||
/*
|
/*
|
||||||
@ -288,13 +565,13 @@ void cpu_clock_init(void)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* MS0/CLK0 is the source for the MAX2837 clock input. */
|
/* MS0/CLK0 is the source for the MAX2837 clock input. */
|
||||||
si5351c_configure_multisynth(0, 2048, 0, 1, 0); /* 40MHz */
|
si5351c_configure_multisynth(&clock_gen, 0, 2048, 0, 1, 0); /* 40MHz */
|
||||||
|
|
||||||
/* MS4/CLK4 is the source for the LPC43xx microcontroller. */
|
/* MS4/CLK4 is the source for the LPC43xx microcontroller. */
|
||||||
si5351c_configure_multisynth(4, 8021, 0, 3, 0); /* 12MHz */
|
si5351c_configure_multisynth(&clock_gen, 4, 8021, 0, 3, 0); /* 12MHz */
|
||||||
|
|
||||||
/* MS5/CLK5 is the source for the RFFC5071 mixer. */
|
/* MS5/CLK5 is the source for the RFFC5071 mixer. */
|
||||||
si5351c_configure_multisynth(5, 1536, 0, 1, 0); /* 50MHz */
|
si5351c_configure_multisynth(&clock_gen, 5, 1536, 0, 1, 0); /* 50MHz */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (defined JAWBREAKER || defined HACKRF_ONE)
|
#if (defined JAWBREAKER || defined HACKRF_ONE)
|
||||||
@ -311,32 +588,32 @@ void cpu_clock_init(void)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* MS3/CLK3 is the source for the external clock output. */
|
/* MS3/CLK3 is the source for the external clock output. */
|
||||||
si5351c_configure_multisynth(3, 80*128-512, 0, 1, 0); /* 800/80 = 10MHz */
|
si5351c_configure_multisynth(&clock_gen, 3, 80*128-512, 0, 1, 0); /* 800/80 = 10MHz */
|
||||||
|
|
||||||
/* MS4/CLK4 is the source for the RFFC5071 mixer. */
|
/* MS4/CLK4 is the source for the RFFC5071 mixer. */
|
||||||
si5351c_configure_multisynth(4, 16*128-512, 0, 1, 0); /* 800/16 = 50MHz */
|
si5351c_configure_multisynth(&clock_gen, 4, 16*128-512, 0, 1, 0); /* 800/16 = 50MHz */
|
||||||
|
|
||||||
/* MS5/CLK5 is the source for the MAX2837 clock input. */
|
/* MS5/CLK5 is the source for the MAX2837 clock input. */
|
||||||
si5351c_configure_multisynth(5, 20*128-512, 0, 1, 0); /* 800/20 = 40MHz */
|
si5351c_configure_multisynth(&clock_gen, 5, 20*128-512, 0, 1, 0); /* 800/20 = 40MHz */
|
||||||
|
|
||||||
/* MS6/CLK6 is unused. */
|
/* MS6/CLK6 is unused. */
|
||||||
/* MS7/CLK7 is the source for the LPC43xx microcontroller. */
|
/* MS7/CLK7 is the source for the LPC43xx microcontroller. */
|
||||||
uint8_t ms7data[] = { 90, 255, 20, 0 };
|
uint8_t ms7data[] = { 90, 255, 20, 0 };
|
||||||
si5351c_write(ms7data, sizeof(ms7data));
|
si5351c_write(&clock_gen, ms7data, sizeof(ms7data));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Set to 10 MHz, the common rate between Jellybean and Jawbreaker. */
|
/* Set to 10 MHz, the common rate between Jellybean and Jawbreaker. */
|
||||||
sample_rate_set(10000000);
|
sample_rate_set(10000000);
|
||||||
|
|
||||||
si5351c_set_clock_source(PLL_SOURCE_XTAL);
|
si5351c_set_clock_source(&clock_gen, PLL_SOURCE_XTAL);
|
||||||
// soft reset
|
// soft reset
|
||||||
uint8_t resetdata[] = { 177, 0xac };
|
uint8_t resetdata[] = { 177, 0xac };
|
||||||
si5351c_write(resetdata, sizeof(resetdata));
|
si5351c_write(&clock_gen, resetdata, sizeof(resetdata));
|
||||||
si5351c_enable_clock_outputs();
|
si5351c_enable_clock_outputs(&clock_gen);
|
||||||
|
|
||||||
//FIXME disable I2C
|
//FIXME disable I2C
|
||||||
/* Kick I2C0 down to 400kHz when we switch over to APB1 clock = 204MHz */
|
/* Kick I2C0 down to 400kHz when we switch over to APB1 clock = 204MHz */
|
||||||
i2c0_init(255);
|
i2c_bus_start(clock_gen.bus, &i2c_config_si5351c_fast_clock);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 12MHz clock is entering LPC XTAL1/OSC input now. On
|
* 12MHz clock is entering LPC XTAL1/OSC input now. On
|
||||||
@ -411,6 +688,12 @@ void cpu_clock_init(void)
|
|||||||
/* Switch APB3 clock over to use PLL1 (204MHz) */
|
/* Switch APB3 clock over to use PLL1 (204MHz) */
|
||||||
CGU_BASE_APB3_CLK = CGU_BASE_APB3_CLK_AUTOBLOCK(1)
|
CGU_BASE_APB3_CLK = CGU_BASE_APB3_CLK_AUTOBLOCK(1)
|
||||||
| CGU_BASE_APB3_CLK_CLK_SEL(CGU_SRC_PLL1);
|
| CGU_BASE_APB3_CLK_CLK_SEL(CGU_SRC_PLL1);
|
||||||
|
|
||||||
|
CGU_BASE_SSP0_CLK = CGU_BASE_SSP0_CLK_AUTOBLOCK(1)
|
||||||
|
| CGU_BASE_SSP0_CLK_CLK_SEL(CGU_SRC_PLL1);
|
||||||
|
|
||||||
|
CGU_BASE_SSP1_CLK = CGU_BASE_SSP1_CLK_AUTOBLOCK(1)
|
||||||
|
| CGU_BASE_SSP1_CLK_CLK_SEL(CGU_SRC_PLL1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -504,70 +787,14 @@ void cpu_clock_pll1_max_speed(void)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
void ssp1_set_mode_max2837(void)
|
||||||
{
|
{
|
||||||
/* FIXME speed up once everything is working reliably */
|
spi_bus_start(max2837.bus, &ssp_config_max2837);
|
||||||
/*
|
|
||||||
// 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)
|
void ssp1_set_mode_max5864(void)
|
||||||
{
|
{
|
||||||
/* FIXME speed up once everything is working reliably */
|
spi_bus_start(max5864.bus, &ssp_config_max5864);
|
||||||
/*
|
|
||||||
// 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) {
|
void pin_setup(void) {
|
||||||
@ -577,10 +804,10 @@ void pin_setup(void) {
|
|||||||
scu_pinmux(SCU_PINMUX_CPLD_TMS, 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);
|
scu_pinmux(SCU_PINMUX_CPLD_TDI, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0);
|
||||||
|
|
||||||
GPIO_DIR(PORT_CPLD_TDO) &= ~PIN_CPLD_TDO;
|
gpio_input(&gpio_cpld_tdo);
|
||||||
GPIO_DIR(PORT_CPLD_TCK) &= ~PIN_CPLD_TCK;
|
gpio_input(&gpio_cpld_tck);
|
||||||
GPIO_DIR(PORT_CPLD_TMS) &= ~PIN_CPLD_TMS;
|
gpio_input(&gpio_cpld_tms);
|
||||||
GPIO_DIR(PORT_CPLD_TDI) &= ~PIN_CPLD_TDI;
|
gpio_input(&gpio_cpld_tdi);
|
||||||
|
|
||||||
/* Configure SCU Pin Mux as GPIO */
|
/* Configure SCU Pin Mux as GPIO */
|
||||||
scu_pinmux(SCU_PINMUX_LED1, SCU_GPIO_NOPULL);
|
scu_pinmux(SCU_PINMUX_LED1, SCU_GPIO_NOPULL);
|
||||||
@ -596,49 +823,62 @@ void pin_setup(void) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Configure all GPIO as Input (safe state) */
|
/* Configure all GPIO as Input (safe state) */
|
||||||
GPIO0_DIR = 0;
|
gpio_init();
|
||||||
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. */
|
gpio_output(&gpio_led[0]);
|
||||||
GPIO2_DIR |= (PIN_LED1 | PIN_LED2 | PIN_LED3);
|
gpio_output(&gpio_led[1]);
|
||||||
|
gpio_output(&gpio_led[2]);
|
||||||
|
|
||||||
/* GPIO3[6] on P6_10 as output. */
|
gpio_output(&gpio_1v8_enable);
|
||||||
GPIO3_DIR |= PIN_EN1V8;
|
|
||||||
|
|
||||||
rf_path_pin_setup();
|
#ifdef HACKRF_ONE
|
||||||
|
/* Configure RF power supply (VAA) switch control signal as output */
|
||||||
|
gpio_output(&gpio_vaa_disable);
|
||||||
|
|
||||||
/* Configure SSP1 Peripheral (to be moved later in SSP driver) */
|
/* Safe state: start with VAA turned off: */
|
||||||
scu_pinmux(SCU_SSP1_MISO, (SCU_SSP_IO | SCU_CONF_FUNCTION5));
|
disable_rf_power();
|
||||||
scu_pinmux(SCU_SSP1_MOSI, (SCU_SSP_IO | SCU_CONF_FUNCTION5));
|
#endif
|
||||||
scu_pinmux(SCU_SSP1_SCK, (SCU_SSP_IO | SCU_CONF_FUNCTION1));
|
|
||||||
scu_pinmux(SCU_SSP1_SSEL, (SCU_SSP_IO | SCU_CONF_FUNCTION1));
|
/* enable input on SCL and SDA pins */
|
||||||
|
SCU_SFSI2C0 = SCU_I2C0_NOMINAL;
|
||||||
|
|
||||||
|
spi_bus_start(&spi_bus_ssp1, &ssp_config_max2837);
|
||||||
|
spi_bus_start(&spi_bus_rffc5071, &rffc5071_spi_config);
|
||||||
|
|
||||||
|
rf_path_pin_setup(&rf_path);
|
||||||
|
|
||||||
/* Configure external clock in */
|
/* Configure external clock in */
|
||||||
scu_pinmux(SCU_PINMUX_GP_CLKIN, SCU_CLK_IN | SCU_CONF_FUNCTION1);
|
scu_pinmux(SCU_PINMUX_GP_CLKIN, SCU_CLK_IN | SCU_CONF_FUNCTION1);
|
||||||
|
|
||||||
sgpio_configure_pin_functions();
|
sgpio_configure_pin_functions(&sgpio_config);
|
||||||
}
|
}
|
||||||
|
|
||||||
void enable_1v8_power(void) {
|
void enable_1v8_power(void) {
|
||||||
gpio_set(PORT_EN1V8, PIN_EN1V8);
|
gpio_set(&gpio_1v8_enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
void disable_1v8_power(void) {
|
void disable_1v8_power(void) {
|
||||||
gpio_clear(PORT_EN1V8, PIN_EN1V8);
|
gpio_clear(&gpio_1v8_enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HACKRF_ONE
|
#ifdef HACKRF_ONE
|
||||||
void enable_rf_power(void) {
|
void enable_rf_power(void) {
|
||||||
gpio_clear(PORT_NO_VAA_ENABLE, PIN_NO_VAA_ENABLE);
|
gpio_clear(&gpio_vaa_disable);
|
||||||
}
|
}
|
||||||
|
|
||||||
void disable_rf_power(void) {
|
void disable_rf_power(void) {
|
||||||
gpio_set(PORT_NO_VAA_ENABLE, PIN_NO_VAA_ENABLE);
|
gpio_set(&gpio_vaa_disable);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void led_on(const led_t led) {
|
||||||
|
gpio_set(&gpio_led[led]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void led_off(const led_t led) {
|
||||||
|
gpio_clear(&gpio_led[led]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void led_toggle(const led_t led) {
|
||||||
|
gpio_toggle(&gpio_led[led]);
|
||||||
|
}
|
||||||
|
@ -32,6 +32,17 @@ extern "C"
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "si5351c.h"
|
||||||
|
#include "spi_ssp.h"
|
||||||
|
|
||||||
|
#include "max2837.h"
|
||||||
|
#include "max5864.h"
|
||||||
|
#include "rffc5071.h"
|
||||||
|
#include "w25q80bv.h"
|
||||||
|
#include "sgpio.h"
|
||||||
|
#include "rf_path.h"
|
||||||
|
#include "cpld_jtag.h"
|
||||||
|
|
||||||
/* hardware identification number */
|
/* hardware identification number */
|
||||||
#define BOARD_ID_JELLYBEAN 0
|
#define BOARD_ID_JELLYBEAN 0
|
||||||
#define BOARD_ID_JAWBREAKER 1
|
#define BOARD_ID_JAWBREAKER 1
|
||||||
@ -206,142 +217,6 @@ extern "C"
|
|||||||
|
|
||||||
#define SCU_PINMUX_GP_CLKIN (P4_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 {
|
typedef enum {
|
||||||
TRANSCEIVER_MODE_OFF = 0,
|
TRANSCEIVER_MODE_OFF = 0,
|
||||||
TRANSCEIVER_MODE_RX = 1,
|
TRANSCEIVER_MODE_RX = 1,
|
||||||
@ -352,10 +227,23 @@ typedef enum {
|
|||||||
|
|
||||||
void delay(uint32_t duration);
|
void delay(uint32_t duration);
|
||||||
|
|
||||||
|
/* TODO: Hide these configurations */
|
||||||
|
extern si5351c_driver_t clock_gen;
|
||||||
|
extern const ssp_config_t ssp_config_w25q80bv;
|
||||||
|
extern const ssp_config_t ssp_config_max2837;
|
||||||
|
extern const ssp_config_t ssp_config_max5864;
|
||||||
|
|
||||||
|
extern max2837_driver_t max2837;
|
||||||
|
extern max5864_driver_t max5864;
|
||||||
|
extern rffc5071_driver_t rffc5072;
|
||||||
|
extern w25q80bv_driver_t spi_flash;
|
||||||
|
extern sgpio_config_t sgpio_config;
|
||||||
|
extern rf_path_t rf_path;
|
||||||
|
extern jtag_t jtag_cpld;
|
||||||
|
|
||||||
void cpu_clock_init(void);
|
void cpu_clock_init(void);
|
||||||
void cpu_clock_pll1_low_speed(void);
|
void cpu_clock_pll1_low_speed(void);
|
||||||
void cpu_clock_pll1_max_speed(void);
|
void cpu_clock_pll1_max_speed(void);
|
||||||
void ssp1_init(void);
|
|
||||||
void ssp1_set_mode_max2837(void);
|
void ssp1_set_mode_max2837(void);
|
||||||
void ssp1_set_mode_max5864(void);
|
void ssp1_set_mode_max5864(void);
|
||||||
|
|
||||||
@ -373,6 +261,16 @@ void enable_rf_power(void);
|
|||||||
void disable_rf_power(void);
|
void disable_rf_power(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
LED1 = 0,
|
||||||
|
LED2 = 1,
|
||||||
|
LED3 = 2,
|
||||||
|
} led_t;
|
||||||
|
|
||||||
|
void led_on(const led_t led);
|
||||||
|
void led_off(const led_t led);
|
||||||
|
void led_toggle(const led_t led);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
39
firmware/common/i2c_bus.c
Normal file
39
firmware/common/i2c_bus.c
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
||||||
|
*
|
||||||
|
* 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 "i2c_bus.h"
|
||||||
|
|
||||||
|
void i2c_bus_start(i2c_bus_t* const bus, const void* const config) {
|
||||||
|
bus->start(bus, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
void i2c_bus_stop(i2c_bus_t* const bus) {
|
||||||
|
bus->stop(bus);
|
||||||
|
}
|
||||||
|
|
||||||
|
void i2c_bus_transfer(
|
||||||
|
i2c_bus_t* const bus,
|
||||||
|
const uint_fast8_t slave_address,
|
||||||
|
const uint8_t* const tx, const size_t tx_count,
|
||||||
|
uint8_t* const rx, const size_t rx_count
|
||||||
|
) {
|
||||||
|
bus->transfer(bus, slave_address, tx, tx_count, rx, rx_count);
|
||||||
|
}
|
52
firmware/common/i2c_bus.h
Normal file
52
firmware/common/i2c_bus.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
||||||
|
*
|
||||||
|
* 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 __I2C_BUS_H__
|
||||||
|
#define __I2C_BUS_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
struct i2c_bus_t;
|
||||||
|
typedef struct i2c_bus_t i2c_bus_t;
|
||||||
|
|
||||||
|
struct i2c_bus_t {
|
||||||
|
void* const obj;
|
||||||
|
void (*start)(i2c_bus_t* const bus, const void* const config);
|
||||||
|
void (*stop)(i2c_bus_t* const bus);
|
||||||
|
void (*transfer)(
|
||||||
|
i2c_bus_t* const bus,
|
||||||
|
const uint_fast8_t slave_address,
|
||||||
|
const uint8_t* const tx, const size_t tx_count,
|
||||||
|
uint8_t* const rx, const size_t rx_count
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
void i2c_bus_start(i2c_bus_t* const bus, const void* const config);
|
||||||
|
void i2c_bus_stop(i2c_bus_t* const bus);
|
||||||
|
void i2c_bus_transfer(
|
||||||
|
i2c_bus_t* const bus,
|
||||||
|
const uint_fast8_t slave_address,
|
||||||
|
const uint8_t* const tx, const size_t tx_count,
|
||||||
|
uint8_t* const rx, const size_t rx_count
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif/*__I2C_BUS_H__*/
|
62
firmware/common/i2c_lpc.c
Normal file
62
firmware/common/i2c_lpc.c
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* 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 "i2c_lpc.h"
|
||||||
|
|
||||||
|
#include <libopencm3/lpc43xx/i2c.h>
|
||||||
|
|
||||||
|
/* FIXME return i2c0 status from each function */
|
||||||
|
|
||||||
|
void i2c_lpc_start(i2c_bus_t* const bus, const void* const _config) {
|
||||||
|
const i2c_lpc_config_t* const config = _config;
|
||||||
|
|
||||||
|
const uint32_t port = (uint32_t)bus->obj;
|
||||||
|
i2c_init(port, config->duty_cycle_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void i2c_lpc_stop(i2c_bus_t* const bus) {
|
||||||
|
const uint32_t port = (uint32_t)bus->obj;
|
||||||
|
i2c_disable(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
void i2c_lpc_transfer(i2c_bus_t* const bus,
|
||||||
|
const uint_fast8_t slave_address,
|
||||||
|
const uint8_t* const data_tx, const size_t count_tx,
|
||||||
|
uint8_t* const data_rx, const size_t count_rx
|
||||||
|
) {
|
||||||
|
const uint32_t port = (uint32_t)bus->obj;
|
||||||
|
i2c_tx_start(port);
|
||||||
|
i2c_tx_byte(port, (slave_address << 1) | I2C_WRITE);
|
||||||
|
for(size_t i=0; i<count_tx; i++) {
|
||||||
|
i2c_tx_byte(port, data_tx[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if( data_rx ) {
|
||||||
|
i2c_tx_start(port);
|
||||||
|
i2c_tx_byte(port, (slave_address << 1) | I2C_READ);
|
||||||
|
for(size_t i=0; i<count_rx; i++) {
|
||||||
|
data_rx[i] = i2c_rx_byte(port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i2c_stop(port);
|
||||||
|
}
|
42
firmware/common/i2c_lpc.h
Normal file
42
firmware/common/i2c_lpc.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
||||||
|
*
|
||||||
|
* 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 __I2C_LPC_H__
|
||||||
|
#define __I2C_LPC_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "i2c_bus.h"
|
||||||
|
|
||||||
|
typedef struct i2c_lpc_config_t {
|
||||||
|
const uint16_t duty_cycle_count;
|
||||||
|
} i2c_lpc_config_t;
|
||||||
|
|
||||||
|
void i2c_lpc_start(i2c_bus_t* const bus, const void* const config);
|
||||||
|
void i2c_lpc_stop(i2c_bus_t* const bus);
|
||||||
|
void i2c_lpc_transfer(i2c_bus_t* const bus,
|
||||||
|
const uint_fast8_t slave_address,
|
||||||
|
const uint8_t* const data_tx, const size_t count_tx,
|
||||||
|
uint8_t* const data_rx, const size_t count_rx
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif/*__I2C_LPC_H__*/
|
@ -1,3 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 Will Code? (TODO: Proper attribution)
|
||||||
|
* 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 max2837.c' prints out what test
|
* 'gcc -DTEST -DDEBUG -O2 -o test max2837.c' prints out what test
|
||||||
* program would do if it had a real spi library
|
* program would do if it had a real spi library
|
||||||
@ -11,19 +33,8 @@
|
|||||||
#include "max2837.h"
|
#include "max2837.h"
|
||||||
#include "max2837_regs.def" // private register def macros
|
#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. */
|
/* Default register values. */
|
||||||
static uint16_t max2837_regs_default[MAX2837_NUM_REGS] = {
|
static const uint16_t max2837_regs_default[MAX2837_NUM_REGS] = {
|
||||||
0x150, /* 0 */
|
0x150, /* 0 */
|
||||||
0x002, /* 1 */
|
0x002, /* 1 */
|
||||||
0x1f4, /* 2 */
|
0x1f4, /* 2 */
|
||||||
@ -62,283 +73,130 @@ static uint16_t max2837_regs_default[MAX2837_NUM_REGS] = {
|
|||||||
0x080, /* 30 */
|
0x080, /* 30 */
|
||||||
0x000 }; /* 31 */
|
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. */
|
/* Set up all registers according to defaults specified in docs. */
|
||||||
void max2837_init(void)
|
static void max2837_init(max2837_driver_t* const drv)
|
||||||
{
|
{
|
||||||
LOG("# max2837_init\n");
|
drv->target_init(drv);
|
||||||
memcpy(max2837_regs, max2837_regs_default, sizeof(max2837_regs));
|
max2837_set_mode(drv, MAX2837_MODE_SHUTDOWN);
|
||||||
max2837_regs_dirty = 0xffffffff;
|
|
||||||
|
memcpy(drv->regs, max2837_regs_default, sizeof(drv->regs));
|
||||||
|
drv->regs_dirty = 0xffffffff;
|
||||||
|
|
||||||
/* Write default register values to chip. */
|
/* Write default register values to chip. */
|
||||||
max2837_regs_commit();
|
max2837_regs_commit(drv);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set up pins for GPIO and SPI control, configure SSP peripheral for SPI, and
|
* Set up pins for GPIO and SPI control, configure SSP peripheral for SPI, and
|
||||||
* set our own default register configuration.
|
* set our own default register configuration.
|
||||||
*/
|
*/
|
||||||
void max2837_setup(void)
|
void max2837_setup(max2837_driver_t* const drv)
|
||||||
{
|
{
|
||||||
LOG("# max2837_setup\n");
|
max2837_init(drv);
|
||||||
#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. */
|
/* Use SPI control instead of B1-B7 pins for gain settings. */
|
||||||
set_MAX2837_TXVGA_GAIN_SPI_EN(1);
|
set_MAX2837_TXVGA_GAIN_SPI_EN(drv, 1);
|
||||||
set_MAX2837_TXVGA_GAIN_MSB_SPI_EN(1);
|
set_MAX2837_TXVGA_GAIN_MSB_SPI_EN(drv, 1);
|
||||||
//set_MAX2837_TXVGA_GAIN(0x3f); /* maximum attenuation */
|
//set_MAX2837_TXVGA_GAIN(0x3f); /* maximum attenuation */
|
||||||
set_MAX2837_TXVGA_GAIN(0x00); /* minimum attenuation */
|
set_MAX2837_TXVGA_GAIN(drv, 0x00); /* minimum attenuation */
|
||||||
set_MAX2837_VGAMUX_enable(1);
|
set_MAX2837_VGAMUX_enable(drv, 1);
|
||||||
set_MAX2837_VGA_EN(1);
|
set_MAX2837_VGA_EN(drv, 1);
|
||||||
set_MAX2837_HPC_RXGAIN_EN(0);
|
set_MAX2837_HPC_RXGAIN_EN(drv, 0);
|
||||||
set_MAX2837_HPC_STOP(MAX2837_STOP_1K);
|
set_MAX2837_HPC_STOP(drv, MAX2837_STOP_1K);
|
||||||
set_MAX2837_LNAgain_SPI_EN(1);
|
set_MAX2837_LNAgain_SPI_EN(drv, 1);
|
||||||
set_MAX2837_LNAgain(MAX2837_LNAgain_MAX); /* maximum gain */
|
set_MAX2837_LNAgain(drv, MAX2837_LNAgain_MAX); /* maximum gain */
|
||||||
set_MAX2837_VGAgain_SPI_EN(1);
|
set_MAX2837_VGAgain_SPI_EN(drv, 1);
|
||||||
set_MAX2837_VGA(0x18); /* reasonable gain for noisy 2.4GHz environment */
|
set_MAX2837_VGA(drv, 0x18); /* reasonable gain for noisy 2.4GHz environment */
|
||||||
|
|
||||||
/* maximum rx output common-mode voltage */
|
/* maximum rx output common-mode voltage */
|
||||||
set_MAX2837_BUFF_VCM(MAX2837_BUFF_VCM_1_25);
|
set_MAX2837_BUFF_VCM(drv, MAX2837_BUFF_VCM_1_25);
|
||||||
|
|
||||||
/* configure baseband filter for 8 MHz TX */
|
/* configure baseband filter for 8 MHz TX */
|
||||||
set_MAX2837_LPF_EN(1);
|
set_MAX2837_LPF_EN(drv, 1);
|
||||||
set_MAX2837_ModeCtrl(MAX2837_ModeCtrl_RxLPF);
|
set_MAX2837_ModeCtrl(drv, MAX2837_ModeCtrl_RxLPF);
|
||||||
set_MAX2837_FT(MAX2837_FT_5M);
|
set_MAX2837_FT(drv, MAX2837_FT_5M);
|
||||||
|
|
||||||
max2837_regs_commit();
|
max2837_regs_commit(drv);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SPI register read. */
|
static uint16_t max2837_read(max2837_driver_t* const drv, uint8_t r) {
|
||||||
uint16_t max2837_spi_read(uint8_t r) {
|
uint16_t value = (1 << 15) | (r << 10);
|
||||||
gpio_clear(PORT_XCVR_CS, PIN_XCVR_CS);
|
spi_bus_transfer(drv->bus, &value, 1);
|
||||||
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;
|
return value & 0x3ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SPI register write */
|
static void max2837_write(max2837_driver_t* const drv, uint8_t r, uint16_t v) {
|
||||||
void max2837_spi_write(uint8_t r, uint16_t v) {
|
uint16_t value = (r << 10) | (v & 0x3ff);
|
||||||
|
spi_bus_transfer(drv->bus, &value, 1);
|
||||||
#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)
|
uint16_t max2837_reg_read(max2837_driver_t* const drv, uint8_t r)
|
||||||
{
|
{
|
||||||
if ((max2837_regs_dirty >> r) & 0x1) {
|
if ((drv->regs_dirty >> r) & 0x1) {
|
||||||
max2837_regs[r] = max2837_spi_read(r);
|
drv->regs[r] = max2837_read(drv, r);
|
||||||
};
|
};
|
||||||
return max2837_regs[r];
|
return drv->regs[r];
|
||||||
}
|
}
|
||||||
|
|
||||||
void max2837_reg_write(uint8_t r, uint16_t v)
|
void max2837_reg_write(max2837_driver_t* const drv, uint8_t r, uint16_t v)
|
||||||
{
|
{
|
||||||
max2837_regs[r] = v;
|
drv->regs[r] = v;
|
||||||
max2837_spi_write(r, v);
|
max2837_write(drv, r, v);
|
||||||
MAX2837_REG_SET_CLEAN(r);
|
MAX2837_REG_SET_CLEAN(drv, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This functions should not be needed, and might be confusing. DELETE. */
|
static inline void max2837_reg_commit(max2837_driver_t* const drv, uint8_t r)
|
||||||
void max2837_regs_read(void)
|
|
||||||
{
|
{
|
||||||
;
|
max2837_reg_write(drv, r, drv->regs[r]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void max2837_reg_commit(uint8_t r)
|
void max2837_regs_commit(max2837_driver_t* const drv)
|
||||||
{
|
|
||||||
max2837_reg_write(r,max2837_regs[r]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void max2837_regs_commit(void)
|
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
for(r = 0; r < MAX2837_NUM_REGS; r++) {
|
for(r = 0; r < MAX2837_NUM_REGS; r++) {
|
||||||
if ((max2837_regs_dirty >> r) & 0x1) {
|
if ((drv->regs_dirty >> r) & 0x1) {
|
||||||
max2837_reg_commit(r);
|
max2837_reg_commit(drv, r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void max2837_mode_shutdown(void) {
|
void max2837_set_mode(max2837_driver_t* const drv, const max2837_mode_t new_mode) {
|
||||||
/* All circuit blocks are powered down, except the 4-wire serial bus
|
drv->set_mode(drv, new_mode);
|
||||||
* and its internal programmable registers.
|
|
||||||
*/
|
|
||||||
gpio_clear(PORT_XCVR_ENABLE,
|
|
||||||
(PIN_XCVR_ENABLE | PIN_XCVR_RXENABLE | PIN_XCVR_TXENABLE));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void max2837_mode_standby(void) {
|
max2837_mode_t max2837_mode(max2837_driver_t* const drv) {
|
||||||
/* Used to enable the frequency synthesizer block while the rest of the
|
return drv->mode;
|
||||||
* 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) {
|
void max2837_start(max2837_driver_t* const drv)
|
||||||
/* 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(drv, 1);
|
||||||
set_MAX2837_EN_SPI(1);
|
max2837_regs_commit(drv);
|
||||||
max2837_regs_commit();
|
max2837_set_mode(drv, MAX2837_MODE_STANDBY);
|
||||||
#if !defined TEST
|
|
||||||
max2837_mode_standby();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void max2837_tx(void)
|
void max2837_tx(max2837_driver_t* const drv)
|
||||||
{
|
{
|
||||||
LOG("# max2837_tx\n");
|
set_MAX2837_ModeCtrl(drv, MAX2837_ModeCtrl_TxLPF);
|
||||||
#if !defined TEST
|
max2837_regs_commit(drv);
|
||||||
|
max2837_set_mode(drv, MAX2837_MODE_TX);
|
||||||
set_MAX2837_ModeCtrl(MAX2837_ModeCtrl_TxLPF);
|
|
||||||
max2837_regs_commit();
|
|
||||||
max2837_mode_tx();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void max2837_rx(void)
|
void max2837_rx(max2837_driver_t* const drv)
|
||||||
{
|
{
|
||||||
LOG("# max2837_rx\n");
|
set_MAX2837_ModeCtrl(drv, MAX2837_ModeCtrl_RxLPF);
|
||||||
|
max2837_regs_commit(drv);
|
||||||
set_MAX2837_ModeCtrl(MAX2837_ModeCtrl_RxLPF);
|
max2837_set_mode(drv, MAX2837_MODE_RX);
|
||||||
max2837_regs_commit();
|
|
||||||
|
|
||||||
#if !defined TEST
|
|
||||||
max2837_mode_rx();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void max2837_stop(void)
|
void max2837_stop(max2837_driver_t* const drv)
|
||||||
{
|
{
|
||||||
LOG("# max2837_stop\n");
|
set_MAX2837_EN_SPI(drv, 0);
|
||||||
set_MAX2837_EN_SPI(0);
|
max2837_regs_commit(drv);
|
||||||
max2837_regs_commit();
|
max2837_set_mode(drv, MAX2837_MODE_SHUTDOWN);
|
||||||
#if !defined TEST
|
|
||||||
max2837_mode_shutdown();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void max2837_set_frequency(uint32_t freq)
|
void max2837_set_frequency(max2837_driver_t* const drv, uint32_t freq)
|
||||||
{
|
{
|
||||||
uint8_t band;
|
uint8_t band;
|
||||||
uint8_t lna_band;
|
uint8_t lna_band;
|
||||||
@ -366,9 +224,6 @@ void max2837_set_frequency(uint32_t freq)
|
|||||||
lna_band = MAX2837_LNAband_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 */
|
/* ASSUME 40MHz PLL. Ratio = F*(4/3)/40,000,000 = F/30,000,000 */
|
||||||
div_int = freq / 30000000;
|
div_int = freq / 30000000;
|
||||||
div_rem = freq % 30000000;
|
div_rem = freq % 30000000;
|
||||||
@ -382,22 +237,21 @@ void max2837_set_frequency(uint32_t freq)
|
|||||||
div_rem -= div_cmp;
|
div_rem -= div_cmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LOG("# int %ld, frac %ld\n", div_int, div_frac);
|
|
||||||
|
|
||||||
/* Band settings */
|
/* Band settings */
|
||||||
set_MAX2837_LOGEN_BSW(band);
|
set_MAX2837_LOGEN_BSW(drv, band);
|
||||||
set_MAX2837_LNAband(lna_band);
|
set_MAX2837_LNAband(drv, lna_band);
|
||||||
|
|
||||||
/* Write order matters here, so commit INT and FRAC_HI before
|
/* Write order matters here, so commit INT and FRAC_HI before
|
||||||
* committing FRAC_LO, which is the trigger for VCO
|
* committing FRAC_LO, which is the trigger for VCO
|
||||||
* auto-select. TODO - it's cleaner this way, but it would be
|
* auto-select. TODO - it's cleaner this way, but it would be
|
||||||
* faster to explicitly commit the registers explicitly so the
|
* faster to explicitly commit the registers explicitly so the
|
||||||
* dirty bits aren't scanned twice. */
|
* dirty bits aren't scanned twice. */
|
||||||
set_MAX2837_SYN_INT(div_int);
|
set_MAX2837_SYN_INT(drv, div_int);
|
||||||
set_MAX2837_SYN_FRAC_HI((div_frac >> 10) & 0x3ff);
|
set_MAX2837_SYN_FRAC_HI(drv, (div_frac >> 10) & 0x3ff);
|
||||||
max2837_regs_commit();
|
max2837_regs_commit(drv);
|
||||||
set_MAX2837_SYN_FRAC_LO(div_frac & 0x3ff);
|
set_MAX2837_SYN_FRAC_LO(drv, div_frac & 0x3ff);
|
||||||
max2837_regs_commit();
|
max2837_regs_commit(drv);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -425,7 +279,7 @@ static const max2837_ft_t max2837_ft[] = {
|
|||||||
{ 0, 0 },
|
{ 0, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
bool max2837_set_lpf_bandwidth(const uint32_t bandwidth_hz) {
|
bool max2837_set_lpf_bandwidth(max2837_driver_t* const drv, const uint32_t bandwidth_hz) {
|
||||||
const max2837_ft_t* p = max2837_ft;
|
const max2837_ft_t* p = max2837_ft;
|
||||||
while( p->bandwidth_hz != 0 ) {
|
while( p->bandwidth_hz != 0 ) {
|
||||||
if( p->bandwidth_hz >= bandwidth_hz ) {
|
if( p->bandwidth_hz >= bandwidth_hz ) {
|
||||||
@ -435,15 +289,15 @@ bool max2837_set_lpf_bandwidth(const uint32_t bandwidth_hz) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if( p->bandwidth_hz != 0 ) {
|
if( p->bandwidth_hz != 0 ) {
|
||||||
set_MAX2837_FT(p->ft);
|
set_MAX2837_FT(drv, p->ft);
|
||||||
max2837_regs_commit();
|
max2837_regs_commit(drv);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool max2837_set_lna_gain(const uint32_t gain_db) {
|
bool max2837_set_lna_gain(max2837_driver_t* const drv, const uint32_t gain_db) {
|
||||||
uint16_t val;
|
uint16_t val;
|
||||||
switch(gain_db){
|
switch(gain_db){
|
||||||
case 40:
|
case 40:
|
||||||
@ -467,21 +321,21 @@ bool max2837_set_lna_gain(const uint32_t gain_db) {
|
|||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
set_MAX2837_LNAgain(val);
|
set_MAX2837_LNAgain(drv, val);
|
||||||
max2837_reg_commit(1);
|
max2837_reg_commit(drv, 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool max2837_set_vga_gain(const uint32_t gain_db) {
|
bool max2837_set_vga_gain(max2837_driver_t* const drv, const uint32_t gain_db) {
|
||||||
if( (gain_db & 0x1) || gain_db > 62)/* 0b11111*2 */
|
if( (gain_db & 0x1) || gain_db > 62)/* 0b11111*2 */
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
set_MAX2837_VGA( 31-(gain_db >> 1) );
|
set_MAX2837_VGA(drv, 31-(gain_db >> 1) );
|
||||||
max2837_reg_commit(5);
|
max2837_reg_commit(drv, 5);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool max2837_set_txvga_gain(const uint32_t gain_db) {
|
bool max2837_set_txvga_gain(max2837_driver_t* const drv, const uint32_t gain_db) {
|
||||||
uint16_t val=0;
|
uint16_t val=0;
|
||||||
if(gain_db <16){
|
if(gain_db <16){
|
||||||
val = 31-gain_db;
|
val = 31-gain_db;
|
||||||
@ -490,18 +344,7 @@ bool max2837_set_txvga_gain(const uint32_t gain_db) {
|
|||||||
val = 31-(gain_db-16);
|
val = 31-(gain_db-16);
|
||||||
}
|
}
|
||||||
|
|
||||||
set_MAX2837_TXVGA_GAIN(val);
|
set_MAX2837_TXVGA_GAIN(drv, val);
|
||||||
max2837_reg_commit(29);
|
max2837_reg_commit(drv, 29);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TEST
|
|
||||||
int main(int ac, char **av)
|
|
||||||
{
|
|
||||||
max2837_setup();
|
|
||||||
max2837_set_frequency(2441000000);
|
|
||||||
max2837_start();
|
|
||||||
max2837_tx();
|
|
||||||
max2837_stop();
|
|
||||||
}
|
|
||||||
#endif //TEST
|
|
||||||
|
@ -1,42 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 Will Code? (TODO: Proper attribution)
|
||||||
|
* 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 __MAX2837_H
|
#ifndef __MAX2837_H
|
||||||
#define __MAX2837_H
|
#define __MAX2837_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
/* TODO - make this a private header for max2837.c only, make new max2837.h */
|
#include "gpio.h"
|
||||||
|
#include "spi_bus.h"
|
||||||
|
|
||||||
/* 32 registers, each containing 10 bits of data. */
|
/* 32 registers, each containing 10 bits of data. */
|
||||||
#define MAX2837_NUM_REGS 32
|
#define MAX2837_NUM_REGS 32
|
||||||
#define MAX2837_DATA_REGS_MAX_VALUE 1024
|
#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 {
|
typedef enum {
|
||||||
MAX2837_MODE_SHUTDOWN,
|
MAX2837_MODE_SHUTDOWN,
|
||||||
MAX2837_MODE_STANDBY,
|
MAX2837_MODE_STANDBY,
|
||||||
@ -44,27 +40,63 @@ typedef enum {
|
|||||||
MAX2837_MODE_RX
|
MAX2837_MODE_RX
|
||||||
} max2837_mode_t;
|
} max2837_mode_t;
|
||||||
|
|
||||||
void max2837_mode_shutdown(void);
|
struct max2837_driver_t;
|
||||||
void max2837_mode_standby(void);
|
typedef struct max2837_driver_t max2837_driver_t;
|
||||||
void max2837_mode_tx(void);
|
|
||||||
void max2837_mode_rx(void);
|
|
||||||
|
|
||||||
max2837_mode_t max2837_mode(void);
|
struct max2837_driver_t {
|
||||||
void max2837_set_mode(const max2837_mode_t new_mode);
|
spi_bus_t* const bus;
|
||||||
|
gpio_t gpio_enable;
|
||||||
|
gpio_t gpio_rx_enable;
|
||||||
|
gpio_t gpio_tx_enable;
|
||||||
|
#ifdef JELLYBEAN
|
||||||
|
gpio_t gpio_rxhp;
|
||||||
|
gpio_t gpio_b1;
|
||||||
|
gpio_t gpio_b2;
|
||||||
|
gpio_t gpio_b3;
|
||||||
|
gpio_t gpio_b4;
|
||||||
|
gpio_t gpio_b5;
|
||||||
|
gpio_t gpio_b6;
|
||||||
|
gpio_t gpio_b7;
|
||||||
|
#endif
|
||||||
|
void (*target_init)(max2837_driver_t* const drv);
|
||||||
|
void (*set_mode)(max2837_driver_t* const drv, const max2837_mode_t new_mode);
|
||||||
|
max2837_mode_t mode;
|
||||||
|
uint16_t regs[MAX2837_NUM_REGS];
|
||||||
|
uint32_t regs_dirty;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Initialize chip. */
|
||||||
|
extern void max2837_setup(max2837_driver_t* const drv);
|
||||||
|
|
||||||
|
/* Read a register via SPI. Save a copy to memory and return
|
||||||
|
* value. Mark clean. */
|
||||||
|
extern uint16_t max2837_reg_read(max2837_driver_t* const drv, uint8_t r);
|
||||||
|
|
||||||
|
/* Write value to register via SPI and save a copy to memory. Mark
|
||||||
|
* clean. */
|
||||||
|
extern void max2837_reg_write(max2837_driver_t* const drv, 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 max2837_regs_commit(max2837_driver_t* const drv);
|
||||||
|
|
||||||
|
max2837_mode_t max2837_mode(max2837_driver_t* const drv);
|
||||||
|
void max2837_set_mode(max2837_driver_t* const drv, const max2837_mode_t new_mode);
|
||||||
|
|
||||||
/* Turn on/off all chip functions. Does not control oscillator and CLKOUT */
|
/* Turn on/off all chip functions. Does not control oscillator and CLKOUT */
|
||||||
extern void max2837_start(void);
|
extern void max2837_start(max2837_driver_t* const drv);
|
||||||
extern void max2837_stop(void);
|
extern void max2837_stop(max2837_driver_t* const drv);
|
||||||
|
|
||||||
/* Set frequency in Hz. Frequency setting is a multi-step function
|
/* Set frequency in Hz. Frequency setting is a multi-step function
|
||||||
* where order of register writes matters. */
|
* where order of register writes matters. */
|
||||||
extern void max2837_set_frequency(uint32_t freq);
|
extern void max2837_set_frequency(max2837_driver_t* const drv, uint32_t freq);
|
||||||
bool max2837_set_lpf_bandwidth(const uint32_t bandwidth_hz);
|
bool max2837_set_lpf_bandwidth(max2837_driver_t* const drv, const uint32_t bandwidth_hz);
|
||||||
bool max2837_set_lna_gain(const uint32_t gain_db);
|
bool max2837_set_lna_gain(max2837_driver_t* const drv, const uint32_t gain_db);
|
||||||
bool max2837_set_vga_gain(const uint32_t gain_db);
|
bool max2837_set_vga_gain(max2837_driver_t* const drv, const uint32_t gain_db);
|
||||||
bool max2837_set_txvga_gain(const uint32_t gain_db);
|
bool max2837_set_txvga_gain(max2837_driver_t* const drv, const uint32_t gain_db);
|
||||||
|
|
||||||
extern void max2837_tx(void);
|
extern void max2837_tx(max2837_driver_t* const drv);
|
||||||
extern void max2837_rx(void);
|
extern void max2837_rx(max2837_driver_t* const drv);
|
||||||
|
|
||||||
#endif // __MAX2837_H
|
#endif // __MAX2837_H
|
||||||
|
@ -9,19 +9,22 @@
|
|||||||
* (structs). This may be used in firmware, or on host predefined
|
* (structs). This may be used in firmware, or on host predefined
|
||||||
* register loads. */
|
* register loads. */
|
||||||
|
|
||||||
|
#define MAX2837_REG_SET_CLEAN(_d, _r) (_d->regs_dirty &= ~(1UL<<_r))
|
||||||
|
#define MAX2837_REG_SET_DIRTY(_d, _r) (_d->regs_dirty |= (1UL<<_r))
|
||||||
|
|
||||||
/* On set_, register is always set dirty, even if nothing
|
/* On set_, register is always set dirty, even if nothing
|
||||||
* changed. This makes sure that write that have side effects,
|
* changed. This makes sure that write that have side effects,
|
||||||
* e.g. frequency setting, are not skipped. */
|
* e.g. frequency setting, are not skipped. */
|
||||||
|
|
||||||
/* n=name, r=regnum, o=offset (bits from LSB), l=length (bits) */
|
/* n=name, r=regnum, o=offset (bits from LSB), l=length (bits) */
|
||||||
#define __MREG__(n,r,o,l) \
|
#define __MREG__(n,r,o,l) \
|
||||||
static inline uint16_t get_##n(void) { \
|
static inline uint16_t get_##n(max2837_driver_t* const _d) { \
|
||||||
return (max2837_regs[r] >> (o-l+1)) & ((1<<l)-1); \
|
return (_d->regs[r] >> (o-l+1)) & ((1<<l)-1); \
|
||||||
} \
|
} \
|
||||||
static inline void set_##n(uint16_t v) { \
|
static inline void set_##n(max2837_driver_t* const _d, uint16_t v) { \
|
||||||
max2837_regs[r] &= ~(((1<<l)-1)<<(o-l+1)); \
|
_d->regs[r] &= ~(((1<<l)-1)<<(o-l+1)); \
|
||||||
max2837_regs[r] |= ((v&((1<<l)-1))<<(o-l+1)); \
|
_d->regs[r] |= ((v&((1<<l)-1))<<(o-l+1)); \
|
||||||
MAX2837_REG_SET_DIRTY(r); \
|
MAX2837_REG_SET_DIRTY(_d, r); \
|
||||||
}
|
}
|
||||||
|
|
||||||
/* REG 0 */
|
/* REG 0 */
|
||||||
|
105
firmware/common/max2837_target.c
Normal file
105
firmware/common/max2837_target.c
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 Will Code? (TODO: Proper attribution)
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "max2837_target.h"
|
||||||
|
|
||||||
|
#include <libopencm3/lpc43xx/scu.h>
|
||||||
|
#include "hackrf_core.h"
|
||||||
|
|
||||||
|
void max2837_target_init(max2837_driver_t* const drv) {
|
||||||
|
/* 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_XCVR_CS, SCU_GPIO_FAST);
|
||||||
|
|
||||||
|
/* 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. */
|
||||||
|
gpio_output(drv->gpio_enable);
|
||||||
|
gpio_output(drv->gpio_rx_enable);
|
||||||
|
gpio_output(drv->gpio_tx_enable);
|
||||||
|
#ifdef JELLYBEAN
|
||||||
|
gpio_output(drv->gpio_rxhp);
|
||||||
|
gpio_output(drv->gpio_b1);
|
||||||
|
gpio_output(drv->gpio_b2);
|
||||||
|
gpio_output(drv->gpio_b3);
|
||||||
|
gpio_output(drv->gpio_b4);
|
||||||
|
gpio_output(drv->gpio_b5);
|
||||||
|
gpio_output(drv->gpio_b6);
|
||||||
|
gpio_output(drv->gpio_b7);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef JELLYBEAN
|
||||||
|
gpio_set(drv->gpio_rxhp);
|
||||||
|
gpio_set(drv->gpio_b1);
|
||||||
|
gpio_set(drv->gpio_b2);
|
||||||
|
gpio_set(drv->gpio_b3);
|
||||||
|
gpio_set(drv->gpio_b4);
|
||||||
|
gpio_set(drv->gpio_b5);
|
||||||
|
gpio_set(drv->gpio_b6);
|
||||||
|
gpio_set(drv->gpio_b7);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void max2837_target_set_mode(max2837_driver_t* const drv, const max2837_mode_t new_mode) {
|
||||||
|
/* MAX2837_MODE_SHUTDOWN:
|
||||||
|
* All circuit blocks are powered down, except the 4-wire serial bus
|
||||||
|
* and its internal programmable registers.
|
||||||
|
*
|
||||||
|
* MAX2837_MODE_STANDBY:
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* MAX2837_MODE_TX:
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* MAX2837_MODE_RX:
|
||||||
|
* 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_write(drv->gpio_enable, new_mode != MAX2837_MODE_SHUTDOWN);
|
||||||
|
gpio_write(drv->gpio_rx_enable, new_mode == MAX2837_MODE_RX);
|
||||||
|
gpio_write(drv->gpio_tx_enable, new_mode == MAX2837_MODE_TX);
|
||||||
|
drv->mode = new_mode;
|
||||||
|
}
|
31
firmware/common/max2837_target.h
Normal file
31
firmware/common/max2837_target.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 Will Code? (TODO: Proper attribution)
|
||||||
|
* 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 __MAX2837_TARGET_H
|
||||||
|
#define __MAX2837_TARGET_H
|
||||||
|
|
||||||
|
#include "max2837.h"
|
||||||
|
|
||||||
|
void max2837_target_init(max2837_driver_t* const drv);
|
||||||
|
void max2837_target_set_mode(max2837_driver_t* const drv, const max2837_mode_t new_mode);
|
||||||
|
|
||||||
|
#endif // __MAX2837_TARGET_H
|
@ -21,16 +21,18 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <libopencm3/lpc43xx/gpio.h>
|
|
||||||
#include <libopencm3/lpc43xx/ssp.h>
|
|
||||||
|
|
||||||
#include "hackrf_core.h"
|
|
||||||
#include "max5864.h"
|
#include "max5864.h"
|
||||||
|
|
||||||
void max5864_spi_write(uint_fast8_t value) {
|
static void max5864_write(max5864_driver_t* const drv, uint8_t value) {
|
||||||
gpio_clear(PORT_AD_CS, PIN_AD_CS);
|
spi_bus_transfer(drv->bus, &value, 1);
|
||||||
ssp_transfer(SSP1_NUM, value);
|
}
|
||||||
gpio_set(PORT_AD_CS, PIN_AD_CS);
|
|
||||||
|
static void max5864_init(max5864_driver_t* const drv) {
|
||||||
|
drv->target_init(drv);
|
||||||
|
}
|
||||||
|
|
||||||
|
void max5864_setup(max5864_driver_t* const drv) {
|
||||||
|
max5864_init(drv);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set MAX5864 operation mode to "Shutdown":
|
/* Set MAX5864 operation mode to "Shutdown":
|
||||||
@ -39,9 +41,9 @@ void max5864_spi_write(uint_fast8_t value) {
|
|||||||
* ADCs: off (bus is tri-stated)
|
* ADCs: off (bus is tri-stated)
|
||||||
* DACs: off (set input bus to zero or OVdd)
|
* DACs: off (set input bus to zero or OVdd)
|
||||||
*/
|
*/
|
||||||
void max5864_shutdown()
|
void max5864_shutdown(max5864_driver_t* const drv)
|
||||||
{
|
{
|
||||||
max5864_spi_write(0x00);
|
max5864_write(drv, 0x00);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set MAX5864 operation mode to "Standby":
|
/* Set MAX5864 operation mode to "Standby":
|
||||||
@ -50,9 +52,9 @@ void max5864_shutdown()
|
|||||||
* ADCs: off (bus is tri-stated)
|
* ADCs: off (bus is tri-stated)
|
||||||
* DACs: off (set input bus to zero or OVdd)
|
* DACs: off (set input bus to zero or OVdd)
|
||||||
*/
|
*/
|
||||||
void max5864_standby()
|
void max5864_standby(max5864_driver_t* const drv)
|
||||||
{
|
{
|
||||||
max5864_spi_write(0x05);
|
max5864_write(drv, 0x05);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set MAX5864 operation mode to "Idle":
|
/* Set MAX5864 operation mode to "Idle":
|
||||||
@ -61,9 +63,9 @@ void max5864_standby()
|
|||||||
* ADCs: off (bus is tri-stated)
|
* ADCs: off (bus is tri-stated)
|
||||||
* DACs: off (set input bus to zero or OVdd)
|
* DACs: off (set input bus to zero or OVdd)
|
||||||
*/
|
*/
|
||||||
void max5864_idle()
|
void max5864_idle(max5864_driver_t* const drv)
|
||||||
{
|
{
|
||||||
max5864_spi_write(0x01);
|
max5864_write(drv, 0x01);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set MAX5864 operation mode to "Rx":
|
/* Set MAX5864 operation mode to "Rx":
|
||||||
@ -72,9 +74,9 @@ void max5864_idle()
|
|||||||
* ADCs: on
|
* ADCs: on
|
||||||
* DACs: off (set input bus to zero or OVdd)
|
* DACs: off (set input bus to zero or OVdd)
|
||||||
*/
|
*/
|
||||||
void max5864_rx()
|
void max5864_rx(max5864_driver_t* const drv)
|
||||||
{
|
{
|
||||||
max5864_spi_write(0x02);
|
max5864_write(drv, 0x02);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set MAX5864 operation mode to "Tx":
|
/* Set MAX5864 operation mode to "Tx":
|
||||||
@ -83,9 +85,9 @@ void max5864_rx()
|
|||||||
* ADCs: off (bus is tri-stated)
|
* ADCs: off (bus is tri-stated)
|
||||||
* DACs: on
|
* DACs: on
|
||||||
*/
|
*/
|
||||||
void max5864_tx()
|
void max5864_tx(max5864_driver_t* const drv)
|
||||||
{
|
{
|
||||||
max5864_spi_write(0x03);
|
max5864_write(drv, 0x03);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set MAX5864 operation mode to "Xcvr":
|
/* Set MAX5864 operation mode to "Xcvr":
|
||||||
@ -94,7 +96,7 @@ void max5864_tx()
|
|||||||
* ADCs: on
|
* ADCs: on
|
||||||
* DACs: on
|
* DACs: on
|
||||||
*/
|
*/
|
||||||
void max5864_xcvr()
|
void max5864_xcvr(max5864_driver_t* const drv)
|
||||||
{
|
{
|
||||||
max5864_spi_write(0x04);
|
max5864_write(drv, 0x04);
|
||||||
}
|
}
|
||||||
|
@ -22,11 +22,23 @@
|
|||||||
#ifndef __MAX5864_H
|
#ifndef __MAX5864_H
|
||||||
#define __MAX5864_H
|
#define __MAX5864_H
|
||||||
|
|
||||||
void max5864_shutdown();
|
#include "spi_bus.h"
|
||||||
void max5864_standby();
|
|
||||||
void max5864_idle();
|
struct max5864_driver_t;
|
||||||
void max5864_rx();
|
typedef struct max5864_driver_t max5864_driver_t;
|
||||||
void max5864_tx();
|
|
||||||
void max5864_xcvr();
|
struct max5864_driver_t {
|
||||||
|
spi_bus_t* const bus;
|
||||||
|
void (*target_init)(max5864_driver_t* const drv);
|
||||||
|
};
|
||||||
|
|
||||||
|
void max5864_setup(max5864_driver_t* const drv);
|
||||||
|
|
||||||
|
void max5864_shutdown(max5864_driver_t* const drv);
|
||||||
|
void max5864_standby(max5864_driver_t* const drv);
|
||||||
|
void max5864_idle(max5864_driver_t* const drv);
|
||||||
|
void max5864_rx(max5864_driver_t* const drv);
|
||||||
|
void max5864_tx(max5864_driver_t* const drv);
|
||||||
|
void max5864_xcvr(max5864_driver_t* const drv);
|
||||||
|
|
||||||
#endif // __MAX5864_H
|
#endif // __MAX5864_H
|
||||||
|
40
firmware/common/max5864_target.c
Normal file
40
firmware/common/max5864_target.c
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
||||||
|
*
|
||||||
|
* 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 "max5864_target.h"
|
||||||
|
|
||||||
|
#include <libopencm3/lpc43xx/scu.h>
|
||||||
|
#include "hackrf_core.h"
|
||||||
|
|
||||||
|
void max5864_target_init(max5864_driver_t* const drv) {
|
||||||
|
(void)drv;
|
||||||
|
|
||||||
|
/* 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));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
}
|
29
firmware/common/max5864_target.h
Normal file
29
firmware/common/max5864_target.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
||||||
|
*
|
||||||
|
* 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_TARGET_H__
|
||||||
|
#define __MAX5864_TARGET_H__
|
||||||
|
|
||||||
|
#include "max5864.h"
|
||||||
|
|
||||||
|
void max5864_target_init(max5864_driver_t* const drv);
|
||||||
|
|
||||||
|
#endif/*__MAX5864_TARGET_H__*/
|
@ -22,7 +22,6 @@
|
|||||||
|
|
||||||
#include "rf_path.h"
|
#include "rf_path.h"
|
||||||
|
|
||||||
#include <libopencm3/lpc43xx/gpio.h>
|
|
||||||
#include <libopencm3/lpc43xx/scu.h>
|
#include <libopencm3/lpc43xx/scu.h>
|
||||||
|
|
||||||
#include <hackrf_core.h>
|
#include <hackrf_core.h>
|
||||||
@ -84,58 +83,58 @@ uint8_t switchctrl = SWITCHCTRL_SAFE;
|
|||||||
#define SWITCHCTRL_ANT_PWR (1 << 6) /* turn on antenna port power */
|
#define SWITCHCTRL_ANT_PWR (1 << 6) /* turn on antenna port power */
|
||||||
|
|
||||||
#ifdef HACKRF_ONE
|
#ifdef HACKRF_ONE
|
||||||
static void switchctrl_set_hackrf_one(uint8_t ctrl) {
|
static void switchctrl_set_hackrf_one(rf_path_t* const rf_path, uint8_t ctrl) {
|
||||||
if (ctrl & SWITCHCTRL_TX) {
|
if (ctrl & SWITCHCTRL_TX) {
|
||||||
gpio_set(PORT_TX, PIN_TX);
|
gpio_set(rf_path->gpio_tx);
|
||||||
gpio_clear(PORT_RX, PIN_RX);
|
gpio_clear(rf_path->gpio_rx);
|
||||||
} else {
|
} else {
|
||||||
gpio_clear(PORT_TX, PIN_TX);
|
gpio_clear(rf_path->gpio_tx);
|
||||||
gpio_set(PORT_RX, PIN_RX);
|
gpio_set(rf_path->gpio_rx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctrl & SWITCHCTRL_MIX_BYPASS) {
|
if (ctrl & SWITCHCTRL_MIX_BYPASS) {
|
||||||
gpio_set(PORT_MIX_BYPASS, PIN_MIX_BYPASS);
|
gpio_set(rf_path->gpio_mix_bypass);
|
||||||
gpio_clear(PORT_NO_MIX_BYPASS, PIN_NO_MIX_BYPASS);
|
gpio_clear(rf_path->gpio_no_mix_bypass);
|
||||||
if (ctrl & SWITCHCTRL_TX) {
|
if (ctrl & SWITCHCTRL_TX) {
|
||||||
gpio_set(PORT_TX_MIX_BP, PIN_TX_MIX_BP);
|
gpio_set(rf_path->gpio_tx_mix_bp);
|
||||||
gpio_clear(PORT_RX_MIX_BP, PIN_RX_MIX_BP);
|
gpio_clear(rf_path->gpio_rx_mix_bp);
|
||||||
} else {
|
} else {
|
||||||
gpio_clear(PORT_TX_MIX_BP, PIN_TX_MIX_BP);
|
gpio_clear(rf_path->gpio_tx_mix_bp);
|
||||||
gpio_set(PORT_RX_MIX_BP, PIN_RX_MIX_BP);
|
gpio_set(rf_path->gpio_rx_mix_bp);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
gpio_clear(PORT_MIX_BYPASS, PIN_MIX_BYPASS);
|
gpio_clear(rf_path->gpio_mix_bypass);
|
||||||
gpio_set(PORT_NO_MIX_BYPASS, PIN_NO_MIX_BYPASS);
|
gpio_set(rf_path->gpio_no_mix_bypass);
|
||||||
gpio_clear(PORT_TX_MIX_BP, PIN_TX_MIX_BP);
|
gpio_clear(rf_path->gpio_tx_mix_bp);
|
||||||
gpio_clear(PORT_RX_MIX_BP, PIN_RX_MIX_BP);
|
gpio_clear(rf_path->gpio_rx_mix_bp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctrl & SWITCHCTRL_HP) {
|
if (ctrl & SWITCHCTRL_HP) {
|
||||||
gpio_set(PORT_HP, PIN_HP);
|
gpio_set(rf_path->gpio_hp);
|
||||||
gpio_clear(PORT_LP, PIN_LP);
|
gpio_clear(rf_path->gpio_lp);
|
||||||
} else {
|
} else {
|
||||||
gpio_clear(PORT_HP, PIN_HP);
|
gpio_clear(rf_path->gpio_hp);
|
||||||
gpio_set(PORT_LP, PIN_LP);
|
gpio_set(rf_path->gpio_lp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctrl & SWITCHCTRL_AMP_BYPASS) {
|
if (ctrl & SWITCHCTRL_AMP_BYPASS) {
|
||||||
gpio_set(PORT_AMP_BYPASS, PIN_AMP_BYPASS);
|
gpio_set(rf_path->gpio_amp_bypass);
|
||||||
gpio_clear(PORT_TX_AMP, PIN_TX_AMP);
|
gpio_clear(rf_path->gpio_tx_amp);
|
||||||
gpio_set(PORT_NO_TX_AMP_PWR, PIN_NO_TX_AMP_PWR);
|
gpio_set(rf_path->gpio_no_tx_amp_pwr);
|
||||||
gpio_clear(PORT_RX_AMP, PIN_RX_AMP);
|
gpio_clear(rf_path->gpio_rx_amp);
|
||||||
gpio_set(PORT_NO_RX_AMP_PWR, PIN_NO_RX_AMP_PWR);
|
gpio_set(rf_path->gpio_no_rx_amp_pwr);
|
||||||
} else if (ctrl & SWITCHCTRL_TX) {
|
} else if (ctrl & SWITCHCTRL_TX) {
|
||||||
gpio_clear(PORT_AMP_BYPASS, PIN_AMP_BYPASS);
|
gpio_clear(rf_path->gpio_amp_bypass);
|
||||||
gpio_set(PORT_TX_AMP, PIN_TX_AMP);
|
gpio_set(rf_path->gpio_tx_amp);
|
||||||
gpio_clear(PORT_NO_TX_AMP_PWR, PIN_NO_TX_AMP_PWR);
|
gpio_clear(rf_path->gpio_no_tx_amp_pwr);
|
||||||
gpio_clear(PORT_RX_AMP, PIN_RX_AMP);
|
gpio_clear(rf_path->gpio_rx_amp);
|
||||||
gpio_set(PORT_NO_RX_AMP_PWR, PIN_NO_RX_AMP_PWR);
|
gpio_set(rf_path->gpio_no_rx_amp_pwr);
|
||||||
} else {
|
} else {
|
||||||
gpio_clear(PORT_AMP_BYPASS, PIN_AMP_BYPASS);
|
gpio_clear(rf_path->gpio_amp_bypass);
|
||||||
gpio_clear(PORT_TX_AMP, PIN_TX_AMP);
|
gpio_clear(rf_path->gpio_tx_amp);
|
||||||
gpio_set(PORT_NO_TX_AMP_PWR, PIN_NO_TX_AMP_PWR);
|
gpio_set(rf_path->gpio_no_tx_amp_pwr);
|
||||||
gpio_set(PORT_RX_AMP, PIN_RX_AMP);
|
gpio_set(rf_path->gpio_rx_amp);
|
||||||
gpio_clear(PORT_NO_RX_AMP_PWR, PIN_NO_RX_AMP_PWR);
|
gpio_clear(rf_path->gpio_no_rx_amp_pwr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -144,29 +143,29 @@ static void switchctrl_set_hackrf_one(uint8_t ctrl) {
|
|||||||
* is unset:
|
* is unset:
|
||||||
*/
|
*/
|
||||||
if (ctrl & SWITCHCTRL_NO_TX_AMP_PWR)
|
if (ctrl & SWITCHCTRL_NO_TX_AMP_PWR)
|
||||||
gpio_set(PORT_NO_TX_AMP_PWR, PIN_NO_TX_AMP_PWR);
|
gpio_set(rf_path->gpio_no_tx_amp_pwr);
|
||||||
if (ctrl & SWITCHCTRL_NO_RX_AMP_PWR)
|
if (ctrl & SWITCHCTRL_NO_RX_AMP_PWR)
|
||||||
gpio_set(PORT_NO_RX_AMP_PWR, PIN_NO_RX_AMP_PWR);
|
gpio_set(rf_path->gpio_no_rx_amp_pwr);
|
||||||
|
|
||||||
if (ctrl & SWITCHCTRL_ANT_PWR) {
|
if (ctrl & SWITCHCTRL_ANT_PWR) {
|
||||||
rffc5071_set_gpo(0x00); /* turn on antenna power by clearing GPO1 */
|
rffc5071_set_gpo(&rffc5072, 0x00); /* turn on antenna power by clearing GPO1 */
|
||||||
} else {
|
} else {
|
||||||
rffc5071_set_gpo(0x01); /* turn off antenna power by setting GPO1 */
|
rffc5071_set_gpo(&rffc5072, 0x01); /* turn off antenna power by setting GPO1 */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void switchctrl_set(const uint8_t gpo) {
|
static void switchctrl_set(rf_path_t* const rf_path, const uint8_t gpo) {
|
||||||
#ifdef JAWBREAKER
|
#ifdef JAWBREAKER
|
||||||
rffc5071_set_gpo(gpo);
|
rffc5071_set_gpo(&rffc5072, gpo);
|
||||||
#elif HACKRF_ONE
|
#elif HACKRF_ONE
|
||||||
switchctrl_set_hackrf_one(gpo);
|
switchctrl_set_hackrf_one(rf_path, gpo);
|
||||||
#else
|
#else
|
||||||
(void)gpo;
|
(void)gpo;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void rf_path_pin_setup() {
|
void rf_path_pin_setup(rf_path_t* const rf_path) {
|
||||||
#ifdef HACKRF_ONE
|
#ifdef HACKRF_ONE
|
||||||
/* Configure RF switch control signals */
|
/* Configure RF switch control signals */
|
||||||
scu_pinmux(SCU_HP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
|
scu_pinmux(SCU_HP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
|
||||||
@ -187,149 +186,152 @@ void rf_path_pin_setup() {
|
|||||||
scu_pinmux(SCU_NO_VAA_ENABLE, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
|
scu_pinmux(SCU_NO_VAA_ENABLE, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
|
||||||
|
|
||||||
/* Configure RF switch control signals as outputs */
|
/* Configure RF switch control signals as outputs */
|
||||||
GPIO0_DIR |= PIN_AMP_BYPASS;
|
gpio_output(rf_path->gpio_amp_bypass);
|
||||||
GPIO1_DIR |= (PIN_NO_MIX_BYPASS | PIN_RX_AMP | PIN_NO_RX_AMP_PWR);
|
gpio_output(rf_path->gpio_no_mix_bypass);
|
||||||
GPIO2_DIR |= (PIN_HP | PIN_LP | PIN_TX_MIX_BP | PIN_RX_MIX_BP | PIN_TX_AMP);
|
gpio_output(rf_path->gpio_rx_amp);
|
||||||
GPIO3_DIR |= PIN_NO_TX_AMP_PWR;
|
gpio_output(rf_path->gpio_no_rx_amp_pwr);
|
||||||
GPIO5_DIR |= (PIN_TX | PIN_MIX_BYPASS | PIN_RX);
|
gpio_output(rf_path->gpio_hp);
|
||||||
|
gpio_output(rf_path->gpio_lp);
|
||||||
|
gpio_output(rf_path->gpio_tx_mix_bp);
|
||||||
|
gpio_output(rf_path->gpio_rx_mix_bp);
|
||||||
|
gpio_output(rf_path->gpio_tx_amp);
|
||||||
|
gpio_output(rf_path->gpio_no_tx_amp_pwr);
|
||||||
|
gpio_output(rf_path->gpio_tx);
|
||||||
|
gpio_output(rf_path->gpio_mix_bypass);
|
||||||
|
gpio_output(rf_path->gpio_rx);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Safe (initial) switch settings turn off both amplifiers and antenna port
|
* Safe (initial) switch settings turn off both amplifiers and antenna port
|
||||||
* power and enable both amp bypass and mixer bypass.
|
* power and enable both amp bypass and mixer bypass.
|
||||||
*/
|
*/
|
||||||
switchctrl_set(SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_MIX_BYPASS);
|
switchctrl_set(rf_path, 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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void rf_path_init(void) {
|
void rf_path_init(rf_path_t* const rf_path) {
|
||||||
ssp1_set_mode_max5864();
|
ssp1_set_mode_max5864();
|
||||||
max5864_shutdown();
|
max5864_setup(&max5864);
|
||||||
|
max5864_shutdown(&max5864);
|
||||||
|
|
||||||
ssp1_set_mode_max2837();
|
ssp1_set_mode_max2837();
|
||||||
max2837_setup();
|
max2837_setup(&max2837);
|
||||||
max2837_start();
|
max2837_start(&max2837);
|
||||||
|
|
||||||
rffc5071_setup();
|
rffc5071_setup(&rffc5072);
|
||||||
switchctrl_set(switchctrl);
|
switchctrl_set(rf_path, switchctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rf_path_set_direction(const rf_path_direction_t direction) {
|
void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t direction) {
|
||||||
/* Turn off TX and RX amplifiers, then enable based on direction and bypass state. */
|
/* 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;
|
rf_path->switchctrl |= SWITCHCTRL_NO_TX_AMP_PWR | SWITCHCTRL_NO_RX_AMP_PWR;
|
||||||
switch(direction) {
|
switch(direction) {
|
||||||
case RF_PATH_DIRECTION_TX:
|
case RF_PATH_DIRECTION_TX:
|
||||||
switchctrl |= SWITCHCTRL_TX;
|
rf_path->switchctrl |= SWITCHCTRL_TX;
|
||||||
if( (switchctrl & SWITCHCTRL_AMP_BYPASS) == 0 ) {
|
if( (rf_path->switchctrl & SWITCHCTRL_AMP_BYPASS) == 0 ) {
|
||||||
/* TX amplifier is in path, be sure to enable TX amplifier. */
|
/* TX amplifier is in path, be sure to enable TX amplifier. */
|
||||||
switchctrl &= ~SWITCHCTRL_NO_TX_AMP_PWR;
|
rf_path->switchctrl &= ~SWITCHCTRL_NO_TX_AMP_PWR;
|
||||||
}
|
}
|
||||||
rffc5071_tx();
|
rffc5071_tx(&rffc5072);
|
||||||
if( switchctrl & SWITCHCTRL_MIX_BYPASS ) {
|
if( rf_path->switchctrl & SWITCHCTRL_MIX_BYPASS ) {
|
||||||
rffc5071_disable();
|
rffc5071_disable(&rffc5072);
|
||||||
} else {
|
} else {
|
||||||
rffc5071_enable();
|
rffc5071_enable(&rffc5072);
|
||||||
}
|
}
|
||||||
ssp1_set_mode_max5864();
|
ssp1_set_mode_max5864();
|
||||||
max5864_tx();
|
max5864_tx(&max5864);
|
||||||
ssp1_set_mode_max2837();
|
ssp1_set_mode_max2837();
|
||||||
max2837_tx();
|
max2837_tx(&max2837);
|
||||||
sgpio_configure(SGPIO_DIRECTION_TX);
|
sgpio_configure(&sgpio_config, SGPIO_DIRECTION_TX);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RF_PATH_DIRECTION_RX:
|
case RF_PATH_DIRECTION_RX:
|
||||||
switchctrl &= ~SWITCHCTRL_TX;
|
rf_path->switchctrl &= ~SWITCHCTRL_TX;
|
||||||
if( (switchctrl & SWITCHCTRL_AMP_BYPASS) == 0 ) {
|
if( (rf_path->switchctrl & SWITCHCTRL_AMP_BYPASS) == 0 ) {
|
||||||
/* RX amplifier is in path, be sure to enable RX amplifier. */
|
/* RX amplifier is in path, be sure to enable RX amplifier. */
|
||||||
switchctrl &= ~SWITCHCTRL_NO_RX_AMP_PWR;
|
rf_path->switchctrl &= ~SWITCHCTRL_NO_RX_AMP_PWR;
|
||||||
}
|
}
|
||||||
rffc5071_rx();
|
rffc5071_rx(&rffc5072);
|
||||||
if( switchctrl & SWITCHCTRL_MIX_BYPASS ) {
|
if( rf_path->switchctrl & SWITCHCTRL_MIX_BYPASS ) {
|
||||||
rffc5071_disable();
|
rffc5071_disable(&rffc5072);
|
||||||
} else {
|
} else {
|
||||||
rffc5071_enable();
|
rffc5071_enable(&rffc5072);
|
||||||
}
|
}
|
||||||
ssp1_set_mode_max5864();
|
ssp1_set_mode_max5864();
|
||||||
max5864_rx();
|
max5864_rx(&max5864);
|
||||||
ssp1_set_mode_max2837();
|
ssp1_set_mode_max2837();
|
||||||
max2837_rx();
|
max2837_rx(&max2837);
|
||||||
sgpio_configure(SGPIO_DIRECTION_RX);
|
sgpio_configure(&sgpio_config, SGPIO_DIRECTION_RX);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RF_PATH_DIRECTION_OFF:
|
case RF_PATH_DIRECTION_OFF:
|
||||||
default:
|
default:
|
||||||
#ifdef HACKRF_ONE
|
#ifdef HACKRF_ONE
|
||||||
rf_path_set_antenna(0);
|
rf_path_set_antenna(rf_path, 0);
|
||||||
#endif
|
#endif
|
||||||
rf_path_set_lna(0);
|
rf_path_set_lna(rf_path, 0);
|
||||||
/* Set RF path to receive direction when "off" */
|
/* Set RF path to receive direction when "off" */
|
||||||
switchctrl &= ~SWITCHCTRL_TX;
|
rf_path->switchctrl &= ~SWITCHCTRL_TX;
|
||||||
rffc5071_disable();
|
rffc5071_disable(&rffc5072);
|
||||||
ssp1_set_mode_max5864();
|
ssp1_set_mode_max5864();
|
||||||
max5864_standby();
|
max5864_standby(&max5864);
|
||||||
ssp1_set_mode_max2837();
|
ssp1_set_mode_max2837();
|
||||||
max2837_set_mode(MAX2837_MODE_STANDBY);
|
max2837_set_mode(&max2837, MAX2837_MODE_STANDBY);
|
||||||
sgpio_configure(SGPIO_DIRECTION_RX);
|
sgpio_configure(&sgpio_config, SGPIO_DIRECTION_RX);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switchctrl_set(switchctrl);
|
switchctrl_set(rf_path, rf_path->switchctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rf_path_set_filter(const rf_path_filter_t filter) {
|
void rf_path_set_filter(rf_path_t* const rf_path, const rf_path_filter_t filter) {
|
||||||
switch(filter) {
|
switch(filter) {
|
||||||
default:
|
default:
|
||||||
case RF_PATH_FILTER_BYPASS:
|
case RF_PATH_FILTER_BYPASS:
|
||||||
switchctrl |= SWITCHCTRL_MIX_BYPASS;
|
rf_path->switchctrl |= SWITCHCTRL_MIX_BYPASS;
|
||||||
rffc5071_disable();
|
rffc5071_disable(&rffc5072);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RF_PATH_FILTER_LOW_PASS:
|
case RF_PATH_FILTER_LOW_PASS:
|
||||||
switchctrl &= ~(SWITCHCTRL_HP | SWITCHCTRL_MIX_BYPASS);
|
rf_path->switchctrl &= ~(SWITCHCTRL_HP | SWITCHCTRL_MIX_BYPASS);
|
||||||
rffc5071_enable();
|
rffc5071_enable(&rffc5072);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RF_PATH_FILTER_HIGH_PASS:
|
case RF_PATH_FILTER_HIGH_PASS:
|
||||||
switchctrl &= ~SWITCHCTRL_MIX_BYPASS;
|
rf_path->switchctrl &= ~SWITCHCTRL_MIX_BYPASS;
|
||||||
switchctrl |= SWITCHCTRL_HP;
|
rf_path->switchctrl |= SWITCHCTRL_HP;
|
||||||
rffc5071_enable();
|
rffc5071_enable(&rffc5072);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switchctrl_set(switchctrl);
|
switchctrl_set(rf_path, rf_path->switchctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rf_path_set_lna(const uint_fast8_t enable) {
|
void rf_path_set_lna(rf_path_t* const rf_path, const uint_fast8_t enable) {
|
||||||
if( enable ) {
|
if( enable ) {
|
||||||
if( switchctrl & SWITCHCTRL_TX ) {
|
if( rf_path->switchctrl & SWITCHCTRL_TX ) {
|
||||||
/* AMP_BYPASS=0, NO_RX_AMP_PWR=1, NO_TX_AMP_PWR=0 */
|
/* AMP_BYPASS=0, NO_RX_AMP_PWR=1, NO_TX_AMP_PWR=0 */
|
||||||
switchctrl |= SWITCHCTRL_NO_RX_AMP_PWR;
|
rf_path->switchctrl |= SWITCHCTRL_NO_RX_AMP_PWR;
|
||||||
switchctrl &= ~(SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_NO_TX_AMP_PWR);
|
rf_path->switchctrl &= ~(SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_NO_TX_AMP_PWR);
|
||||||
} else {
|
} else {
|
||||||
/* AMP_BYPASS=0, NO_RX_AMP_PWR=0, NO_TX_AMP_PWR=1 */
|
/* AMP_BYPASS=0, NO_RX_AMP_PWR=0, NO_TX_AMP_PWR=1 */
|
||||||
switchctrl |= SWITCHCTRL_NO_TX_AMP_PWR;
|
rf_path->switchctrl |= SWITCHCTRL_NO_TX_AMP_PWR;
|
||||||
switchctrl &= ~(SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_NO_RX_AMP_PWR);
|
rf_path->switchctrl &= ~(SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_NO_RX_AMP_PWR);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* AMP_BYPASS=1, NO_RX_AMP_PWR=1, NO_TX_AMP_PWR=1 */
|
/* 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;
|
rf_path->switchctrl |= SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_NO_TX_AMP_PWR | SWITCHCTRL_NO_RX_AMP_PWR;
|
||||||
}
|
}
|
||||||
|
|
||||||
switchctrl_set(switchctrl);
|
switchctrl_set(rf_path, rf_path->switchctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* antenna port power control */
|
/* antenna port power control */
|
||||||
void rf_path_set_antenna(const uint_fast8_t enable) {
|
void rf_path_set_antenna(rf_path_t* const rf_path, const uint_fast8_t enable) {
|
||||||
if (enable) {
|
if (enable) {
|
||||||
switchctrl |= SWITCHCTRL_ANT_PWR;
|
rf_path->switchctrl |= SWITCHCTRL_ANT_PWR;
|
||||||
} else {
|
} else {
|
||||||
switchctrl &= ~(SWITCHCTRL_ANT_PWR);
|
rf_path->switchctrl &= ~(SWITCHCTRL_ANT_PWR);
|
||||||
}
|
}
|
||||||
|
|
||||||
switchctrl_set(switchctrl);
|
switchctrl_set(rf_path, rf_path->switchctrl);
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,7 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
void rf_path_pin_setup(void);
|
#include "gpio.h"
|
||||||
void rf_path_init(void);
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
RF_PATH_DIRECTION_OFF,
|
RF_PATH_DIRECTION_OFF,
|
||||||
@ -34,17 +33,39 @@ typedef enum {
|
|||||||
RF_PATH_DIRECTION_TX,
|
RF_PATH_DIRECTION_TX,
|
||||||
} rf_path_direction_t;
|
} rf_path_direction_t;
|
||||||
|
|
||||||
void rf_path_set_direction(const rf_path_direction_t direction);
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
RF_PATH_FILTER_BYPASS = 0,
|
RF_PATH_FILTER_BYPASS = 0,
|
||||||
RF_PATH_FILTER_LOW_PASS = 1,
|
RF_PATH_FILTER_LOW_PASS = 1,
|
||||||
RF_PATH_FILTER_HIGH_PASS = 2,
|
RF_PATH_FILTER_HIGH_PASS = 2,
|
||||||
} rf_path_filter_t;
|
} rf_path_filter_t;
|
||||||
|
|
||||||
void rf_path_set_filter(const rf_path_filter_t filter);
|
typedef struct rf_path_t {
|
||||||
|
uint8_t switchctrl;
|
||||||
|
#ifdef HACKRF_ONE
|
||||||
|
gpio_t gpio_hp;
|
||||||
|
gpio_t gpio_lp;
|
||||||
|
gpio_t gpio_tx_mix_bp;
|
||||||
|
gpio_t gpio_no_mix_bypass;
|
||||||
|
gpio_t gpio_rx_mix_bp;
|
||||||
|
gpio_t gpio_tx_amp;
|
||||||
|
gpio_t gpio_tx;
|
||||||
|
gpio_t gpio_mix_bypass;
|
||||||
|
gpio_t gpio_rx;
|
||||||
|
gpio_t gpio_no_tx_amp_pwr;
|
||||||
|
gpio_t gpio_amp_bypass;
|
||||||
|
gpio_t gpio_rx_amp;
|
||||||
|
gpio_t gpio_no_rx_amp_pwr;
|
||||||
|
#endif
|
||||||
|
} rf_path_t;
|
||||||
|
|
||||||
void rf_path_set_lna(const uint_fast8_t enable);
|
void rf_path_pin_setup(rf_path_t* const rf_path);
|
||||||
void rf_path_set_antenna(const uint_fast8_t enable);
|
void rf_path_init(rf_path_t* const rf_path);
|
||||||
|
|
||||||
|
void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t direction);
|
||||||
|
|
||||||
|
void rf_path_set_filter(rf_path_t* const rf_path, const rf_path_filter_t filter);
|
||||||
|
|
||||||
|
void rf_path_set_lna(rf_path_t* const rf_path, const uint_fast8_t enable);
|
||||||
|
void rf_path_set_antenna(rf_path_t* const rf_path, const uint_fast8_t enable);
|
||||||
|
|
||||||
#endif/*__RFPATH_H__*/
|
#endif/*__RFPATH_H__*/
|
||||||
|
@ -36,19 +36,10 @@
|
|||||||
#include "rffc5071.h"
|
#include "rffc5071.h"
|
||||||
#include "rffc5071_regs.def" // private register def macros
|
#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"
|
#include "hackrf_core.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Default register values. */
|
/* Default register values. */
|
||||||
static uint16_t rffc5071_regs_default[RFFC5071_NUM_REGS] = {
|
static const uint16_t rffc5071_regs_default[RFFC5071_NUM_REGS] = {
|
||||||
0xbefa, /* 00 */
|
0xbefa, /* 00 */
|
||||||
0x4064, /* 01 */
|
0x4064, /* 01 */
|
||||||
0x9055, /* 02 */
|
0x9055, /* 02 */
|
||||||
@ -81,327 +72,139 @@ static uint16_t rffc5071_regs_default[RFFC5071_NUM_REGS] = {
|
|||||||
0x1000, /* 1D */
|
0x1000, /* 1D */
|
||||||
0x0005, /* 1E */ };
|
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. */
|
/* Set up all registers according to defaults specified in docs. */
|
||||||
void rffc5071_init(void)
|
void rffc5071_init(rffc5071_driver_t* const drv)
|
||||||
{
|
{
|
||||||
LOG("# rffc5071_init\n");
|
memcpy(drv->regs, rffc5071_regs_default, sizeof(drv->regs));
|
||||||
memcpy(rffc5071_regs, rffc5071_regs_default, sizeof(rffc5071_regs));
|
drv->regs_dirty = 0x7fffffff;
|
||||||
rffc5071_regs_dirty = 0x7fffffff;
|
|
||||||
|
|
||||||
/* Write default register values to chip. */
|
/* Write default register values to chip. */
|
||||||
rffc5071_regs_commit();
|
rffc5071_regs_commit(drv);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set up pins for GPIO and SPI control, configure SSP peripheral for SPI, and
|
* Set up pins for GPIO and SPI control, configure SSP peripheral for SPI, and
|
||||||
* set our own default register configuration.
|
* set our own default register configuration.
|
||||||
*/
|
*/
|
||||||
void rffc5071_setup(void)
|
void rffc5071_setup(rffc5071_driver_t* const drv)
|
||||||
{
|
{
|
||||||
rffc5071_init();
|
gpio_set(drv->gpio_reset);
|
||||||
LOG("# rffc5071_setup\n");
|
gpio_output(drv->gpio_reset);
|
||||||
#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. */
|
rffc5071_init(drv);
|
||||||
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 */
|
/* initial setup */
|
||||||
/* put zeros in freq contol registers */
|
/* put zeros in freq contol registers */
|
||||||
set_RFFC5071_P2N(0);
|
set_RFFC5071_P2N(drv, 0);
|
||||||
set_RFFC5071_P2LODIV(0);
|
set_RFFC5071_P2LODIV(drv, 0);
|
||||||
set_RFFC5071_P2PRESC(0);
|
set_RFFC5071_P2PRESC(drv, 0);
|
||||||
set_RFFC5071_P2VCOSEL(0);
|
set_RFFC5071_P2VCOSEL(drv, 0);
|
||||||
|
|
||||||
set_RFFC5071_P2N(0);
|
set_RFFC5071_P2N(drv, 0);
|
||||||
set_RFFC5071_P2LODIV(0);
|
set_RFFC5071_P2LODIV(drv, 0);
|
||||||
set_RFFC5071_P2PRESC(0);
|
set_RFFC5071_P2PRESC(drv, 0);
|
||||||
set_RFFC5071_P2VCOSEL(0);
|
set_RFFC5071_P2VCOSEL(drv, 0);
|
||||||
|
|
||||||
set_RFFC5071_P2N(0);
|
set_RFFC5071_P2N(drv, 0);
|
||||||
set_RFFC5071_P2LODIV(0);
|
set_RFFC5071_P2LODIV(drv, 0);
|
||||||
set_RFFC5071_P2PRESC(0);
|
set_RFFC5071_P2PRESC(drv, 0);
|
||||||
set_RFFC5071_P2VCOSEL(0);
|
set_RFFC5071_P2VCOSEL(drv, 0);
|
||||||
|
|
||||||
/* set ENBL and MODE to be configured via 3-wire interface,
|
/* set ENBL and MODE to be configured via 3-wire interface,
|
||||||
* not control pins. */
|
* not control pins. */
|
||||||
set_RFFC5071_SIPIN(1);
|
set_RFFC5071_SIPIN(drv, 1);
|
||||||
|
|
||||||
/* GPOs are active at all times */
|
/* GPOs are active at all times */
|
||||||
set_RFFC5071_GATE(1);
|
set_RFFC5071_GATE(drv, 1);
|
||||||
|
|
||||||
rffc5071_regs_commit();
|
rffc5071_regs_commit(drv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void serial_delay(void)
|
static uint16_t rffc5071_spi_read(rffc5071_driver_t* const drv, uint8_t r) {
|
||||||
{
|
(void)drv;
|
||||||
uint32_t i;
|
|
||||||
|
|
||||||
for (i = 0; i < 2; i++)
|
uint16_t data[] = { 0x80 | (r & 0x7f), 0xffff };
|
||||||
__asm__("nop");
|
spi_bus_transfer(drv->bus, data, 2);
|
||||||
|
return data[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SPI register read.
|
static void rffc5071_spi_write(rffc5071_driver_t* const drv, uint8_t r, uint16_t v) {
|
||||||
*
|
(void)drv;
|
||||||
* 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;
|
uint16_t data[] = { 0x00 | (r & 0x7f), v };
|
||||||
int msb = 1 << (bits -1);
|
spi_bus_transfer(drv->bus, data, 2);
|
||||||
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
|
uint16_t rffc5071_reg_read(rffc5071_driver_t* const drv, uint8_t r)
|
||||||
*
|
|
||||||
* 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. */
|
/* Readback register is not cached. */
|
||||||
if (r == RFFC5071_READBACK_REG)
|
if (r == RFFC5071_READBACK_REG)
|
||||||
return rffc5071_spi_read(r);
|
return rffc5071_spi_read(drv, r);
|
||||||
|
|
||||||
/* Discard uncommited write when reading. This shouldn't
|
/* Discard uncommited write when reading. This shouldn't
|
||||||
* happen, and probably has not been tested. */
|
* happen, and probably has not been tested. */
|
||||||
if ((rffc5071_regs_dirty >> r) & 0x1) {
|
if ((drv->regs_dirty >> r) & 0x1) {
|
||||||
rffc5071_regs[r] = rffc5071_spi_read(r);
|
drv->regs[r] = rffc5071_spi_read(drv, r);
|
||||||
};
|
};
|
||||||
return rffc5071_regs[r];
|
return drv->regs[r];
|
||||||
}
|
}
|
||||||
|
|
||||||
void rffc5071_reg_write(uint8_t r, uint16_t v)
|
void rffc5071_reg_write(rffc5071_driver_t* const drv, uint8_t r, uint16_t v)
|
||||||
{
|
{
|
||||||
rffc5071_regs[r] = v;
|
drv->regs[r] = v;
|
||||||
rffc5071_spi_write(r, v);
|
rffc5071_spi_write(drv, r, v);
|
||||||
RFFC5071_REG_SET_CLEAN(r);
|
RFFC5071_REG_SET_CLEAN(drv, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void rffc5071_reg_commit(uint8_t r)
|
static inline void rffc5071_reg_commit(rffc5071_driver_t* const drv, uint8_t r)
|
||||||
{
|
{
|
||||||
rffc5071_reg_write(r,rffc5071_regs[r]);
|
rffc5071_reg_write(drv, r, drv->regs[r]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rffc5071_regs_commit(void)
|
void rffc5071_regs_commit(rffc5071_driver_t* const drv)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
for(r = 0; r < RFFC5071_NUM_REGS; r++) {
|
for(r = 0; r < RFFC5071_NUM_REGS; r++) {
|
||||||
if ((rffc5071_regs_dirty >> r) & 0x1) {
|
if ((drv->regs_dirty >> r) & 0x1) {
|
||||||
rffc5071_reg_commit(r);
|
rffc5071_reg_commit(drv, r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void rffc5071_tx(void) {
|
void rffc5071_tx(rffc5071_driver_t* const drv) {
|
||||||
LOG("# rffc5071_tx\n");
|
set_RFFC5071_ENBL(drv, 0);
|
||||||
set_RFFC5071_ENBL(0);
|
set_RFFC5071_FULLD(drv, 0);
|
||||||
set_RFFC5071_FULLD(0);
|
set_RFFC5071_MODE(drv, 1); /* mixer 2 used for both RX and TX */
|
||||||
set_RFFC5071_MODE(1); /* mixer 2 used for both RX and TX */
|
rffc5071_regs_commit(drv);
|
||||||
rffc5071_regs_commit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void rffc5071_rx(void) {
|
void rffc5071_rx(rffc5071_driver_t* const drv) {
|
||||||
LOG("# rfc5071_rx\n");
|
set_RFFC5071_ENBL(drv, 0);
|
||||||
set_RFFC5071_ENBL(0);
|
set_RFFC5071_FULLD(drv, 0);
|
||||||
set_RFFC5071_FULLD(0);
|
set_RFFC5071_MODE(drv, 1); /* mixer 2 used for both RX and TX */
|
||||||
set_RFFC5071_MODE(1); /* mixer 2 used for both RX and TX */
|
rffc5071_regs_commit(drv);
|
||||||
rffc5071_regs_commit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function turns on both mixer (full-duplex) on the RFFC5071, but our
|
* This function turns on both mixer (full-duplex) on the RFFC5071, but our
|
||||||
* current hardware designs do not support full-duplex operation.
|
* current hardware designs do not support full-duplex operation.
|
||||||
*/
|
*/
|
||||||
void rffc5071_rxtx(void) {
|
void rffc5071_rxtx(rffc5071_driver_t* const drv) {
|
||||||
LOG("# rfc5071_rxtx\n");
|
set_RFFC5071_ENBL(drv, 0);
|
||||||
set_RFFC5071_ENBL(0);
|
set_RFFC5071_FULLD(drv, 1); /* mixer 1 and mixer 2 (RXTX) */
|
||||||
set_RFFC5071_FULLD(1); /* mixer 1 and mixer 2 (RXTX) */
|
rffc5071_regs_commit(drv);
|
||||||
rffc5071_regs_commit();
|
|
||||||
|
|
||||||
rffc5071_enable();
|
rffc5071_enable(drv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rffc5071_disable(void) {
|
void rffc5071_disable(rffc5071_driver_t* const drv) {
|
||||||
LOG("# rfc5071_disable\n");
|
set_RFFC5071_ENBL(drv, 0);
|
||||||
set_RFFC5071_ENBL(0);
|
rffc5071_regs_commit(drv);
|
||||||
rffc5071_regs_commit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void rffc5071_enable(void) {
|
void rffc5071_enable(rffc5071_driver_t* const drv) {
|
||||||
LOG("# rfc5071_enable\n");
|
set_RFFC5071_ENBL(drv, 1);
|
||||||
set_RFFC5071_ENBL(1);
|
rffc5071_regs_commit(drv);
|
||||||
rffc5071_regs_commit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define LO_MAX 5400
|
#define LO_MAX 5400
|
||||||
@ -409,7 +212,7 @@ void rffc5071_enable(void) {
|
|||||||
#define FREQ_ONE_MHZ (1000*1000)
|
#define FREQ_ONE_MHZ (1000*1000)
|
||||||
|
|
||||||
/* configure frequency synthesizer in integer mode (lo in MHz) */
|
/* configure frequency synthesizer in integer mode (lo in MHz) */
|
||||||
uint64_t rffc5071_config_synth_int(uint16_t lo) {
|
uint64_t rffc5071_config_synth_int(rffc5071_driver_t* const drv, uint16_t lo) {
|
||||||
uint8_t lodiv;
|
uint8_t lodiv;
|
||||||
uint16_t fvco;
|
uint16_t fvco;
|
||||||
uint8_t fbkdiv;
|
uint8_t fbkdiv;
|
||||||
@ -418,8 +221,6 @@ uint64_t rffc5071_config_synth_int(uint16_t lo) {
|
|||||||
uint16_t p1nmsb;
|
uint16_t p1nmsb;
|
||||||
uint8_t p1nlsb;
|
uint8_t p1nlsb;
|
||||||
|
|
||||||
LOG("# config_synth_int\n");
|
|
||||||
|
|
||||||
/* Calculate n_lo */
|
/* Calculate n_lo */
|
||||||
uint8_t n_lo = 0;
|
uint8_t n_lo = 0;
|
||||||
uint16_t x = LO_MAX / lo;
|
uint16_t x = LO_MAX / lo;
|
||||||
@ -438,10 +239,10 @@ uint64_t rffc5071_config_synth_int(uint16_t lo) {
|
|||||||
* and will be unaffected. */
|
* and will be unaffected. */
|
||||||
if (fvco > 3200) {
|
if (fvco > 3200) {
|
||||||
fbkdiv = 4;
|
fbkdiv = 4;
|
||||||
set_RFFC5071_PLLCPL(3);
|
set_RFFC5071_PLLCPL(drv, 3);
|
||||||
} else {
|
} else {
|
||||||
fbkdiv = 2;
|
fbkdiv = 2;
|
||||||
set_RFFC5071_PLLCPL(2);
|
set_RFFC5071_PLLCPL(drv, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t tmp_n = ((uint64_t)fvco << 29ULL) / (fbkdiv*REF_FREQ) ;
|
uint64_t tmp_n = ((uint64_t)fvco << 29ULL) / (fbkdiv*REF_FREQ) ;
|
||||||
@ -452,63 +253,42 @@ uint64_t rffc5071_config_synth_int(uint16_t lo) {
|
|||||||
|
|
||||||
tune_freq_hz = (REF_FREQ * (tmp_n >> 5ULL) * fbkdiv * FREQ_ONE_MHZ)
|
tune_freq_hz = (REF_FREQ * (tmp_n >> 5ULL) * fbkdiv * FREQ_ONE_MHZ)
|
||||||
/ (lodiv * (1 << 24ULL));
|
/ (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 */
|
/* Path 1 */
|
||||||
set_RFFC5071_P1LODIV(n_lo);
|
set_RFFC5071_P1LODIV(drv, n_lo);
|
||||||
set_RFFC5071_P1N(n);
|
set_RFFC5071_P1N(drv, n);
|
||||||
set_RFFC5071_P1PRESC(fbkdiv >> 1);
|
set_RFFC5071_P1PRESC(drv, fbkdiv >> 1);
|
||||||
set_RFFC5071_P1NMSB(p1nmsb);
|
set_RFFC5071_P1NMSB(drv, p1nmsb);
|
||||||
set_RFFC5071_P1NLSB(p1nlsb);
|
set_RFFC5071_P1NLSB(drv, p1nlsb);
|
||||||
|
|
||||||
/* Path 2 */
|
/* Path 2 */
|
||||||
set_RFFC5071_P2LODIV(n_lo);
|
set_RFFC5071_P2LODIV(drv, n_lo);
|
||||||
set_RFFC5071_P2N(n);
|
set_RFFC5071_P2N(drv, n);
|
||||||
set_RFFC5071_P2PRESC(fbkdiv >> 1);
|
set_RFFC5071_P2PRESC(drv, fbkdiv >> 1);
|
||||||
set_RFFC5071_P2NMSB(p1nmsb);
|
set_RFFC5071_P2NMSB(drv, p1nmsb);
|
||||||
set_RFFC5071_P2NLSB(p1nlsb);
|
set_RFFC5071_P2NLSB(drv, p1nlsb);
|
||||||
|
|
||||||
rffc5071_regs_commit();
|
rffc5071_regs_commit(drv);
|
||||||
|
|
||||||
return tune_freq_hz;
|
return tune_freq_hz;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* !!!!!!!!!!! hz is currently ignored !!!!!!!!!!! */
|
/* !!!!!!!!!!! hz is currently ignored !!!!!!!!!!! */
|
||||||
uint64_t rffc5071_set_frequency(uint16_t mhz) {
|
uint64_t rffc5071_set_frequency(rffc5071_driver_t* const drv, uint16_t mhz) {
|
||||||
uint32_t tune_freq;
|
uint32_t tune_freq;
|
||||||
|
|
||||||
rffc5071_disable();
|
rffc5071_disable(drv);
|
||||||
tune_freq = rffc5071_config_synth_int(mhz);
|
tune_freq = rffc5071_config_synth_int(drv, mhz);
|
||||||
rffc5071_enable();
|
rffc5071_enable(drv);
|
||||||
|
|
||||||
return tune_freq;
|
return tune_freq;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rffc5071_set_gpo(uint8_t gpo)
|
void rffc5071_set_gpo(rffc5071_driver_t* const drv, uint8_t gpo)
|
||||||
{
|
{
|
||||||
/* We set GPO for both paths just in case. */
|
/* We set GPO for both paths just in case. */
|
||||||
set_RFFC5071_P1GPO(gpo);
|
set_RFFC5071_P1GPO(drv, gpo);
|
||||||
set_RFFC5071_P2GPO(gpo);
|
set_RFFC5071_P2GPO(drv, gpo);
|
||||||
|
|
||||||
rffc5071_regs_commit();
|
rffc5071_regs_commit(drv);
|
||||||
}
|
}
|
||||||
|
|
||||||
#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
|
|
||||||
|
@ -23,43 +23,49 @@
|
|||||||
#ifndef __RFFC5071_H
|
#ifndef __RFFC5071_H
|
||||||
#define __RFFC5071_H
|
#define __RFFC5071_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "spi_bus.h"
|
||||||
|
#include "gpio.h"
|
||||||
|
|
||||||
/* 31 registers, each containing 16 bits of data. */
|
/* 31 registers, each containing 16 bits of data. */
|
||||||
#define RFFC5071_NUM_REGS 31
|
#define RFFC5071_NUM_REGS 31
|
||||||
|
|
||||||
extern uint16_t rffc5071_regs[RFFC5071_NUM_REGS];
|
typedef struct {
|
||||||
extern uint32_t rffc5071_regs_dirty;
|
spi_bus_t* const bus;
|
||||||
|
gpio_t gpio_reset;
|
||||||
#define RFFC5071_REG_SET_CLEAN(r) rffc5071_regs_dirty &= ~(1UL<<r)
|
uint16_t regs[RFFC5071_NUM_REGS];
|
||||||
#define RFFC5071_REG_SET_DIRTY(r) rffc5071_regs_dirty |= (1UL<<r)
|
uint32_t regs_dirty;
|
||||||
|
} rffc5071_driver_t;
|
||||||
|
|
||||||
/* Initialize chip. Call _setup() externally, as it calls _init(). */
|
/* Initialize chip. Call _setup() externally, as it calls _init(). */
|
||||||
extern void rffc5071_init(void);
|
extern void rffc5071_init(rffc5071_driver_t* const drv);
|
||||||
extern void rffc5071_setup(void);
|
extern void rffc5071_setup(rffc5071_driver_t* const drv);
|
||||||
|
|
||||||
/* Read a register via SPI. Save a copy to memory and return
|
/* Read a register via SPI. Save a copy to memory and return
|
||||||
* value. Discard any uncommited changes and mark CLEAN. */
|
* value. Discard any uncommited changes and mark CLEAN. */
|
||||||
extern uint16_t rffc5071_reg_read(uint8_t r);
|
extern uint16_t rffc5071_reg_read(rffc5071_driver_t* const drv, uint8_t r);
|
||||||
|
|
||||||
/* Write value to register via SPI and save a copy to memory. Mark
|
/* Write value to register via SPI and save a copy to memory. Mark
|
||||||
* CLEAN. */
|
* CLEAN. */
|
||||||
extern void rffc5071_reg_write(uint8_t r, uint16_t v);
|
extern void rffc5071_reg_write(rffc5071_driver_t* const drv, uint8_t r, uint16_t v);
|
||||||
|
|
||||||
/* Write all dirty registers via SPI from memory. Mark all clean. Some
|
/* Write all dirty registers via SPI from memory. Mark all clean. Some
|
||||||
* operations require registers to be written in a certain order. Use
|
* operations require registers to be written in a certain order. Use
|
||||||
* provided routines for those operations. */
|
* provided routines for those operations. */
|
||||||
extern void rffc5071_regs_commit(void);
|
extern void rffc5071_regs_commit(rffc5071_driver_t* const drv);
|
||||||
|
|
||||||
/* Set frequency (MHz). */
|
/* Set frequency (MHz). */
|
||||||
extern uint64_t rffc5071_set_frequency(uint16_t mhz);
|
extern uint64_t rffc5071_set_frequency(rffc5071_driver_t* const drv, uint16_t mhz);
|
||||||
|
|
||||||
/* Set up rx only, tx only, or full duplex. Chip should be disabled
|
/* Set up rx only, tx only, or full duplex. Chip should be disabled
|
||||||
* before _tx, _rx, or _rxtx are called. */
|
* before _tx, _rx, or _rxtx are called. */
|
||||||
extern void rffc5071_tx(void);
|
extern void rffc5071_tx(rffc5071_driver_t* const drv);
|
||||||
extern void rffc5071_rx(void);
|
extern void rffc5071_rx(rffc5071_driver_t* const drv);
|
||||||
extern void rffc5071_rxtx(void);
|
extern void rffc5071_rxtx(rffc5071_driver_t* const drv);
|
||||||
extern void rffc5071_enable(void);
|
extern void rffc5071_enable(rffc5071_driver_t* const drv);
|
||||||
extern void rffc5071_disable(void);
|
extern void rffc5071_disable(rffc5071_driver_t* const drv);
|
||||||
|
|
||||||
extern void rffc5071_set_gpo(uint8_t);
|
extern void rffc5071_set_gpo(rffc5071_driver_t* const drv, uint8_t);
|
||||||
|
|
||||||
#endif // __RFFC5071_H
|
#endif // __RFFC5071_H
|
||||||
|
@ -23,6 +23,9 @@
|
|||||||
#ifndef __RFFC5071_REGS_DEF
|
#ifndef __RFFC5071_REGS_DEF
|
||||||
#define __RFFC5071_REGS_DEF
|
#define __RFFC5071_REGS_DEF
|
||||||
|
|
||||||
|
#define RFFC5071_REG_SET_CLEAN(_d, _r) (_d->regs_dirty &= ~(1UL<<_r))
|
||||||
|
#define RFFC5071_REG_SET_DIRTY(_d, _r) (_d->regs_dirty |= (1UL<<_r))
|
||||||
|
|
||||||
#define RFFC5071_READBACK_REG 31
|
#define RFFC5071_READBACK_REG 31
|
||||||
|
|
||||||
/* Generate static inline accessors that operate on the global
|
/* Generate static inline accessors that operate on the global
|
||||||
@ -38,13 +41,13 @@
|
|||||||
/* n=name, r=regnum, o=offset (bits from LSB) of LSB of field,
|
/* n=name, r=regnum, o=offset (bits from LSB) of LSB of field,
|
||||||
* l=length (bits) */
|
* l=length (bits) */
|
||||||
#define __MREG__(n,r,o,l) \
|
#define __MREG__(n,r,o,l) \
|
||||||
static inline uint16_t get_##n(void) { \
|
static inline uint16_t get_##n(rffc5071_driver_t* const _d) { \
|
||||||
return (rffc5071_regs[r] >> o) & ((1L<<l)-1); \
|
return (_d->regs[r] >> o) & ((1L<<l)-1); \
|
||||||
} \
|
} \
|
||||||
static inline void set_##n(uint16_t v) { \
|
static inline void set_##n(rffc5071_driver_t* const _d, uint16_t v) { \
|
||||||
rffc5071_regs[r] &= (uint16_t)(~(((1L<<l)-1)<<o)); \
|
_d->regs[r] &= (uint16_t)(~(((1L<<l)-1)<<o)); \
|
||||||
rffc5071_regs[r] |= (uint16_t)(((v&((1L<<l)-1))<<o)); \
|
_d->regs[r] |= (uint16_t)(((v&((1L<<l)-1))<<o)); \
|
||||||
RFFC5071_REG_SET_DIRTY(r); \
|
RFFC5071_REG_SET_DIRTY(_d, r); \
|
||||||
}
|
}
|
||||||
|
|
||||||
/* REG 00 (0): LF */
|
/* REG 00 (0): LF */
|
||||||
|
187
firmware/common/rffc5071_spi.c
Normal file
187
firmware/common/rffc5071_spi.c
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <libopencm3/lpc43xx/scu.h>
|
||||||
|
#include "hackrf_core.h"
|
||||||
|
|
||||||
|
#include "rffc5071_spi.h"
|
||||||
|
|
||||||
|
static void rffc5071_spi_target_select(spi_bus_t* const bus) {
|
||||||
|
const rffc5071_spi_config_t* const config = bus->config;
|
||||||
|
gpio_clear(config->gpio_select);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rffc5071_spi_target_unselect(spi_bus_t* const bus) {
|
||||||
|
const rffc5071_spi_config_t* const config = bus->config;
|
||||||
|
gpio_set(config->gpio_select);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rffc5071_spi_direction_out(spi_bus_t* const bus) {
|
||||||
|
const rffc5071_spi_config_t* const config = bus->config;
|
||||||
|
gpio_output(config->gpio_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rffc5071_spi_direction_in(spi_bus_t* const bus) {
|
||||||
|
const rffc5071_spi_config_t* const config = bus->config;
|
||||||
|
gpio_input(config->gpio_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rffc5071_spi_data_out(spi_bus_t* const bus, const bool bit) {
|
||||||
|
const rffc5071_spi_config_t* const config = bus->config;
|
||||||
|
gpio_write(config->gpio_data, bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool rffc5071_spi_data_in(spi_bus_t* const bus) {
|
||||||
|
const rffc5071_spi_config_t* const config = bus->config;
|
||||||
|
return gpio_read(config->gpio_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rffc5071_spi_bus_init(spi_bus_t* const bus) {
|
||||||
|
const rffc5071_spi_config_t* const config = bus->config;
|
||||||
|
|
||||||
|
scu_pinmux(SCU_MIXER_SCLK, SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
|
||||||
|
scu_pinmux(SCU_MIXER_SDATA, SCU_GPIO_FAST);
|
||||||
|
|
||||||
|
gpio_output(config->gpio_clock);
|
||||||
|
rffc5071_spi_direction_out(bus);
|
||||||
|
|
||||||
|
gpio_clear(config->gpio_clock);
|
||||||
|
gpio_clear(config->gpio_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rffc5071_spi_target_init(spi_bus_t* const bus) {
|
||||||
|
const rffc5071_spi_config_t* const config = bus->config;
|
||||||
|
|
||||||
|
/* Configure GPIO pins. */
|
||||||
|
scu_pinmux(SCU_MIXER_ENX, SCU_GPIO_FAST);
|
||||||
|
scu_pinmux(SCU_MIXER_RESETX, SCU_GPIO_FAST);
|
||||||
|
|
||||||
|
/* Set GPIO pins as outputs. */
|
||||||
|
gpio_output(config->gpio_select);
|
||||||
|
|
||||||
|
/* set to known state */
|
||||||
|
rffc5071_spi_target_unselect(bus);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rffc5071_spi_start(spi_bus_t* const bus, const void* const config) {
|
||||||
|
bus->config = config;
|
||||||
|
rffc5071_spi_bus_init(bus);
|
||||||
|
rffc5071_spi_target_init(bus);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rffc5071_spi_stop(spi_bus_t* const bus) {
|
||||||
|
(void)bus;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rffc5071_spi_serial_delay(spi_bus_t* const bus) {
|
||||||
|
(void)bus;
|
||||||
|
volatile uint32_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < 2; i++)
|
||||||
|
__asm__("nop");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rffc5071_spi_sck(spi_bus_t* const bus) {
|
||||||
|
const rffc5071_spi_config_t* const config = bus->config;
|
||||||
|
|
||||||
|
rffc5071_spi_serial_delay(bus);
|
||||||
|
gpio_set(config->gpio_clock);
|
||||||
|
|
||||||
|
rffc5071_spi_serial_delay(bus);
|
||||||
|
gpio_clear(config->gpio_clock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t rffc5071_spi_exchange_bit(spi_bus_t* const bus, const uint32_t bit) {
|
||||||
|
rffc5071_spi_data_out(bus, bit);
|
||||||
|
rffc5071_spi_sck(bus);
|
||||||
|
return rffc5071_spi_data_in(bus) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t rffc5071_spi_exchange_word(spi_bus_t* const bus, const uint32_t data, const size_t count) {
|
||||||
|
size_t bits = count;
|
||||||
|
const uint32_t msb = 1UL << (count - 1);
|
||||||
|
uint32_t t = data;
|
||||||
|
|
||||||
|
while (bits--) {
|
||||||
|
t = (t << 1) | rffc5071_spi_exchange_bit(bus, t & msb);
|
||||||
|
}
|
||||||
|
|
||||||
|
return t & ((1UL << count) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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).
|
||||||
|
*/
|
||||||
|
/* 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_transfer(spi_bus_t* const bus, void* const _data, const size_t count) {
|
||||||
|
if( count != 2 ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t* const data = _data;
|
||||||
|
|
||||||
|
const bool direction_read = (data[0] >> 7) & 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The device requires two clocks while ENX is high before a serial
|
||||||
|
* transaction. This is not clearly documented.
|
||||||
|
*/
|
||||||
|
rffc5071_spi_sck(bus);
|
||||||
|
rffc5071_spi_sck(bus);
|
||||||
|
|
||||||
|
rffc5071_spi_target_select(bus);
|
||||||
|
data[0] = rffc5071_spi_exchange_word(bus, data[0], 9);
|
||||||
|
|
||||||
|
if( direction_read ) {
|
||||||
|
rffc5071_spi_direction_in(bus);
|
||||||
|
rffc5071_spi_sck(bus);
|
||||||
|
}
|
||||||
|
data[1] = rffc5071_spi_exchange_word(bus, data[1], 16);
|
||||||
|
|
||||||
|
rffc5071_spi_serial_delay(bus);
|
||||||
|
rffc5071_spi_target_unselect(bus);
|
||||||
|
rffc5071_spi_direction_out(bus);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The device requires a clock while ENX is high after a serial
|
||||||
|
* transaction. This is not clearly documented.
|
||||||
|
*/
|
||||||
|
rffc5071_spi_sck(bus);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rffc5071_spi_transfer_gather(spi_bus_t* const bus, const spi_transfer_t* const transfer, const size_t count) {
|
||||||
|
if( count == 1 ) {
|
||||||
|
rffc5071_spi_transfer(bus, transfer[0].data, transfer[0].count);
|
||||||
|
}
|
||||||
|
}
|
41
firmware/common/rffc5071_spi.h
Normal file
41
firmware/common/rffc5071_spi.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* 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_SPI_H
|
||||||
|
#define __RFFC5071_SPI_H
|
||||||
|
|
||||||
|
#include "spi_bus.h"
|
||||||
|
|
||||||
|
#include "gpio.h"
|
||||||
|
|
||||||
|
typedef struct rffc5071_spi_config_t {
|
||||||
|
gpio_t gpio_select;
|
||||||
|
gpio_t gpio_clock;
|
||||||
|
gpio_t gpio_data;
|
||||||
|
} rffc5071_spi_config_t;
|
||||||
|
|
||||||
|
void rffc5071_spi_start(spi_bus_t* const bus, const void* const config);
|
||||||
|
void rffc5071_spi_stop(spi_bus_t* const bus);
|
||||||
|
void rffc5071_spi_transfer(spi_bus_t* const bus, void* const data, const size_t count);
|
||||||
|
void rffc5071_spi_transfer_gather(spi_bus_t* const bus, const spi_transfer_t* const transfer, const size_t count);
|
||||||
|
|
||||||
|
#endif // __RFFC5071_SPI_H
|
@ -77,7 +77,8 @@ isp_iap_ret_code_t iap_cmd_call(iap_cmd_res_t* iap_cmd_res)
|
|||||||
Alternative way to retrieve Part Id on MCU with no IAP
|
Alternative way to retrieve Part Id on MCU with no IAP
|
||||||
Read Serial No => Read Unique ID in SPIFI (only compatible with W25Q80BV
|
Read Serial No => Read Unique ID in SPIFI (only compatible with W25Q80BV
|
||||||
*/
|
*/
|
||||||
w25q80bv_setup();
|
spi_bus_start(spi_flash.bus, &ssp_config_w25q80bv);
|
||||||
|
w25q80bv_setup(&spi_flash);
|
||||||
|
|
||||||
switch(iap_cmd_res->cmd_param.command_code)
|
switch(iap_cmd_res->cmd_param.command_code)
|
||||||
{
|
{
|
||||||
@ -92,7 +93,7 @@ isp_iap_ret_code_t iap_cmd_call(iap_cmd_res_t* iap_cmd_res)
|
|||||||
/* Only 64bits used */
|
/* Only 64bits used */
|
||||||
iap_cmd_res->status_res.iap_result[0] = 0;
|
iap_cmd_res->status_res.iap_result[0] = 0;
|
||||||
iap_cmd_res->status_res.iap_result[1] = 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] );
|
w25q80bv_get_unique_id(&spi_flash, (w25q80bv_unique_id_t*)&iap_cmd_res->status_res.iap_result[2] );
|
||||||
iap_cmd_res->status_res.status_ret = CMD_SUCCESS;
|
iap_cmd_res->status_res.status_ret = CMD_SUCCESS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
* Boston, MA 02110-1301, USA.
|
* Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <libopencm3/lpc43xx/gpio.h>
|
|
||||||
#include <libopencm3/lpc43xx/scu.h>
|
#include <libopencm3/lpc43xx/scu.h>
|
||||||
#include <libopencm3/lpc43xx/sgpio.h>
|
#include <libopencm3/lpc43xx/sgpio.h>
|
||||||
|
|
||||||
@ -28,9 +27,7 @@
|
|||||||
|
|
||||||
#include <sgpio.h>
|
#include <sgpio.h>
|
||||||
|
|
||||||
static bool sgpio_slice_mode_multislice = true;
|
void sgpio_configure_pin_functions(sgpio_config_t* const config) {
|
||||||
|
|
||||||
void sgpio_configure_pin_functions() {
|
|
||||||
scu_pinmux(SCU_PINMUX_SGPIO0, SCU_GPIO_FAST | SCU_CONF_FUNCTION3);
|
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_SGPIO1, SCU_GPIO_FAST | SCU_CONF_FUNCTION3);
|
||||||
scu_pinmux(SCU_PINMUX_SGPIO2, SCU_GPIO_FAST | SCU_CONF_FUNCTION2);
|
scu_pinmux(SCU_PINMUX_SGPIO2, SCU_GPIO_FAST | SCU_CONF_FUNCTION2);
|
||||||
@ -48,61 +45,20 @@ void sgpio_configure_pin_functions() {
|
|||||||
scu_pinmux(SCU_PINMUX_SGPIO14, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); /* GPIO5[13] */
|
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] */
|
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_decimation(config, 1);
|
||||||
sgpio_cpld_stream_rx_set_q_invert(0);
|
sgpio_cpld_stream_rx_set_q_invert(config, 0);
|
||||||
|
|
||||||
GPIO_DIR(GPIO0) |= GPIOPIN13;
|
gpio_output(config->gpio_rx_q_invert);
|
||||||
GPIO_DIR(GPIO5) |= GPIOPIN14 | GPIOPIN13 | GPIOPIN12;
|
gpio_output(config->gpio_rx_decimation[0]);
|
||||||
}
|
gpio_output(config->gpio_rx_decimation[1]);
|
||||||
|
gpio_output(config->gpio_rx_decimation[2]);
|
||||||
|
|
||||||
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(
|
void sgpio_set_slice_mode(
|
||||||
|
sgpio_config_t* const config,
|
||||||
const bool multi_slice
|
const bool multi_slice
|
||||||
) {
|
) {
|
||||||
sgpio_slice_mode_multislice = multi_slice;
|
config->slice_mode_multislice = multi_slice;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -118,6 +74,7 @@ void sgpio_set_slice_mode(
|
|||||||
SGPIO11 Direction Output (1/High=TX mode LPC43xx=>CPLD=>DAC, 0/Low=RX mode LPC43xx<=CPLD<=ADC)
|
SGPIO11 Direction Output (1/High=TX mode LPC43xx=>CPLD=>DAC, 0/Low=RX mode LPC43xx<=CPLD<=ADC)
|
||||||
*/
|
*/
|
||||||
void sgpio_configure(
|
void sgpio_configure(
|
||||||
|
sgpio_config_t* const config,
|
||||||
const sgpio_direction_t direction
|
const sgpio_direction_t direction
|
||||||
) {
|
) {
|
||||||
// Disable all counters during configuration
|
// Disable all counters during configuration
|
||||||
@ -167,7 +124,7 @@ void sgpio_configure(
|
|||||||
;
|
;
|
||||||
|
|
||||||
const uint_fast8_t output_multiplexing_mode =
|
const uint_fast8_t output_multiplexing_mode =
|
||||||
sgpio_slice_mode_multislice ? 11 : 9;
|
config->slice_mode_multislice ? 11 : 9;
|
||||||
/* SGPIO0 to SGPIO7 */
|
/* SGPIO0 to SGPIO7 */
|
||||||
for(uint_fast8_t i=0; i<8; i++) {
|
for(uint_fast8_t i=0; i<8; i++) {
|
||||||
// SGPIO pin 0 outputs slice A bit "i".
|
// SGPIO pin 0 outputs slice A bit "i".
|
||||||
@ -189,9 +146,9 @@ void sgpio_configure(
|
|||||||
};
|
};
|
||||||
const uint_fast8_t slice_gpdma = SGPIO_SLICE_H;
|
const uint_fast8_t slice_gpdma = SGPIO_SLICE_H;
|
||||||
|
|
||||||
const uint_fast8_t pos = sgpio_slice_mode_multislice ? 0x1f : 0x03;
|
const uint_fast8_t pos = config->slice_mode_multislice ? 0x1f : 0x03;
|
||||||
const bool single_slice = !sgpio_slice_mode_multislice;
|
const bool single_slice = !config->slice_mode_multislice;
|
||||||
const uint_fast8_t slice_count = sgpio_slice_mode_multislice ? 8 : 1;
|
const uint_fast8_t slice_count = config->slice_mode_multislice ? 8 : 1;
|
||||||
const uint_fast8_t clk_capture_mode = (direction == SGPIO_DIRECTION_TX) ? 0 : 1;
|
const uint_fast8_t clk_capture_mode = (direction == SGPIO_DIRECTION_TX) ? 0 : 1;
|
||||||
|
|
||||||
uint32_t slice_enable_mask = 0;
|
uint32_t slice_enable_mask = 0;
|
||||||
@ -236,7 +193,7 @@ void sgpio_configure(
|
|||||||
slice_enable_mask |= (1 << slice_index);
|
slice_enable_mask |= (1 << slice_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( sgpio_slice_mode_multislice == false ) {
|
if( config->slice_mode_multislice == false ) {
|
||||||
SGPIO_MUX_CFG(slice_gpdma) =
|
SGPIO_MUX_CFG(slice_gpdma) =
|
||||||
SGPIO_MUX_CFG_CONCAT_ORDER(0) /* Self-loop */
|
SGPIO_MUX_CFG_CONCAT_ORDER(0) /* Self-loop */
|
||||||
| SGPIO_MUX_CFG_CONCAT_ENABLE(1)
|
| SGPIO_MUX_CFG_CONCAT_ENABLE(1)
|
||||||
@ -274,21 +231,24 @@ void sgpio_configure(
|
|||||||
SGPIO_CTRL_ENABLE = slice_enable_mask;
|
SGPIO_CTRL_ENABLE = slice_enable_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sgpio_cpld_stream_enable() {
|
void sgpio_cpld_stream_enable(sgpio_config_t* const config) {
|
||||||
|
(void)config;
|
||||||
// Enable codec data stream.
|
// Enable codec data stream.
|
||||||
SGPIO_GPIO_OUTREG &= ~(1L << 10); /* SGPIO10 */
|
SGPIO_GPIO_OUTREG &= ~(1L << 10); /* SGPIO10 */
|
||||||
}
|
}
|
||||||
|
|
||||||
void sgpio_cpld_stream_disable() {
|
void sgpio_cpld_stream_disable(sgpio_config_t* const config) {
|
||||||
|
(void)config;
|
||||||
// Disable codec data stream.
|
// Disable codec data stream.
|
||||||
SGPIO_GPIO_OUTREG |= (1L << 10); /* SGPIO10 */
|
SGPIO_GPIO_OUTREG |= (1L << 10); /* SGPIO10 */
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sgpio_cpld_stream_is_enabled() {
|
bool sgpio_cpld_stream_is_enabled(sgpio_config_t* const config) {
|
||||||
|
(void)config;
|
||||||
return (SGPIO_GPIO_OUTREG & (1L << 10)) == 0; /* SGPIO10 */
|
return (SGPIO_GPIO_OUTREG & (1L << 10)) == 0; /* SGPIO10 */
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sgpio_cpld_stream_rx_set_decimation(const uint_fast8_t n) {
|
bool sgpio_cpld_stream_rx_set_decimation(sgpio_config_t* const config, const uint_fast8_t n) {
|
||||||
/* CPLD interface is three bits, SGPIO[15:13]:
|
/* CPLD interface is three bits, SGPIO[15:13]:
|
||||||
* 111: decimate by 1 (skip_n=0, skip no samples)
|
* 111: decimate by 1 (skip_n=0, skip no samples)
|
||||||
* 110: decimate by 2 (skip_n=1, skip every other sample)
|
* 110: decimate by 2 (skip_n=1, skip every other sample)
|
||||||
@ -297,16 +257,13 @@ bool sgpio_cpld_stream_rx_set_decimation(const uint_fast8_t n) {
|
|||||||
* 000: decimate by 8 (skip_n=7, skip seven of eight samples)
|
* 000: decimate by 8 (skip_n=7, skip seven of eight samples)
|
||||||
*/
|
*/
|
||||||
const uint_fast8_t skip_n = n - 1;
|
const uint_fast8_t skip_n = n - 1;
|
||||||
GPIO_SET(GPIO5) = GPIOPIN14 | GPIOPIN13 | GPIOPIN12;
|
gpio_write(config->gpio_rx_decimation[0], (skip_n & 1) == 0);
|
||||||
GPIO_CLR(GPIO5) = (skip_n & 7) << 12;
|
gpio_write(config->gpio_rx_decimation[1], (skip_n & 2) == 0);
|
||||||
|
gpio_write(config->gpio_rx_decimation[2], (skip_n & 4) == 0);
|
||||||
|
|
||||||
return (skip_n < 8);
|
return (skip_n < 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sgpio_cpld_stream_rx_set_q_invert(const uint_fast8_t invert) {
|
void sgpio_cpld_stream_rx_set_q_invert(sgpio_config_t* const config, const uint_fast8_t invert) {
|
||||||
if( invert ) {
|
gpio_write(config->gpio_rx_q_invert, invert);
|
||||||
GPIO_SET(GPIO0) = GPIOPIN13;
|
|
||||||
} else {
|
|
||||||
GPIO_CLR(GPIO0) = GPIOPIN13;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -22,26 +22,39 @@
|
|||||||
#ifndef __SGPIO_H__
|
#ifndef __SGPIO_H__
|
||||||
#define __SGPIO_H__
|
#define __SGPIO_H__
|
||||||
|
|
||||||
#include <hackrf_core.h>
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include <libopencm3/lpc43xx/sgpio.h>
|
||||||
|
|
||||||
|
#include "gpio.h"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SGPIO_DIRECTION_RX,
|
SGPIO_DIRECTION_RX,
|
||||||
SGPIO_DIRECTION_TX,
|
SGPIO_DIRECTION_TX,
|
||||||
} sgpio_direction_t;
|
} sgpio_direction_t;
|
||||||
|
|
||||||
void sgpio_configure_pin_functions();
|
typedef struct sgpio_config_t {
|
||||||
void sgpio_test_interface();
|
gpio_t gpio_rx_q_invert;
|
||||||
|
gpio_t gpio_rx_decimation[3];
|
||||||
|
bool slice_mode_multislice;
|
||||||
|
} sgpio_config_t;
|
||||||
|
|
||||||
|
void sgpio_configure_pin_functions(sgpio_config_t* const config);
|
||||||
|
void sgpio_test_interface(sgpio_config_t* const config);
|
||||||
void sgpio_set_slice_mode(
|
void sgpio_set_slice_mode(
|
||||||
|
sgpio_config_t* const config,
|
||||||
const bool multi_slice
|
const bool multi_slice
|
||||||
);
|
);
|
||||||
void sgpio_configure(
|
void sgpio_configure(
|
||||||
|
sgpio_config_t* const config,
|
||||||
const sgpio_direction_t direction
|
const sgpio_direction_t direction
|
||||||
);
|
);
|
||||||
void sgpio_cpld_stream_enable();
|
void sgpio_cpld_stream_enable(sgpio_config_t* const config);
|
||||||
void sgpio_cpld_stream_disable();
|
void sgpio_cpld_stream_disable(sgpio_config_t* const config);
|
||||||
bool sgpio_cpld_stream_is_enabled();
|
bool sgpio_cpld_stream_is_enabled(sgpio_config_t* const config);
|
||||||
|
|
||||||
bool sgpio_cpld_stream_rx_set_decimation(const uint_fast8_t n);
|
bool sgpio_cpld_stream_rx_set_decimation(sgpio_config_t* const config, const uint_fast8_t n);
|
||||||
void sgpio_cpld_stream_rx_set_q_invert(const uint_fast8_t invert);
|
void sgpio_cpld_stream_rx_set_q_invert(sgpio_config_t* const config, const uint_fast8_t invert);
|
||||||
|
|
||||||
#endif//__SGPIO_H__
|
#endif//__SGPIO_H__
|
||||||
|
@ -21,73 +21,50 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "si5351c.h"
|
#include "si5351c.h"
|
||||||
#include <libopencm3/lpc43xx/i2c.h>
|
|
||||||
|
|
||||||
enum pll_sources active_clock_source;
|
enum pll_sources active_clock_source;
|
||||||
|
|
||||||
/* FIXME return i2c0 status from each function */
|
|
||||||
|
|
||||||
/* write to single register */
|
/* write to single register */
|
||||||
void si5351c_write_single(uint8_t reg, uint8_t val)
|
void si5351c_write_single(si5351c_driver_t* const drv, uint8_t reg, uint8_t val)
|
||||||
{
|
{
|
||||||
i2c0_tx_start();
|
const uint8_t data_tx[] = { reg, val };
|
||||||
i2c0_tx_byte(SI5351C_I2C_ADDR | I2C_WRITE);
|
si5351c_write(drv, data_tx, 2);
|
||||||
i2c0_tx_byte(reg);
|
|
||||||
i2c0_tx_byte(val);
|
|
||||||
i2c0_stop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read single register */
|
/* read single register */
|
||||||
uint8_t si5351c_read_single(uint8_t reg)
|
uint8_t si5351c_read_single(si5351c_driver_t* const drv, uint8_t reg)
|
||||||
{
|
{
|
||||||
uint8_t val;
|
const uint8_t data_tx[] = { reg };
|
||||||
|
uint8_t data_rx[] = { 0x00 };
|
||||||
/* set register address with write */
|
i2c_bus_transfer(drv->bus, drv->i2c_address, data_tx, 1, data_rx, 1);
|
||||||
i2c0_tx_start();
|
return data_rx[0];
|
||||||
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
|
* Write to one or more contiguous registers. data[0] should be the first
|
||||||
* register number, one or more values follow.
|
* register number, one or more values follow.
|
||||||
*/
|
*/
|
||||||
void si5351c_write(uint8_t* const data, const uint_fast8_t data_count)
|
void si5351c_write(si5351c_driver_t* const drv, const uint8_t* const data, const size_t data_count)
|
||||||
{
|
{
|
||||||
uint_fast8_t i;
|
i2c_bus_transfer(drv->bus, drv->i2c_address, data, data_count, NULL, 0);
|
||||||
|
|
||||||
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. */
|
/* Disable all CLKx outputs. */
|
||||||
void si5351c_disable_all_outputs()
|
void si5351c_disable_all_outputs(si5351c_driver_t* const drv)
|
||||||
{
|
{
|
||||||
uint8_t data[] = { 3, 0xFF };
|
uint8_t data[] = { 3, 0xFF };
|
||||||
si5351c_write(data, sizeof(data));
|
si5351c_write(drv, data, sizeof(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Turn off OEB pin control for all CLKx */
|
/* Turn off OEB pin control for all CLKx */
|
||||||
void si5351c_disable_oeb_pin_control()
|
void si5351c_disable_oeb_pin_control(si5351c_driver_t* const drv)
|
||||||
{
|
{
|
||||||
uint8_t data[] = { 9, 0xFF };
|
uint8_t data[] = { 9, 0xFF };
|
||||||
si5351c_write(data, sizeof(data));
|
si5351c_write(drv, data, sizeof(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Power down all CLKx */
|
/* Power down all CLKx */
|
||||||
void si5351c_power_down_all_clocks()
|
void si5351c_power_down_all_clocks(si5351c_driver_t* const drv)
|
||||||
{
|
{
|
||||||
uint8_t data[] = { 16
|
uint8_t data[] = { 16
|
||||||
, SI5351C_CLK_POWERDOWN
|
, SI5351C_CLK_POWERDOWN
|
||||||
@ -99,7 +76,7 @@ void si5351c_power_down_all_clocks()
|
|||||||
, SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE
|
, SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE
|
||||||
, SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE
|
, SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE
|
||||||
};
|
};
|
||||||
si5351c_write(data, sizeof(data));
|
si5351c_write(drv, data, sizeof(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -107,20 +84,20 @@ void si5351c_power_down_all_clocks()
|
|||||||
* Reads as 0xE4 on power-up
|
* Reads as 0xE4 on power-up
|
||||||
* Set to 8pF based on crystal specs and HackRF One testing
|
* Set to 8pF based on crystal specs and HackRF One testing
|
||||||
*/
|
*/
|
||||||
void si5351c_set_crystal_configuration()
|
void si5351c_set_crystal_configuration(si5351c_driver_t* const drv)
|
||||||
{
|
{
|
||||||
uint8_t data[] = { 183, 0x80 };
|
uint8_t data[] = { 183, 0x80 };
|
||||||
si5351c_write(data, sizeof(data));
|
si5351c_write(drv, data, sizeof(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Register 187: Fanout Enable
|
* Register 187: Fanout Enable
|
||||||
* Turn on XO and MultiSynth fanout only.
|
* Turn on XO and MultiSynth fanout only.
|
||||||
*/
|
*/
|
||||||
void si5351c_enable_xo_and_ms_fanout()
|
void si5351c_enable_xo_and_ms_fanout(si5351c_driver_t* const drv)
|
||||||
{
|
{
|
||||||
uint8_t data[] = { 187, 0xD0 };
|
uint8_t data[] = { 187, 0xD0 };
|
||||||
si5351c_write(data, sizeof(data));
|
si5351c_write(drv, data, sizeof(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -129,34 +106,35 @@ void si5351c_enable_xo_and_ms_fanout()
|
|||||||
* PLLA_SRC=0 (XTAL)
|
* PLLA_SRC=0 (XTAL)
|
||||||
* PLLB_SRC=1 (CLKIN)
|
* PLLB_SRC=1 (CLKIN)
|
||||||
*/
|
*/
|
||||||
void si5351c_configure_pll_sources(void)
|
void si5351c_configure_pll_sources(si5351c_driver_t* const drv)
|
||||||
{
|
{
|
||||||
uint8_t data[] = { 15, 0x08 };
|
uint8_t data[] = { 15, 0x08 };
|
||||||
|
|
||||||
si5351c_write(data, sizeof(data));
|
si5351c_write(drv, data, sizeof(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* MultiSynth NA (PLLA) and NB (PLLB) */
|
/* MultiSynth NA (PLLA) and NB (PLLB) */
|
||||||
void si5351c_configure_pll_multisynth(void)
|
void si5351c_configure_pll_multisynth(si5351c_driver_t* const drv)
|
||||||
{
|
{
|
||||||
//init plla to (0x0e00+512)/128*25mhz xtal = 800mhz -> int mode
|
//init plla to (0x0e00+512)/128*25mhz xtal = 800mhz -> int mode
|
||||||
uint8_t data[] = { 26, 0x00, 0x01, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00 };
|
uint8_t data[] = { 26, 0x00, 0x01, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00 };
|
||||||
si5351c_write(data, sizeof(data));
|
si5351c_write(drv, data, sizeof(data));
|
||||||
|
|
||||||
/* 10 MHz input on CLKIN for PLLB */
|
/* 10 MHz input on CLKIN for PLLB */
|
||||||
data[0] = 34;
|
data[0] = 34;
|
||||||
data[4] = 0x26;
|
data[4] = 0x26;
|
||||||
si5351c_write(data, sizeof(data));
|
si5351c_write(drv, data, sizeof(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
void si5351c_reset_pll(void)
|
void si5351c_reset_pll(si5351c_driver_t* const drv)
|
||||||
{
|
{
|
||||||
/* reset PLLA and PLLB */
|
/* reset PLLA and PLLB */
|
||||||
uint8_t data[] = { 177, 0xA0 };
|
uint8_t data[] = { 177, 0xA0 };
|
||||||
si5351c_write(data, sizeof(data));
|
si5351c_write(drv, data, sizeof(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
void si5351c_configure_multisynth(const uint_fast8_t ms_number,
|
void si5351c_configure_multisynth(si5351c_driver_t* const drv,
|
||||||
|
const uint_fast8_t ms_number,
|
||||||
const uint32_t p1, const uint32_t p2, const uint32_t p3,
|
const uint32_t p1, const uint32_t p2, const uint32_t p3,
|
||||||
const uint_fast8_t r_div)
|
const uint_fast8_t r_div)
|
||||||
{
|
{
|
||||||
@ -183,7 +161,7 @@ void si5351c_configure_multisynth(const uint_fast8_t ms_number,
|
|||||||
(((p3 >> 16) & 0xF) << 4) | (((p2 >> 16) & 0xF) << 0),
|
(((p3 >> 16) & 0xF) << 4) | (((p2 >> 16) & 0xF) << 0),
|
||||||
(p2 >> 8) & 0xFF,
|
(p2 >> 8) & 0xFF,
|
||||||
(p2 >> 0) & 0xFF };
|
(p2 >> 0) & 0xFF };
|
||||||
si5351c_write(data, sizeof(data));
|
si5351c_write(drv, data, sizeof(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef JELLYBEAN
|
#ifdef JELLYBEAN
|
||||||
@ -232,15 +210,15 @@ void si5351c_configure_multisynth(const uint_fast8_t ms_number,
|
|||||||
* CLK5_SRC=3 (MS5 as input source)
|
* CLK5_SRC=3 (MS5 as input source)
|
||||||
* CLK5_IDRV=3 (8mA)
|
* CLK5_IDRV=3 (8mA)
|
||||||
*/
|
*/
|
||||||
void si5351c_configure_clock_control()
|
void si5351c_configure_clock_control(si5351c_driver_t* const drv)
|
||||||
{
|
{
|
||||||
uint8_t data[] = { 16, 0x4F, 0x4B, 0x4B, 0x4B, 0x0F, 0x4F, 0xC0, 0xC0 };
|
uint8_t data[] = { 16, 0x4F, 0x4B, 0x4B, 0x4B, 0x0F, 0x4F, 0xC0, 0xC0 };
|
||||||
si5351c_write(data, sizeof(data));
|
si5351c_write(drv, data, sizeof(data));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (defined JAWBREAKER || defined HACKRF_ONE)
|
#if (defined JAWBREAKER || defined HACKRF_ONE)
|
||||||
void si5351c_configure_clock_control(const enum pll_sources source)
|
void si5351c_configure_clock_control(si5351c_driver_t* const drv, const enum pll_sources source)
|
||||||
{
|
{
|
||||||
uint8_t pll;
|
uint8_t pll;
|
||||||
|
|
||||||
@ -261,54 +239,54 @@ void si5351c_configure_clock_control(const enum pll_sources source)
|
|||||||
,SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE /*not connected, but: plla int mode*/
|
,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_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));
|
si5351c_write(drv, data, sizeof(data));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Enable CLK outputs 0, 1, 2, 3, 4, 5, 7 only. */
|
/* Enable CLK outputs 0, 1, 2, 3, 4, 5, 7 only. */
|
||||||
void si5351c_enable_clock_outputs()
|
void si5351c_enable_clock_outputs(si5351c_driver_t* const drv)
|
||||||
{
|
{
|
||||||
uint8_t data[] = { 3, 0x40 };
|
uint8_t data[] = { 3, 0x40 };
|
||||||
si5351c_write(data, sizeof(data));
|
si5351c_write(drv, data, sizeof(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void si5351c_set_int_mode(const uint_fast8_t ms_number, const uint_fast8_t on){
|
void si5351c_set_int_mode(si5351c_driver_t* const drv, const uint_fast8_t ms_number, const uint_fast8_t on){
|
||||||
uint8_t data[] = {16, 0};
|
uint8_t data[] = {16, 0};
|
||||||
|
|
||||||
if(ms_number < 8){
|
if(ms_number < 8){
|
||||||
data[0] = 16 + ms_number;
|
data[0] = 16 + ms_number;
|
||||||
data[1] = si5351c_read_single(data[0]);
|
data[1] = si5351c_read_single(drv, data[0]);
|
||||||
|
|
||||||
if(on)
|
if(on)
|
||||||
data[1] |= SI5351C_CLK_INT_MODE;
|
data[1] |= SI5351C_CLK_INT_MODE;
|
||||||
else
|
else
|
||||||
data[1] &= ~(SI5351C_CLK_INT_MODE);
|
data[1] &= ~(SI5351C_CLK_INT_MODE);
|
||||||
|
|
||||||
si5351c_write(data, 2);
|
si5351c_write(drv, data, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void si5351c_set_clock_source(const enum pll_sources source)
|
void si5351c_set_clock_source(si5351c_driver_t* const drv, const enum pll_sources source)
|
||||||
{
|
{
|
||||||
si5351c_configure_clock_control(source);
|
si5351c_configure_clock_control(drv, source);
|
||||||
active_clock_source = source;
|
active_clock_source = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
void si5351c_activate_best_clock_source(void)
|
void si5351c_activate_best_clock_source(si5351c_driver_t* const drv)
|
||||||
{
|
{
|
||||||
uint8_t device_status = si5351c_read_single(0);
|
uint8_t device_status = si5351c_read_single(drv, 0);
|
||||||
|
|
||||||
if (device_status & SI5351C_LOS) {
|
if (device_status & SI5351C_LOS) {
|
||||||
/* CLKIN not detected */
|
/* CLKIN not detected */
|
||||||
if (active_clock_source == PLL_SOURCE_CLKIN) {
|
if (active_clock_source == PLL_SOURCE_CLKIN) {
|
||||||
si5351c_set_clock_source(PLL_SOURCE_XTAL);
|
si5351c_set_clock_source(drv, PLL_SOURCE_XTAL);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* CLKIN detected */
|
/* CLKIN detected */
|
||||||
if (active_clock_source == PLL_SOURCE_XTAL) {
|
if (active_clock_source == PLL_SOURCE_XTAL) {
|
||||||
si5351c_set_clock_source(PLL_SOURCE_CLKIN);
|
si5351c_set_clock_source(drv, PLL_SOURCE_CLKIN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,8 +30,9 @@ extern "C"
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "i2c_bus.h"
|
||||||
|
|
||||||
#define SI_INTDIV(x) (x*128-512)
|
#define SI_INTDIV(x) (x*128-512)
|
||||||
#define SI5351C_I2C_ADDR (0x60 << 1)
|
|
||||||
|
|
||||||
#define SI5351C_CLK_POWERDOWN (1<<7)
|
#define SI5351C_CLK_POWERDOWN (1<<7)
|
||||||
#define SI5351C_CLK_INT_MODE (1<<6)
|
#define SI5351C_CLK_INT_MODE (1<<6)
|
||||||
@ -62,26 +63,32 @@ enum pll_sources {
|
|||||||
PLL_SOURCE_CLKIN = 1,
|
PLL_SOURCE_CLKIN = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
void si5351c_disable_all_outputs();
|
typedef struct {
|
||||||
void si5351c_disable_oeb_pin_control();
|
i2c_bus_t* const bus;
|
||||||
void si5351c_power_down_all_clocks();
|
uint8_t i2c_address;
|
||||||
void si5351c_set_crystal_configuration();
|
} si5351c_driver_t;
|
||||||
void si5351c_enable_xo_and_ms_fanout();
|
|
||||||
void si5351c_configure_pll_sources(void);
|
void si5351c_disable_all_outputs(si5351c_driver_t* const drv);
|
||||||
void si5351c_configure_pll_multisynth(void);
|
void si5351c_disable_oeb_pin_control(si5351c_driver_t* const drv);
|
||||||
void si5351c_reset_pll(void);
|
void si5351c_power_down_all_clocks(si5351c_driver_t* const drv);
|
||||||
void si5351c_configure_multisynth(const uint_fast8_t ms_number,
|
void si5351c_set_crystal_configuration(si5351c_driver_t* const drv);
|
||||||
|
void si5351c_enable_xo_and_ms_fanout(si5351c_driver_t* const drv);
|
||||||
|
void si5351c_configure_pll_sources(si5351c_driver_t* const drv);
|
||||||
|
void si5351c_configure_pll_multisynth(si5351c_driver_t* const drv);
|
||||||
|
void si5351c_reset_pll(si5351c_driver_t* const drv);
|
||||||
|
void si5351c_configure_multisynth(si5351c_driver_t* const drv,
|
||||||
|
const uint_fast8_t ms_number,
|
||||||
const uint32_t p1, const uint32_t p2, const uint32_t p3,
|
const uint32_t p1, const uint32_t p2, const uint32_t p3,
|
||||||
const uint_fast8_t r_div);
|
const uint_fast8_t r_div);
|
||||||
void si5351c_configure_clock_control(const enum pll_sources source);
|
void si5351c_configure_clock_control(si5351c_driver_t* const drv, const enum pll_sources source);
|
||||||
void si5351c_enable_clock_outputs();
|
void si5351c_enable_clock_outputs(si5351c_driver_t* const drv);
|
||||||
void si5351c_set_int_mode(const uint_fast8_t ms_number, const uint_fast8_t on);
|
void si5351c_set_int_mode(si5351c_driver_t* const drv, const uint_fast8_t ms_number, const uint_fast8_t on);
|
||||||
|
void si5351c_set_clock_source(si5351c_driver_t* const drv, const enum pll_sources source);
|
||||||
|
void si5351c_activate_best_clock_source(si5351c_driver_t* const drv);
|
||||||
|
|
||||||
void si5351c_write_single(uint8_t reg, uint8_t val);
|
void si5351c_write_single(si5351c_driver_t* const drv, uint8_t reg, uint8_t val);
|
||||||
uint8_t si5351c_read_single(uint8_t reg);
|
uint8_t si5351c_read_single(si5351c_driver_t* const drv, uint8_t reg);
|
||||||
void si5351c_write(uint8_t* const data, const uint_fast8_t data_count);
|
void si5351c_write(si5351c_driver_t* const drv, const uint8_t* const data, const size_t data_count);
|
||||||
void si5351c_set_clock_source(const enum pll_sources source);
|
|
||||||
void si5351c_activate_best_clock_source(void);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
38
firmware/common/spi_bus.c
Normal file
38
firmware/common/spi_bus.c
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
||||||
|
*
|
||||||
|
* 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 "spi_bus.h"
|
||||||
|
|
||||||
|
void spi_bus_start(spi_bus_t* const bus, const void* const config) {
|
||||||
|
bus->start(bus, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spi_bus_stop(spi_bus_t* const bus) {
|
||||||
|
bus->stop(bus);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spi_bus_transfer(spi_bus_t* const bus, void* const data, const size_t count) {
|
||||||
|
bus->transfer(bus, data, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spi_bus_transfer_gather(spi_bus_t* const bus, const spi_transfer_t* const transfers, const size_t count) {
|
||||||
|
bus->transfer_gather(bus, transfers, count);
|
||||||
|
}
|
49
firmware/common/spi_bus.h
Normal file
49
firmware/common/spi_bus.h
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
||||||
|
*
|
||||||
|
* 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 __SPI_BUS_H__
|
||||||
|
#define __SPI_BUS_H__
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void* const data;
|
||||||
|
const size_t count;
|
||||||
|
} spi_transfer_t;
|
||||||
|
|
||||||
|
struct spi_bus_t;
|
||||||
|
typedef struct spi_bus_t spi_bus_t;
|
||||||
|
|
||||||
|
struct spi_bus_t {
|
||||||
|
void* const obj;
|
||||||
|
const void* config;
|
||||||
|
void (*start)(spi_bus_t* const bus, const void* const config);
|
||||||
|
void (*stop)(spi_bus_t* const bus);
|
||||||
|
void (*transfer)(spi_bus_t* const bus, void* const data, const size_t count);
|
||||||
|
void (*transfer_gather)(spi_bus_t* const bus, const spi_transfer_t* const transfers, const size_t count);
|
||||||
|
};
|
||||||
|
|
||||||
|
void spi_bus_start(spi_bus_t* const bus, const void* const config);
|
||||||
|
void spi_bus_stop(spi_bus_t* const bus);
|
||||||
|
void spi_bus_transfer(spi_bus_t* const bus, void* const data, const size_t count);
|
||||||
|
void spi_bus_transfer_gather(spi_bus_t* const bus, const spi_transfer_t* const transfers, const size_t count);
|
||||||
|
|
||||||
|
#endif/*__SPI_BUS_H__*/
|
109
firmware/common/spi_ssp.c
Normal file
109
firmware/common/spi_ssp.c
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
||||||
|
*
|
||||||
|
* 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 "spi_ssp.h"
|
||||||
|
|
||||||
|
#include <libopencm3/lpc43xx/rgu.h>
|
||||||
|
#include <libopencm3/lpc43xx/ssp.h>
|
||||||
|
|
||||||
|
void spi_ssp_start(spi_bus_t* const bus, const void* const _config) {
|
||||||
|
const ssp_config_t* const config = _config;
|
||||||
|
|
||||||
|
if( bus->obj == (void*)SSP0_BASE ) {
|
||||||
|
/* Reset SPIFI peripheral before to Erase/Write SPIFI memory through SPI */
|
||||||
|
RESET_CTRL1 = RESET_CTRL1_SPIFI_RST;
|
||||||
|
}
|
||||||
|
|
||||||
|
gpio_set(config->gpio_select);
|
||||||
|
gpio_output(config->gpio_select);
|
||||||
|
|
||||||
|
SSP_CR1(bus->obj) = 0;
|
||||||
|
SSP_CPSR(bus->obj) = config->clock_prescale_rate;
|
||||||
|
SSP_CR0(bus->obj) =
|
||||||
|
(config->serial_clock_rate << 8)
|
||||||
|
| SSP_CPOL_0_CPHA_0
|
||||||
|
| SSP_FRAME_SPI
|
||||||
|
| config->data_bits
|
||||||
|
;
|
||||||
|
SSP_CR1(bus->obj) =
|
||||||
|
SSP_SLAVE_OUT_ENABLE
|
||||||
|
| SSP_MASTER
|
||||||
|
| SSP_ENABLE
|
||||||
|
| SSP_MODE_NORMAL
|
||||||
|
;
|
||||||
|
|
||||||
|
bus->config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
void spi_ssp_stop(spi_bus_t* const bus) {
|
||||||
|
SSP_CR1(bus->obj) = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void spi_ssp_wait_for_tx_fifo_not_full(spi_bus_t* const bus) {
|
||||||
|
while( (SSP_SR(bus->obj) & SSP_SR_TNF) == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void spi_ssp_wait_for_rx_fifo_not_empty(spi_bus_t* const bus) {
|
||||||
|
while( (SSP_SR(bus->obj) & SSP_SR_RNE) == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void spi_ssp_wait_for_not_busy(spi_bus_t* const bus) {
|
||||||
|
while( SSP_SR(bus->obj) & SSP_SR_BSY );
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t spi_ssp_transfer_word(spi_bus_t* const bus, const uint32_t data) {
|
||||||
|
spi_ssp_wait_for_tx_fifo_not_full(bus);
|
||||||
|
SSP_DR(bus->obj) = data;
|
||||||
|
spi_ssp_wait_for_not_busy(bus);
|
||||||
|
spi_ssp_wait_for_rx_fifo_not_empty(bus);
|
||||||
|
return SSP_DR(bus->obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spi_ssp_transfer_gather(spi_bus_t* const bus, const spi_transfer_t* const transfers, const size_t count) {
|
||||||
|
const ssp_config_t* const config = bus->config;
|
||||||
|
|
||||||
|
const bool word_size_u16 = (SSP_CR0(bus->obj) & 0xf) > SSP_DATA_8BITS;
|
||||||
|
|
||||||
|
gpio_clear(config->gpio_select);
|
||||||
|
for(size_t i=0; i<count; i++) {
|
||||||
|
const size_t data_count = transfers[i].count;
|
||||||
|
|
||||||
|
if( word_size_u16 ) {
|
||||||
|
uint16_t* const data = transfers[i].data;
|
||||||
|
for(size_t j=0; j<data_count; j++) {
|
||||||
|
data[j] = spi_ssp_transfer_word(bus, data[j]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uint8_t* const data = transfers[i].data;
|
||||||
|
for(size_t j=0; j<data_count; j++) {
|
||||||
|
data[j] = spi_ssp_transfer_word(bus, data[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gpio_set(config->gpio_select);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spi_ssp_transfer(spi_bus_t* const bus, void* const data, const size_t count) {
|
||||||
|
const spi_transfer_t transfers[] = {
|
||||||
|
{ data, count },
|
||||||
|
};
|
||||||
|
spi_ssp_transfer_gather(bus, transfers, 1);
|
||||||
|
}
|
46
firmware/common/spi_ssp.h
Normal file
46
firmware/common/spi_ssp.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
||||||
|
*
|
||||||
|
* 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 __SPI_SSP_H__
|
||||||
|
#define __SPI_SSP_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "spi_bus.h"
|
||||||
|
|
||||||
|
#include "gpio.h"
|
||||||
|
|
||||||
|
#include <libopencm3/lpc43xx/ssp.h>
|
||||||
|
|
||||||
|
typedef struct ssp_config_t {
|
||||||
|
ssp_datasize_t data_bits;
|
||||||
|
uint8_t serial_clock_rate;
|
||||||
|
uint8_t clock_prescale_rate;
|
||||||
|
gpio_t gpio_select;
|
||||||
|
} ssp_config_t;
|
||||||
|
|
||||||
|
void spi_ssp_start(spi_bus_t* const bus, const void* const config);
|
||||||
|
void spi_ssp_stop(spi_bus_t* const bus);
|
||||||
|
void spi_ssp_transfer(spi_bus_t* const bus, void* const data, const size_t count);
|
||||||
|
void spi_ssp_transfer_gather(spi_bus_t* const bus, const spi_transfer_t* const transfers, const size_t count);
|
||||||
|
|
||||||
|
#endif/*__SPI_SSP_H__*/
|
@ -25,18 +25,16 @@
|
|||||||
#include <libopencm3/lpc43xx/m4/nvic.h>
|
#include <libopencm3/lpc43xx/m4/nvic.h>
|
||||||
#include <libopencm3/lpc43xx/sgpio.h>
|
#include <libopencm3/lpc43xx/sgpio.h>
|
||||||
|
|
||||||
#include <sgpio.h>
|
void baseband_streaming_enable(sgpio_config_t* const sgpio_config) {
|
||||||
|
|
||||||
void baseband_streaming_enable() {
|
|
||||||
nvic_set_priority(NVIC_SGPIO_IRQ, 0);
|
nvic_set_priority(NVIC_SGPIO_IRQ, 0);
|
||||||
nvic_enable_irq(NVIC_SGPIO_IRQ);
|
nvic_enable_irq(NVIC_SGPIO_IRQ);
|
||||||
SGPIO_SET_EN_1 = (1 << SGPIO_SLICE_A);
|
SGPIO_SET_EN_1 = (1 << SGPIO_SLICE_A);
|
||||||
|
|
||||||
sgpio_cpld_stream_enable();
|
sgpio_cpld_stream_enable(sgpio_config);
|
||||||
}
|
}
|
||||||
|
|
||||||
void baseband_streaming_disable() {
|
void baseband_streaming_disable(sgpio_config_t* const sgpio_config) {
|
||||||
sgpio_cpld_stream_disable();
|
sgpio_cpld_stream_disable(sgpio_config);
|
||||||
|
|
||||||
nvic_disable_irq(NVIC_SGPIO_IRQ);
|
nvic_disable_irq(NVIC_SGPIO_IRQ);
|
||||||
}
|
}
|
@ -23,7 +23,9 @@
|
|||||||
#ifndef __STREAMING_H__
|
#ifndef __STREAMING_H__
|
||||||
#define __STREAMING_H__
|
#define __STREAMING_H__
|
||||||
|
|
||||||
void baseband_streaming_enable();
|
#include <sgpio.h>
|
||||||
void baseband_streaming_disable();
|
|
||||||
|
void baseband_streaming_enable(sgpio_config_t* const sgpio_config);
|
||||||
|
void baseband_streaming_disable(sgpio_config_t* const sgpio_config);
|
||||||
|
|
||||||
#endif/*__STREAMING_H__*/
|
#endif/*__STREAMING_H__*/
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include "tuning.h"
|
#include "tuning.h"
|
||||||
|
|
||||||
|
#include <hackrf_core.h>
|
||||||
#include <rffc5071.h>
|
#include <rffc5071.h>
|
||||||
#include <max2837.h>
|
#include <max2837.h>
|
||||||
#include <sgpio.h>
|
#include <sgpio.h>
|
||||||
@ -62,25 +63,25 @@ bool set_freq(const uint64_t freq)
|
|||||||
|
|
||||||
success = true;
|
success = true;
|
||||||
|
|
||||||
const max2837_mode_t prior_max2837_mode = max2837_mode();
|
const max2837_mode_t prior_max2837_mode = max2837_mode(&max2837);
|
||||||
max2837_mode_standby();
|
max2837_set_mode(&max2837, MAX2837_MODE_STANDBY);
|
||||||
if(freq_mhz < MAX_LP_FREQ_MHZ)
|
if(freq_mhz < MAX_LP_FREQ_MHZ)
|
||||||
{
|
{
|
||||||
rf_path_set_filter(RF_PATH_FILTER_LOW_PASS);
|
rf_path_set_filter(&rf_path, RF_PATH_FILTER_LOW_PASS);
|
||||||
/* IF is graduated from 2650 MHz to 2343 MHz */
|
/* IF is graduated from 2650 MHz to 2343 MHz */
|
||||||
max2837_freq_nominal_hz = 2650000000 - (freq / 7);
|
max2837_freq_nominal_hz = 2650000000 - (freq / 7);
|
||||||
RFFC5071_freq_mhz = (max2837_freq_nominal_hz / FREQ_ONE_MHZ) + freq_mhz;
|
RFFC5071_freq_mhz = (max2837_freq_nominal_hz / FREQ_ONE_MHZ) + freq_mhz;
|
||||||
/* Set Freq and read real freq */
|
/* Set Freq and read real freq */
|
||||||
real_RFFC5071_freq_hz = rffc5071_set_frequency(RFFC5071_freq_mhz);
|
real_RFFC5071_freq_hz = rffc5071_set_frequency(&rffc5072, RFFC5071_freq_mhz);
|
||||||
max2837_set_frequency(real_RFFC5071_freq_hz - freq);
|
max2837_set_frequency(&max2837, real_RFFC5071_freq_hz - freq);
|
||||||
sgpio_cpld_stream_rx_set_q_invert(1);
|
sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 1);
|
||||||
}else if( (freq_mhz >= MIN_BYPASS_FREQ_MHZ) && (freq_mhz < MAX_BYPASS_FREQ_MHZ) )
|
}else if( (freq_mhz >= MIN_BYPASS_FREQ_MHZ) && (freq_mhz < MAX_BYPASS_FREQ_MHZ) )
|
||||||
{
|
{
|
||||||
rf_path_set_filter(RF_PATH_FILTER_BYPASS);
|
rf_path_set_filter(&rf_path, RF_PATH_FILTER_BYPASS);
|
||||||
MAX2837_freq_hz = (freq_mhz * FREQ_ONE_MHZ) + freq_hz;
|
MAX2837_freq_hz = (freq_mhz * FREQ_ONE_MHZ) + freq_hz;
|
||||||
/* RFFC5071_freq_mhz <= not used in Bypass mode */
|
/* RFFC5071_freq_mhz <= not used in Bypass mode */
|
||||||
max2837_set_frequency(MAX2837_freq_hz);
|
max2837_set_frequency(&max2837, MAX2837_freq_hz);
|
||||||
sgpio_cpld_stream_rx_set_q_invert(0);
|
sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 0);
|
||||||
}else if( (freq_mhz >= MIN_HP_FREQ_MHZ) && (freq_mhz <= MAX_HP_FREQ_MHZ) )
|
}else if( (freq_mhz >= MIN_HP_FREQ_MHZ) && (freq_mhz <= MAX_HP_FREQ_MHZ) )
|
||||||
{
|
{
|
||||||
if (freq_mhz < MID1_HP_FREQ_MHZ) {
|
if (freq_mhz < MID1_HP_FREQ_MHZ) {
|
||||||
@ -93,18 +94,18 @@ bool set_freq(const uint64_t freq)
|
|||||||
/* IF is graduated from 2500 MHz to 2738 MHz */
|
/* IF is graduated from 2500 MHz to 2738 MHz */
|
||||||
max2837_freq_nominal_hz = 2500000000 + ((freq - 5100000000) / 9);
|
max2837_freq_nominal_hz = 2500000000 + ((freq - 5100000000) / 9);
|
||||||
}
|
}
|
||||||
rf_path_set_filter(RF_PATH_FILTER_HIGH_PASS);
|
rf_path_set_filter(&rf_path, RF_PATH_FILTER_HIGH_PASS);
|
||||||
RFFC5071_freq_mhz = freq_mhz - (max2837_freq_nominal_hz / FREQ_ONE_MHZ);
|
RFFC5071_freq_mhz = freq_mhz - (max2837_freq_nominal_hz / FREQ_ONE_MHZ);
|
||||||
/* Set Freq and read real freq */
|
/* Set Freq and read real freq */
|
||||||
real_RFFC5071_freq_hz = rffc5071_set_frequency(RFFC5071_freq_mhz);
|
real_RFFC5071_freq_hz = rffc5071_set_frequency(&rffc5072, RFFC5071_freq_mhz);
|
||||||
max2837_set_frequency(freq - real_RFFC5071_freq_hz);
|
max2837_set_frequency(&max2837, freq - real_RFFC5071_freq_hz);
|
||||||
sgpio_cpld_stream_rx_set_q_invert(0);
|
sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 0);
|
||||||
}else
|
}else
|
||||||
{
|
{
|
||||||
/* Error freq_mhz too high */
|
/* Error freq_mhz too high */
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
max2837_set_mode(prior_max2837_mode);
|
max2837_set_mode(&max2837, prior_max2837_mode);
|
||||||
if( success ) {
|
if( success ) {
|
||||||
freq_cache = freq;
|
freq_cache = freq;
|
||||||
}
|
}
|
||||||
@ -128,15 +129,15 @@ bool set_freq_explicit(const uint64_t if_freq_hz, const uint64_t lo_freq_hz,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
rf_path_set_filter(path);
|
rf_path_set_filter(&rf_path, path);
|
||||||
max2837_set_frequency(if_freq_hz);
|
max2837_set_frequency(&max2837, if_freq_hz);
|
||||||
if (lo_freq_hz > if_freq_hz) {
|
if (lo_freq_hz > if_freq_hz) {
|
||||||
sgpio_cpld_stream_rx_set_q_invert(1);
|
sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 1);
|
||||||
} else {
|
} else {
|
||||||
sgpio_cpld_stream_rx_set_q_invert(0);
|
sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 0);
|
||||||
}
|
}
|
||||||
if (path != RF_PATH_FILTER_BYPASS) {
|
if (path != RF_PATH_FILTER_BYPASS) {
|
||||||
(void)rffc5071_set_frequency(lo_freq_hz / FREQ_ONE_MHZ);
|
(void)rffc5071_set_frequency(&rffc5072, lo_freq_hz / FREQ_ONE_MHZ);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013 Michael Ossmann
|
* Copyright 2013 Michael Ossmann
|
||||||
* Copyright 2013 Benjamin Vernoux
|
* Copyright 2013 Benjamin Vernoux
|
||||||
|
* Copyright 2014 Jared Boone, ShareBrained Technology
|
||||||
*
|
*
|
||||||
* This file is part of HackRF.
|
* This file is part of HackRF.
|
||||||
*
|
*
|
||||||
@ -27,183 +28,139 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
#include "w25q80bv.h"
|
#include "w25q80bv.h"
|
||||||
#include "hackrf_core.h"
|
|
||||||
#include <libopencm3/lpc43xx/ssp.h>
|
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||||
#include <libopencm3/lpc43xx/scu.h>
|
|
||||||
#include <libopencm3/lpc43xx/gpio.h>
|
#define W25Q80BV_READ_DATA 0x03
|
||||||
#include <libopencm3/lpc43xx/rgu.h>
|
#define W25Q80BV_FAST_READ 0x0b
|
||||||
|
#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 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set up pins for GPIO and SPI control, configure SSP0 peripheral for SPI.
|
* 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.
|
* SSP0_SSEL is controlled by GPIO in order to handle various transfer lengths.
|
||||||
*/
|
*/
|
||||||
|
void w25q80bv_setup(w25q80bv_driver_t* const drv)
|
||||||
void w25q80bv_setup(void)
|
|
||||||
{
|
{
|
||||||
uint8_t device_id;
|
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 */
|
drv->page_len = 256U;
|
||||||
RESET_CTRL1 = RESET_CTRL1_SPIFI_RST;
|
drv->num_pages = 4096U;
|
||||||
|
drv->num_bytes = 1048576U;
|
||||||
|
|
||||||
/* Init SPIFI GPIO to Normal GPIO */
|
drv->target_init(drv);
|
||||||
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;
|
device_id = 0;
|
||||||
while(device_id != W25Q80BV_DEVICE_ID_RES)
|
while(device_id != W25Q80BV_DEVICE_ID_RES)
|
||||||
{
|
{
|
||||||
device_id = w25q80bv_get_device_id();
|
device_id = w25q80bv_get_device_id(drv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t w25q80bv_get_status(void)
|
uint8_t w25q80bv_get_status(w25q80bv_driver_t* const drv)
|
||||||
{
|
{
|
||||||
uint8_t value;
|
uint8_t data[] = { W25Q80BV_READ_STATUS1, 0xFF };
|
||||||
|
spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data));
|
||||||
gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL);
|
return data[1];
|
||||||
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 */
|
/* Release power down / Device ID */
|
||||||
uint8_t w25q80bv_get_device_id(void)
|
uint8_t w25q80bv_get_device_id(w25q80bv_driver_t* const drv)
|
||||||
{
|
{
|
||||||
uint8_t value;
|
uint8_t data[] = {
|
||||||
|
W25Q80BV_DEVICE_ID,
|
||||||
gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL);
|
0xFF, 0xFF, 0xFF, 0xFF
|
||||||
ssp_transfer(SSP0_NUM, W25Q80BV_DEVICE_ID);
|
};
|
||||||
|
spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data));
|
||||||
/* Read 3 dummy bytes */
|
return data[4];
|
||||||
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)
|
void w25q80bv_get_unique_id(w25q80bv_driver_t* const drv, w25q80bv_unique_id_t* unique_id)
|
||||||
{
|
{
|
||||||
int i;
|
uint8_t data[] = {
|
||||||
uint8_t value;
|
W25Q80BV_UNIQUE_ID,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
|
||||||
|
};
|
||||||
|
spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data));
|
||||||
|
|
||||||
gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL);
|
for(size_t i=0; i<8; i++) {
|
||||||
ssp_transfer(SSP0_NUM, W25Q80BV_UNIQUE_ID);
|
unique_id->id_8b[i] = data[5+i];
|
||||||
|
|
||||||
/* 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)
|
void w25q80bv_wait_while_busy(w25q80bv_driver_t* const drv)
|
||||||
{
|
{
|
||||||
while (w25q80bv_get_status() & W25Q80BV_STATUS_BUSY);
|
while (w25q80bv_get_status(drv) & W25Q80BV_STATUS_BUSY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void w25q80bv_write_enable(void)
|
void w25q80bv_write_enable(w25q80bv_driver_t* const drv)
|
||||||
{
|
{
|
||||||
w25q80bv_wait_while_busy();
|
w25q80bv_wait_while_busy(drv);
|
||||||
gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL);
|
|
||||||
ssp_transfer(SSP0_NUM, W25Q80BV_WRITE_ENABLE);
|
uint8_t data[] = { W25Q80BV_WRITE_ENABLE };
|
||||||
gpio_set(PORT_SSP0_SSEL, PIN_SSP0_SSEL);
|
spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
void w25q80bv_chip_erase(void)
|
void w25q80bv_chip_erase(w25q80bv_driver_t* const drv)
|
||||||
{
|
{
|
||||||
uint8_t device_id;
|
uint8_t device_id;
|
||||||
|
|
||||||
device_id = 0;
|
device_id = 0;
|
||||||
while(device_id != W25Q80BV_DEVICE_ID_RES)
|
while(device_id != W25Q80BV_DEVICE_ID_RES)
|
||||||
{
|
{
|
||||||
device_id = w25q80bv_get_device_id();
|
device_id = w25q80bv_get_device_id(drv);
|
||||||
}
|
}
|
||||||
|
|
||||||
w25q80bv_write_enable();
|
w25q80bv_write_enable(drv);
|
||||||
w25q80bv_wait_while_busy();
|
w25q80bv_wait_while_busy(drv);
|
||||||
gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL);
|
|
||||||
ssp_transfer(SSP0_NUM, W25Q80BV_CHIP_ERASE);
|
uint8_t data[] = { W25Q80BV_CHIP_ERASE };
|
||||||
gpio_set(PORT_SSP0_SSEL, PIN_SSP0_SSEL);
|
spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write up a 256 byte page or partial page */
|
/* 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)
|
static void w25q80bv_page_program(w25q80bv_driver_t* const drv, const uint32_t addr, const uint16_t len, uint8_t* data)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
|
|
||||||
/* do nothing if asked to write beyond a page boundary */
|
/* do nothing if asked to write beyond a page boundary */
|
||||||
if (((addr & 0xFF) + len) > W25Q80BV_PAGE_LEN)
|
if (((addr & 0xFF) + len) > drv->page_len)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* do nothing if we would overflow the flash */
|
/* do nothing if we would overflow the flash */
|
||||||
if (addr > (W25Q80BV_NUM_BYTES - len))
|
if (addr > (drv->num_bytes - len))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
w25q80bv_write_enable();
|
w25q80bv_write_enable(drv);
|
||||||
w25q80bv_wait_while_busy();
|
w25q80bv_wait_while_busy(drv);
|
||||||
|
|
||||||
gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL);
|
uint8_t header[] = {
|
||||||
ssp_transfer(SSP0_NUM, W25Q80BV_PAGE_PROGRAM);
|
W25Q80BV_PAGE_PROGRAM,
|
||||||
ssp_transfer(SSP0_NUM, (addr & 0xFF0000) >> 16);
|
(addr & 0xFF0000) >> 16,
|
||||||
ssp_transfer(SSP0_NUM, (addr & 0xFF00) >> 8);
|
(addr & 0xFF00) >> 8,
|
||||||
ssp_transfer(SSP0_NUM, addr & 0xFF);
|
addr & 0xFF
|
||||||
for (i = 0; i < len; i++)
|
};
|
||||||
ssp_transfer(SSP0_NUM, data[i]);
|
|
||||||
gpio_set(PORT_SSP0_SSEL, PIN_SSP0_SSEL);
|
const spi_transfer_t transfers[] = {
|
||||||
|
{ header, ARRAY_SIZE(header) },
|
||||||
|
{ data, len }
|
||||||
|
};
|
||||||
|
|
||||||
|
spi_bus_transfer_gather(drv->bus, transfers, ARRAY_SIZE(transfers));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write an arbitrary number of bytes */
|
/* write an arbitrary number of bytes */
|
||||||
void w25q80bv_program(uint32_t addr, uint32_t len, const uint8_t* data)
|
void w25q80bv_program(w25q80bv_driver_t* const drv, uint32_t addr, uint32_t len, uint8_t* data)
|
||||||
{
|
{
|
||||||
uint16_t first_block_len;
|
uint16_t first_block_len;
|
||||||
uint8_t device_id;
|
uint8_t device_id;
|
||||||
@ -211,57 +168,60 @@ void w25q80bv_program(uint32_t addr, uint32_t len, const uint8_t* data)
|
|||||||
device_id = 0;
|
device_id = 0;
|
||||||
while(device_id != W25Q80BV_DEVICE_ID_RES)
|
while(device_id != W25Q80BV_DEVICE_ID_RES)
|
||||||
{
|
{
|
||||||
device_id = w25q80bv_get_device_id();
|
device_id = w25q80bv_get_device_id(drv);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* do nothing if we would overflow the flash */
|
/* do nothing if we would overflow the flash */
|
||||||
if ((len > W25Q80BV_NUM_BYTES) || (addr > W25Q80BV_NUM_BYTES)
|
if ((len > drv->num_bytes) || (addr > drv->num_bytes)
|
||||||
|| ((addr + len) > W25Q80BV_NUM_BYTES))
|
|| ((addr + len) > drv->num_bytes))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* handle start not at page boundary */
|
/* handle start not at page boundary */
|
||||||
first_block_len = W25Q80BV_PAGE_LEN - (addr % W25Q80BV_PAGE_LEN);
|
first_block_len = drv->page_len - (addr % drv->page_len);
|
||||||
if (len < first_block_len)
|
if (len < first_block_len)
|
||||||
first_block_len = len;
|
first_block_len = len;
|
||||||
if (first_block_len) {
|
if (first_block_len) {
|
||||||
w25q80bv_page_program(addr, first_block_len, data);
|
w25q80bv_page_program(drv, addr, first_block_len, data);
|
||||||
addr += first_block_len;
|
addr += first_block_len;
|
||||||
data += first_block_len;
|
data += first_block_len;
|
||||||
len -= first_block_len;
|
len -= first_block_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* one page at a time on boundaries */
|
/* one page at a time on boundaries */
|
||||||
while (len >= W25Q80BV_PAGE_LEN) {
|
while (len >= drv->page_len) {
|
||||||
w25q80bv_page_program(addr, W25Q80BV_PAGE_LEN, data);
|
w25q80bv_page_program(drv, addr, drv->page_len, data);
|
||||||
addr += W25Q80BV_PAGE_LEN;
|
addr += drv->page_len;
|
||||||
data += W25Q80BV_PAGE_LEN;
|
data += drv->page_len;
|
||||||
len -= W25Q80BV_PAGE_LEN;
|
len -= drv->page_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* handle end not at page boundary */
|
/* handle end not at page boundary */
|
||||||
if (len) {
|
if (len) {
|
||||||
w25q80bv_page_program(addr, len, data);
|
w25q80bv_page_program(drv, addr, len, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void w25q80bv_read(uint32_t addr, uint32_t len, uint8_t* const data)
|
/* write an arbitrary number of bytes */
|
||||||
|
void w25q80bv_read(w25q80bv_driver_t* const drv, uint32_t addr, uint32_t len, uint8_t* const data)
|
||||||
{
|
{
|
||||||
uint32_t i;
|
|
||||||
|
|
||||||
/* do nothing if we would overflow the flash */
|
/* do nothing if we would overflow the flash */
|
||||||
if ((len > W25Q80BV_NUM_BYTES) || (addr > W25Q80BV_NUM_BYTES)
|
if ((len > drv->num_bytes) || (addr > drv->num_bytes)
|
||||||
|| ((addr + len) > W25Q80BV_NUM_BYTES))
|
|| ((addr + len) > drv->num_bytes))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
w25q80bv_wait_while_busy();
|
w25q80bv_wait_while_busy(drv);
|
||||||
|
|
||||||
gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL);
|
uint8_t header[] = {
|
||||||
ssp_transfer(SSP0_NUM, W25Q80BV_FAST_READ);
|
W25Q80BV_FAST_READ,
|
||||||
ssp_transfer(SSP0_NUM, (addr >> 16) & 0xFF);
|
(addr & 0xFF0000) >> 16,
|
||||||
ssp_transfer(SSP0_NUM, (addr >> 8) & 0xFF);
|
(addr & 0xFF00) >> 8,
|
||||||
ssp_transfer(SSP0_NUM, (addr >> 0) & 0xFF);
|
addr & 0xFF
|
||||||
ssp_transfer(SSP0_NUM, 0xFF);
|
};
|
||||||
for (i = 0; i < len; i++)
|
|
||||||
data[i] = ssp_transfer(SSP0_NUM, 0xFF);
|
const spi_transfer_t transfers[] = {
|
||||||
gpio_set(PORT_SSP0_SSEL, PIN_SSP0_SSEL);
|
{ header, ARRAY_SIZE(header) },
|
||||||
|
{ data, len }
|
||||||
|
};
|
||||||
|
|
||||||
|
spi_bus_transfer_gather(drv->bus, transfers, ARRAY_SIZE(transfers));
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013 Michael Ossmann
|
* Copyright 2013 Michael Ossmann
|
||||||
* Copyright 2013 Benjamin Vernoux
|
* Copyright 2013 Benjamin Vernoux
|
||||||
|
* Copyright 2014 Jared Boone, ShareBrained Technology
|
||||||
*
|
*
|
||||||
* This file is part of HackRF.
|
* This file is part of HackRF.
|
||||||
*
|
*
|
||||||
@ -23,23 +24,11 @@
|
|||||||
#ifndef __W25Q80BV_H__
|
#ifndef __W25Q80BV_H__
|
||||||
#define __W25Q80BV_H__
|
#define __W25Q80BV_H__
|
||||||
|
|
||||||
#define W25Q80BV_PAGE_LEN 256U
|
#include <stdint.h>
|
||||||
#define W25Q80BV_NUM_PAGES 4096U
|
#include <stddef.h>
|
||||||
#define W25Q80BV_NUM_BYTES 1048576U
|
|
||||||
|
|
||||||
#define W25Q80BV_READ_DATA 0x03
|
#include "spi_bus.h"
|
||||||
#define W25Q80BV_FAST_READ 0x0b
|
#include "gpio.h"
|
||||||
#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
|
typedef union
|
||||||
{
|
{
|
||||||
@ -48,11 +37,24 @@ typedef union
|
|||||||
uint8_t id_8b[8]; /* 8*8bits 64bits Unique ID */
|
uint8_t id_8b[8]; /* 8*8bits 64bits Unique ID */
|
||||||
} w25q80bv_unique_id_t;
|
} w25q80bv_unique_id_t;
|
||||||
|
|
||||||
void w25q80bv_setup(void);
|
struct w25q80bv_driver_t;
|
||||||
void w25q80bv_chip_erase(void);
|
typedef struct w25q80bv_driver_t w25q80bv_driver_t;
|
||||||
void w25q80bv_program(uint32_t addr, uint32_t len, const uint8_t* data);
|
|
||||||
uint8_t w25q80bv_get_device_id(void);
|
struct w25q80bv_driver_t {
|
||||||
void w25q80bv_get_unique_id(w25q80bv_unique_id_t* unique_id);
|
spi_bus_t* bus;
|
||||||
void w25q80bv_read(uint32_t addr, uint32_t len, uint8_t* const data);
|
gpio_t gpio_hold;
|
||||||
|
gpio_t gpio_wp;
|
||||||
|
void (*target_init)(w25q80bv_driver_t* const drv);
|
||||||
|
size_t page_len;
|
||||||
|
size_t num_pages;
|
||||||
|
size_t num_bytes;
|
||||||
|
};
|
||||||
|
|
||||||
|
void w25q80bv_setup(w25q80bv_driver_t* const drv);
|
||||||
|
void w25q80bv_chip_erase(w25q80bv_driver_t* const drv);
|
||||||
|
void w25q80bv_program(w25q80bv_driver_t* const drv, uint32_t addr, uint32_t len, uint8_t* data);
|
||||||
|
uint8_t w25q80bv_get_device_id(w25q80bv_driver_t* const drv);
|
||||||
|
void w25q80bv_get_unique_id(w25q80bv_driver_t* const drv, w25q80bv_unique_id_t* unique_id);
|
||||||
|
void w25q80bv_read(w25q80bv_driver_t* const drv, uint32_t addr, uint32_t len, uint8_t* const data);
|
||||||
|
|
||||||
#endif//__W25Q80BV_H__
|
#endif//__W25Q80BV_H__
|
||||||
|
59
firmware/common/w25q80bv_target.c
Normal file
59
firmware/common/w25q80bv_target.c
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
||||||
|
*
|
||||||
|
* 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 "w25q80bv_target.h"
|
||||||
|
|
||||||
|
#include <libopencm3/lpc43xx/scu.h>
|
||||||
|
#include "hackrf_core.h"
|
||||||
|
|
||||||
|
/* TODO: Why is SSEL being controlled manually when SSP0 could do it
|
||||||
|
* automatically?
|
||||||
|
*/
|
||||||
|
|
||||||
|
void w25q80bv_target_init(w25q80bv_driver_t* const drv) {
|
||||||
|
(void)drv;
|
||||||
|
|
||||||
|
/* 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(drv->gpio_hold);
|
||||||
|
gpio_set(drv->gpio_wp);
|
||||||
|
|
||||||
|
/* Set GPIO pins as outputs. */
|
||||||
|
gpio_output(drv->gpio_hold);
|
||||||
|
gpio_output(drv->gpio_wp);
|
||||||
|
}
|
29
firmware/common/w25q80bv_target.h
Normal file
29
firmware/common/w25q80bv_target.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
||||||
|
*
|
||||||
|
* 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_TARGET_H__
|
||||||
|
#define __W25Q80BV_TARGET_H__
|
||||||
|
|
||||||
|
#include "w25q80bv.h"
|
||||||
|
|
||||||
|
void w25q80bv_target_init(w25q80bv_driver_t* const drv);
|
||||||
|
|
||||||
|
#endif/*__W25Q80BV_TARGET_H__*/
|
@ -197,7 +197,7 @@ typedef struct tagSXsvfInfo
|
|||||||
} SXsvfInfo;
|
} SXsvfInfo;
|
||||||
|
|
||||||
/* Declare pointer to functions that perform XSVF commands */
|
/* Declare pointer to functions that perform XSVF commands */
|
||||||
typedef int (*TXsvfDoCmdFuncPtr)( SXsvfInfo* );
|
typedef int (*TXsvfDoCmdFuncPtr)( jtag_gpio_t* const gpio, SXsvfInfo* );
|
||||||
|
|
||||||
|
|
||||||
/*============================================================================
|
/*============================================================================
|
||||||
@ -267,24 +267,24 @@ typedef int (*TXsvfDoCmdFuncPtr)( SXsvfInfo* );
|
|||||||
* XSVF Function Prototypes
|
* XSVF Function Prototypes
|
||||||
============================================================================*/
|
============================================================================*/
|
||||||
|
|
||||||
int xsvfDoIllegalCmd( SXsvfInfo* pXsvfInfo ); /* Illegal command function */
|
int xsvfDoIllegalCmd( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo ); /* Illegal command function */
|
||||||
int xsvfDoXCOMPLETE( SXsvfInfo* pXsvfInfo );
|
int xsvfDoXCOMPLETE( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo );
|
||||||
int xsvfDoXTDOMASK( SXsvfInfo* pXsvfInfo );
|
int xsvfDoXTDOMASK( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo );
|
||||||
int xsvfDoXSIR( SXsvfInfo* pXsvfInfo );
|
int xsvfDoXSIR( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo );
|
||||||
int xsvfDoXSIR2( SXsvfInfo* pXsvfInfo );
|
int xsvfDoXSIR2( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo );
|
||||||
int xsvfDoXSDR( SXsvfInfo* pXsvfInfo );
|
int xsvfDoXSDR( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo );
|
||||||
int xsvfDoXRUNTEST( SXsvfInfo* pXsvfInfo );
|
int xsvfDoXRUNTEST( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo );
|
||||||
int xsvfDoXREPEAT( SXsvfInfo* pXsvfInfo );
|
int xsvfDoXREPEAT( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo );
|
||||||
int xsvfDoXSDRSIZE( SXsvfInfo* pXsvfInfo );
|
int xsvfDoXSDRSIZE( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo );
|
||||||
int xsvfDoXSDRTDO( SXsvfInfo* pXsvfInfo );
|
int xsvfDoXSDRTDO( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo );
|
||||||
int xsvfDoXSETSDRMASKS( SXsvfInfo* pXsvfInfo );
|
int xsvfDoXSETSDRMASKS( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo );
|
||||||
int xsvfDoXSDRINC( SXsvfInfo* pXsvfInfo );
|
int xsvfDoXSDRINC( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo );
|
||||||
int xsvfDoXSDRBCE( SXsvfInfo* pXsvfInfo );
|
int xsvfDoXSDRBCE( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo );
|
||||||
int xsvfDoXSDRTDOBCE( SXsvfInfo* pXsvfInfo );
|
int xsvfDoXSDRTDOBCE( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo );
|
||||||
int xsvfDoXSTATE( SXsvfInfo* pXsvfInfo );
|
int xsvfDoXSTATE( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo );
|
||||||
int xsvfDoXENDXR( SXsvfInfo* pXsvfInfo );
|
int xsvfDoXENDXR( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo );
|
||||||
int xsvfDoXCOMMENT( SXsvfInfo* pXsvfInfo );
|
int xsvfDoXCOMMENT( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo );
|
||||||
int xsvfDoXWAIT( SXsvfInfo* pXsvfInfo );
|
int xsvfDoXWAIT( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo );
|
||||||
/* Insert new command functions here */
|
/* Insert new command functions here */
|
||||||
|
|
||||||
/*============================================================================
|
/*============================================================================
|
||||||
@ -476,11 +476,11 @@ short xsvfGetAsNumBytes( long lNumBits )
|
|||||||
* Parameters: sTms - new TMS value.
|
* Parameters: sTms - new TMS value.
|
||||||
* Returns: void.
|
* Returns: void.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
void xsvfTmsTransition( short sTms )
|
void xsvfTmsTransition(jtag_gpio_t* const gpio, short sTms )
|
||||||
{
|
{
|
||||||
setPort( TMS, sTms );
|
setPort(gpio, TMS, sTms );
|
||||||
setPort( TCK, 0 );
|
setPort(gpio, TCK, 0 );
|
||||||
setPort( TCK, 1 );
|
setPort(gpio, TCK, 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
@ -496,7 +496,8 @@ void xsvfTmsTransition( short sTms )
|
|||||||
* ucTargetState - New target TAP state.
|
* ucTargetState - New target TAP state.
|
||||||
* Returns: int - 0 = success; otherwise error.
|
* Returns: int - 0 = success; otherwise error.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
int xsvfGotoTapState( unsigned char* pucTapState,
|
int xsvfGotoTapState( jtag_gpio_t* const gpio,
|
||||||
|
unsigned char* pucTapState,
|
||||||
unsigned char ucTargetState )
|
unsigned char ucTargetState )
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -506,11 +507,11 @@ int xsvfGotoTapState( unsigned char* pucTapState,
|
|||||||
if ( ucTargetState == XTAPSTATE_RESET )
|
if ( ucTargetState == XTAPSTATE_RESET )
|
||||||
{
|
{
|
||||||
/* If RESET, always perform TMS reset sequence to reset/sync TAPs */
|
/* If RESET, always perform TMS reset sequence to reset/sync TAPs */
|
||||||
xsvfTmsTransition( 1 );
|
xsvfTmsTransition( gpio, 1 );
|
||||||
for ( i = 0; i < 5; ++i )
|
for ( i = 0; i < 5; ++i )
|
||||||
{
|
{
|
||||||
setPort( TCK, 0 );
|
setPort(gpio, TCK, 0 );
|
||||||
setPort( TCK, 1 );
|
setPort(gpio, TCK, 1 );
|
||||||
}
|
}
|
||||||
*pucTapState = XTAPSTATE_RESET;
|
*pucTapState = XTAPSTATE_RESET;
|
||||||
XSVFDBG_PRINTF( 3, " TMS Reset Sequence -> Test-Logic-Reset\n" );
|
XSVFDBG_PRINTF( 3, " TMS Reset Sequence -> Test-Logic-Reset\n" );
|
||||||
@ -532,14 +533,14 @@ int xsvfGotoTapState( unsigned char* pucTapState,
|
|||||||
or in IRPAUSE to comply with SVF standard */
|
or in IRPAUSE to comply with SVF standard */
|
||||||
if ( ucTargetState == XTAPSTATE_PAUSEDR )
|
if ( ucTargetState == XTAPSTATE_PAUSEDR )
|
||||||
{
|
{
|
||||||
xsvfTmsTransition( 1 );
|
xsvfTmsTransition( gpio, 1 );
|
||||||
*pucTapState = XTAPSTATE_EXIT2DR;
|
*pucTapState = XTAPSTATE_EXIT2DR;
|
||||||
XSVFDBG_PRINTF1( 3, " TAP State = %s\n",
|
XSVFDBG_PRINTF1( 3, " TAP State = %s\n",
|
||||||
xsvf_pzTapState[ *pucTapState ] );
|
xsvf_pzTapState[ *pucTapState ] );
|
||||||
}
|
}
|
||||||
else if ( ucTargetState == XTAPSTATE_PAUSEIR )
|
else if ( ucTargetState == XTAPSTATE_PAUSEIR )
|
||||||
{
|
{
|
||||||
xsvfTmsTransition( 1 );
|
xsvfTmsTransition( gpio, 1 );
|
||||||
*pucTapState = XTAPSTATE_EXIT2IR;
|
*pucTapState = XTAPSTATE_EXIT2IR;
|
||||||
XSVFDBG_PRINTF1( 3, " TAP State = %s\n",
|
XSVFDBG_PRINTF1( 3, " TAP State = %s\n",
|
||||||
xsvf_pzTapState[ *pucTapState ] );
|
xsvf_pzTapState[ *pucTapState ] );
|
||||||
@ -552,138 +553,138 @@ int xsvfGotoTapState( unsigned char* pucTapState,
|
|||||||
switch ( *pucTapState )
|
switch ( *pucTapState )
|
||||||
{
|
{
|
||||||
case XTAPSTATE_RESET:
|
case XTAPSTATE_RESET:
|
||||||
xsvfTmsTransition( 0 );
|
xsvfTmsTransition( gpio, 0 );
|
||||||
*pucTapState = XTAPSTATE_RUNTEST;
|
*pucTapState = XTAPSTATE_RUNTEST;
|
||||||
break;
|
break;
|
||||||
case XTAPSTATE_RUNTEST:
|
case XTAPSTATE_RUNTEST:
|
||||||
xsvfTmsTransition( 1 );
|
xsvfTmsTransition( gpio, 1 );
|
||||||
*pucTapState = XTAPSTATE_SELECTDR;
|
*pucTapState = XTAPSTATE_SELECTDR;
|
||||||
break;
|
break;
|
||||||
case XTAPSTATE_SELECTDR:
|
case XTAPSTATE_SELECTDR:
|
||||||
if ( ucTargetState >= XTAPSTATE_IRSTATES )
|
if ( ucTargetState >= XTAPSTATE_IRSTATES )
|
||||||
{
|
{
|
||||||
xsvfTmsTransition( 1 );
|
xsvfTmsTransition( gpio, 1 );
|
||||||
*pucTapState = XTAPSTATE_SELECTIR;
|
*pucTapState = XTAPSTATE_SELECTIR;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
xsvfTmsTransition( 0 );
|
xsvfTmsTransition( gpio, 0 );
|
||||||
*pucTapState = XTAPSTATE_CAPTUREDR;
|
*pucTapState = XTAPSTATE_CAPTUREDR;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XTAPSTATE_CAPTUREDR:
|
case XTAPSTATE_CAPTUREDR:
|
||||||
if ( ucTargetState == XTAPSTATE_SHIFTDR )
|
if ( ucTargetState == XTAPSTATE_SHIFTDR )
|
||||||
{
|
{
|
||||||
xsvfTmsTransition( 0 );
|
xsvfTmsTransition( gpio, 0 );
|
||||||
*pucTapState = XTAPSTATE_SHIFTDR;
|
*pucTapState = XTAPSTATE_SHIFTDR;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
xsvfTmsTransition( 1 );
|
xsvfTmsTransition( gpio, 1 );
|
||||||
*pucTapState = XTAPSTATE_EXIT1DR;
|
*pucTapState = XTAPSTATE_EXIT1DR;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XTAPSTATE_SHIFTDR:
|
case XTAPSTATE_SHIFTDR:
|
||||||
xsvfTmsTransition( 1 );
|
xsvfTmsTransition( gpio, 1 );
|
||||||
*pucTapState = XTAPSTATE_EXIT1DR;
|
*pucTapState = XTAPSTATE_EXIT1DR;
|
||||||
break;
|
break;
|
||||||
case XTAPSTATE_EXIT1DR:
|
case XTAPSTATE_EXIT1DR:
|
||||||
if ( ucTargetState == XTAPSTATE_PAUSEDR )
|
if ( ucTargetState == XTAPSTATE_PAUSEDR )
|
||||||
{
|
{
|
||||||
xsvfTmsTransition( 0 );
|
xsvfTmsTransition( gpio, 0 );
|
||||||
*pucTapState = XTAPSTATE_PAUSEDR;
|
*pucTapState = XTAPSTATE_PAUSEDR;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
xsvfTmsTransition( 1 );
|
xsvfTmsTransition( gpio, 1 );
|
||||||
*pucTapState = XTAPSTATE_UPDATEDR;
|
*pucTapState = XTAPSTATE_UPDATEDR;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XTAPSTATE_PAUSEDR:
|
case XTAPSTATE_PAUSEDR:
|
||||||
xsvfTmsTransition( 1 );
|
xsvfTmsTransition( gpio, 1 );
|
||||||
*pucTapState = XTAPSTATE_EXIT2DR;
|
*pucTapState = XTAPSTATE_EXIT2DR;
|
||||||
break;
|
break;
|
||||||
case XTAPSTATE_EXIT2DR:
|
case XTAPSTATE_EXIT2DR:
|
||||||
if ( ucTargetState == XTAPSTATE_SHIFTDR )
|
if ( ucTargetState == XTAPSTATE_SHIFTDR )
|
||||||
{
|
{
|
||||||
xsvfTmsTransition( 0 );
|
xsvfTmsTransition( gpio, 0 );
|
||||||
*pucTapState = XTAPSTATE_SHIFTDR;
|
*pucTapState = XTAPSTATE_SHIFTDR;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
xsvfTmsTransition( 1 );
|
xsvfTmsTransition( gpio, 1 );
|
||||||
*pucTapState = XTAPSTATE_UPDATEDR;
|
*pucTapState = XTAPSTATE_UPDATEDR;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XTAPSTATE_UPDATEDR:
|
case XTAPSTATE_UPDATEDR:
|
||||||
if ( ucTargetState == XTAPSTATE_RUNTEST )
|
if ( ucTargetState == XTAPSTATE_RUNTEST )
|
||||||
{
|
{
|
||||||
xsvfTmsTransition( 0 );
|
xsvfTmsTransition( gpio, 0 );
|
||||||
*pucTapState = XTAPSTATE_RUNTEST;
|
*pucTapState = XTAPSTATE_RUNTEST;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
xsvfTmsTransition( 1 );
|
xsvfTmsTransition( gpio, 1 );
|
||||||
*pucTapState = XTAPSTATE_SELECTDR;
|
*pucTapState = XTAPSTATE_SELECTDR;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XTAPSTATE_SELECTIR:
|
case XTAPSTATE_SELECTIR:
|
||||||
xsvfTmsTransition( 0 );
|
xsvfTmsTransition( gpio, 0 );
|
||||||
*pucTapState = XTAPSTATE_CAPTUREIR;
|
*pucTapState = XTAPSTATE_CAPTUREIR;
|
||||||
break;
|
break;
|
||||||
case XTAPSTATE_CAPTUREIR:
|
case XTAPSTATE_CAPTUREIR:
|
||||||
if ( ucTargetState == XTAPSTATE_SHIFTIR )
|
if ( ucTargetState == XTAPSTATE_SHIFTIR )
|
||||||
{
|
{
|
||||||
xsvfTmsTransition( 0 );
|
xsvfTmsTransition( gpio, 0 );
|
||||||
*pucTapState = XTAPSTATE_SHIFTIR;
|
*pucTapState = XTAPSTATE_SHIFTIR;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
xsvfTmsTransition( 1 );
|
xsvfTmsTransition( gpio, 1 );
|
||||||
*pucTapState = XTAPSTATE_EXIT1IR;
|
*pucTapState = XTAPSTATE_EXIT1IR;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XTAPSTATE_SHIFTIR:
|
case XTAPSTATE_SHIFTIR:
|
||||||
xsvfTmsTransition( 1 );
|
xsvfTmsTransition( gpio, 1 );
|
||||||
*pucTapState = XTAPSTATE_EXIT1IR;
|
*pucTapState = XTAPSTATE_EXIT1IR;
|
||||||
break;
|
break;
|
||||||
case XTAPSTATE_EXIT1IR:
|
case XTAPSTATE_EXIT1IR:
|
||||||
if ( ucTargetState == XTAPSTATE_PAUSEIR )
|
if ( ucTargetState == XTAPSTATE_PAUSEIR )
|
||||||
{
|
{
|
||||||
xsvfTmsTransition( 0 );
|
xsvfTmsTransition( gpio, 0 );
|
||||||
*pucTapState = XTAPSTATE_PAUSEIR;
|
*pucTapState = XTAPSTATE_PAUSEIR;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
xsvfTmsTransition( 1 );
|
xsvfTmsTransition( gpio, 1 );
|
||||||
*pucTapState = XTAPSTATE_UPDATEIR;
|
*pucTapState = XTAPSTATE_UPDATEIR;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XTAPSTATE_PAUSEIR:
|
case XTAPSTATE_PAUSEIR:
|
||||||
xsvfTmsTransition( 1 );
|
xsvfTmsTransition( gpio, 1 );
|
||||||
*pucTapState = XTAPSTATE_EXIT2IR;
|
*pucTapState = XTAPSTATE_EXIT2IR;
|
||||||
break;
|
break;
|
||||||
case XTAPSTATE_EXIT2IR:
|
case XTAPSTATE_EXIT2IR:
|
||||||
if ( ucTargetState == XTAPSTATE_SHIFTIR )
|
if ( ucTargetState == XTAPSTATE_SHIFTIR )
|
||||||
{
|
{
|
||||||
xsvfTmsTransition( 0 );
|
xsvfTmsTransition( gpio, 0 );
|
||||||
*pucTapState = XTAPSTATE_SHIFTIR;
|
*pucTapState = XTAPSTATE_SHIFTIR;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
xsvfTmsTransition( 1 );
|
xsvfTmsTransition( gpio, 1 );
|
||||||
*pucTapState = XTAPSTATE_UPDATEIR;
|
*pucTapState = XTAPSTATE_UPDATEIR;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XTAPSTATE_UPDATEIR:
|
case XTAPSTATE_UPDATEIR:
|
||||||
if ( ucTargetState == XTAPSTATE_RUNTEST )
|
if ( ucTargetState == XTAPSTATE_RUNTEST )
|
||||||
{
|
{
|
||||||
xsvfTmsTransition( 0 );
|
xsvfTmsTransition( gpio, 0 );
|
||||||
*pucTapState = XTAPSTATE_RUNTEST;
|
*pucTapState = XTAPSTATE_RUNTEST;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
xsvfTmsTransition( 1 );
|
xsvfTmsTransition( gpio, 1 );
|
||||||
*pucTapState = XTAPSTATE_SELECTDR;
|
*pucTapState = XTAPSTATE_SELECTDR;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -714,7 +715,8 @@ int xsvfGotoTapState( unsigned char* pucTapState,
|
|||||||
* iExitShift - 1=exit at end of shift; 0=stay in Shift-DR.
|
* iExitShift - 1=exit at end of shift; 0=stay in Shift-DR.
|
||||||
* Returns: void.
|
* Returns: void.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
void xsvfShiftOnly( long lNumBits,
|
void xsvfShiftOnly( jtag_gpio_t* const gpio,
|
||||||
|
long lNumBits,
|
||||||
lenVal* plvTdi,
|
lenVal* plvTdi,
|
||||||
lenVal* plvTdoCaptured,
|
lenVal* plvTdoCaptured,
|
||||||
int iExitShift )
|
int iExitShift )
|
||||||
@ -749,25 +751,25 @@ void xsvfShiftOnly( long lNumBits,
|
|||||||
if ( iExitShift && !lNumBits )
|
if ( iExitShift && !lNumBits )
|
||||||
{
|
{
|
||||||
/* Exit Shift-DR state */
|
/* Exit Shift-DR state */
|
||||||
setPort( TMS, 1 );
|
setPort(gpio, TMS, 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the new TDI value */
|
/* Set the new TDI value */
|
||||||
setPort( TDI, (short)(ucTdiByte & 1) );
|
setPort(gpio, TDI, (short)(ucTdiByte & 1) );
|
||||||
ucTdiByte >>= 1;
|
ucTdiByte >>= 1;
|
||||||
|
|
||||||
/* Set TCK low */
|
/* Set TCK low */
|
||||||
setPort( TCK, 0 );
|
setPort(gpio, TCK, 0 );
|
||||||
|
|
||||||
if ( pucTdo )
|
if ( pucTdo )
|
||||||
{
|
{
|
||||||
/* Save the TDO value */
|
/* Save the TDO value */
|
||||||
ucTdoBit = readTDOBit();
|
ucTdoBit = readTDOBit(gpio);
|
||||||
ucTdoByte |= ( ucTdoBit << i );
|
ucTdoByte |= ( ucTdoBit << i );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set TCK high */
|
/* Set TCK high */
|
||||||
setPort( TCK, 1 );
|
setPort(gpio, TCK, 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save the TDO byte value */
|
/* Save the TDO byte value */
|
||||||
@ -802,7 +804,8 @@ void xsvfShiftOnly( long lNumBits,
|
|||||||
* Skip the waitTime() if plvTdoMask->val[0:plvTdoMask->len-1]
|
* Skip the waitTime() if plvTdoMask->val[0:plvTdoMask->len-1]
|
||||||
* is NOT all zeros and sMatch==1.
|
* is NOT all zeros and sMatch==1.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
int xsvfShift( unsigned char* pucTapState,
|
int xsvfShift( jtag_gpio_t* const gpio,
|
||||||
|
unsigned char* pucTapState,
|
||||||
unsigned char ucStartState,
|
unsigned char ucStartState,
|
||||||
long lNumBits,
|
long lNumBits,
|
||||||
lenVal* plvTdi,
|
lenVal* plvTdi,
|
||||||
@ -837,9 +840,9 @@ int xsvfShift( unsigned char* pucTapState,
|
|||||||
if ( lRunTestTime )
|
if ( lRunTestTime )
|
||||||
{
|
{
|
||||||
/* Wait for prespecified XRUNTEST time */
|
/* Wait for prespecified XRUNTEST time */
|
||||||
xsvfGotoTapState( pucTapState, XTAPSTATE_RUNTEST );
|
xsvfGotoTapState( gpio, pucTapState, XTAPSTATE_RUNTEST );
|
||||||
XSVFDBG_PRINTF1( 3, " Wait = %ld usec\n", lRunTestTime );
|
XSVFDBG_PRINTF1( 3, " Wait = %ld usec\n", lRunTestTime );
|
||||||
waitTime( lRunTestTime );
|
waitTime( gpio, lRunTestTime );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -847,10 +850,10 @@ int xsvfShift( unsigned char* pucTapState,
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
/* Goto Shift-DR or Shift-IR */
|
/* Goto Shift-DR or Shift-IR */
|
||||||
xsvfGotoTapState( pucTapState, ucStartState );
|
xsvfGotoTapState( gpio, pucTapState, ucStartState );
|
||||||
|
|
||||||
/* Shift TDI and capture TDO */
|
/* Shift TDI and capture TDO */
|
||||||
xsvfShiftOnly( lNumBits, plvTdi, plvTdoCaptured, iExitShift );
|
xsvfShiftOnly( gpio, lNumBits, plvTdi, plvTdoCaptured, iExitShift );
|
||||||
|
|
||||||
if ( plvTdoExpected )
|
if ( plvTdoExpected )
|
||||||
{
|
{
|
||||||
@ -880,24 +883,24 @@ int xsvfShift( unsigned char* pucTapState,
|
|||||||
XSVFDBG_PRINTF( 4, "\n");
|
XSVFDBG_PRINTF( 4, "\n");
|
||||||
XSVFDBG_PRINTF1( 3, " Retry #%d\n", ( ucRepeat + 1 ) );
|
XSVFDBG_PRINTF1( 3, " Retry #%d\n", ( ucRepeat + 1 ) );
|
||||||
/* Do exception handling retry - ShiftDR only */
|
/* Do exception handling retry - ShiftDR only */
|
||||||
xsvfGotoTapState( pucTapState, XTAPSTATE_PAUSEDR );
|
xsvfGotoTapState( gpio, pucTapState, XTAPSTATE_PAUSEDR );
|
||||||
/* Shift 1 extra bit */
|
/* Shift 1 extra bit */
|
||||||
xsvfGotoTapState( pucTapState, XTAPSTATE_SHIFTDR );
|
xsvfGotoTapState( gpio, pucTapState, XTAPSTATE_SHIFTDR );
|
||||||
/* Increment RUNTEST time by an additional 25% */
|
/* Increment RUNTEST time by an additional 25% */
|
||||||
lRunTestTime += ( lRunTestTime >> 2 );
|
lRunTestTime += ( lRunTestTime >> 2 );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Do normal exit from Shift-XR */
|
/* Do normal exit from Shift-XR */
|
||||||
xsvfGotoTapState( pucTapState, ucEndState );
|
xsvfGotoTapState( gpio, pucTapState, ucEndState );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( lRunTestTime )
|
if ( lRunTestTime )
|
||||||
{
|
{
|
||||||
/* Wait for prespecified XRUNTEST time */
|
/* Wait for prespecified XRUNTEST time */
|
||||||
xsvfGotoTapState( pucTapState, XTAPSTATE_RUNTEST );
|
xsvfGotoTapState( gpio, pucTapState, XTAPSTATE_RUNTEST );
|
||||||
XSVFDBG_PRINTF1( 3, " Wait = %ld usec\n", lRunTestTime );
|
XSVFDBG_PRINTF1( 3, " Wait = %ld usec\n", lRunTestTime );
|
||||||
waitTime( lRunTestTime );
|
waitTime( gpio, lRunTestTime );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while ( iMismatch && ( ucRepeat++ < ucMaxRepeat ) );
|
} while ( iMismatch && ( ucRepeat++ < ucMaxRepeat ) );
|
||||||
@ -941,7 +944,8 @@ int xsvfShift( unsigned char* pucTapState,
|
|||||||
* ucMaxRepeat - maximum xc9500/xl retries.
|
* ucMaxRepeat - maximum xc9500/xl retries.
|
||||||
* Returns: int - 0 = success; otherwise TDO mismatch.
|
* Returns: int - 0 = success; otherwise TDO mismatch.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
int xsvfBasicXSDRTDO( unsigned char* pucTapState,
|
int xsvfBasicXSDRTDO( jtag_gpio_t* const gpio,
|
||||||
|
unsigned char* pucTapState,
|
||||||
long lShiftLengthBits,
|
long lShiftLengthBits,
|
||||||
short sShiftLengthBytes,
|
short sShiftLengthBytes,
|
||||||
lenVal* plvTdi,
|
lenVal* plvTdi,
|
||||||
@ -957,7 +961,7 @@ int xsvfBasicXSDRTDO( unsigned char* pucTapState,
|
|||||||
{
|
{
|
||||||
readVal( plvTdoExpected, sShiftLengthBytes );
|
readVal( plvTdoExpected, sShiftLengthBytes );
|
||||||
}
|
}
|
||||||
return( xsvfShift( pucTapState, XTAPSTATE_SHIFTDR, lShiftLengthBits,
|
return( xsvfShift( gpio, pucTapState, XTAPSTATE_SHIFTDR, lShiftLengthBits,
|
||||||
plvTdi, plvTdoCaptured, plvTdoExpected, plvTdoMask,
|
plvTdi, plvTdoCaptured, plvTdoExpected, plvTdoMask,
|
||||||
ucEndState, lRunTestTime, ucMaxRepeat ) );
|
ucEndState, lRunTestTime, ucMaxRepeat ) );
|
||||||
}
|
}
|
||||||
@ -1052,8 +1056,9 @@ void xsvfDoSDRMasking( lenVal* plvTdi,
|
|||||||
* Parameters: pXsvfInfo - XSVF information pointer.
|
* Parameters: pXsvfInfo - XSVF information pointer.
|
||||||
* Returns: int - 0 = success; non-zero = error.
|
* Returns: int - 0 = success; non-zero = error.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
int xsvfDoIllegalCmd( SXsvfInfo* pXsvfInfo )
|
int xsvfDoIllegalCmd( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo )
|
||||||
{
|
{
|
||||||
|
(void)gpio;
|
||||||
XSVFDBG_PRINTF2( 0, "ERROR: Encountered unsupported command #%d (%s)\n",
|
XSVFDBG_PRINTF2( 0, "ERROR: Encountered unsupported command #%d (%s)\n",
|
||||||
((unsigned int)(pXsvfInfo->ucCommand)),
|
((unsigned int)(pXsvfInfo->ucCommand)),
|
||||||
((pXsvfInfo->ucCommand < XLASTCMD)
|
((pXsvfInfo->ucCommand < XLASTCMD)
|
||||||
@ -1070,8 +1075,9 @@ int xsvfDoIllegalCmd( SXsvfInfo* pXsvfInfo )
|
|||||||
* Parameters: pXsvfInfo - XSVF information pointer.
|
* Parameters: pXsvfInfo - XSVF information pointer.
|
||||||
* Returns: int - 0 = success; non-zero = error.
|
* Returns: int - 0 = success; non-zero = error.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
int xsvfDoXCOMPLETE( SXsvfInfo* pXsvfInfo )
|
int xsvfDoXCOMPLETE( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo )
|
||||||
{
|
{
|
||||||
|
(void)gpio;
|
||||||
pXsvfInfo->ucComplete = 1;
|
pXsvfInfo->ucComplete = 1;
|
||||||
return( XSVF_ERROR_NONE );
|
return( XSVF_ERROR_NONE );
|
||||||
}
|
}
|
||||||
@ -1083,8 +1089,9 @@ int xsvfDoXCOMPLETE( SXsvfInfo* pXsvfInfo )
|
|||||||
* Parameters: pXsvfInfo - XSVF information pointer.
|
* Parameters: pXsvfInfo - XSVF information pointer.
|
||||||
* Returns: int - 0 = success; non-zero = error.
|
* Returns: int - 0 = success; non-zero = error.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
int xsvfDoXTDOMASK( SXsvfInfo* pXsvfInfo )
|
int xsvfDoXTDOMASK( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo )
|
||||||
{
|
{
|
||||||
|
(void)gpio;
|
||||||
readVal( &(pXsvfInfo->lvTdoMask), pXsvfInfo->sShiftLengthBytes );
|
readVal( &(pXsvfInfo->lvTdoMask), pXsvfInfo->sShiftLengthBytes );
|
||||||
XSVFDBG_PRINTF( 4, " TDO Mask = ");
|
XSVFDBG_PRINTF( 4, " TDO Mask = ");
|
||||||
XSVFDBG_PRINTLENVAL( 4, &(pXsvfInfo->lvTdoMask) );
|
XSVFDBG_PRINTLENVAL( 4, &(pXsvfInfo->lvTdoMask) );
|
||||||
@ -1101,7 +1108,7 @@ int xsvfDoXTDOMASK( SXsvfInfo* pXsvfInfo )
|
|||||||
* Parameters: pXsvfInfo - XSVF information pointer.
|
* Parameters: pXsvfInfo - XSVF information pointer.
|
||||||
* Returns: int - 0 = success; non-zero = error.
|
* Returns: int - 0 = success; non-zero = error.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
int xsvfDoXSIR( SXsvfInfo* pXsvfInfo )
|
int xsvfDoXSIR( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo )
|
||||||
{
|
{
|
||||||
unsigned char ucShiftIrBits;
|
unsigned char ucShiftIrBits;
|
||||||
short sShiftIrBytes;
|
short sShiftIrBytes;
|
||||||
@ -1123,7 +1130,7 @@ int xsvfDoXSIR( SXsvfInfo* pXsvfInfo )
|
|||||||
readVal( &(pXsvfInfo->lvTdi), xsvfGetAsNumBytes( ucShiftIrBits ) );
|
readVal( &(pXsvfInfo->lvTdi), xsvfGetAsNumBytes( ucShiftIrBits ) );
|
||||||
|
|
||||||
/* Shift the data */
|
/* Shift the data */
|
||||||
iErrorCode = xsvfShift( &(pXsvfInfo->ucTapState), XTAPSTATE_SHIFTIR,
|
iErrorCode = xsvfShift( gpio, &(pXsvfInfo->ucTapState), XTAPSTATE_SHIFTIR,
|
||||||
ucShiftIrBits, &(pXsvfInfo->lvTdi),
|
ucShiftIrBits, &(pXsvfInfo->lvTdi),
|
||||||
/*plvTdoCaptured*/0, /*plvTdoExpected*/0,
|
/*plvTdoCaptured*/0, /*plvTdoExpected*/0,
|
||||||
/*plvTdoMask*/0, pXsvfInfo->ucEndIR,
|
/*plvTdoMask*/0, pXsvfInfo->ucEndIR,
|
||||||
@ -1146,7 +1153,7 @@ int xsvfDoXSIR( SXsvfInfo* pXsvfInfo )
|
|||||||
* Parameters: pXsvfInfo - XSVF information pointer.
|
* Parameters: pXsvfInfo - XSVF information pointer.
|
||||||
* Returns: int - 0 = success; non-zero = error.
|
* Returns: int - 0 = success; non-zero = error.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
int xsvfDoXSIR2( SXsvfInfo* pXsvfInfo )
|
int xsvfDoXSIR2( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo )
|
||||||
{
|
{
|
||||||
long lShiftIrBits;
|
long lShiftIrBits;
|
||||||
short sShiftIrBytes;
|
short sShiftIrBytes;
|
||||||
@ -1168,7 +1175,7 @@ int xsvfDoXSIR2( SXsvfInfo* pXsvfInfo )
|
|||||||
readVal( &(pXsvfInfo->lvTdi), xsvfGetAsNumBytes( lShiftIrBits ) );
|
readVal( &(pXsvfInfo->lvTdi), xsvfGetAsNumBytes( lShiftIrBits ) );
|
||||||
|
|
||||||
/* Shift the data */
|
/* Shift the data */
|
||||||
iErrorCode = xsvfShift( &(pXsvfInfo->ucTapState), XTAPSTATE_SHIFTIR,
|
iErrorCode = xsvfShift( gpio, &(pXsvfInfo->ucTapState), XTAPSTATE_SHIFTIR,
|
||||||
lShiftIrBits, &(pXsvfInfo->lvTdi),
|
lShiftIrBits, &(pXsvfInfo->lvTdi),
|
||||||
/*plvTdoCaptured*/0, /*plvTdoExpected*/0,
|
/*plvTdoCaptured*/0, /*plvTdoExpected*/0,
|
||||||
/*plvTdoMask*/0, pXsvfInfo->ucEndIR,
|
/*plvTdoMask*/0, pXsvfInfo->ucEndIR,
|
||||||
@ -1192,12 +1199,12 @@ int xsvfDoXSIR2( SXsvfInfo* pXsvfInfo )
|
|||||||
* Parameters: pXsvfInfo - XSVF information pointer.
|
* Parameters: pXsvfInfo - XSVF information pointer.
|
||||||
* Returns: int - 0 = success; non-zero = error.
|
* Returns: int - 0 = success; non-zero = error.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
int xsvfDoXSDR( SXsvfInfo* pXsvfInfo )
|
int xsvfDoXSDR( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo )
|
||||||
{
|
{
|
||||||
int iErrorCode;
|
int iErrorCode;
|
||||||
readVal( &(pXsvfInfo->lvTdi), pXsvfInfo->sShiftLengthBytes );
|
readVal( &(pXsvfInfo->lvTdi), pXsvfInfo->sShiftLengthBytes );
|
||||||
/* use TDOExpected from last XSDRTDO instruction */
|
/* use TDOExpected from last XSDRTDO instruction */
|
||||||
iErrorCode = xsvfShift( &(pXsvfInfo->ucTapState), XTAPSTATE_SHIFTDR,
|
iErrorCode = xsvfShift( gpio, &(pXsvfInfo->ucTapState), XTAPSTATE_SHIFTDR,
|
||||||
pXsvfInfo->lShiftLengthBits, &(pXsvfInfo->lvTdi),
|
pXsvfInfo->lShiftLengthBits, &(pXsvfInfo->lvTdi),
|
||||||
&(pXsvfInfo->lvTdoCaptured),
|
&(pXsvfInfo->lvTdoCaptured),
|
||||||
&(pXsvfInfo->lvTdoExpected),
|
&(pXsvfInfo->lvTdoExpected),
|
||||||
@ -1217,8 +1224,9 @@ int xsvfDoXSDR( SXsvfInfo* pXsvfInfo )
|
|||||||
* Parameters: pXsvfInfo - XSVF information pointer.
|
* Parameters: pXsvfInfo - XSVF information pointer.
|
||||||
* Returns: int - 0 = success; non-zero = error.
|
* Returns: int - 0 = success; non-zero = error.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
int xsvfDoXRUNTEST( SXsvfInfo* pXsvfInfo )
|
int xsvfDoXRUNTEST( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo )
|
||||||
{
|
{
|
||||||
|
(void)gpio;
|
||||||
readVal( &(pXsvfInfo->lvTdi), 4 );
|
readVal( &(pXsvfInfo->lvTdi), 4 );
|
||||||
pXsvfInfo->lRunTestTime = value( &(pXsvfInfo->lvTdi) );
|
pXsvfInfo->lRunTestTime = value( &(pXsvfInfo->lvTdi) );
|
||||||
XSVFDBG_PRINTF1( 3, " XRUNTEST = %ld\n", pXsvfInfo->lRunTestTime );
|
XSVFDBG_PRINTF1( 3, " XRUNTEST = %ld\n", pXsvfInfo->lRunTestTime );
|
||||||
@ -1232,8 +1240,9 @@ int xsvfDoXRUNTEST( SXsvfInfo* pXsvfInfo )
|
|||||||
* Parameters: pXsvfInfo - XSVF information pointer.
|
* Parameters: pXsvfInfo - XSVF information pointer.
|
||||||
* Returns: int - 0 = success; non-zero = error.
|
* Returns: int - 0 = success; non-zero = error.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
int xsvfDoXREPEAT( SXsvfInfo* pXsvfInfo )
|
int xsvfDoXREPEAT( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo )
|
||||||
{
|
{
|
||||||
|
(void)gpio;
|
||||||
readByte( &(pXsvfInfo->ucMaxRepeat) );
|
readByte( &(pXsvfInfo->ucMaxRepeat) );
|
||||||
XSVFDBG_PRINTF1( 3, " XREPEAT = %d\n",
|
XSVFDBG_PRINTF1( 3, " XREPEAT = %d\n",
|
||||||
((unsigned int)(pXsvfInfo->ucMaxRepeat)) );
|
((unsigned int)(pXsvfInfo->ucMaxRepeat)) );
|
||||||
@ -1247,8 +1256,9 @@ int xsvfDoXREPEAT( SXsvfInfo* pXsvfInfo )
|
|||||||
* Parameters: pXsvfInfo - XSVF information pointer.
|
* Parameters: pXsvfInfo - XSVF information pointer.
|
||||||
* Returns: int - 0 = success; non-zero = error.
|
* Returns: int - 0 = success; non-zero = error.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
int xsvfDoXSDRSIZE( SXsvfInfo* pXsvfInfo )
|
int xsvfDoXSDRSIZE( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo )
|
||||||
{
|
{
|
||||||
|
(void)gpio;
|
||||||
int iErrorCode;
|
int iErrorCode;
|
||||||
iErrorCode = XSVF_ERROR_NONE;
|
iErrorCode = XSVF_ERROR_NONE;
|
||||||
readVal( &(pXsvfInfo->lvTdi), 4 );
|
readVal( &(pXsvfInfo->lvTdi), 4 );
|
||||||
@ -1272,10 +1282,10 @@ int xsvfDoXSDRSIZE( SXsvfInfo* pXsvfInfo )
|
|||||||
* Parameters: pXsvfInfo - XSVF information pointer.
|
* Parameters: pXsvfInfo - XSVF information pointer.
|
||||||
* Returns: int - 0 = success; non-zero = error.
|
* Returns: int - 0 = success; non-zero = error.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
int xsvfDoXSDRTDO( SXsvfInfo* pXsvfInfo )
|
int xsvfDoXSDRTDO( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo )
|
||||||
{
|
{
|
||||||
int iErrorCode;
|
int iErrorCode;
|
||||||
iErrorCode = xsvfBasicXSDRTDO( &(pXsvfInfo->ucTapState),
|
iErrorCode = xsvfBasicXSDRTDO( gpio, &(pXsvfInfo->ucTapState),
|
||||||
pXsvfInfo->lShiftLengthBits,
|
pXsvfInfo->lShiftLengthBits,
|
||||||
pXsvfInfo->sShiftLengthBytes,
|
pXsvfInfo->sShiftLengthBytes,
|
||||||
&(pXsvfInfo->lvTdi),
|
&(pXsvfInfo->lvTdi),
|
||||||
@ -1303,8 +1313,9 @@ int xsvfDoXSDRTDO( SXsvfInfo* pXsvfInfo )
|
|||||||
* Returns: int - 0 = success; non-zero = error.
|
* Returns: int - 0 = success; non-zero = error.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
#ifdef XSVF_SUPPORT_COMPRESSION
|
#ifdef XSVF_SUPPORT_COMPRESSION
|
||||||
int xsvfDoXSETSDRMASKS( SXsvfInfo* pXsvfInfo )
|
int xsvfDoXSETSDRMASKS( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo )
|
||||||
{
|
{
|
||||||
|
(void)gpio;
|
||||||
/* read the addressMask */
|
/* read the addressMask */
|
||||||
readVal( &(pXsvfInfo->lvAddressMask), pXsvfInfo->sShiftLengthBytes );
|
readVal( &(pXsvfInfo->lvAddressMask), pXsvfInfo->sShiftLengthBytes );
|
||||||
/* read the dataMask */
|
/* read the dataMask */
|
||||||
@ -1338,7 +1349,7 @@ int xsvfDoXSETSDRMASKS( SXsvfInfo* pXsvfInfo )
|
|||||||
* Returns: int - 0 = success; non-zero = error.
|
* Returns: int - 0 = success; non-zero = error.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
#ifdef XSVF_SUPPORT_COMPRESSION
|
#ifdef XSVF_SUPPORT_COMPRESSION
|
||||||
int xsvfDoXSDRINC( SXsvfInfo* pXsvfInfo )
|
int xsvfDoXSDRINC( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo )
|
||||||
{
|
{
|
||||||
int iErrorCode;
|
int iErrorCode;
|
||||||
int iDataMaskLen;
|
int iDataMaskLen;
|
||||||
@ -1347,7 +1358,7 @@ int xsvfDoXSDRINC( SXsvfInfo* pXsvfInfo )
|
|||||||
unsigned char i;
|
unsigned char i;
|
||||||
|
|
||||||
readVal( &(pXsvfInfo->lvTdi), pXsvfInfo->sShiftLengthBytes );
|
readVal( &(pXsvfInfo->lvTdi), pXsvfInfo->sShiftLengthBytes );
|
||||||
iErrorCode = xsvfShift( &(pXsvfInfo->ucTapState), XTAPSTATE_SHIFTDR,
|
iErrorCode = xsvfShift( gpio, &(pXsvfInfo->ucTapState), XTAPSTATE_SHIFTDR,
|
||||||
pXsvfInfo->lShiftLengthBits,
|
pXsvfInfo->lShiftLengthBits,
|
||||||
&(pXsvfInfo->lvTdi), &(pXsvfInfo->lvTdoCaptured),
|
&(pXsvfInfo->lvTdi), &(pXsvfInfo->lvTdoCaptured),
|
||||||
&(pXsvfInfo->lvTdoExpected),
|
&(pXsvfInfo->lvTdoExpected),
|
||||||
@ -1379,7 +1390,7 @@ int xsvfDoXSDRINC( SXsvfInfo* pXsvfInfo )
|
|||||||
&(pXsvfInfo->lvNextData),
|
&(pXsvfInfo->lvNextData),
|
||||||
&(pXsvfInfo->lvAddressMask),
|
&(pXsvfInfo->lvAddressMask),
|
||||||
&(pXsvfInfo->lvDataMask) );
|
&(pXsvfInfo->lvDataMask) );
|
||||||
iErrorCode = xsvfShift( &(pXsvfInfo->ucTapState),
|
iErrorCode = xsvfShift( gpio, &(pXsvfInfo->ucTapState),
|
||||||
XTAPSTATE_SHIFTDR,
|
XTAPSTATE_SHIFTDR,
|
||||||
pXsvfInfo->lShiftLengthBits,
|
pXsvfInfo->lShiftLengthBits,
|
||||||
&(pXsvfInfo->lvTdi),
|
&(pXsvfInfo->lvTdi),
|
||||||
@ -1410,13 +1421,13 @@ int xsvfDoXSDRINC( SXsvfInfo* pXsvfInfo )
|
|||||||
* Parameters: pXsvfInfo - XSVF information pointer.
|
* Parameters: pXsvfInfo - XSVF information pointer.
|
||||||
* Returns: int - 0 = success; non-zero = error.
|
* Returns: int - 0 = success; non-zero = error.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
int xsvfDoXSDRBCE( SXsvfInfo* pXsvfInfo )
|
int xsvfDoXSDRBCE( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo )
|
||||||
{
|
{
|
||||||
unsigned char ucEndDR;
|
unsigned char ucEndDR;
|
||||||
int iErrorCode;
|
int iErrorCode;
|
||||||
ucEndDR = (unsigned char)(( pXsvfInfo->ucCommand == XSDRE ) ?
|
ucEndDR = (unsigned char)(( pXsvfInfo->ucCommand == XSDRE ) ?
|
||||||
pXsvfInfo->ucEndDR : XTAPSTATE_SHIFTDR);
|
pXsvfInfo->ucEndDR : XTAPSTATE_SHIFTDR);
|
||||||
iErrorCode = xsvfBasicXSDRTDO( &(pXsvfInfo->ucTapState),
|
iErrorCode = xsvfBasicXSDRTDO( gpio, &(pXsvfInfo->ucTapState),
|
||||||
pXsvfInfo->lShiftLengthBits,
|
pXsvfInfo->lShiftLengthBits,
|
||||||
pXsvfInfo->sShiftLengthBytes,
|
pXsvfInfo->sShiftLengthBytes,
|
||||||
&(pXsvfInfo->lvTdi),
|
&(pXsvfInfo->lvTdi),
|
||||||
@ -1441,13 +1452,13 @@ int xsvfDoXSDRBCE( SXsvfInfo* pXsvfInfo )
|
|||||||
* Parameters: pXsvfInfo - XSVF information pointer.
|
* Parameters: pXsvfInfo - XSVF information pointer.
|
||||||
* Returns: int - 0 = success; non-zero = error.
|
* Returns: int - 0 = success; non-zero = error.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
int xsvfDoXSDRTDOBCE( SXsvfInfo* pXsvfInfo )
|
int xsvfDoXSDRTDOBCE( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo )
|
||||||
{
|
{
|
||||||
unsigned char ucEndDR;
|
unsigned char ucEndDR;
|
||||||
int iErrorCode;
|
int iErrorCode;
|
||||||
ucEndDR = (unsigned char)(( pXsvfInfo->ucCommand == XSDRTDOE ) ?
|
ucEndDR = (unsigned char)(( pXsvfInfo->ucCommand == XSDRTDOE ) ?
|
||||||
pXsvfInfo->ucEndDR : XTAPSTATE_SHIFTDR);
|
pXsvfInfo->ucEndDR : XTAPSTATE_SHIFTDR);
|
||||||
iErrorCode = xsvfBasicXSDRTDO( &(pXsvfInfo->ucTapState),
|
iErrorCode = xsvfBasicXSDRTDO( gpio, &(pXsvfInfo->ucTapState),
|
||||||
pXsvfInfo->lShiftLengthBits,
|
pXsvfInfo->lShiftLengthBits,
|
||||||
pXsvfInfo->sShiftLengthBytes,
|
pXsvfInfo->sShiftLengthBytes,
|
||||||
&(pXsvfInfo->lvTdi),
|
&(pXsvfInfo->lvTdi),
|
||||||
@ -1470,12 +1481,12 @@ int xsvfDoXSDRTDOBCE( SXsvfInfo* pXsvfInfo )
|
|||||||
* Parameters: pXsvfInfo - XSVF information pointer.
|
* Parameters: pXsvfInfo - XSVF information pointer.
|
||||||
* Returns: int - 0 = success; non-zero = error.
|
* Returns: int - 0 = success; non-zero = error.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
int xsvfDoXSTATE( SXsvfInfo* pXsvfInfo )
|
int xsvfDoXSTATE( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo )
|
||||||
{
|
{
|
||||||
unsigned char ucNextState;
|
unsigned char ucNextState;
|
||||||
int iErrorCode;
|
int iErrorCode;
|
||||||
readByte( &ucNextState );
|
readByte( &ucNextState );
|
||||||
iErrorCode = xsvfGotoTapState( &(pXsvfInfo->ucTapState), ucNextState );
|
iErrorCode = xsvfGotoTapState( gpio, &(pXsvfInfo->ucTapState), ucNextState );
|
||||||
if ( iErrorCode != XSVF_ERROR_NONE )
|
if ( iErrorCode != XSVF_ERROR_NONE )
|
||||||
{
|
{
|
||||||
pXsvfInfo->iErrorCode = iErrorCode;
|
pXsvfInfo->iErrorCode = iErrorCode;
|
||||||
@ -1492,8 +1503,9 @@ int xsvfDoXSTATE( SXsvfInfo* pXsvfInfo )
|
|||||||
* Parameters: pXsvfInfo - XSVF information pointer.
|
* Parameters: pXsvfInfo - XSVF information pointer.
|
||||||
* Returns: int - 0 = success; non-zero = error.
|
* Returns: int - 0 = success; non-zero = error.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
int xsvfDoXENDXR( SXsvfInfo* pXsvfInfo )
|
int xsvfDoXENDXR( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo )
|
||||||
{
|
{
|
||||||
|
(void)gpio;
|
||||||
int iErrorCode;
|
int iErrorCode;
|
||||||
unsigned char ucEndState;
|
unsigned char ucEndState;
|
||||||
|
|
||||||
@ -1549,8 +1561,10 @@ int xsvfDoXENDXR( SXsvfInfo* pXsvfInfo )
|
|||||||
* Parameters: pXsvfInfo - XSVF information pointer.
|
* Parameters: pXsvfInfo - XSVF information pointer.
|
||||||
* Returns: int - 0 = success; non-zero = error.
|
* Returns: int - 0 = success; non-zero = error.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
int xsvfDoXCOMMENT( SXsvfInfo* pXsvfInfo )
|
int xsvfDoXCOMMENT( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo )
|
||||||
{
|
{
|
||||||
|
(void)gpio;
|
||||||
|
|
||||||
/* Use the comment for debugging */
|
/* Use the comment for debugging */
|
||||||
/* Otherwise, read through the comment to the end '\0' and ignore */
|
/* Otherwise, read through the comment to the end '\0' and ignore */
|
||||||
unsigned char ucText;
|
unsigned char ucText;
|
||||||
@ -1587,7 +1601,7 @@ int xsvfDoXCOMMENT( SXsvfInfo* pXsvfInfo )
|
|||||||
* Parameters: pXsvfInfo - XSVF information pointer.
|
* Parameters: pXsvfInfo - XSVF information pointer.
|
||||||
* Returns: int - 0 = success; non-zero = error.
|
* Returns: int - 0 = success; non-zero = error.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
int xsvfDoXWAIT( SXsvfInfo* pXsvfInfo )
|
int xsvfDoXWAIT( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo )
|
||||||
{
|
{
|
||||||
unsigned char ucWaitState;
|
unsigned char ucWaitState;
|
||||||
unsigned char ucEndState;
|
unsigned char ucEndState;
|
||||||
@ -1611,16 +1625,16 @@ int xsvfDoXWAIT( SXsvfInfo* pXsvfInfo )
|
|||||||
/* If not already in <wait_state>, go to <wait_state> */
|
/* If not already in <wait_state>, go to <wait_state> */
|
||||||
if ( pXsvfInfo->ucTapState != ucWaitState )
|
if ( pXsvfInfo->ucTapState != ucWaitState )
|
||||||
{
|
{
|
||||||
xsvfGotoTapState( &(pXsvfInfo->ucTapState), ucWaitState );
|
xsvfGotoTapState( gpio, &(pXsvfInfo->ucTapState), ucWaitState );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for <wait_time> microseconds */
|
/* Wait for <wait_time> microseconds */
|
||||||
waitTime( lWaitTime );
|
waitTime( gpio, lWaitTime );
|
||||||
|
|
||||||
/* If not already in <end_state>, go to <end_state> */
|
/* If not already in <end_state>, go to <end_state> */
|
||||||
if ( pXsvfInfo->ucTapState != ucEndState )
|
if ( pXsvfInfo->ucTapState != ucEndState )
|
||||||
{
|
{
|
||||||
xsvfGotoTapState( &(pXsvfInfo->ucTapState), ucEndState );
|
xsvfGotoTapState( gpio, &(pXsvfInfo->ucTapState), ucEndState );
|
||||||
}
|
}
|
||||||
|
|
||||||
return( XSVF_ERROR_NONE );
|
return( XSVF_ERROR_NONE );
|
||||||
@ -1641,7 +1655,7 @@ int xsvfDoXWAIT( SXsvfInfo* pXsvfInfo )
|
|||||||
* Parameters: pXsvfInfo - ptr to the XSVF information.
|
* Parameters: pXsvfInfo - ptr to the XSVF information.
|
||||||
* Returns: int - 0 = success; otherwise error.
|
* Returns: int - 0 = success; otherwise error.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
int xsvfInitialize( SXsvfInfo* pXsvfInfo )
|
int xsvfInitialize( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo )
|
||||||
{
|
{
|
||||||
/* Initialize values */
|
/* Initialize values */
|
||||||
pXsvfInfo->iErrorCode = xsvfInfoInit( pXsvfInfo );
|
pXsvfInfo->iErrorCode = xsvfInfoInit( pXsvfInfo );
|
||||||
@ -1649,7 +1663,7 @@ int xsvfInitialize( SXsvfInfo* pXsvfInfo )
|
|||||||
if ( !pXsvfInfo->iErrorCode )
|
if ( !pXsvfInfo->iErrorCode )
|
||||||
{
|
{
|
||||||
/* Initialize the TAPs */
|
/* Initialize the TAPs */
|
||||||
pXsvfInfo->iErrorCode = xsvfGotoTapState( &(pXsvfInfo->ucTapState),
|
pXsvfInfo->iErrorCode = xsvfGotoTapState( gpio, &(pXsvfInfo->ucTapState),
|
||||||
XTAPSTATE_RESET );
|
XTAPSTATE_RESET );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1666,7 +1680,7 @@ int xsvfInitialize( SXsvfInfo* pXsvfInfo )
|
|||||||
* Parameters: pXsvfInfo - ptr to the XSVF information.
|
* Parameters: pXsvfInfo - ptr to the XSVF information.
|
||||||
* Returns: int - 0 = success; otherwise error.
|
* Returns: int - 0 = success; otherwise error.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
int xsvfRun( SXsvfInfo* pXsvfInfo )
|
int xsvfRun( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo )
|
||||||
{
|
{
|
||||||
/* Process the XSVF commands */
|
/* Process the XSVF commands */
|
||||||
if ( (!pXsvfInfo->iErrorCode) && (!pXsvfInfo->ucComplete) )
|
if ( (!pXsvfInfo->iErrorCode) && (!pXsvfInfo->ucComplete) )
|
||||||
@ -1682,12 +1696,12 @@ int xsvfRun( SXsvfInfo* pXsvfInfo )
|
|||||||
xsvf_pzCommandName[pXsvfInfo->ucCommand] );
|
xsvf_pzCommandName[pXsvfInfo->ucCommand] );
|
||||||
/* If your compiler cannot take this form,
|
/* If your compiler cannot take this form,
|
||||||
then convert to a switch statement */
|
then convert to a switch statement */
|
||||||
xsvf_pfDoCmd[ pXsvfInfo->ucCommand ]( pXsvfInfo );
|
xsvf_pfDoCmd[ pXsvfInfo->ucCommand ]( gpio, pXsvfInfo );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Illegal command value. Func sets error code. */
|
/* Illegal command value. Func sets error code. */
|
||||||
xsvfDoIllegalCmd( pXsvfInfo );
|
xsvfDoIllegalCmd( gpio, pXsvfInfo );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1717,15 +1731,15 @@ void xsvfCleanup( SXsvfInfo* pXsvfInfo )
|
|||||||
* Parameters: none.
|
* Parameters: none.
|
||||||
* Returns: int - Legacy result values: 1 == success; 0 == failed.
|
* Returns: int - Legacy result values: 1 == success; 0 == failed.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
int xsvfExecute()
|
int xsvfExecute(jtag_gpio_t* const gpio)
|
||||||
{
|
{
|
||||||
SXsvfInfo xsvfInfo;
|
SXsvfInfo xsvfInfo;
|
||||||
|
|
||||||
xsvfInitialize( &xsvfInfo );
|
xsvfInitialize( gpio, &xsvfInfo );
|
||||||
|
|
||||||
while ( !xsvfInfo.iErrorCode && (!xsvfInfo.ucComplete) )
|
while ( !xsvfInfo.iErrorCode && (!xsvfInfo.ucComplete) )
|
||||||
{
|
{
|
||||||
xsvfRun( &xsvfInfo );
|
xsvfRun( gpio, &xsvfInfo );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( xsvfInfo.iErrorCode )
|
if ( xsvfInfo.iErrorCode )
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
#ifndef XSVF_MICRO_H
|
#ifndef XSVF_MICRO_H
|
||||||
#define XSVF_MICRO_H
|
#define XSVF_MICRO_H
|
||||||
|
|
||||||
|
#include "cpld_jtag.h"
|
||||||
|
|
||||||
/* Legacy error codes for xsvfExecute from original XSVF player v2.0 */
|
/* Legacy error codes for xsvfExecute from original XSVF player v2.0 */
|
||||||
#define XSVF_LEGACY_SUCCESS 1
|
#define XSVF_LEGACY_SUCCESS 1
|
||||||
#define XSVF_LEGACY_ERROR 0
|
#define XSVF_LEGACY_ERROR 0
|
||||||
@ -36,7 +38,7 @@
|
|||||||
* Parameters: none.
|
* Parameters: none.
|
||||||
* Returns: int - For error codes see above.
|
* Returns: int - For error codes see above.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
extern int xsvfExecute();
|
extern int xsvfExecute(jtag_gpio_t* const gpio);
|
||||||
|
|
||||||
#endif /* XSVF_MICRO_H */
|
#endif /* XSVF_MICRO_H */
|
||||||
|
|
||||||
|
@ -13,7 +13,8 @@
|
|||||||
|
|
||||||
#include "hackrf_core.h"
|
#include "hackrf_core.h"
|
||||||
#include "cpld_jtag.h"
|
#include "cpld_jtag.h"
|
||||||
#include <libopencm3/lpc43xx/gpio.h>
|
|
||||||
|
#include "gpio.h"
|
||||||
|
|
||||||
void delay_jtag(uint32_t duration)
|
void delay_jtag(uint32_t duration)
|
||||||
{
|
{
|
||||||
@ -38,23 +39,23 @@ void delay_jtag(uint32_t duration)
|
|||||||
|
|
||||||
/* setPort: Implement to set the named JTAG signal (p) to the new value (v).*/
|
/* setPort: Implement to set the named JTAG signal (p) to the new value (v).*/
|
||||||
/* if in debugging mode, then just set the variables */
|
/* if in debugging mode, then just set the variables */
|
||||||
void setPort(short p,short val)
|
void setPort(jtag_gpio_t* const gpio, short p, short val)
|
||||||
{
|
{
|
||||||
if (p==TMS) {
|
if (p==TMS) {
|
||||||
if (val)
|
if (val)
|
||||||
gpio_set(PORT_CPLD_TMS, PIN_CPLD_TMS);
|
gpio_set(gpio->gpio_tms);
|
||||||
else
|
else
|
||||||
gpio_clear(PORT_CPLD_TMS, PIN_CPLD_TMS);
|
gpio_clear(gpio->gpio_tms);
|
||||||
} if (p==TDI) {
|
} if (p==TDI) {
|
||||||
if (val)
|
if (val)
|
||||||
gpio_set(PORT_CPLD_TDI, PIN_CPLD_TDI);
|
gpio_set(gpio->gpio_tdi);
|
||||||
else
|
else
|
||||||
gpio_clear(PORT_CPLD_TDI, PIN_CPLD_TDI);
|
gpio_clear(gpio->gpio_tdi);
|
||||||
} if (p==TCK) {
|
} if (p==TCK) {
|
||||||
if (val)
|
if (val)
|
||||||
gpio_set(PORT_CPLD_TCK, PIN_CPLD_TCK);
|
gpio_set(gpio->gpio_tck);
|
||||||
else
|
else
|
||||||
gpio_clear(PORT_CPLD_TCK, PIN_CPLD_TCK);
|
gpio_clear(gpio->gpio_tck);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* conservative delay */
|
/* conservative delay */
|
||||||
@ -63,11 +64,11 @@ void setPort(short p,short val)
|
|||||||
|
|
||||||
|
|
||||||
/* toggle tck LH. No need to modify this code. It is output via setPort. */
|
/* toggle tck LH. No need to modify this code. It is output via setPort. */
|
||||||
void pulseClock()
|
void pulseClock(jtag_gpio_t* const gpio)
|
||||||
{
|
{
|
||||||
setPort(TCK,0); /* set the TCK port to low */
|
setPort(gpio, TCK,0); /* set the TCK port to low */
|
||||||
delay_jtag(200);
|
delay_jtag(200);
|
||||||
setPort(TCK,1); /* set the TCK port to high */
|
setPort(gpio, TCK,1); /* set the TCK port to high */
|
||||||
delay_jtag(200);
|
delay_jtag(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,10 +82,10 @@ void readByte(unsigned char *data)
|
|||||||
|
|
||||||
/* readTDOBit: Implement to return the current value of the JTAG TDO signal.*/
|
/* readTDOBit: Implement to return the current value of the JTAG TDO signal.*/
|
||||||
/* read the TDO bit from port */
|
/* read the TDO bit from port */
|
||||||
unsigned char readTDOBit()
|
unsigned char readTDOBit(jtag_gpio_t* const gpio)
|
||||||
{
|
{
|
||||||
delay_jtag(2000);
|
delay_jtag(2000);
|
||||||
return CPLD_TDO_STATE;
|
return gpio_read(gpio->gpio_tdo);;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* waitTime: Implement as follows: */
|
/* waitTime: Implement as follows: */
|
||||||
@ -96,7 +97,7 @@ unsigned char readTDOBit()
|
|||||||
/* RECOMMENDED IMPLEMENTATION: Pulse TCK at least microsec times AND */
|
/* RECOMMENDED IMPLEMENTATION: Pulse TCK at least microsec times AND */
|
||||||
/* continue pulsing TCK until the microsec wait */
|
/* continue pulsing TCK until the microsec wait */
|
||||||
/* requirement is also satisfied. */
|
/* requirement is also satisfied. */
|
||||||
void waitTime(long microsec)
|
void waitTime(jtag_gpio_t* const gpio, long microsec)
|
||||||
{
|
{
|
||||||
static long tckCyclesPerMicrosec = 1; /* must be at least 1 */
|
static long tckCyclesPerMicrosec = 1; /* must be at least 1 */
|
||||||
long tckCycles = microsec * tckCyclesPerMicrosec;
|
long tckCycles = microsec * tckCyclesPerMicrosec;
|
||||||
@ -108,6 +109,6 @@ void waitTime(long microsec)
|
|||||||
in order to satisfy the microsec wait time requirement. */
|
in order to satisfy the microsec wait time requirement. */
|
||||||
for ( i = 0; i < tckCycles; ++i )
|
for ( i = 0; i < tckCycles; ++i )
|
||||||
{
|
{
|
||||||
pulseClock();
|
pulseClock(gpio);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
#ifndef ports_dot_h
|
#ifndef ports_dot_h
|
||||||
#define ports_dot_h
|
#define ports_dot_h
|
||||||
|
|
||||||
|
#include "cpld_jtag.h"
|
||||||
|
|
||||||
/* these constants are used to send the appropriate ports to setPort */
|
/* these constants are used to send the appropriate ports to setPort */
|
||||||
/* they should be enumerated types, but some of the microcontroller */
|
/* they should be enumerated types, but some of the microcontroller */
|
||||||
/* compilers don't like enumerated types */
|
/* compilers don't like enumerated types */
|
||||||
@ -15,17 +17,17 @@
|
|||||||
#define TDI (short) 2
|
#define TDI (short) 2
|
||||||
|
|
||||||
/* set the port "p" (TCK, TMS, or TDI) to val (0 or 1) */
|
/* set the port "p" (TCK, TMS, or TDI) to val (0 or 1) */
|
||||||
extern void setPort(short p, short val);
|
extern void setPort(jtag_gpio_t* const gpio, short p, short val);
|
||||||
|
|
||||||
/* read the TDO bit and store it in val */
|
/* read the TDO bit and store it in val */
|
||||||
extern unsigned char readTDOBit();
|
extern unsigned char readTDOBit(jtag_gpio_t* const gpio);
|
||||||
|
|
||||||
/* make clock go down->up->down*/
|
/* make clock go down->up->down*/
|
||||||
extern void pulseClock();
|
extern void pulseClock(jtag_gpio_t* const gpio);
|
||||||
|
|
||||||
/* read the next byte of data from the xsvf file */
|
/* read the next byte of data from the xsvf file */
|
||||||
extern void readByte(unsigned char *data);
|
extern void readByte(unsigned char *data);
|
||||||
|
|
||||||
extern void waitTime(long microsec);
|
extern void waitTime(jtag_gpio_t* const gpio, long microsec);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -135,8 +135,18 @@ macro(DeclareTargets)
|
|||||||
${PATH_HACKRF_FIRMWARE_COMMON}/rf_path.c
|
${PATH_HACKRF_FIRMWARE_COMMON}/rf_path.c
|
||||||
${PATH_HACKRF_FIRMWARE_COMMON}/si5351c.c
|
${PATH_HACKRF_FIRMWARE_COMMON}/si5351c.c
|
||||||
${PATH_HACKRF_FIRMWARE_COMMON}/max2837.c
|
${PATH_HACKRF_FIRMWARE_COMMON}/max2837.c
|
||||||
|
${PATH_HACKRF_FIRMWARE_COMMON}/max2837_target.c
|
||||||
${PATH_HACKRF_FIRMWARE_COMMON}/max5864.c
|
${PATH_HACKRF_FIRMWARE_COMMON}/max5864.c
|
||||||
|
${PATH_HACKRF_FIRMWARE_COMMON}/max5864_target.c
|
||||||
${PATH_HACKRF_FIRMWARE_COMMON}/rffc5071.c
|
${PATH_HACKRF_FIRMWARE_COMMON}/rffc5071.c
|
||||||
|
${PATH_HACKRF_FIRMWARE_COMMON}/i2c_bus.c
|
||||||
|
${PATH_HACKRF_FIRMWARE_COMMON}/i2c_lpc.c
|
||||||
|
${PATH_HACKRF_FIRMWARE_COMMON}/rffc5071_spi.c
|
||||||
|
${PATH_HACKRF_FIRMWARE_COMMON}/w25q80bv.c
|
||||||
|
${PATH_HACKRF_FIRMWARE_COMMON}/w25q80bv_target.c
|
||||||
|
${PATH_HACKRF_FIRMWARE_COMMON}/spi_bus.c
|
||||||
|
${PATH_HACKRF_FIRMWARE_COMMON}/spi_ssp.c
|
||||||
|
${PATH_HACKRF_FIRMWARE_COMMON}/gpio_lpc.c
|
||||||
m0_bin.s
|
m0_bin.s
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -44,7 +44,6 @@ set(SRC_M4
|
|||||||
usb_api_transceiver.c
|
usb_api_transceiver.c
|
||||||
"${PATH_HACKRF_FIRMWARE_COMMON}/usb_queue.c"
|
"${PATH_HACKRF_FIRMWARE_COMMON}/usb_queue.c"
|
||||||
"${PATH_HACKRF_FIRMWARE_COMMON}/fault_handler.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}/cpld_jtag.c"
|
||||||
"${PATH_HACKRF_FIRMWARE_COMMON}/xapp058/lenval.c"
|
"${PATH_HACKRF_FIRMWARE_COMMON}/xapp058/lenval.c"
|
||||||
"${PATH_HACKRF_FIRMWARE_COMMON}/xapp058/micro.c"
|
"${PATH_HACKRF_FIRMWARE_COMMON}/xapp058/micro.c"
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
|
|
||||||
#include <libopencm3/cm3/vector.h>
|
#include <libopencm3/cm3/vector.h>
|
||||||
|
|
||||||
#include <libopencm3/lpc43xx/gpio.h>
|
|
||||||
#include <libopencm3/lpc43xx/m4/nvic.h>
|
#include <libopencm3/lpc43xx/m4/nvic.h>
|
||||||
|
|
||||||
#include <streaming.h>
|
#include <streaming.h>
|
||||||
@ -43,16 +42,13 @@
|
|||||||
#include "usb_api_spiflash.h"
|
#include "usb_api_spiflash.h"
|
||||||
|
|
||||||
#include "usb_api_transceiver.h"
|
#include "usb_api_transceiver.h"
|
||||||
#include "rf_path.h"
|
|
||||||
#include "sgpio_isr.h"
|
#include "sgpio_isr.h"
|
||||||
#include "usb_bulk_buffer.h"
|
#include "usb_bulk_buffer.h"
|
||||||
#include "si5351c.h"
|
|
||||||
#include "w25q80bv.h"
|
|
||||||
|
|
||||||
static volatile transceiver_mode_t _transceiver_mode = TRANSCEIVER_MODE_OFF;
|
static volatile transceiver_mode_t _transceiver_mode = TRANSCEIVER_MODE_OFF;
|
||||||
|
|
||||||
void set_transceiver_mode(const transceiver_mode_t new_transceiver_mode) {
|
void set_transceiver_mode(const transceiver_mode_t new_transceiver_mode) {
|
||||||
baseband_streaming_disable();
|
baseband_streaming_disable(&sgpio_config);
|
||||||
|
|
||||||
usb_endpoint_disable(&usb_endpoint_bulk_in);
|
usb_endpoint_disable(&usb_endpoint_bulk_in);
|
||||||
usb_endpoint_disable(&usb_endpoint_bulk_out);
|
usb_endpoint_disable(&usb_endpoint_bulk_out);
|
||||||
@ -60,27 +56,27 @@ void set_transceiver_mode(const transceiver_mode_t new_transceiver_mode) {
|
|||||||
_transceiver_mode = new_transceiver_mode;
|
_transceiver_mode = new_transceiver_mode;
|
||||||
|
|
||||||
if( _transceiver_mode == TRANSCEIVER_MODE_RX ) {
|
if( _transceiver_mode == TRANSCEIVER_MODE_RX ) {
|
||||||
gpio_clear(PORT_LED1_3, PIN_LED3);
|
led_off(LED3);
|
||||||
gpio_set(PORT_LED1_3, PIN_LED2);
|
led_on(LED2);
|
||||||
usb_endpoint_init(&usb_endpoint_bulk_in);
|
usb_endpoint_init(&usb_endpoint_bulk_in);
|
||||||
rf_path_set_direction(RF_PATH_DIRECTION_RX);
|
rf_path_set_direction(&rf_path, RF_PATH_DIRECTION_RX);
|
||||||
vector_table.irq[NVIC_SGPIO_IRQ] = sgpio_isr_rx;
|
vector_table.irq[NVIC_SGPIO_IRQ] = sgpio_isr_rx;
|
||||||
} else if (_transceiver_mode == TRANSCEIVER_MODE_TX) {
|
} else if (_transceiver_mode == TRANSCEIVER_MODE_TX) {
|
||||||
gpio_clear(PORT_LED1_3, PIN_LED2);
|
led_off(LED2);
|
||||||
gpio_set(PORT_LED1_3, PIN_LED3);
|
led_on(LED3);
|
||||||
usb_endpoint_init(&usb_endpoint_bulk_out);
|
usb_endpoint_init(&usb_endpoint_bulk_out);
|
||||||
rf_path_set_direction(RF_PATH_DIRECTION_TX);
|
rf_path_set_direction(&rf_path, RF_PATH_DIRECTION_TX);
|
||||||
vector_table.irq[NVIC_SGPIO_IRQ] = sgpio_isr_tx;
|
vector_table.irq[NVIC_SGPIO_IRQ] = sgpio_isr_tx;
|
||||||
} else {
|
} else {
|
||||||
gpio_clear(PORT_LED1_3, PIN_LED2);
|
led_off(LED2);
|
||||||
gpio_clear(PORT_LED1_3, PIN_LED3);
|
led_off(LED3);
|
||||||
rf_path_set_direction(RF_PATH_DIRECTION_OFF);
|
rf_path_set_direction(&rf_path, RF_PATH_DIRECTION_OFF);
|
||||||
vector_table.irq[NVIC_SGPIO_IRQ] = sgpio_isr_rx;
|
vector_table.irq[NVIC_SGPIO_IRQ] = sgpio_isr_rx;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( _transceiver_mode != TRANSCEIVER_MODE_OFF ) {
|
if( _transceiver_mode != TRANSCEIVER_MODE_OFF ) {
|
||||||
si5351c_activate_best_clock_source();
|
si5351c_activate_best_clock_source(&clock_gen);
|
||||||
baseband_streaming_enable();
|
baseband_streaming_enable(&sgpio_config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,7 +175,7 @@ void usb_configuration_changed(
|
|||||||
if( device->configuration->number == 1 ) {
|
if( device->configuration->number == 1 ) {
|
||||||
// transceiver configuration
|
// transceiver configuration
|
||||||
cpu_clock_pll1_max_speed();
|
cpu_clock_pll1_max_speed();
|
||||||
gpio_set(PORT_LED1_3, PIN_LED1);
|
led_on(LED1);
|
||||||
} else if( device->configuration->number == 2 ) {
|
} else if( device->configuration->number == 2 ) {
|
||||||
// CPLD update configuration
|
// CPLD update configuration
|
||||||
cpu_clock_pll1_max_speed();
|
cpu_clock_pll1_max_speed();
|
||||||
@ -188,7 +184,7 @@ void usb_configuration_changed(
|
|||||||
} else {
|
} else {
|
||||||
/* Configuration number equal 0 means usb bus reset. */
|
/* Configuration number equal 0 means usb bus reset. */
|
||||||
cpu_clock_pll1_low_speed();
|
cpu_clock_pll1_low_speed();
|
||||||
gpio_clear(PORT_LED1_3, PIN_LED1);
|
led_off(LED1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,9 +221,6 @@ int main(void) {
|
|||||||
#endif
|
#endif
|
||||||
cpu_clock_init();
|
cpu_clock_init();
|
||||||
|
|
||||||
/* Code is not running from SPI flash, initialize for flash read/write over USB */
|
|
||||||
w25q80bv_setup();
|
|
||||||
|
|
||||||
usb_set_descriptor_by_serial_number();
|
usb_set_descriptor_by_serial_number();
|
||||||
|
|
||||||
usb_set_configuration_changed_cb(usb_configuration_changed);
|
usb_set_configuration_changed_cb(usb_configuration_changed);
|
||||||
@ -247,9 +240,7 @@ int main(void) {
|
|||||||
|
|
||||||
usb_run(&usb_device);
|
usb_run(&usb_device);
|
||||||
|
|
||||||
ssp1_init();
|
rf_path_init(&rf_path);
|
||||||
|
|
||||||
rf_path_init();
|
|
||||||
|
|
||||||
unsigned int phase = 0;
|
unsigned int phase = 0;
|
||||||
while(true) {
|
while(true) {
|
||||||
|
@ -22,8 +22,6 @@
|
|||||||
|
|
||||||
#include "usb_api_cpld.h"
|
#include "usb_api_cpld.h"
|
||||||
|
|
||||||
#include <libopencm3/lpc43xx/gpio.h>
|
|
||||||
|
|
||||||
#include <hackrf_core.h>
|
#include <hackrf_core.h>
|
||||||
#include <cpld_jtag.h>
|
#include <cpld_jtag.h>
|
||||||
#include <usb_queue.h>
|
#include <usb_queue.h>
|
||||||
@ -63,7 +61,6 @@ static void refill_cpld_buffer(void)
|
|||||||
void cpld_update(void)
|
void cpld_update(void)
|
||||||
{
|
{
|
||||||
#define WAIT_LOOP_DELAY (6000000)
|
#define WAIT_LOOP_DELAY (6000000)
|
||||||
#define ALL_LEDS (PIN_LED1|PIN_LED2|PIN_LED3)
|
|
||||||
int i;
|
int i;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
@ -72,7 +69,7 @@ void cpld_update(void)
|
|||||||
|
|
||||||
refill_cpld_buffer();
|
refill_cpld_buffer();
|
||||||
|
|
||||||
error = cpld_jtag_program(sizeof(cpld_xsvf_buffer),
|
error = cpld_jtag_program(&jtag_cpld, sizeof(cpld_xsvf_buffer),
|
||||||
cpld_xsvf_buffer,
|
cpld_xsvf_buffer,
|
||||||
refill_cpld_buffer);
|
refill_cpld_buffer);
|
||||||
if(error == 0)
|
if(error == 0)
|
||||||
@ -80,17 +77,21 @@ void cpld_update(void)
|
|||||||
/* blink LED1, LED2, and LED3 on success */
|
/* blink LED1, LED2, and LED3 on success */
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
gpio_set(PORT_LED1_3, ALL_LEDS); /* LEDs on */
|
led_on(LED1);
|
||||||
|
led_on(LED2);
|
||||||
|
led_on(LED3);
|
||||||
for (i = 0; i < WAIT_LOOP_DELAY; i++) /* Wait a bit. */
|
for (i = 0; i < WAIT_LOOP_DELAY; i++) /* Wait a bit. */
|
||||||
__asm__("nop");
|
__asm__("nop");
|
||||||
gpio_clear(PORT_LED1_3, ALL_LEDS); /* LEDs off */
|
led_off(LED1);
|
||||||
|
led_off(LED2);
|
||||||
|
led_off(LED3);
|
||||||
for (i = 0; i < WAIT_LOOP_DELAY; i++) /* Wait a bit. */
|
for (i = 0; i < WAIT_LOOP_DELAY; i++) /* Wait a bit. */
|
||||||
__asm__("nop");
|
__asm__("nop");
|
||||||
}
|
}
|
||||||
}else
|
}else
|
||||||
{
|
{
|
||||||
/* LED3 (Red) steady on error */
|
/* LED3 (Red) steady on error */
|
||||||
gpio_set(PORT_LED1_3, PIN_LED3); /* LEDs on */
|
led_on(LED3);
|
||||||
while (1);
|
while (1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,14 +22,16 @@
|
|||||||
|
|
||||||
#include "usb_api_register.h"
|
#include "usb_api_register.h"
|
||||||
|
|
||||||
|
#include <hackrf_core.h>
|
||||||
#include <usb_queue.h>
|
#include <usb_queue.h>
|
||||||
#include <max2837.h>
|
#include <max2837.h>
|
||||||
#include <si5351c.h>
|
|
||||||
#include <rffc5071.h>
|
#include <rffc5071.h>
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <hackrf_core.h>
|
||||||
|
|
||||||
usb_request_status_t usb_vendor_request_write_max2837(
|
usb_request_status_t usb_vendor_request_write_max2837(
|
||||||
usb_endpoint_t* const endpoint,
|
usb_endpoint_t* const endpoint,
|
||||||
const usb_transfer_stage_t stage
|
const usb_transfer_stage_t stage
|
||||||
@ -37,7 +39,7 @@ usb_request_status_t usb_vendor_request_write_max2837(
|
|||||||
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
||||||
if( endpoint->setup.index < MAX2837_NUM_REGS ) {
|
if( endpoint->setup.index < MAX2837_NUM_REGS ) {
|
||||||
if( endpoint->setup.value < MAX2837_DATA_REGS_MAX_VALUE ) {
|
if( endpoint->setup.value < MAX2837_DATA_REGS_MAX_VALUE ) {
|
||||||
max2837_reg_write(endpoint->setup.index, endpoint->setup.value);
|
max2837_reg_write(&max2837, endpoint->setup.index, endpoint->setup.value);
|
||||||
usb_transfer_schedule_ack(endpoint->in);
|
usb_transfer_schedule_ack(endpoint->in);
|
||||||
return USB_REQUEST_STATUS_OK;
|
return USB_REQUEST_STATUS_OK;
|
||||||
}
|
}
|
||||||
@ -54,7 +56,7 @@ usb_request_status_t usb_vendor_request_read_max2837(
|
|||||||
) {
|
) {
|
||||||
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
||||||
if( endpoint->setup.index < MAX2837_NUM_REGS ) {
|
if( endpoint->setup.index < MAX2837_NUM_REGS ) {
|
||||||
const uint16_t value = max2837_reg_read(endpoint->setup.index);
|
const uint16_t value = max2837_reg_read(&max2837, endpoint->setup.index);
|
||||||
endpoint->buffer[0] = value & 0xff;
|
endpoint->buffer[0] = value & 0xff;
|
||||||
endpoint->buffer[1] = value >> 8;
|
endpoint->buffer[1] = value >> 8;
|
||||||
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 2,
|
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 2,
|
||||||
@ -75,7 +77,7 @@ usb_request_status_t usb_vendor_request_write_si5351c(
|
|||||||
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
||||||
if( endpoint->setup.index < 256 ) {
|
if( endpoint->setup.index < 256 ) {
|
||||||
if( endpoint->setup.value < 256 ) {
|
if( endpoint->setup.value < 256 ) {
|
||||||
si5351c_write_single(endpoint->setup.index, endpoint->setup.value);
|
si5351c_write_single(&clock_gen, endpoint->setup.index, endpoint->setup.value);
|
||||||
usb_transfer_schedule_ack(endpoint->in);
|
usb_transfer_schedule_ack(endpoint->in);
|
||||||
return USB_REQUEST_STATUS_OK;
|
return USB_REQUEST_STATUS_OK;
|
||||||
}
|
}
|
||||||
@ -92,7 +94,7 @@ usb_request_status_t usb_vendor_request_read_si5351c(
|
|||||||
) {
|
) {
|
||||||
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
||||||
if( endpoint->setup.index < 256 ) {
|
if( endpoint->setup.index < 256 ) {
|
||||||
const uint8_t value = si5351c_read_single(endpoint->setup.index);
|
const uint8_t value = si5351c_read_single(&clock_gen, endpoint->setup.index);
|
||||||
endpoint->buffer[0] = value;
|
endpoint->buffer[0] = value;
|
||||||
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1,
|
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
@ -113,7 +115,7 @@ usb_request_status_t usb_vendor_request_write_rffc5071(
|
|||||||
{
|
{
|
||||||
if( endpoint->setup.index < RFFC5071_NUM_REGS )
|
if( endpoint->setup.index < RFFC5071_NUM_REGS )
|
||||||
{
|
{
|
||||||
rffc5071_reg_write(endpoint->setup.index, endpoint->setup.value);
|
rffc5071_reg_write(&rffc5072, endpoint->setup.index, endpoint->setup.value);
|
||||||
usb_transfer_schedule_ack(endpoint->in);
|
usb_transfer_schedule_ack(endpoint->in);
|
||||||
return USB_REQUEST_STATUS_OK;
|
return USB_REQUEST_STATUS_OK;
|
||||||
}
|
}
|
||||||
@ -132,7 +134,7 @@ usb_request_status_t usb_vendor_request_read_rffc5071(
|
|||||||
{
|
{
|
||||||
if( endpoint->setup.index < RFFC5071_NUM_REGS )
|
if( endpoint->setup.index < RFFC5071_NUM_REGS )
|
||||||
{
|
{
|
||||||
value = rffc5071_reg_read(endpoint->setup.index);
|
value = rffc5071_reg_read(&rffc5072, endpoint->setup.index);
|
||||||
endpoint->buffer[0] = value & 0xff;
|
endpoint->buffer[0] = value & 0xff;
|
||||||
endpoint->buffer[1] = value >> 8;
|
endpoint->buffer[1] = value >> 8;
|
||||||
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 2,
|
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 2,
|
||||||
|
@ -26,16 +26,21 @@
|
|||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include <hackrf_core.h>
|
||||||
|
|
||||||
#include <w25q80bv.h>
|
#include <w25q80bv.h>
|
||||||
|
|
||||||
uint8_t spiflash_buffer[W25Q80BV_PAGE_LEN];
|
/* Buffer size == spi_flash.page_len */
|
||||||
|
uint8_t spiflash_buffer[256U];
|
||||||
|
|
||||||
usb_request_status_t usb_vendor_request_erase_spiflash(
|
usb_request_status_t usb_vendor_request_erase_spiflash(
|
||||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage)
|
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage)
|
||||||
{
|
{
|
||||||
if (stage == USB_TRANSFER_STAGE_SETUP) {
|
if (stage == USB_TRANSFER_STAGE_SETUP) {
|
||||||
|
spi_bus_start(spi_flash.bus, &ssp_config_w25q80bv);
|
||||||
|
w25q80bv_setup(&spi_flash);
|
||||||
/* only chip erase is implemented */
|
/* only chip erase is implemented */
|
||||||
w25q80bv_chip_erase();
|
w25q80bv_chip_erase(&spi_flash);
|
||||||
usb_transfer_schedule_ack(endpoint->in);
|
usb_transfer_schedule_ack(endpoint->in);
|
||||||
}
|
}
|
||||||
return USB_REQUEST_STATUS_OK;
|
return USB_REQUEST_STATUS_OK;
|
||||||
@ -50,23 +55,25 @@ usb_request_status_t usb_vendor_request_write_spiflash(
|
|||||||
if (stage == USB_TRANSFER_STAGE_SETUP) {
|
if (stage == USB_TRANSFER_STAGE_SETUP) {
|
||||||
addr = (endpoint->setup.value << 16) | endpoint->setup.index;
|
addr = (endpoint->setup.value << 16) | endpoint->setup.index;
|
||||||
len = endpoint->setup.length;
|
len = endpoint->setup.length;
|
||||||
if ((len > W25Q80BV_PAGE_LEN) || (addr > W25Q80BV_NUM_BYTES)
|
if ((len > spi_flash.page_len) || (addr > spi_flash.num_bytes)
|
||||||
|| ((addr + len) > W25Q80BV_NUM_BYTES)) {
|
|| ((addr + len) > spi_flash.num_bytes)) {
|
||||||
return USB_REQUEST_STATUS_STALL;
|
return USB_REQUEST_STATUS_STALL;
|
||||||
} else {
|
} else {
|
||||||
usb_transfer_schedule_block(endpoint->out, &spiflash_buffer[0], len,
|
usb_transfer_schedule_block(endpoint->out, &spiflash_buffer[0], len,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
|
spi_bus_start(spi_flash.bus, &ssp_config_w25q80bv);
|
||||||
|
w25q80bv_setup(&spi_flash);
|
||||||
return USB_REQUEST_STATUS_OK;
|
return USB_REQUEST_STATUS_OK;
|
||||||
}
|
}
|
||||||
} else if (stage == USB_TRANSFER_STAGE_DATA) {
|
} else if (stage == USB_TRANSFER_STAGE_DATA) {
|
||||||
addr = (endpoint->setup.value << 16) | endpoint->setup.index;
|
addr = (endpoint->setup.value << 16) | endpoint->setup.index;
|
||||||
len = endpoint->setup.length;
|
len = endpoint->setup.length;
|
||||||
/* This check is redundant but makes me feel better. */
|
/* This check is redundant but makes me feel better. */
|
||||||
if ((len > W25Q80BV_PAGE_LEN) || (addr > W25Q80BV_NUM_BYTES)
|
if ((len > spi_flash.page_len) || (addr > spi_flash.num_bytes)
|
||||||
|| ((addr + len) > W25Q80BV_NUM_BYTES)) {
|
|| ((addr + len) > spi_flash.num_bytes)) {
|
||||||
return USB_REQUEST_STATUS_STALL;
|
return USB_REQUEST_STATUS_STALL;
|
||||||
} else {
|
} else {
|
||||||
w25q80bv_program(addr, len, &spiflash_buffer[0]);
|
w25q80bv_program(&spi_flash, addr, len, &spiflash_buffer[0]);
|
||||||
usb_transfer_schedule_ack(endpoint->in);
|
usb_transfer_schedule_ack(endpoint->in);
|
||||||
return USB_REQUEST_STATUS_OK;
|
return USB_REQUEST_STATUS_OK;
|
||||||
}
|
}
|
||||||
@ -85,11 +92,11 @@ usb_request_status_t usb_vendor_request_read_spiflash(
|
|||||||
{
|
{
|
||||||
addr = (endpoint->setup.value << 16) | endpoint->setup.index;
|
addr = (endpoint->setup.value << 16) | endpoint->setup.index;
|
||||||
len = endpoint->setup.length;
|
len = endpoint->setup.length;
|
||||||
if ((len > W25Q80BV_PAGE_LEN) || (addr > W25Q80BV_NUM_BYTES)
|
if ((len > spi_flash.page_len) || (addr > spi_flash.num_bytes)
|
||||||
|| ((addr + len) > W25Q80BV_NUM_BYTES)) {
|
|| ((addr + len) > spi_flash.num_bytes)) {
|
||||||
return USB_REQUEST_STATUS_STALL;
|
return USB_REQUEST_STATUS_STALL;
|
||||||
} else {
|
} else {
|
||||||
w25q80bv_read(addr, len, &spiflash_buffer[0]);
|
w25q80bv_read(&spi_flash, addr, len, &spiflash_buffer[0]);
|
||||||
usb_transfer_schedule_block(endpoint->in, &spiflash_buffer[0], len,
|
usb_transfer_schedule_block(endpoint->in, &spiflash_buffer[0], len,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
return USB_REQUEST_STATUS_OK;
|
return USB_REQUEST_STATUS_OK;
|
||||||
@ -99,8 +106,8 @@ usb_request_status_t usb_vendor_request_read_spiflash(
|
|||||||
addr = (endpoint->setup.value << 16) | endpoint->setup.index;
|
addr = (endpoint->setup.value << 16) | endpoint->setup.index;
|
||||||
len = endpoint->setup.length;
|
len = endpoint->setup.length;
|
||||||
/* This check is redundant but makes me feel better. */
|
/* This check is redundant but makes me feel better. */
|
||||||
if ((len > W25Q80BV_PAGE_LEN) || (addr > W25Q80BV_NUM_BYTES)
|
if ((len > spi_flash.page_len) || (addr > spi_flash.num_bytes)
|
||||||
|| ((addr + len) > W25Q80BV_NUM_BYTES))
|
|| ((addr + len) > spi_flash.num_bytes))
|
||||||
{
|
{
|
||||||
return USB_REQUEST_STATUS_STALL;
|
return USB_REQUEST_STATUS_STALL;
|
||||||
} else
|
} else
|
||||||
|
@ -22,8 +22,6 @@
|
|||||||
|
|
||||||
#include "usb_api_transceiver.h"
|
#include "usb_api_transceiver.h"
|
||||||
|
|
||||||
#include <libopencm3/lpc43xx/gpio.h>
|
|
||||||
|
|
||||||
#include <max2837.h>
|
#include <max2837.h>
|
||||||
#include <rf_path.h>
|
#include <rf_path.h>
|
||||||
#include <tuning.h>
|
#include <tuning.h>
|
||||||
@ -125,11 +123,11 @@ usb_request_status_t usb_vendor_request_set_amp_enable(
|
|||||||
if (stage == USB_TRANSFER_STAGE_SETUP) {
|
if (stage == USB_TRANSFER_STAGE_SETUP) {
|
||||||
switch (endpoint->setup.value) {
|
switch (endpoint->setup.value) {
|
||||||
case 0:
|
case 0:
|
||||||
rf_path_set_lna(0);
|
rf_path_set_lna(&rf_path, 0);
|
||||||
usb_transfer_schedule_ack(endpoint->in);
|
usb_transfer_schedule_ack(endpoint->in);
|
||||||
return USB_REQUEST_STATUS_OK;
|
return USB_REQUEST_STATUS_OK;
|
||||||
case 1:
|
case 1:
|
||||||
rf_path_set_lna(1);
|
rf_path_set_lna(&rf_path, 1);
|
||||||
usb_transfer_schedule_ack(endpoint->in);
|
usb_transfer_schedule_ack(endpoint->in);
|
||||||
return USB_REQUEST_STATUS_OK;
|
return USB_REQUEST_STATUS_OK;
|
||||||
default:
|
default:
|
||||||
@ -145,7 +143,7 @@ usb_request_status_t usb_vendor_request_set_lna_gain(
|
|||||||
const usb_transfer_stage_t stage)
|
const usb_transfer_stage_t stage)
|
||||||
{
|
{
|
||||||
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
||||||
const uint8_t value = max2837_set_lna_gain(endpoint->setup.index);
|
const uint8_t value = max2837_set_lna_gain(&max2837, endpoint->setup.index);
|
||||||
endpoint->buffer[0] = value;
|
endpoint->buffer[0] = value;
|
||||||
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1,
|
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
@ -159,7 +157,7 @@ usb_request_status_t usb_vendor_request_set_vga_gain(
|
|||||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage)
|
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage)
|
||||||
{
|
{
|
||||||
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
||||||
const uint8_t value = max2837_set_vga_gain(endpoint->setup.index);
|
const uint8_t value = max2837_set_vga_gain(&max2837, endpoint->setup.index);
|
||||||
endpoint->buffer[0] = value;
|
endpoint->buffer[0] = value;
|
||||||
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1,
|
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
@ -173,7 +171,7 @@ usb_request_status_t usb_vendor_request_set_txvga_gain(
|
|||||||
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage)
|
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage)
|
||||||
{
|
{
|
||||||
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
if( stage == USB_TRANSFER_STAGE_SETUP ) {
|
||||||
const uint8_t value = max2837_set_txvga_gain(endpoint->setup.index);
|
const uint8_t value = max2837_set_txvga_gain(&max2837, endpoint->setup.index);
|
||||||
endpoint->buffer[0] = value;
|
endpoint->buffer[0] = value;
|
||||||
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1,
|
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
@ -189,11 +187,11 @@ usb_request_status_t usb_vendor_request_set_antenna_enable(
|
|||||||
if (stage == USB_TRANSFER_STAGE_SETUP) {
|
if (stage == USB_TRANSFER_STAGE_SETUP) {
|
||||||
switch (endpoint->setup.value) {
|
switch (endpoint->setup.value) {
|
||||||
case 0:
|
case 0:
|
||||||
rf_path_set_antenna(0);
|
rf_path_set_antenna(&rf_path, 0);
|
||||||
usb_transfer_schedule_ack(endpoint->in);
|
usb_transfer_schedule_ack(endpoint->in);
|
||||||
return USB_REQUEST_STATUS_OK;
|
return USB_REQUEST_STATUS_OK;
|
||||||
case 1:
|
case 1:
|
||||||
rf_path_set_antenna(1);
|
rf_path_set_antenna(&rf_path, 1);
|
||||||
usb_transfer_schedule_ack(endpoint->in);
|
usb_transfer_schedule_ack(endpoint->in);
|
||||||
return USB_REQUEST_STATUS_OK;
|
return USB_REQUEST_STATUS_OK;
|
||||||
default:
|
default:
|
||||||
|
Submodule firmware/libopencm3 updated: 854c112a0e...50c51c7b5f
@ -19,14 +19,7 @@
|
|||||||
* Boston, MA 02110-1301, USA.
|
* Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <libopencm3/lpc43xx/gpio.h>
|
|
||||||
#include <libopencm3/lpc43xx/scu.h>
|
|
||||||
#include <libopencm3/lpc43xx/i2c.h>
|
|
||||||
#include <libopencm3/lpc43xx/ssp.h>
|
|
||||||
|
|
||||||
#include "hackrf_core.h"
|
#include "hackrf_core.h"
|
||||||
#include "max2837.h"
|
|
||||||
#include "rffc5071.h"
|
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
@ -38,21 +31,20 @@ int main(void)
|
|||||||
enable_rf_power();
|
enable_rf_power();
|
||||||
#endif
|
#endif
|
||||||
cpu_clock_init();
|
cpu_clock_init();
|
||||||
ssp1_init();
|
|
||||||
|
|
||||||
gpio_set(PORT_LED1_3, (PIN_LED1)); /* LED1 on */
|
led_on(LED1);
|
||||||
|
|
||||||
ssp1_set_mode_max2837();
|
ssp1_set_mode_max2837();
|
||||||
max2837_setup();
|
max2837_setup(&max2837);
|
||||||
rffc5071_setup();
|
rffc5071_setup(&rffc5072);
|
||||||
gpio_set(PORT_LED1_3, (PIN_LED2)); /* LED2 on */
|
led_on(LED2);
|
||||||
|
|
||||||
max2837_set_frequency(freq);
|
max2837_set_frequency(&max2837, freq);
|
||||||
max2837_start();
|
max2837_start(&max2837);
|
||||||
max2837_tx();
|
max2837_tx(&max2837);
|
||||||
gpio_set(PORT_LED1_3, (PIN_LED3)); /* LED3 on */
|
led_on(LED3);
|
||||||
while (1);
|
while (1);
|
||||||
max2837_stop();
|
max2837_stop(&max2837);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -20,17 +20,14 @@
|
|||||||
* Boston, MA 02110-1301, USA.
|
* Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <libopencm3/lpc43xx/gpio.h>
|
|
||||||
#include <libopencm3/lpc43xx/sgpio.h>
|
#include <libopencm3/lpc43xx/sgpio.h>
|
||||||
|
|
||||||
#include <hackrf_core.h>
|
#include <hackrf_core.h>
|
||||||
#include <rf_path.h>
|
|
||||||
#include <sgpio.h>
|
|
||||||
#include <tuning.h>
|
#include <tuning.h>
|
||||||
|
|
||||||
void tx_test() {
|
void tx_test() {
|
||||||
sgpio_set_slice_mode(false);
|
sgpio_set_slice_mode(&sgpio_config, false);
|
||||||
sgpio_configure(TRANSCEIVER_MODE_TX);
|
sgpio_configure(&sgpio_config, TRANSCEIVER_MODE_TX);
|
||||||
|
|
||||||
// LSB goes out first, samples are 0x<Q1><I1><Q0><I0>
|
// LSB goes out first, samples are 0x<Q1><I1><Q0><I0>
|
||||||
volatile uint32_t buffer[] = {
|
volatile uint32_t buffer[] = {
|
||||||
@ -41,7 +38,7 @@ void tx_test() {
|
|||||||
};
|
};
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
|
|
||||||
sgpio_cpld_stream_enable();
|
sgpio_cpld_stream_enable(&sgpio_config);
|
||||||
|
|
||||||
while(true) {
|
while(true) {
|
||||||
while(SGPIO_STATUS_1 == 0);
|
while(SGPIO_STATUS_1 == 0);
|
||||||
@ -51,20 +48,20 @@ void tx_test() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void rx_test() {
|
void rx_test() {
|
||||||
sgpio_set_slice_mode(false);
|
sgpio_set_slice_mode(&sgpio_config, false);
|
||||||
sgpio_configure(TRANSCEIVER_MODE_RX);
|
sgpio_configure(&sgpio_config, TRANSCEIVER_MODE_RX);
|
||||||
|
|
||||||
volatile uint32_t buffer[4096];
|
volatile uint32_t buffer[4096];
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
int16_t magsq;
|
int16_t magsq;
|
||||||
int8_t sigi, sigq;
|
int8_t sigi, sigq;
|
||||||
|
|
||||||
sgpio_cpld_stream_enable();
|
sgpio_cpld_stream_enable(&sgpio_config);
|
||||||
|
|
||||||
gpio_set(PORT_LED1_3, (PIN_LED2)); /* LED2 on */
|
led_on(LED2);
|
||||||
while(true) {
|
while(true) {
|
||||||
while(SGPIO_STATUS_1 == 0);
|
while(SGPIO_STATUS_1 == 0);
|
||||||
gpio_set(PORT_LED1_3, (PIN_LED1)); /* LED1 on */
|
led_on(LED1);
|
||||||
SGPIO_CLR_STATUS_1 = 1;
|
SGPIO_CLR_STATUS_1 = 1;
|
||||||
buffer[i & 4095] = SGPIO_REG_SS(SGPIO_SLICE_A);
|
buffer[i & 4095] = SGPIO_REG_SS(SGPIO_SLICE_A);
|
||||||
|
|
||||||
@ -79,9 +76,9 @@ void rx_test() {
|
|||||||
|
|
||||||
/* illuminate LED3 only when magsq exceeds threshold */
|
/* illuminate LED3 only when magsq exceeds threshold */
|
||||||
if (magsq > 0x3c00)
|
if (magsq > 0x3c00)
|
||||||
gpio_set(PORT_LED1_3, (PIN_LED3)); /* LED3 on */
|
led_on(LED3);
|
||||||
else
|
else
|
||||||
gpio_clear(PORT_LED1_3, (PIN_LED3)); /* LED3 off */
|
led_off(LED3);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -96,14 +93,13 @@ int main(void) {
|
|||||||
enable_rf_power();
|
enable_rf_power();
|
||||||
#endif
|
#endif
|
||||||
cpu_clock_init();
|
cpu_clock_init();
|
||||||
ssp1_init();
|
rf_path_init(&rf_path);
|
||||||
rf_path_init();
|
rf_path_set_direction(&rf_path, RF_PATH_DIRECTION_RX);
|
||||||
rf_path_set_direction(RF_PATH_DIRECTION_RX);
|
|
||||||
|
|
||||||
set_freq(freq);
|
set_freq(freq);
|
||||||
|
|
||||||
rx_test();
|
rx_test();
|
||||||
gpio_set(PORT_LED1_3, (PIN_LED2)); /* LED2 on */
|
led_on(LED2);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
|
@ -19,22 +19,15 @@
|
|||||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
* Boston, MA 02110-1301, USA.
|
* Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <libopencm3/lpc43xx/gpio.h>
|
|
||||||
#include <libopencm3/lpc43xx/scu.h>
|
|
||||||
#include <libopencm3/lpc43xx/sgpio.h>
|
#include <libopencm3/lpc43xx/sgpio.h>
|
||||||
#include <libopencm3/lpc43xx/cgu.h>
|
|
||||||
#include <libopencm3/cm3/scs.h>
|
|
||||||
|
|
||||||
#include <hackrf_core.h>
|
#include <hackrf_core.h>
|
||||||
#include <max5864.h>
|
|
||||||
#include <sgpio.h>
|
|
||||||
|
|
||||||
volatile uint32_t buffer[4096];
|
volatile uint32_t buffer[4096];
|
||||||
|
|
||||||
void tx_test() {
|
void tx_test() {
|
||||||
sgpio_set_slice_mode(false);
|
sgpio_set_slice_mode(&sgpio_config, false);
|
||||||
sgpio_configure(TRANSCEIVER_MODE_TX);
|
sgpio_configure(&sgpio_config, TRANSCEIVER_MODE_TX);
|
||||||
|
|
||||||
// LSB goes out first, samples are 0x<Q1><I1><Q0><I0>
|
// LSB goes out first, samples are 0x<Q1><I1><Q0><I0>
|
||||||
buffer[0] = 0xda808080;
|
buffer[0] = 0xda808080;
|
||||||
@ -44,7 +37,7 @@ void tx_test() {
|
|||||||
|
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
|
|
||||||
sgpio_cpld_stream_enable();
|
sgpio_cpld_stream_enable(&sgpio_config);
|
||||||
|
|
||||||
while(true) {
|
while(true) {
|
||||||
while(SGPIO_STATUS_1 == 0);
|
while(SGPIO_STATUS_1 == 0);
|
||||||
@ -54,12 +47,12 @@ void tx_test() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void rx_test() {
|
void rx_test() {
|
||||||
sgpio_set_slice_mode(false);
|
sgpio_set_slice_mode(&sgpio_config, false);
|
||||||
sgpio_configure(TRANSCEIVER_MODE_RX);
|
sgpio_configure(&sgpio_config, TRANSCEIVER_MODE_RX);
|
||||||
|
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
|
|
||||||
sgpio_cpld_stream_enable();
|
sgpio_cpld_stream_enable(&sgpio_config);
|
||||||
|
|
||||||
while(true) {
|
while(true) {
|
||||||
while(SGPIO_STATUS_1 == 0);
|
while(SGPIO_STATUS_1 == 0);
|
||||||
@ -72,12 +65,12 @@ int main(void) {
|
|||||||
pin_setup();
|
pin_setup();
|
||||||
enable_1v8_power();
|
enable_1v8_power();
|
||||||
cpu_clock_init();
|
cpu_clock_init();
|
||||||
ssp1_init();
|
|
||||||
|
|
||||||
gpio_set(PORT_LED1_3, PIN_LED1);
|
led_on(LED1);
|
||||||
|
|
||||||
ssp1_set_mode_max5864();
|
ssp1_set_mode_max5864();
|
||||||
max5864_xcvr();
|
max5864_setup(&max5864);
|
||||||
|
max5864_xcvr(&max5864);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
|
@ -21,11 +21,8 @@
|
|||||||
* Boston, MA 02110-1301, USA.
|
* Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <libopencm3/lpc43xx/gpio.h>
|
|
||||||
#include <libopencm3/lpc43xx/scu.h>
|
#include <libopencm3/lpc43xx/scu.h>
|
||||||
#include <libopencm3/lpc43xx/sgpio.h>
|
#include <libopencm3/lpc43xx/sgpio.h>
|
||||||
#include <libopencm3/lpc43xx/cgu.h>
|
|
||||||
#include <libopencm3/cm3/scs.h>
|
|
||||||
|
|
||||||
#include <hackrf_core.h>
|
#include <hackrf_core.h>
|
||||||
|
|
||||||
@ -353,8 +350,7 @@ int main(void)
|
|||||||
pin_setup();
|
pin_setup();
|
||||||
enable_1v8_power();
|
enable_1v8_power();
|
||||||
cpu_clock_init();
|
cpu_clock_init();
|
||||||
ssp1_init();
|
led_on(LED1);
|
||||||
gpio_set(PORT_LED1_3, PIN_LED1);
|
|
||||||
|
|
||||||
//test_sgpio_sliceA_D();
|
//test_sgpio_sliceA_D();
|
||||||
test_sgpio_interface();
|
test_sgpio_interface();
|
||||||
|
@ -19,13 +19,7 @@
|
|||||||
* Boston, MA 02110-1301, USA.
|
* Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <libopencm3/lpc43xx/gpio.h>
|
|
||||||
#include <libopencm3/lpc43xx/scu.h>
|
|
||||||
#include <libopencm3/lpc43xx/i2c.h>
|
|
||||||
#include <libopencm3/lpc43xx/ssp.h>
|
|
||||||
|
|
||||||
#include "hackrf_core.h"
|
#include "hackrf_core.h"
|
||||||
#include "max2837.h"
|
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
@ -37,19 +31,18 @@ int main(void)
|
|||||||
enable_rf_power();
|
enable_rf_power();
|
||||||
#endif
|
#endif
|
||||||
cpu_clock_init();
|
cpu_clock_init();
|
||||||
ssp1_init();
|
|
||||||
|
|
||||||
gpio_set(PORT_LED1_3, (PIN_LED1)); /* LED1 on */
|
led_on(LED1);
|
||||||
|
|
||||||
ssp1_set_mode_max2837();
|
ssp1_set_mode_max2837();
|
||||||
max2837_setup();
|
max2837_setup(&max2837);
|
||||||
gpio_set(PORT_LED1_3, (PIN_LED2)); /* LED2 on */
|
led_on(LED2);
|
||||||
max2837_set_frequency(freq);
|
max2837_set_frequency(&max2837, freq);
|
||||||
max2837_start();
|
max2837_start(&max2837);
|
||||||
max2837_tx();
|
max2837_tx(&max2837);
|
||||||
gpio_set(PORT_LED1_3, (PIN_LED3)); /* LED3 on */
|
led_on(LED3);
|
||||||
while (1);
|
while (1);
|
||||||
max2837_stop();
|
max2837_stop(&max2837);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -19,11 +19,7 @@
|
|||||||
* Boston, MA 02110-1301, USA.
|
* Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <libopencm3/lpc43xx/gpio.h>
|
|
||||||
#include <libopencm3/lpc43xx/scu.h>
|
|
||||||
|
|
||||||
#include "hackrf_core.h"
|
#include "hackrf_core.h"
|
||||||
#include "w25q80bv.h"
|
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
@ -39,17 +35,19 @@ int main(void)
|
|||||||
/* program test data to SPI flash */
|
/* program test data to SPI flash */
|
||||||
for (i = 0; i < 515; i++)
|
for (i = 0; i < 515; i++)
|
||||||
buf[i] = (i * 3) & 0xFF;
|
buf[i] = (i * 3) & 0xFF;
|
||||||
w25q80bv_setup();
|
w25q80bv_setup(&w25q80bv);
|
||||||
w25q80bv_chip_erase();
|
w25q80bv_chip_erase(&w25q80bv);
|
||||||
w25q80bv_program(790, 515, &buf[0]);
|
w25q80bv_program(&w25q80bv, 790, 515, &buf[0]);
|
||||||
|
|
||||||
/* blink LED1 and LED3 */
|
/* blink LED1 and LED3 */
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
gpio_set(PORT_LED1_3, (PIN_LED1|PIN_LED3)); /* LEDs on */
|
led_on(LED1);
|
||||||
|
led_on(LED3);
|
||||||
for (i = 0; i < 8000000; i++) /* Wait a bit. */
|
for (i = 0; i < 8000000; i++) /* Wait a bit. */
|
||||||
__asm__("nop");
|
__asm__("nop");
|
||||||
gpio_clear(PORT_LED1_3, (PIN_LED1|PIN_LED3)); /* LED off */
|
led_off(LED1);
|
||||||
|
led_off(LED3);
|
||||||
for (i = 0; i < 8000000; i++) /* Wait a bit. */
|
for (i = 0; i < 8000000; i++) /* Wait a bit. */
|
||||||
__asm__("nop");
|
__asm__("nop");
|
||||||
}
|
}
|
||||||
|
@ -19,10 +19,6 @@
|
|||||||
* Boston, MA 02110-1301, USA.
|
* Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <libopencm3/lpc43xx/gpio.h>
|
|
||||||
#include <libopencm3/lpc43xx/scu.h>
|
|
||||||
#include <libopencm3/lpc43xx/i2c.h>
|
|
||||||
|
|
||||||
#include "hackrf_core.h"
|
#include "hackrf_core.h"
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
@ -35,23 +31,27 @@ int main(void)
|
|||||||
|
|
||||||
cpu_clock_init();
|
cpu_clock_init();
|
||||||
|
|
||||||
gpio_set(PORT_LED1_3, (PIN_LED1|PIN_LED2|PIN_LED3)); /* LEDs on */
|
led_on(LED1);
|
||||||
|
led_on(LED2);
|
||||||
|
led_on(LED3);
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
gpio_set(PORT_LED1_3, (PIN_LED1)); /* LEDs on */
|
led_on(LED1);
|
||||||
for (i = 0; i < 2000000; i++) /* Wait a bit. */
|
for (i = 0; i < 2000000; i++) /* Wait a bit. */
|
||||||
__asm__("nop");
|
__asm__("nop");
|
||||||
|
|
||||||
gpio_set(PORT_LED1_3, (PIN_LED1|PIN_LED2)); /* LEDs on */
|
led_on(LED2);
|
||||||
for (i = 0; i < 2000000; i++) /* Wait a bit. */
|
for (i = 0; i < 2000000; i++) /* Wait a bit. */
|
||||||
__asm__("nop");
|
__asm__("nop");
|
||||||
|
|
||||||
gpio_set(PORT_LED1_3, (PIN_LED1|PIN_LED2|PIN_LED3)); /* LED off */
|
led_on(LED3);
|
||||||
for (i = 0; i < 2000000; i++) /* Wait a bit. */
|
for (i = 0; i < 2000000; i++) /* Wait a bit. */
|
||||||
__asm__("nop");
|
__asm__("nop");
|
||||||
|
|
||||||
gpio_clear(PORT_LED1_3, (PIN_LED1|PIN_LED2|PIN_LED3)); /* LED off */
|
led_off(LED1);
|
||||||
|
led_off(LED2);
|
||||||
|
led_off(LED3);
|
||||||
for (i = 0; i < 2000000; i++) /* Wait a bit. */
|
for (i = 0; i < 2000000; i++) /* Wait a bit. */
|
||||||
__asm__("nop");
|
__asm__("nop");
|
||||||
}
|
}
|
||||||
|
@ -19,9 +19,6 @@
|
|||||||
* Boston, MA 02110-1301, USA.
|
* Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <libopencm3/lpc43xx/gpio.h>
|
|
||||||
#include <libopencm3/lpc43xx/scu.h>
|
|
||||||
#include <libopencm3/lpc43xx/i2c.h>
|
|
||||||
#include <libopencm3/lpc43xx/m4/nvic.h>
|
#include <libopencm3/lpc43xx/m4/nvic.h>
|
||||||
#include <libopencm3/cm3/systick.h>
|
#include <libopencm3/cm3/systick.h>
|
||||||
#include <libopencm3/cm3/scs.h>
|
#include <libopencm3/cm3/scs.h>
|
||||||
@ -139,19 +136,21 @@ int main(void)
|
|||||||
|
|
||||||
systick_setup();
|
systick_setup();
|
||||||
|
|
||||||
gpio_set(PORT_LED1_3, (PIN_LED1|PIN_LED2|PIN_LED3)); /* LEDs on */
|
led_on(LED1);
|
||||||
|
led_on(LED2);
|
||||||
|
led_on(LED3);
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
gpio_set(PORT_LED1_3, (PIN_LED1)); /* LED1 on */
|
led_on(LED1);
|
||||||
gpio_set(PORT_LED1_3, (PIN_LED2)); /* LED2 on */
|
led_on(LED2);
|
||||||
gpio_set(PORT_LED1_3, (PIN_LED3)); /* LED3 on */
|
led_on(LED3);
|
||||||
|
|
||||||
sys_tick_wait_time_ms(500);
|
sys_tick_wait_time_ms(500);
|
||||||
|
|
||||||
gpio_clear(PORT_LED1_3, (PIN_LED3)); /* LED3 off */
|
led_off(LED1);
|
||||||
gpio_clear(PORT_LED1_3, (PIN_LED2)); /* LED2 off */
|
led_off(LED2);
|
||||||
gpio_clear(PORT_LED1_3, (PIN_LED1)); /* LED1 off */
|
led_off(LED3);
|
||||||
|
|
||||||
sys_tick_wait_time_ms(500);
|
sys_tick_wait_time_ms(500);
|
||||||
}
|
}
|
||||||
|
@ -19,9 +19,6 @@
|
|||||||
* Boston, MA 02110-1301, USA.
|
* Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <libopencm3/lpc43xx/gpio.h>
|
|
||||||
#include <libopencm3/lpc43xx/scu.h>
|
|
||||||
#include <libopencm3/lpc43xx/i2c.h>
|
|
||||||
#include <libopencm3/lpc43xx/m4/nvic.h>
|
#include <libopencm3/lpc43xx/m4/nvic.h>
|
||||||
#include <libopencm3/cm3/systick.h>
|
#include <libopencm3/cm3/systick.h>
|
||||||
#include <libopencm3/cm3/scs.h>
|
#include <libopencm3/cm3/scs.h>
|
||||||
|
@ -19,9 +19,6 @@
|
|||||||
* Boston, MA 02110-1301, USA.
|
* Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <libopencm3/lpc43xx/gpio.h>
|
|
||||||
#include <libopencm3/lpc43xx/scu.h>
|
|
||||||
#include <libopencm3/lpc43xx/i2c.h>
|
|
||||||
#include <libopencm3/lpc43xx/m4/nvic.h>
|
#include <libopencm3/lpc43xx/m4/nvic.h>
|
||||||
#include <libopencm3/cm3/systick.h>
|
#include <libopencm3/cm3/systick.h>
|
||||||
#include <libopencm3/cm3/scs.h>
|
#include <libopencm3/cm3/scs.h>
|
||||||
@ -138,7 +135,7 @@ extern uint32_t test_nb_instruction_per_sec_150_nop_asm();
|
|||||||
extern uint32_t test_nb_instruction_per_sec_200_nop_asm();
|
extern uint32_t test_nb_instruction_per_sec_200_nop_asm();
|
||||||
extern uint32_t test_nb_instruction_per_sec_1000_nop_asm();
|
extern uint32_t test_nb_instruction_per_sec_1000_nop_asm();
|
||||||
|
|
||||||
#define LED1_TOGGLE() (gpio_toggle(PORT_LED1_3, (PIN_LED1)))
|
#define LED1_TOGGLE() (led_toggle(LED1))
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
@ -152,7 +149,7 @@ int main(void)
|
|||||||
|
|
||||||
systick_setup();
|
systick_setup();
|
||||||
|
|
||||||
gpio_clear(PORT_LED1_3, (PIN_LED1)); /* LED1 off */
|
led_off(LED1);
|
||||||
|
|
||||||
/* Test number of instruction per second (MIPS) slow blink ON 1s, OFF 1s */
|
/* Test number of instruction per second (MIPS) slow blink ON 1s, OFF 1s */
|
||||||
LED1_TOGGLE();
|
LED1_TOGGLE();
|
||||||
@ -192,15 +189,15 @@ LED1_TOGGLE();
|
|||||||
/* Test finished fast blink */
|
/* Test finished fast blink */
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
gpio_set(PORT_LED1_3, (PIN_LED1)); /* LED1 on */
|
led_on(LED1);
|
||||||
gpio_set(PORT_LED1_3, (PIN_LED2)); /* LED2 on */
|
led_on(LED2);
|
||||||
gpio_set(PORT_LED1_3, (PIN_LED3)); /* LED3 on */
|
led_on(LED3);
|
||||||
|
|
||||||
sys_tick_wait_time_ms(250);
|
sys_tick_wait_time_ms(250);
|
||||||
|
|
||||||
gpio_clear(PORT_LED1_3, (PIN_LED3)); /* LED3 off */
|
led_off(LED1);
|
||||||
gpio_clear(PORT_LED1_3, (PIN_LED2)); /* LED2 off */
|
led_off(LED2);
|
||||||
gpio_clear(PORT_LED1_3, (PIN_LED1)); /* LED1 off */
|
led_off(LED3);
|
||||||
|
|
||||||
sys_tick_wait_time_ms(250);
|
sys_tick_wait_time_ms(250);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user