diff --git a/firmware/blinky/blinky.c b/firmware/blinky/blinky.c index 0201cff4..143c9940 100644 --- a/firmware/blinky/blinky.c +++ b/firmware/blinky/blinky.c @@ -19,13 +19,8 @@ * Boston, MA 02110-1301, USA. */ -#include -#include - #include "hackrf_core.h" -uint32_t boot0, boot1, boot2, boot3; - int main(void) { int i; @@ -34,18 +29,20 @@ int main(void) /* enable all power supplies */ 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) { - boot0 = BOOT0_STATE; - boot1 = BOOT1_STATE; - boot2 = BOOT2_STATE; - boot3 = BOOT3_STATE; + led_on(LED1); + led_on(LED2); + led_on(LED3); - gpio_set(PORT_LED1_3, (PIN_LED1|PIN_LED2|PIN_LED3)); /* LEDs on */ for (i = 0; i < 2000000; i++) /* Wait a bit. */ __asm__("nop"); - gpio_clear(PORT_LED1_3, (PIN_LED1|PIN_LED2|PIN_LED3)); /* LED off */ + + led_off(LED1); + led_off(LED2); + led_off(LED3); + for (i = 0; i < 2000000; i++) /* Wait a bit. */ __asm__("nop"); } diff --git a/firmware/common/cpld_jtag.c b/firmware/common/cpld_jtag.c index 50430fee..ca117ccc 100644 --- a/firmware/common/cpld_jtag.c +++ b/firmware/common/cpld_jtag.c @@ -22,7 +22,6 @@ #include "cpld_jtag.h" #include "hackrf_core.h" #include "xapp058/micro.h" -#include #include #include @@ -30,47 +29,45 @@ static refill_buffer_cb refill_buffer; static uint32_t xsvf_buffer_len, xsvf_pos; 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_TCK, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); scu_pinmux(SCU_PINMUX_CPLD_TMS, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); scu_pinmux(SCU_PINMUX_CPLD_TDI, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); - /* TDO is an input */ - GPIO_DIR(PORT_CPLD_TDO) &= ~PIN_CPLD_TDO; - - /* the rest are outputs */ - GPIO_DIR(PORT_CPLD_TCK) |= PIN_CPLD_TCK; - GPIO_DIR(PORT_CPLD_TMS) |= PIN_CPLD_TMS; - GPIO_DIR(PORT_CPLD_TDI) |= PIN_CPLD_TDI; + gpio_input(jtag->gpio->gpio_tdo); + gpio_output(jtag->gpio->gpio_tck); + gpio_output(jtag->gpio->gpio_tms); + gpio_output(jtag->gpio->gpio_tdi); } /* 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_TCK, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); scu_pinmux(SCU_PINMUX_CPLD_TMS, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); scu_pinmux(SCU_PINMUX_CPLD_TDI, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); - GPIO_DIR(PORT_CPLD_TDO) &= ~PIN_CPLD_TDO; - GPIO_DIR(PORT_CPLD_TCK) &= ~PIN_CPLD_TCK; - GPIO_DIR(PORT_CPLD_TMS) &= ~PIN_CPLD_TMS; - GPIO_DIR(PORT_CPLD_TDI) &= ~PIN_CPLD_TDI; + gpio_input(jtag->gpio->gpio_tdo); + gpio_input(jtag->gpio->gpio_tck); + gpio_input(jtag->gpio->gpio_tms); + gpio_input(jtag->gpio->gpio_tdi); } /* return 0 if success else return error code see xsvfExecute() */ int cpld_jtag_program( + jtag_t* const jtag, const uint32_t buffer_length, unsigned char* const buffer, refill_buffer_cb refill ) { int error; - cpld_jtag_setup(); + cpld_jtag_setup(jtag); xsvf_buffer = buffer; xsvf_buffer_len = buffer_length; refill_buffer = refill; - error = xsvfExecute(); - cpld_jtag_release(); + error = xsvfExecute(jtag->gpio); + cpld_jtag_release(jtag); return error; } diff --git a/firmware/common/cpld_jtag.h b/firmware/common/cpld_jtag.h index 56f55a2a..5805bbc8 100644 --- a/firmware/common/cpld_jtag.h +++ b/firmware/common/cpld_jtag.h @@ -24,9 +24,22 @@ #include +#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); -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. * @@ -34,6 +47,7 @@ void cpld_jtag_release(void); * contents of the buffer has been streamed to the CPLD the given * refill_buffer callback will be called. */ int cpld_jtag_program( + jtag_t* const jtag, const uint32_t buffer_length, unsigned char* const buffer, refill_buffer_cb refill diff --git a/firmware/common/gpio.h b/firmware/common/gpio.h new file mode 100644 index 00000000..fe60ff61 --- /dev/null +++ b/firmware/common/gpio.h @@ -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 + +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__*/ diff --git a/firmware/common/gpio_lpc.c b/firmware/common/gpio_lpc.c new file mode 100644 index 00000000..b5e217c4 --- /dev/null +++ b/firmware/common/gpio_lpc.c @@ -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 + +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; +} diff --git a/firmware/common/gpio_lpc.h b/firmware/common/gpio_lpc.h new file mode 100644 index 00000000..ef981fe8 --- /dev/null +++ b/firmware/common/gpio_lpc.h @@ -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 + +#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__*/ diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index b862ba4f..32d3b97d 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -23,18 +23,295 @@ #include "hackrf_core.h" #include "si5351c.h" +#include "spi_ssp.h" #include "max2837.h" +#include "max2837_target.h" +#include "max5864.h" +#include "max5864_target.h" #include "rffc5071.h" -#include "sgpio.h" -#include "rf_path.h" -#include +#include "rffc5071_spi.h" +#include "w25q80bv.h" +#include "w25q80bv_target.h" +#include "i2c_bus.h" +#include "i2c_lpc.h" #include -#include #include #include +#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) +/* 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) { 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 ? */ if (a & 0x1 || b) - si5351c_set_int_mode(0, 0); + si5351c_set_int_mode(&clock_gen, 0, 0); else - si5351c_set_int_mode(0, 1); + si5351c_set_int_mode(&clock_gen, 0, 1); /* Final MS values */ 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; /* 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). */ - 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) */ - 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; } @@ -174,13 +451,13 @@ bool sample_rate_set(const uint32_t sample_rate_hz) { * values are irrelevant. */ /* 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). */ - 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. */ - si5351c_configure_multisynth(3, 4608, 0, 1, r_div_sgpio); + si5351c_configure_multisynth(&clock_gen, 3, 4608, 0, 1, r_div_sgpio); return true; #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). */ - 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). */ - 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) */ - 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; #endif } 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 @@ -264,15 +541,15 @@ void cpu_clock_init(void) /* use IRC as clock source for APB3 */ 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_oeb_pin_control(); - si5351c_power_down_all_clocks(); - si5351c_set_crystal_configuration(); - si5351c_enable_xo_and_ms_fanout(); - si5351c_configure_pll_sources(); - si5351c_configure_pll_multisynth(); + si5351c_disable_all_outputs(&clock_gen); + si5351c_disable_oeb_pin_control(&clock_gen); + si5351c_power_down_all_clocks(&clock_gen); + si5351c_set_crystal_configuration(&clock_gen); + si5351c_enable_xo_and_ms_fanout(&clock_gen); + si5351c_configure_pll_sources(&clock_gen); + si5351c_configure_pll_multisynth(&clock_gen); #ifdef JELLYBEAN /* @@ -288,13 +565,13 @@ void cpu_clock_init(void) */ /* 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. */ - 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. */ - si5351c_configure_multisynth(5, 1536, 0, 1, 0); /* 50MHz */ + si5351c_configure_multisynth(&clock_gen, 5, 1536, 0, 1, 0); /* 50MHz */ #endif #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. */ - 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. */ - 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. */ - 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. */ /* MS7/CLK7 is the source for the LPC43xx microcontroller. */ uint8_t ms7data[] = { 90, 255, 20, 0 }; - si5351c_write(ms7data, sizeof(ms7data)); + si5351c_write(&clock_gen, ms7data, sizeof(ms7data)); #endif /* Set to 10 MHz, the common rate between Jellybean and Jawbreaker. */ sample_rate_set(10000000); - si5351c_set_clock_source(PLL_SOURCE_XTAL); + si5351c_set_clock_source(&clock_gen, PLL_SOURCE_XTAL); // soft reset uint8_t resetdata[] = { 177, 0xac }; - si5351c_write(resetdata, sizeof(resetdata)); - si5351c_enable_clock_outputs(); + si5351c_write(&clock_gen, resetdata, sizeof(resetdata)); + si5351c_enable_clock_outputs(&clock_gen); //FIXME disable I2C /* 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 @@ -411,6 +688,12 @@ void cpu_clock_init(void) /* Switch APB3 clock over to use PLL1 (204MHz) */ CGU_BASE_APB3_CLK = CGU_BASE_APB3_CLK_AUTOBLOCK(1) | CGU_BASE_APB3_CLK_CLK_SEL(CGU_SRC_PLL1); + + 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) { - /* FIXME speed up once everything is working reliably */ - /* - // Freq About 0.0498MHz / 49.8KHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz - const uint8_t serial_clock_rate = 32; - const uint8_t clock_prescale_rate = 128; - */ - // Freq About 4.857MHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz - const uint8_t serial_clock_rate = 21; - const uint8_t clock_prescale_rate = 2; - - ssp_init(SSP1_NUM, - SSP_DATA_16BITS, - SSP_FRAME_SPI, - SSP_CPOL_0_CPHA_0, - serial_clock_rate, - clock_prescale_rate, - SSP_MODE_NORMAL, - SSP_MASTER, - SSP_SLAVE_OUT_ENABLE); + spi_bus_start(max2837.bus, &ssp_config_max2837); } void ssp1_set_mode_max5864(void) { - /* FIXME speed up once everything is working reliably */ - /* - // Freq About 0.0498MHz / 49.8KHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz - const uint8_t serial_clock_rate = 32; - const uint8_t clock_prescale_rate = 128; - */ - // Freq About 4.857MHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz - const uint8_t serial_clock_rate = 21; - const uint8_t clock_prescale_rate = 2; - - ssp_init(SSP1_NUM, - SSP_DATA_8BITS, - SSP_FRAME_SPI, - SSP_CPOL_0_CPHA_0, - serial_clock_rate, - clock_prescale_rate, - SSP_MODE_NORMAL, - SSP_MASTER, - SSP_SLAVE_OUT_ENABLE); + spi_bus_start(max5864.bus, &ssp_config_max5864); } 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_TDI, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); - GPIO_DIR(PORT_CPLD_TDO) &= ~PIN_CPLD_TDO; - GPIO_DIR(PORT_CPLD_TCK) &= ~PIN_CPLD_TCK; - GPIO_DIR(PORT_CPLD_TMS) &= ~PIN_CPLD_TMS; - GPIO_DIR(PORT_CPLD_TDI) &= ~PIN_CPLD_TDI; + gpio_input(&gpio_cpld_tdo); + gpio_input(&gpio_cpld_tck); + gpio_input(&gpio_cpld_tms); + gpio_input(&gpio_cpld_tdi); /* Configure SCU Pin Mux as GPIO */ scu_pinmux(SCU_PINMUX_LED1, SCU_GPIO_NOPULL); @@ -596,49 +823,62 @@ void pin_setup(void) { #endif /* Configure all GPIO as Input (safe state) */ - GPIO0_DIR = 0; - GPIO1_DIR = 0; - GPIO2_DIR = 0; - GPIO3_DIR = 0; - GPIO4_DIR = 0; - GPIO5_DIR = 0; - GPIO6_DIR = 0; - GPIO7_DIR = 0; + gpio_init(); - /* Configure GPIO2[1/2/8] (P4_1/2 P6_12) as output. */ - GPIO2_DIR |= (PIN_LED1 | PIN_LED2 | PIN_LED3); + gpio_output(&gpio_led[0]); + gpio_output(&gpio_led[1]); + gpio_output(&gpio_led[2]); - /* GPIO3[6] on P6_10 as output. */ - GPIO3_DIR |= PIN_EN1V8; + gpio_output(&gpio_1v8_enable); - rf_path_pin_setup(); - - /* Configure SSP1 Peripheral (to be moved later in SSP driver) */ - scu_pinmux(SCU_SSP1_MISO, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); - scu_pinmux(SCU_SSP1_MOSI, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); - scu_pinmux(SCU_SSP1_SCK, (SCU_SSP_IO | SCU_CONF_FUNCTION1)); - scu_pinmux(SCU_SSP1_SSEL, (SCU_SSP_IO | SCU_CONF_FUNCTION1)); +#ifdef HACKRF_ONE + /* Configure RF power supply (VAA) switch control signal as output */ + gpio_output(&gpio_vaa_disable); + + /* Safe state: start with VAA turned off: */ + disable_rf_power(); +#endif + + /* 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 */ 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) { - gpio_set(PORT_EN1V8, PIN_EN1V8); + gpio_set(&gpio_1v8_enable); } void disable_1v8_power(void) { - gpio_clear(PORT_EN1V8, PIN_EN1V8); + gpio_clear(&gpio_1v8_enable); } #ifdef HACKRF_ONE 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) { - gpio_set(PORT_NO_VAA_ENABLE, PIN_NO_VAA_ENABLE); + gpio_set(&gpio_vaa_disable); } #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]); +} diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index bad03a40..a1b9b00f 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -32,6 +32,17 @@ extern "C" #include #include +#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 */ #define BOARD_ID_JELLYBEAN 0 #define BOARD_ID_JAWBREAKER 1 @@ -206,142 +217,6 @@ extern "C" #define SCU_PINMUX_GP_CLKIN (P4_7) -/* - * GPIO Pins - */ - -/* GPIO Output */ -#define PIN_LED1 (BIT1) /* GPIO2[1] on P4_1 */ -#define PIN_LED2 (BIT2) /* GPIO2[2] on P4_2 */ -#define PIN_LED3 (BIT8) /* GPIO2[8] on P6_12 */ -#define PORT_LED1_3 (GPIO2) /* PORT for LED1, 2 & 3 */ - -#define PIN_EN1V8 (BIT6) /* GPIO3[6] on P6_10 */ -#define PORT_EN1V8 (GPIO3) - -#define PIN_XCVR_CS (BIT15) /* GPIO0[15] on P1_20 */ -#define PORT_XCVR_CS (GPIO0) /* PORT for CS */ -#define PIN_XCVR_ENABLE (BIT6) /* GPIO2[6] on P4_6 */ -#define PIN_XCVR_RXENABLE (BIT5) /* GPIO2[5] on P4_5 */ -#define PIN_XCVR_TXENABLE (BIT4) /* GPIO2[4] on P4_4 */ -#define PORT_XCVR_ENABLE (GPIO2) /* PORT for ENABLE, TXENABLE, RXENABLE */ -#ifdef JELLYBEAN -#define PIN_XCVR_RXHP (BIT0) /* GPIO2[0] on P4_0 */ -#define PORT_XCVR_RXHP (GPIO2) -#define PIN_XCVR_B1 (BIT9) /* GPIO2[9] on P5_0 */ -#define PIN_XCVR_B2 (BIT10) /* GPIO2[10] on P5_1 */ -#define PIN_XCVR_B3 (BIT11) /* GPIO2[11] on P5_2 */ -#define PIN_XCVR_B4 (BIT12) /* GPIO2[12] on P5_3 */ -#define PIN_XCVR_B5 (BIT13) /* GPIO2[13] on P5_4 */ -#define PIN_XCVR_B6 (BIT14) /* GPIO2[14] on P5_5 */ -#define PIN_XCVR_B7 (BIT15) /* GPIO2[15] on P5_6 */ -#define PORT_XCVR_B (GPIO2) -#endif - -#define PIN_AD_CS (BIT7) /* GPIO2[7] on P5_7 */ -#define PORT_AD_CS (GPIO2) /* PORT for AD_CS */ - -#ifdef JELLYBEAN -#define PIN_MIXER_ENX (BIT8) /* GPIO3[8] on P7_0 */ -#define PORT_MIXER_ENX (GPIO3) -#define PIN_MIXER_SCLK (BIT9) /* GPIO3[9] on P7_1 */ -#define PORT_MIXER_SCLK (GPIO3) -#define PIN_MIXER_SDATA (BIT10) /* GPIO3[10] on P7_2 */ -#define PORT_MIXER_SDATA (GPIO3) -#define PIN_MIXER_RESETX (BIT11) /* GPIO3[11] on P7_3 */ -#define PORT_MIXER_RESETX (GPIO3) -#endif -#if (defined JAWBREAKER || defined HACKRF_ONE) -#define PIN_MIXER_ENX (BIT13) /* GPIO2[13] on P5_4 */ -#define PORT_MIXER_ENX (GPIO2) -#define PIN_MIXER_SCLK (BIT6) /* GPIO5[6] on P2_6 */ -#define PORT_MIXER_SCLK (GPIO5) -#define PIN_MIXER_SDATA (BIT3) /* GPIO3[3] on P6_4 */ -#define PORT_MIXER_SDATA (GPIO3) -#define PIN_MIXER_RESETX (BIT14) /* GPIO2[14] on P5_5 */ -#define PORT_MIXER_RESETX (GPIO2) -#endif - -#ifdef JAWBREAKER -#define PIN_RF_LDO_ENABLE (BIT9) /* GPIO2[9] on P5_0 */ -#define PORT_RF_LDO_ENABLE (GPIO2) /* PORT for RF_LDO_ENABLE */ -#endif - -#ifdef HACKRF_ONE -#define PIN_NO_VAA_ENABLE (BIT9) /* GPIO2[9] on P5_0 */ -#define PORT_NO_VAA_ENABLE (GPIO2) /* PORT for NO_VAA_ENABLE */ -#endif - -#define PIN_FLASH_HOLD (BIT14) /* GPIO1[14] on P3_4 */ -#define PIN_FLASH_WP (BIT15) /* GPIO1[15] on P3_5 */ -#define PORT_FLASH (GPIO1) -#define PIN_SSP0_SSEL (BIT11) /* GPIO5[11] on P3_8 */ -#define PORT_SSP0_SSEL (GPIO5) - -/* RF switch control */ -#ifdef HACKRF_ONE -#define PIN_HP (GPIOPIN0) /* GPIO2[0] on P4_0 */ -#define PORT_HP (GPIO2) -#define PIN_LP (GPIOPIN10) /* GPIO2[10] on P5_1 */ -#define PORT_LP (GPIO2) -#define PIN_TX_MIX_BP (GPIOPIN11) /* GPIO2[11] on P5_2 */ -#define PORT_TX_MIX_BP (GPIO2) -#define PIN_NO_MIX_BYPASS (GPIOPIN0) /* GPIO1[0] on P1_7 */ -#define PORT_NO_MIX_BYPASS (GPIO1) -#define PIN_RX_MIX_BP (GPIOPIN12) /* GPIO2[12] on P5_3 */ -#define PORT_RX_MIX_BP (GPIO2) -#define PIN_TX_AMP (GPIOPIN15) /* GPIO2[15] on P5_6 */ -#define PORT_TX_AMP (GPIO2) -#define PIN_TX (GPIOPIN15) /* GPIO5[15] on P6_7 */ -#define PORT_TX (GPIO5) -#define PIN_MIX_BYPASS (GPIOPIN16) /* GPIO5[16] on P6_8 */ -#define PORT_MIX_BYPASS (GPIO5) -#define PIN_RX (GPIOPIN5) /* GPIO5[5] on P2_5 */ -#define PORT_RX (GPIO5) -#define PIN_NO_TX_AMP_PWR (GPIOPIN5) /* GPIO3[5] on P6_9 */ -#define PORT_NO_TX_AMP_PWR (GPIO3) -#define PIN_AMP_BYPASS (GPIOPIN14) /* GPIO0[14] on P2_10 */ -#define PORT_AMP_BYPASS (GPIO0) -#define PIN_RX_AMP (GPIOPIN11) /* GPIO1[11] on P2_11 */ -#define PORT_RX_AMP (GPIO1) -#define PIN_NO_RX_AMP_PWR (GPIOPIN12) /* GPIO1[12] on P2_12 */ -#define PORT_NO_RX_AMP_PWR (GPIO1) -#endif - -/* GPIO Input */ -#define PIN_BOOT0 (BIT8) /* GPIO0[8] on P1_1 */ -#define PIN_BOOT1 (BIT9) /* GPIO0[9] on P1_2 */ -#define PIN_BOOT2 (BIT7) /* GPIO5[7] on P2_8 */ -#define PIN_BOOT3 (BIT10) /* GPIO1[10] on P2_9 */ - -/* CPLD JTAG interface GPIO pins */ -#define PIN_CPLD_TDO (GPIOPIN18) -#define PORT_CPLD_TDO (GPIO5) -#define PIN_CPLD_TCK (GPIOPIN0) -#define PORT_CPLD_TCK (GPIO3) -#ifdef HACKRF_ONE -#define PIN_CPLD_TMS (GPIOPIN4) -#define PORT_CPLD_TMS (GPIO3) -#define PIN_CPLD_TDI (GPIOPIN1) -#define PORT_CPLD_TDI (GPIO3) -#else -#define PIN_CPLD_TMS (GPIOPIN1) -#define PORT_CPLD_TMS (GPIO3) -#define PIN_CPLD_TDI (GPIOPIN4) -#define PORT_CPLD_TDI (GPIO3) -#endif - -/* Read GPIO Pin */ -#define GPIO_STATE(port, pin) ((GPIO_PIN(port) & (pin)) == (pin)) -#define BOOT0_STATE GPIO_STATE(GPIO0, PIN_BOOT0) -#define BOOT1_STATE GPIO_STATE(GPIO0, PIN_BOOT1) -#define BOOT2_STATE GPIO_STATE(GPIO5, PIN_BOOT2) -#define BOOT3_STATE GPIO_STATE(GPIO1, PIN_BOOT3) -#define MIXER_SDATA_STATE GPIO_STATE(PORT_MIXER_SDATA, PIN_MIXER_SDATA) -#define CPLD_TDO_STATE GPIO_STATE(PORT_CPLD_TDO, PIN_CPLD_TDO) - -/* TODO add other Pins */ - typedef enum { TRANSCEIVER_MODE_OFF = 0, TRANSCEIVER_MODE_RX = 1, @@ -352,10 +227,23 @@ typedef enum { 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_pll1_low_speed(void); void cpu_clock_pll1_max_speed(void); -void ssp1_init(void); void ssp1_set_mode_max2837(void); void ssp1_set_mode_max5864(void); @@ -373,6 +261,16 @@ void enable_rf_power(void); void disable_rf_power(void); #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 } #endif diff --git a/firmware/common/i2c_bus.c b/firmware/common/i2c_bus.c new file mode 100644 index 00000000..7b5497e0 --- /dev/null +++ b/firmware/common/i2c_bus.c @@ -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); +} diff --git a/firmware/common/i2c_bus.h b/firmware/common/i2c_bus.h new file mode 100644 index 00000000..04b83499 --- /dev/null +++ b/firmware/common/i2c_bus.h @@ -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 +#include + +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__*/ diff --git a/firmware/common/i2c_lpc.c b/firmware/common/i2c_lpc.c new file mode 100644 index 00000000..f7bf4393 --- /dev/null +++ b/firmware/common/i2c_lpc.c @@ -0,0 +1,62 @@ +/* + * Copyright 2012 Michael Ossmann + * Copyright 2012 Jared Boone + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "i2c_lpc.h" + +#include + +/* 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 +#include + +#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__*/ diff --git a/firmware/common/max2837.c b/firmware/common/max2837.c index 020763d6..d99b740f 100644 --- a/firmware/common/max2837.c +++ b/firmware/common/max2837.c @@ -1,3 +1,25 @@ +/* + * Copyright 2012 Will Code? (TODO: Proper attribution) + * Copyright 2014 Jared Boone + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + /* * 'gcc -DTEST -DDEBUG -O2 -o test max2837.c' prints out what test * program would do if it had a real spi library @@ -11,19 +33,8 @@ #include "max2837.h" #include "max2837_regs.def" // private register def macros -#if (defined DEBUG || defined BUS_PIRATE) -#include -#define LOG printf -#else -#define LOG(x,...) -#include -#include -#include -#include "hackrf_core.h" -#endif - /* Default register values. */ -static uint16_t max2837_regs_default[MAX2837_NUM_REGS] = { +static const uint16_t max2837_regs_default[MAX2837_NUM_REGS] = { 0x150, /* 0 */ 0x002, /* 1 */ 0x1f4, /* 2 */ @@ -62,283 +73,130 @@ static uint16_t max2837_regs_default[MAX2837_NUM_REGS] = { 0x080, /* 30 */ 0x000 }; /* 31 */ -uint16_t max2837_regs[MAX2837_NUM_REGS]; - -/* Mark all regsisters dirty so all will be written at init. */ -uint32_t max2837_regs_dirty = 0xffffffff; - /* Set up all registers according to defaults specified in docs. */ -void max2837_init(void) +static void max2837_init(max2837_driver_t* const drv) { - LOG("# max2837_init\n"); - memcpy(max2837_regs, max2837_regs_default, sizeof(max2837_regs)); - max2837_regs_dirty = 0xffffffff; + drv->target_init(drv); + max2837_set_mode(drv, MAX2837_MODE_SHUTDOWN); + + memcpy(drv->regs, max2837_regs_default, sizeof(drv->regs)); + drv->regs_dirty = 0xffffffff; /* 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 our own default register configuration. */ -void max2837_setup(void) +void max2837_setup(max2837_driver_t* const drv) { - LOG("# max2837_setup\n"); -#if !defined TEST - /* Configure XCVR_CTL GPIO pins. */ -#ifdef JELLYBEAN - scu_pinmux(SCU_XCVR_RXHP, SCU_GPIO_FAST); - scu_pinmux(SCU_XCVR_B1, SCU_GPIO_FAST); - scu_pinmux(SCU_XCVR_B2, SCU_GPIO_FAST); - scu_pinmux(SCU_XCVR_B3, SCU_GPIO_FAST); - scu_pinmux(SCU_XCVR_B4, SCU_GPIO_FAST); - scu_pinmux(SCU_XCVR_B5, SCU_GPIO_FAST); - scu_pinmux(SCU_XCVR_B6, SCU_GPIO_FAST); - scu_pinmux(SCU_XCVR_B7, SCU_GPIO_FAST); -#endif - scu_pinmux(SCU_XCVR_ENABLE, SCU_GPIO_FAST); - scu_pinmux(SCU_XCVR_RXENABLE, SCU_GPIO_FAST); - scu_pinmux(SCU_XCVR_TXENABLE, SCU_GPIO_FAST); - - /* Set GPIO pins as outputs. */ - GPIO2_DIR |= (PIN_XCVR_ENABLE | PIN_XCVR_RXENABLE | PIN_XCVR_TXENABLE); -#ifdef JELLYBEAN - GPIO_DIR(PORT_XCVR_RXHP) |= PIN_XCVR_RXHP; - GPIO_DIR(PORT_XCVR_B) |= - PIN_XCVR_B1 - | PIN_XCVR_B2 - | PIN_XCVR_B3 - | PIN_XCVR_B4 - | PIN_XCVR_B5 - | PIN_XCVR_B6 - | PIN_XCVR_B7 - ; -#endif - - max2837_mode_shutdown(); -#ifdef JELLYBEAN - gpio_set(PORT_XCVR_RXHP, PIN_XCVR_RXHP); - gpio_set(PORT_XCVR_B, - PIN_XCVR_B1 - | PIN_XCVR_B2 - | PIN_XCVR_B3 - | PIN_XCVR_B4 - | PIN_XCVR_B5 - | PIN_XCVR_B6 - | PIN_XCVR_B7 - ); -#endif -#endif - - max2837_init(); - LOG("# max2837_init done\n"); - + max2837_init(drv); + /* Use SPI control instead of B1-B7 pins for gain settings. */ - set_MAX2837_TXVGA_GAIN_SPI_EN(1); - set_MAX2837_TXVGA_GAIN_MSB_SPI_EN(1); + set_MAX2837_TXVGA_GAIN_SPI_EN(drv, 1); + set_MAX2837_TXVGA_GAIN_MSB_SPI_EN(drv, 1); //set_MAX2837_TXVGA_GAIN(0x3f); /* maximum attenuation */ - set_MAX2837_TXVGA_GAIN(0x00); /* minimum attenuation */ - set_MAX2837_VGAMUX_enable(1); - set_MAX2837_VGA_EN(1); - set_MAX2837_HPC_RXGAIN_EN(0); - set_MAX2837_HPC_STOP(MAX2837_STOP_1K); - set_MAX2837_LNAgain_SPI_EN(1); - set_MAX2837_LNAgain(MAX2837_LNAgain_MAX); /* maximum gain */ - set_MAX2837_VGAgain_SPI_EN(1); - set_MAX2837_VGA(0x18); /* reasonable gain for noisy 2.4GHz environment */ + set_MAX2837_TXVGA_GAIN(drv, 0x00); /* minimum attenuation */ + set_MAX2837_VGAMUX_enable(drv, 1); + set_MAX2837_VGA_EN(drv, 1); + set_MAX2837_HPC_RXGAIN_EN(drv, 0); + set_MAX2837_HPC_STOP(drv, MAX2837_STOP_1K); + set_MAX2837_LNAgain_SPI_EN(drv, 1); + set_MAX2837_LNAgain(drv, MAX2837_LNAgain_MAX); /* maximum gain */ + set_MAX2837_VGAgain_SPI_EN(drv, 1); + set_MAX2837_VGA(drv, 0x18); /* reasonable gain for noisy 2.4GHz environment */ /* 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 */ - set_MAX2837_LPF_EN(1); - set_MAX2837_ModeCtrl(MAX2837_ModeCtrl_RxLPF); - set_MAX2837_FT(MAX2837_FT_5M); + set_MAX2837_LPF_EN(drv, 1); + set_MAX2837_ModeCtrl(drv, MAX2837_ModeCtrl_RxLPF); + set_MAX2837_FT(drv, MAX2837_FT_5M); - max2837_regs_commit(); + max2837_regs_commit(drv); } -/* SPI register read. */ -uint16_t max2837_spi_read(uint8_t r) { - gpio_clear(PORT_XCVR_CS, PIN_XCVR_CS); - const uint16_t value = ssp_transfer(SSP1_NUM, (uint16_t)((1 << 15) | (r << 10))); - gpio_set(PORT_XCVR_CS, PIN_XCVR_CS); +static uint16_t max2837_read(max2837_driver_t* const drv, uint8_t r) { + uint16_t value = (1 << 15) | (r << 10); + spi_bus_transfer(drv->bus, &value, 1); return value & 0x3ff; } -/* SPI register write */ -void max2837_spi_write(uint8_t r, uint16_t v) { - -#ifdef BUS_PIRATE - LOG("{0x%02x 0x%02x]\n", 0x00 | ((uint16_t)r<<2) | ((v>>8) & 0x3), - v & 0xff); -#elif DEBUG - LOG("0x%03x -> reg%d\n", v, r); -#else - gpio_clear(PORT_XCVR_CS, PIN_XCVR_CS); - ssp_transfer(SSP1_NUM, (uint16_t)((r << 10) | (v & 0x3ff))); - gpio_set(PORT_XCVR_CS, PIN_XCVR_CS); -#endif +static void max2837_write(max2837_driver_t* const drv, uint8_t r, uint16_t v) { + uint16_t value = (r << 10) | (v & 0x3ff); + spi_bus_transfer(drv->bus, &value, 1); } -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) { - max2837_regs[r] = max2837_spi_read(r); + if ((drv->regs_dirty >> r) & 0x1) { + 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; - max2837_spi_write(r, v); - MAX2837_REG_SET_CLEAN(r); + drv->regs[r] = v; + max2837_write(drv, r, v); + MAX2837_REG_SET_CLEAN(drv, r); } -/* This functions should not be needed, and might be confusing. DELETE. */ -void max2837_regs_read(void) +static inline void max2837_reg_commit(max2837_driver_t* const drv, uint8_t r) { - ; + max2837_reg_write(drv, r, drv->regs[r]); } -static inline void max2837_reg_commit(uint8_t r) -{ - max2837_reg_write(r,max2837_regs[r]); -} - -void max2837_regs_commit(void) +void max2837_regs_commit(max2837_driver_t* const drv) { int r; for(r = 0; r < MAX2837_NUM_REGS; r++) { - if ((max2837_regs_dirty >> r) & 0x1) { - max2837_reg_commit(r); + if ((drv->regs_dirty >> r) & 0x1) { + max2837_reg_commit(drv, r); } } } -void max2837_mode_shutdown(void) { - /* All circuit blocks are powered down, except the 4-wire serial bus - * and its internal programmable registers. - */ - gpio_clear(PORT_XCVR_ENABLE, - (PIN_XCVR_ENABLE | PIN_XCVR_RXENABLE | PIN_XCVR_TXENABLE)); +void max2837_set_mode(max2837_driver_t* const drv, const max2837_mode_t new_mode) { + drv->set_mode(drv, new_mode); } -void max2837_mode_standby(void) { - /* Used to enable the frequency synthesizer block while the rest of the - * device is powered down. In this mode, PLL, VCO, and LO generator - * are on, so that Tx or Rx modes can be quickly enabled from this mode. - * These and other blocks can be selectively enabled in this mode. - */ - gpio_clear(PORT_XCVR_ENABLE, (PIN_XCVR_RXENABLE | PIN_XCVR_TXENABLE)); - gpio_set(PORT_XCVR_ENABLE, PIN_XCVR_ENABLE); +max2837_mode_t max2837_mode(max2837_driver_t* const drv) { + return drv->mode; } -void max2837_mode_tx(void) { - /* All Tx circuit blocks are powered on. The external PA is powered on - * after a programmable delay using the on-chip PA bias DAC. The slow- - * charging Rx circuits are in a precharged “idle-off” state for fast - * Tx-to-Rx turnaround time. - */ - gpio_clear(PORT_XCVR_ENABLE, PIN_XCVR_RXENABLE); - gpio_set(PORT_XCVR_ENABLE, - (PIN_XCVR_ENABLE | PIN_XCVR_TXENABLE)); -} - -void max2837_mode_rx(void) { - /* All Rx circuit blocks are powered on and active. Antenna signal is - * applied; RF is downconverted, filtered, and buffered at Rx BB I and Q - * outputs. The slow- charging Tx circuits are in a precharged “idle-off” - * state for fast Rx-to-Tx turnaround time. - */ - gpio_clear(PORT_XCVR_ENABLE, PIN_XCVR_TXENABLE); - gpio_set(PORT_XCVR_ENABLE, - (PIN_XCVR_ENABLE | PIN_XCVR_RXENABLE)); -} - -max2837_mode_t max2837_mode(void) { - if( gpio_get(PORT_XCVR_ENABLE, PIN_XCVR_ENABLE) ) { - if( gpio_get(PORT_XCVR_ENABLE, PIN_XCVR_TXENABLE) ) { - return MAX2837_MODE_TX; - } else if( gpio_get(PORT_XCVR_ENABLE, PIN_XCVR_RXENABLE) ) { - return MAX2837_MODE_RX; - } else { - return MAX2837_MODE_STANDBY; - } - } else { - return MAX2837_MODE_SHUTDOWN; - } -} - -void max2837_set_mode(const max2837_mode_t new_mode) { - switch(new_mode) { - case MAX2837_MODE_SHUTDOWN: - max2837_mode_shutdown(); - break; - - case MAX2837_MODE_STANDBY: - max2837_mode_standby(); - break; - - case MAX2837_MODE_TX: - max2837_mode_tx(); - break; - - case MAX2837_MODE_RX: - max2837_mode_rx(); - break; - - default: - break; - } -} - -void max2837_start(void) +void max2837_start(max2837_driver_t* const drv) { - LOG("# max2837_start\n"); - set_MAX2837_EN_SPI(1); - max2837_regs_commit(); -#if !defined TEST - max2837_mode_standby(); -#endif + set_MAX2837_EN_SPI(drv, 1); + max2837_regs_commit(drv); + max2837_set_mode(drv, MAX2837_MODE_STANDBY); } -void max2837_tx(void) +void max2837_tx(max2837_driver_t* const drv) { - LOG("# max2837_tx\n"); -#if !defined TEST - - set_MAX2837_ModeCtrl(MAX2837_ModeCtrl_TxLPF); - max2837_regs_commit(); - max2837_mode_tx(); -#endif + set_MAX2837_ModeCtrl(drv, MAX2837_ModeCtrl_TxLPF); + max2837_regs_commit(drv); + max2837_set_mode(drv, MAX2837_MODE_TX); } -void max2837_rx(void) +void max2837_rx(max2837_driver_t* const drv) { - LOG("# max2837_rx\n"); - - set_MAX2837_ModeCtrl(MAX2837_ModeCtrl_RxLPF); - max2837_regs_commit(); - -#if !defined TEST - max2837_mode_rx(); -#endif + set_MAX2837_ModeCtrl(drv, MAX2837_ModeCtrl_RxLPF); + max2837_regs_commit(drv); + max2837_set_mode(drv, MAX2837_MODE_RX); } -void max2837_stop(void) +void max2837_stop(max2837_driver_t* const drv) { - LOG("# max2837_stop\n"); - set_MAX2837_EN_SPI(0); - max2837_regs_commit(); -#if !defined TEST - max2837_mode_shutdown(); -#endif + set_MAX2837_EN_SPI(drv, 0); + max2837_regs_commit(drv); + max2837_set_mode(drv, MAX2837_MODE_SHUTDOWN); } -void max2837_set_frequency(uint32_t freq) +void max2837_set_frequency(max2837_driver_t* const drv, uint32_t freq) { uint8_t band; uint8_t lna_band; @@ -366,9 +224,6 @@ void max2837_set_frequency(uint32_t freq) lna_band = MAX2837_LNAband_2_6; } - LOG("# max2837_set_frequency %ld, band %d, lna band %d\n", - freq, band, lna_band); - /* ASSUME 40MHz PLL. Ratio = F*(4/3)/40,000,000 = F/30,000,000 */ div_int = freq / 30000000; div_rem = freq % 30000000; @@ -382,22 +237,21 @@ void max2837_set_frequency(uint32_t freq) div_rem -= div_cmp; } } - LOG("# int %ld, frac %ld\n", div_int, div_frac); /* Band settings */ - set_MAX2837_LOGEN_BSW(band); - set_MAX2837_LNAband(lna_band); + set_MAX2837_LOGEN_BSW(drv, band); + set_MAX2837_LNAband(drv, lna_band); /* Write order matters here, so commit INT and FRAC_HI before * committing FRAC_LO, which is the trigger for VCO * auto-select. TODO - it's cleaner this way, but it would be * faster to explicitly commit the registers explicitly so the * dirty bits aren't scanned twice. */ - set_MAX2837_SYN_INT(div_int); - set_MAX2837_SYN_FRAC_HI((div_frac >> 10) & 0x3ff); - max2837_regs_commit(); - set_MAX2837_SYN_FRAC_LO(div_frac & 0x3ff); - max2837_regs_commit(); + set_MAX2837_SYN_INT(drv, div_int); + set_MAX2837_SYN_FRAC_HI(drv, (div_frac >> 10) & 0x3ff); + max2837_regs_commit(drv); + set_MAX2837_SYN_FRAC_LO(drv, div_frac & 0x3ff); + max2837_regs_commit(drv); } typedef struct { @@ -425,7 +279,7 @@ static const max2837_ft_t max2837_ft[] = { { 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; while( p->bandwidth_hz != 0 ) { 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 ) { - set_MAX2837_FT(p->ft); - max2837_regs_commit(); + set_MAX2837_FT(drv, p->ft); + max2837_regs_commit(drv); return true; } else { 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; switch(gain_db){ case 40: @@ -467,21 +321,21 @@ bool max2837_set_lna_gain(const uint32_t gain_db) { default: return false; } - set_MAX2837_LNAgain(val); - max2837_reg_commit(1); + set_MAX2837_LNAgain(drv, val); + max2837_reg_commit(drv, 1); 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 */ return false; - set_MAX2837_VGA( 31-(gain_db >> 1) ); - max2837_reg_commit(5); + set_MAX2837_VGA(drv, 31-(gain_db >> 1) ); + max2837_reg_commit(drv, 5); 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; if(gain_db <16){ val = 31-gain_db; @@ -490,18 +344,7 @@ bool max2837_set_txvga_gain(const uint32_t gain_db) { val = 31-(gain_db-16); } - set_MAX2837_TXVGA_GAIN(val); - max2837_reg_commit(29); + set_MAX2837_TXVGA_GAIN(drv, val); + max2837_reg_commit(drv, 29); return true; } - -#ifdef TEST -int main(int ac, char **av) -{ - max2837_setup(); - max2837_set_frequency(2441000000); - max2837_start(); - max2837_tx(); - max2837_stop(); -} -#endif //TEST diff --git a/firmware/common/max2837.h b/firmware/common/max2837.h index 582a0966..a9962fad 100644 --- a/firmware/common/max2837.h +++ b/firmware/common/max2837.h @@ -1,42 +1,38 @@ +/* + * Copyright 2012 Will Code? (TODO: Proper attribution) + * Copyright 2014 Jared Boone + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + #ifndef __MAX2837_H #define __MAX2837_H #include #include -/* 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. */ #define MAX2837_NUM_REGS 32 #define MAX2837_DATA_REGS_MAX_VALUE 1024 -/* TODO - these externs will be local to max2837.c ... don't define here? */ -extern uint16_t max2837_regs[MAX2837_NUM_REGS]; -extern uint32_t max2837_regs_dirty; - -#define MAX2837_REG_SET_CLEAN(r) max2837_regs_dirty &= ~(1UL<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 * changed. This makes sure that write that have side effects, * e.g. frequency setting, are not skipped. */ /* n=name, r=regnum, o=offset (bits from LSB), l=length (bits) */ #define __MREG__(n,r,o,l) \ -static inline uint16_t get_##n(void) { \ - return (max2837_regs[r] >> (o-l+1)) & ((1<regs[r] >> (o-l+1)) & ((1<regs[r] &= ~(((1<regs[r] |= ((v&((1< + * + * 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 +#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; +} diff --git a/firmware/common/max2837_target.h b/firmware/common/max2837_target.h new file mode 100644 index 00000000..0fc24ec9 --- /dev/null +++ b/firmware/common/max2837_target.h @@ -0,0 +1,31 @@ +/* + * Copyright 2012 Will Code? (TODO: Proper attribution) + * Copyright 2014 Jared Boone + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __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 diff --git a/firmware/common/max5864.c b/firmware/common/max5864.c index 094ed700..ed704a2d 100644 --- a/firmware/common/max5864.c +++ b/firmware/common/max5864.c @@ -21,16 +21,18 @@ #include -#include -#include - -#include "hackrf_core.h" #include "max5864.h" -void max5864_spi_write(uint_fast8_t value) { - gpio_clear(PORT_AD_CS, PIN_AD_CS); - ssp_transfer(SSP1_NUM, value); - gpio_set(PORT_AD_CS, PIN_AD_CS); +static void max5864_write(max5864_driver_t* const drv, uint8_t value) { + spi_bus_transfer(drv->bus, &value, 1); +} + +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": @@ -39,9 +41,9 @@ void max5864_spi_write(uint_fast8_t value) { * ADCs: off (bus is tri-stated) * 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": @@ -50,9 +52,9 @@ void max5864_shutdown() * ADCs: off (bus is tri-stated) * 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": @@ -61,9 +63,9 @@ void max5864_standby() * ADCs: off (bus is tri-stated) * 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": @@ -72,9 +74,9 @@ void max5864_idle() * ADCs: on * 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": @@ -83,9 +85,9 @@ void max5864_rx() * ADCs: off (bus is tri-stated) * 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": @@ -94,7 +96,7 @@ void max5864_tx() * ADCs: on * DACs: on */ -void max5864_xcvr() +void max5864_xcvr(max5864_driver_t* const drv) { - max5864_spi_write(0x04); + max5864_write(drv, 0x04); } diff --git a/firmware/common/max5864.h b/firmware/common/max5864.h index 72519645..aba4357d 100644 --- a/firmware/common/max5864.h +++ b/firmware/common/max5864.h @@ -22,11 +22,23 @@ #ifndef __MAX5864_H #define __MAX5864_H -void max5864_shutdown(); -void max5864_standby(); -void max5864_idle(); -void max5864_rx(); -void max5864_tx(); -void max5864_xcvr(); +#include "spi_bus.h" + +struct max5864_driver_t; +typedef struct max5864_driver_t max5864_driver_t; + +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 diff --git a/firmware/common/max5864_target.c b/firmware/common/max5864_target.c new file mode 100644 index 00000000..7a49ec24 --- /dev/null +++ b/firmware/common/max5864_target.c @@ -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 +#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); +} diff --git a/firmware/common/max5864_target.h b/firmware/common/max5864_target.h new file mode 100644 index 00000000..be684e2c --- /dev/null +++ b/firmware/common/max5864_target.h @@ -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__*/ diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index f33bebb1..14f83e0e 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -22,7 +22,6 @@ #include "rf_path.h" -#include #include #include @@ -84,58 +83,58 @@ uint8_t switchctrl = SWITCHCTRL_SAFE; #define SWITCHCTRL_ANT_PWR (1 << 6) /* turn on antenna port power */ #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) { - gpio_set(PORT_TX, PIN_TX); - gpio_clear(PORT_RX, PIN_RX); + gpio_set(rf_path->gpio_tx); + gpio_clear(rf_path->gpio_rx); } else { - gpio_clear(PORT_TX, PIN_TX); - gpio_set(PORT_RX, PIN_RX); + gpio_clear(rf_path->gpio_tx); + gpio_set(rf_path->gpio_rx); } if (ctrl & SWITCHCTRL_MIX_BYPASS) { - gpio_set(PORT_MIX_BYPASS, PIN_MIX_BYPASS); - gpio_clear(PORT_NO_MIX_BYPASS, PIN_NO_MIX_BYPASS); + gpio_set(rf_path->gpio_mix_bypass); + gpio_clear(rf_path->gpio_no_mix_bypass); if (ctrl & SWITCHCTRL_TX) { - gpio_set(PORT_TX_MIX_BP, PIN_TX_MIX_BP); - gpio_clear(PORT_RX_MIX_BP, PIN_RX_MIX_BP); + gpio_set(rf_path->gpio_tx_mix_bp); + gpio_clear(rf_path->gpio_rx_mix_bp); } else { - gpio_clear(PORT_TX_MIX_BP, PIN_TX_MIX_BP); - gpio_set(PORT_RX_MIX_BP, PIN_RX_MIX_BP); + gpio_clear(rf_path->gpio_tx_mix_bp); + gpio_set(rf_path->gpio_rx_mix_bp); } } else { - gpio_clear(PORT_MIX_BYPASS, PIN_MIX_BYPASS); - gpio_set(PORT_NO_MIX_BYPASS, PIN_NO_MIX_BYPASS); - gpio_clear(PORT_TX_MIX_BP, PIN_TX_MIX_BP); - gpio_clear(PORT_RX_MIX_BP, PIN_RX_MIX_BP); + gpio_clear(rf_path->gpio_mix_bypass); + gpio_set(rf_path->gpio_no_mix_bypass); + gpio_clear(rf_path->gpio_tx_mix_bp); + gpio_clear(rf_path->gpio_rx_mix_bp); } if (ctrl & SWITCHCTRL_HP) { - gpio_set(PORT_HP, PIN_HP); - gpio_clear(PORT_LP, PIN_LP); + gpio_set(rf_path->gpio_hp); + gpio_clear(rf_path->gpio_lp); } else { - gpio_clear(PORT_HP, PIN_HP); - gpio_set(PORT_LP, PIN_LP); + gpio_clear(rf_path->gpio_hp); + gpio_set(rf_path->gpio_lp); } if (ctrl & SWITCHCTRL_AMP_BYPASS) { - gpio_set(PORT_AMP_BYPASS, PIN_AMP_BYPASS); - gpio_clear(PORT_TX_AMP, PIN_TX_AMP); - gpio_set(PORT_NO_TX_AMP_PWR, PIN_NO_TX_AMP_PWR); - gpio_clear(PORT_RX_AMP, PIN_RX_AMP); - gpio_set(PORT_NO_RX_AMP_PWR, PIN_NO_RX_AMP_PWR); + gpio_set(rf_path->gpio_amp_bypass); + gpio_clear(rf_path->gpio_tx_amp); + gpio_set(rf_path->gpio_no_tx_amp_pwr); + gpio_clear(rf_path->gpio_rx_amp); + gpio_set(rf_path->gpio_no_rx_amp_pwr); } else if (ctrl & SWITCHCTRL_TX) { - gpio_clear(PORT_AMP_BYPASS, PIN_AMP_BYPASS); - gpio_set(PORT_TX_AMP, PIN_TX_AMP); - gpio_clear(PORT_NO_TX_AMP_PWR, PIN_NO_TX_AMP_PWR); - gpio_clear(PORT_RX_AMP, PIN_RX_AMP); - gpio_set(PORT_NO_RX_AMP_PWR, PIN_NO_RX_AMP_PWR); + gpio_clear(rf_path->gpio_amp_bypass); + gpio_set(rf_path->gpio_tx_amp); + gpio_clear(rf_path->gpio_no_tx_amp_pwr); + gpio_clear(rf_path->gpio_rx_amp); + gpio_set(rf_path->gpio_no_rx_amp_pwr); } else { - gpio_clear(PORT_AMP_BYPASS, PIN_AMP_BYPASS); - gpio_clear(PORT_TX_AMP, PIN_TX_AMP); - gpio_set(PORT_NO_TX_AMP_PWR, PIN_NO_TX_AMP_PWR); - gpio_set(PORT_RX_AMP, PIN_RX_AMP); - gpio_clear(PORT_NO_RX_AMP_PWR, PIN_NO_RX_AMP_PWR); + gpio_clear(rf_path->gpio_amp_bypass); + gpio_clear(rf_path->gpio_tx_amp); + gpio_set(rf_path->gpio_no_tx_amp_pwr); + gpio_set(rf_path->gpio_rx_amp); + gpio_clear(rf_path->gpio_no_rx_amp_pwr); } /* @@ -144,29 +143,29 @@ static void switchctrl_set_hackrf_one(uint8_t ctrl) { * is unset: */ 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) - 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) { - rffc5071_set_gpo(0x00); /* turn on antenna power by clearing GPO1 */ + rffc5071_set_gpo(&rffc5072, 0x00); /* turn on antenna power by clearing GPO1 */ } 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 -static void switchctrl_set(const uint8_t gpo) { +static void switchctrl_set(rf_path_t* const rf_path, const uint8_t gpo) { #ifdef JAWBREAKER - rffc5071_set_gpo(gpo); + rffc5071_set_gpo(&rffc5072, gpo); #elif HACKRF_ONE - switchctrl_set_hackrf_one(gpo); + switchctrl_set_hackrf_one(rf_path, gpo); #else (void)gpo; #endif } -void rf_path_pin_setup() { +void rf_path_pin_setup(rf_path_t* const rf_path) { #ifdef HACKRF_ONE /* Configure RF switch control signals */ 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); /* Configure RF switch control signals as outputs */ - GPIO0_DIR |= PIN_AMP_BYPASS; - GPIO1_DIR |= (PIN_NO_MIX_BYPASS | PIN_RX_AMP | PIN_NO_RX_AMP_PWR); - GPIO2_DIR |= (PIN_HP | PIN_LP | PIN_TX_MIX_BP | PIN_RX_MIX_BP | PIN_TX_AMP); - GPIO3_DIR |= PIN_NO_TX_AMP_PWR; - GPIO5_DIR |= (PIN_TX | PIN_MIX_BYPASS | PIN_RX); + gpio_output(rf_path->gpio_amp_bypass); + gpio_output(rf_path->gpio_no_mix_bypass); + gpio_output(rf_path->gpio_rx_amp); + gpio_output(rf_path->gpio_no_rx_amp_pwr); + 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 * power and enable both amp bypass and mixer bypass. */ - switchctrl_set(SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_MIX_BYPASS); - - /* Configure RF power supply (VAA) switch control signal as output */ - GPIO_DIR(PORT_NO_VAA_ENABLE) |= PIN_NO_VAA_ENABLE; - - /* Safe state: start with VAA turned off: */ - disable_rf_power(); + switchctrl_set(rf_path, SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_MIX_BYPASS); #endif } -void rf_path_init(void) { +void rf_path_init(rf_path_t* const rf_path) { ssp1_set_mode_max5864(); - max5864_shutdown(); + max5864_setup(&max5864); + max5864_shutdown(&max5864); ssp1_set_mode_max2837(); - max2837_setup(); - max2837_start(); + max2837_setup(&max2837); + max2837_start(&max2837); - rffc5071_setup(); - switchctrl_set(switchctrl); + rffc5071_setup(&rffc5072); + 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. */ - 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) { case RF_PATH_DIRECTION_TX: - switchctrl |= SWITCHCTRL_TX; - if( (switchctrl & SWITCHCTRL_AMP_BYPASS) == 0 ) { + rf_path->switchctrl |= SWITCHCTRL_TX; + if( (rf_path->switchctrl & SWITCHCTRL_AMP_BYPASS) == 0 ) { /* 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(); - if( switchctrl & SWITCHCTRL_MIX_BYPASS ) { - rffc5071_disable(); + rffc5071_tx(&rffc5072); + if( rf_path->switchctrl & SWITCHCTRL_MIX_BYPASS ) { + rffc5071_disable(&rffc5072); } else { - rffc5071_enable(); + rffc5071_enable(&rffc5072); } ssp1_set_mode_max5864(); - max5864_tx(); + max5864_tx(&max5864); ssp1_set_mode_max2837(); - max2837_tx(); - sgpio_configure(SGPIO_DIRECTION_TX); + max2837_tx(&max2837); + sgpio_configure(&sgpio_config, SGPIO_DIRECTION_TX); break; case RF_PATH_DIRECTION_RX: - switchctrl &= ~SWITCHCTRL_TX; - if( (switchctrl & SWITCHCTRL_AMP_BYPASS) == 0 ) { + rf_path->switchctrl &= ~SWITCHCTRL_TX; + if( (rf_path->switchctrl & SWITCHCTRL_AMP_BYPASS) == 0 ) { /* 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(); - if( switchctrl & SWITCHCTRL_MIX_BYPASS ) { - rffc5071_disable(); + rffc5071_rx(&rffc5072); + if( rf_path->switchctrl & SWITCHCTRL_MIX_BYPASS ) { + rffc5071_disable(&rffc5072); } else { - rffc5071_enable(); + rffc5071_enable(&rffc5072); } ssp1_set_mode_max5864(); - max5864_rx(); + max5864_rx(&max5864); ssp1_set_mode_max2837(); - max2837_rx(); - sgpio_configure(SGPIO_DIRECTION_RX); + max2837_rx(&max2837); + sgpio_configure(&sgpio_config, SGPIO_DIRECTION_RX); break; case RF_PATH_DIRECTION_OFF: default: #ifdef HACKRF_ONE - rf_path_set_antenna(0); + rf_path_set_antenna(rf_path, 0); #endif rf_path_set_lna(0); /* Set RF path to receive direction when "off" */ - switchctrl &= ~SWITCHCTRL_TX; - rffc5071_disable(); + rf_path->switchctrl &= ~SWITCHCTRL_TX; + rffc5071_disable(&rffc5072); ssp1_set_mode_max5864(); - max5864_standby(); + max5864_standby(&max5864); ssp1_set_mode_max2837(); - max2837_set_mode(MAX2837_MODE_STANDBY); - sgpio_configure(SGPIO_DIRECTION_RX); + max2837_set_mode(&max2837, MAX2837_MODE_STANDBY); + sgpio_configure(&sgpio_config, SGPIO_DIRECTION_RX); 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) { default: case RF_PATH_FILTER_BYPASS: - switchctrl |= SWITCHCTRL_MIX_BYPASS; - rffc5071_disable(); + rf_path->switchctrl |= SWITCHCTRL_MIX_BYPASS; + rffc5071_disable(&rffc5072); break; case RF_PATH_FILTER_LOW_PASS: - switchctrl &= ~(SWITCHCTRL_HP | SWITCHCTRL_MIX_BYPASS); - rffc5071_enable(); + rf_path->switchctrl &= ~(SWITCHCTRL_HP | SWITCHCTRL_MIX_BYPASS); + rffc5071_enable(&rffc5072); break; case RF_PATH_FILTER_HIGH_PASS: - switchctrl &= ~SWITCHCTRL_MIX_BYPASS; - switchctrl |= SWITCHCTRL_HP; - rffc5071_enable(); + rf_path->switchctrl &= ~SWITCHCTRL_MIX_BYPASS; + rf_path->switchctrl |= SWITCHCTRL_HP; + rffc5071_enable(&rffc5072); 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( switchctrl & SWITCHCTRL_TX ) { + if( rf_path->switchctrl & SWITCHCTRL_TX ) { /* AMP_BYPASS=0, NO_RX_AMP_PWR=1, NO_TX_AMP_PWR=0 */ - switchctrl |= SWITCHCTRL_NO_RX_AMP_PWR; - switchctrl &= ~(SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_NO_TX_AMP_PWR); + rf_path->switchctrl |= SWITCHCTRL_NO_RX_AMP_PWR; + rf_path->switchctrl &= ~(SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_NO_TX_AMP_PWR); } else { /* AMP_BYPASS=0, NO_RX_AMP_PWR=0, NO_TX_AMP_PWR=1 */ - switchctrl |= SWITCHCTRL_NO_TX_AMP_PWR; - switchctrl &= ~(SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_NO_RX_AMP_PWR); + rf_path->switchctrl |= SWITCHCTRL_NO_TX_AMP_PWR; + rf_path->switchctrl &= ~(SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_NO_RX_AMP_PWR); } } else { /* AMP_BYPASS=1, NO_RX_AMP_PWR=1, NO_TX_AMP_PWR=1 */ - switchctrl |= SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_NO_TX_AMP_PWR | SWITCHCTRL_NO_RX_AMP_PWR; + 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 */ -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) { - switchctrl |= SWITCHCTRL_ANT_PWR; + rf_path->switchctrl |= SWITCHCTRL_ANT_PWR; } else { - switchctrl &= ~(SWITCHCTRL_ANT_PWR); + rf_path->switchctrl &= ~(SWITCHCTRL_ANT_PWR); } - switchctrl_set(switchctrl); + switchctrl_set(rf_path, rf_path->switchctrl); } diff --git a/firmware/common/rf_path.h b/firmware/common/rf_path.h index 7fe1fa79..205d3fdd 100644 --- a/firmware/common/rf_path.h +++ b/firmware/common/rf_path.h @@ -25,8 +25,7 @@ #include -void rf_path_pin_setup(void); -void rf_path_init(void); +#include "gpio.h" typedef enum { RF_PATH_DIRECTION_OFF, @@ -34,17 +33,39 @@ typedef enum { RF_PATH_DIRECTION_TX, } rf_path_direction_t; -void rf_path_set_direction(const rf_path_direction_t direction); - typedef enum { RF_PATH_FILTER_BYPASS = 0, RF_PATH_FILTER_LOW_PASS = 1, RF_PATH_FILTER_HIGH_PASS = 2, } rf_path_filter_t; -void rf_path_set_filter(const rf_path_filter_t filter); +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_set_antenna(const uint_fast8_t enable); +void rf_path_pin_setup(rf_path_t* const rf_path); +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__*/ diff --git a/firmware/common/rffc5071.c b/firmware/common/rffc5071.c index 96745eb4..71ba9f5c 100644 --- a/firmware/common/rffc5071.c +++ b/firmware/common/rffc5071.c @@ -36,19 +36,10 @@ #include "rffc5071.h" #include "rffc5071_regs.def" // private register def macros -#if (defined DEBUG) -#include -#define LOG printf -#else -#define LOG(x,...) -#include -#include -#include #include "hackrf_core.h" -#endif /* Default register values. */ -static uint16_t rffc5071_regs_default[RFFC5071_NUM_REGS] = { +static const uint16_t rffc5071_regs_default[RFFC5071_NUM_REGS] = { 0xbefa, /* 00 */ 0x4064, /* 01 */ 0x9055, /* 02 */ @@ -81,327 +72,139 @@ static uint16_t rffc5071_regs_default[RFFC5071_NUM_REGS] = { 0x1000, /* 1D */ 0x0005, /* 1E */ }; -uint16_t rffc5071_regs[RFFC5071_NUM_REGS]; - -/* Mark all regsisters dirty so all will be written at init. */ -uint32_t rffc5071_regs_dirty = 0x7fffffff; - /* Set up all registers according to defaults specified in docs. */ -void rffc5071_init(void) +void rffc5071_init(rffc5071_driver_t* const drv) { - LOG("# rffc5071_init\n"); - memcpy(rffc5071_regs, rffc5071_regs_default, sizeof(rffc5071_regs)); - rffc5071_regs_dirty = 0x7fffffff; + memcpy(drv->regs, rffc5071_regs_default, sizeof(drv->regs)); + drv->regs_dirty = 0x7fffffff; /* 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 our own default register configuration. */ -void rffc5071_setup(void) +void rffc5071_setup(rffc5071_driver_t* const drv) { - rffc5071_init(); - LOG("# rffc5071_setup\n"); -#if !defined TEST - /* Configure GPIO pins. */ - scu_pinmux(SCU_MIXER_ENX, SCU_GPIO_FAST); - scu_pinmux(SCU_MIXER_SCLK, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - scu_pinmux(SCU_MIXER_SDATA, SCU_GPIO_FAST); - scu_pinmux(SCU_MIXER_RESETX, SCU_GPIO_FAST); + gpio_set(drv->gpio_reset); + gpio_output(drv->gpio_reset); - /* Set GPIO pins as outputs. */ - GPIO_DIR(PORT_MIXER_ENX) |= PIN_MIXER_ENX; - GPIO_DIR(PORT_MIXER_SCLK) |= PIN_MIXER_SCLK; - GPIO_DIR(PORT_MIXER_SDATA) |= PIN_MIXER_SDATA; - GPIO_DIR(PORT_MIXER_RESETX) |= PIN_MIXER_RESETX; - - /* set to known state */ - gpio_set(PORT_MIXER_ENX, PIN_MIXER_ENX); /* active low */ - gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA); - gpio_set(PORT_MIXER_RESETX, PIN_MIXER_RESETX); /* active low */ -#endif + rffc5071_init(drv); /* initial setup */ /* put zeros in freq contol registers */ - set_RFFC5071_P2N(0); - set_RFFC5071_P2LODIV(0); - set_RFFC5071_P2PRESC(0); - set_RFFC5071_P2VCOSEL(0); + set_RFFC5071_P2N(drv, 0); + set_RFFC5071_P2LODIV(drv, 0); + set_RFFC5071_P2PRESC(drv, 0); + set_RFFC5071_P2VCOSEL(drv, 0); - set_RFFC5071_P2N(0); - set_RFFC5071_P2LODIV(0); - set_RFFC5071_P2PRESC(0); - set_RFFC5071_P2VCOSEL(0); + set_RFFC5071_P2N(drv, 0); + set_RFFC5071_P2LODIV(drv, 0); + set_RFFC5071_P2PRESC(drv, 0); + set_RFFC5071_P2VCOSEL(drv, 0); - set_RFFC5071_P2N(0); - set_RFFC5071_P2LODIV(0); - set_RFFC5071_P2PRESC(0); - set_RFFC5071_P2VCOSEL(0); + set_RFFC5071_P2N(drv, 0); + set_RFFC5071_P2LODIV(drv, 0); + set_RFFC5071_P2PRESC(drv, 0); + set_RFFC5071_P2VCOSEL(drv, 0); /* set ENBL and MODE to be configured via 3-wire interface, * not control pins. */ - set_RFFC5071_SIPIN(1); + set_RFFC5071_SIPIN(drv, 1); /* 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) -{ - uint32_t i; +static uint16_t rffc5071_spi_read(rffc5071_driver_t* const drv, uint8_t r) { + (void)drv; - for (i = 0; i < 2; i++) - __asm__("nop"); + uint16_t data[] = { 0x80 | (r & 0x7f), 0xffff }; + spi_bus_transfer(drv->bus, data, 2); + return data[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). - */ -uint16_t rffc5071_spi_read(uint8_t r) { +static void rffc5071_spi_write(rffc5071_driver_t* const drv, uint8_t r, uint16_t v) { + (void)drv; - int bits = 9; - int msb = 1 << (bits -1); - uint32_t data = 0x80 | (r & 0x7f); - -#if DEBUG - LOG("reg%d = 0\n", r); - return 0; -#else - /* make sure everything is starting in the correct state */ - gpio_set(PORT_MIXER_ENX, PIN_MIXER_ENX); - gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA); - - /* - * The device requires two clocks while ENX is high before a serial - * transaction. This is not clearly documented. - */ - serial_delay(); - gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - - serial_delay(); - gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - - serial_delay(); - gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - - serial_delay(); - gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - - /* start transaction by bringing ENX low */ - gpio_clear(PORT_MIXER_ENX, PIN_MIXER_ENX); - - while (bits--) { - if (data & msb) - gpio_set(PORT_MIXER_SDATA, PIN_MIXER_SDATA); - else - gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA); - data <<= 1; - - serial_delay(); - gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - - serial_delay(); - gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - } - - serial_delay(); - gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - - serial_delay(); - gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - - bits = 16; - data = 0; - /* set SDATA line as input */ - GPIO_DIR(PORT_MIXER_SDATA) &= ~PIN_MIXER_SDATA; - - while (bits--) { - data <<= 1; - - serial_delay(); - gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - - serial_delay(); - gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - if (MIXER_SDATA_STATE) - data |= 1; - } - /* set SDATA line as output */ - GPIO_DIR(PORT_MIXER_SDATA) |= PIN_MIXER_SDATA; - - serial_delay(); - gpio_set(PORT_MIXER_ENX, PIN_MIXER_ENX); - - /* - * The device requires a clock while ENX is high after a serial - * transaction. This is not clearly documented. - */ - gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - - serial_delay(); - gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - - return data; -#endif /* DEBUG */ + uint16_t data[] = { 0x00 | (r & 0x7f), v }; + spi_bus_transfer(drv->bus, data, 2); } -/* SPI register write - * - * Send 25 bits: - * first bit is ignored, - * second bit is zero for write operation, - * next 7 bits are register address, - * next 16 bits are register value. - */ -void rffc5071_spi_write(uint8_t r, uint16_t v) { - -#if DEBUG - LOG("0x%04x -> reg%d\n", v, r); -#else - - int bits = 25; - int msb = 1 << (bits -1); - uint32_t data = ((r & 0x7f) << 16) | v; - - /* make sure everything is starting in the correct state */ - gpio_set(PORT_MIXER_ENX, PIN_MIXER_ENX); - gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA); - - /* - * The device requires two clocks while ENX is high before a serial - * transaction. This is not clearly documented. - */ - serial_delay(); - gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - - serial_delay(); - gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - - serial_delay(); - gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - - serial_delay(); - gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - - /* start transaction by bringing ENX low */ - gpio_clear(PORT_MIXER_ENX, PIN_MIXER_ENX); - - while (bits--) { - if (data & msb) - gpio_set(PORT_MIXER_SDATA, PIN_MIXER_SDATA); - else - gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA); - data <<= 1; - - serial_delay(); - gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - - serial_delay(); - gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - } - - gpio_set(PORT_MIXER_ENX, PIN_MIXER_ENX); - - /* - * The device requires a clock while ENX is high after a serial - * transaction. This is not clearly documented. - */ - serial_delay(); - gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - - serial_delay(); - gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); -#endif -} - -uint16_t rffc5071_reg_read(uint8_t r) +uint16_t rffc5071_reg_read(rffc5071_driver_t* const drv, uint8_t r) { /* Readback register is not cached. */ if (r == RFFC5071_READBACK_REG) - return rffc5071_spi_read(r); + return rffc5071_spi_read(drv, r); /* Discard uncommited write when reading. This shouldn't * happen, and probably has not been tested. */ - if ((rffc5071_regs_dirty >> r) & 0x1) { - rffc5071_regs[r] = rffc5071_spi_read(r); + if ((drv->regs_dirty >> r) & 0x1) { + 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; - rffc5071_spi_write(r, v); - RFFC5071_REG_SET_CLEAN(r); + drv->regs[r] = v; + rffc5071_spi_write(drv, r, v); + 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; for(r = 0; r < RFFC5071_NUM_REGS; r++) { - if ((rffc5071_regs_dirty >> r) & 0x1) { - rffc5071_reg_commit(r); + if ((drv->regs_dirty >> r) & 0x1) { + rffc5071_reg_commit(drv, r); } } } -void rffc5071_tx(void) { - LOG("# rffc5071_tx\n"); - set_RFFC5071_ENBL(0); - set_RFFC5071_FULLD(0); - set_RFFC5071_MODE(1); /* mixer 2 used for both RX and TX */ - rffc5071_regs_commit(); +void rffc5071_tx(rffc5071_driver_t* const drv) { + set_RFFC5071_ENBL(drv, 0); + set_RFFC5071_FULLD(drv, 0); + set_RFFC5071_MODE(drv, 1); /* mixer 2 used for both RX and TX */ + rffc5071_regs_commit(drv); } -void rffc5071_rx(void) { - LOG("# rfc5071_rx\n"); - set_RFFC5071_ENBL(0); - set_RFFC5071_FULLD(0); - set_RFFC5071_MODE(1); /* mixer 2 used for both RX and TX */ - rffc5071_regs_commit(); +void rffc5071_rx(rffc5071_driver_t* const drv) { + set_RFFC5071_ENBL(drv, 0); + set_RFFC5071_FULLD(drv, 0); + set_RFFC5071_MODE(drv, 1); /* mixer 2 used for both RX and TX */ + rffc5071_regs_commit(drv); } /* * This function turns on both mixer (full-duplex) on the RFFC5071, but our * current hardware designs do not support full-duplex operation. */ -void rffc5071_rxtx(void) { - LOG("# rfc5071_rxtx\n"); - set_RFFC5071_ENBL(0); - set_RFFC5071_FULLD(1); /* mixer 1 and mixer 2 (RXTX) */ - rffc5071_regs_commit(); +void rffc5071_rxtx(rffc5071_driver_t* const drv) { + set_RFFC5071_ENBL(drv, 0); + set_RFFC5071_FULLD(drv, 1); /* mixer 1 and mixer 2 (RXTX) */ + rffc5071_regs_commit(drv); - rffc5071_enable(); + rffc5071_enable(drv); } -void rffc5071_disable(void) { - LOG("# rfc5071_disable\n"); - set_RFFC5071_ENBL(0); - rffc5071_regs_commit(); +void rffc5071_disable(rffc5071_driver_t* const drv) { + set_RFFC5071_ENBL(drv, 0); + rffc5071_regs_commit(drv); } -void rffc5071_enable(void) { - LOG("# rfc5071_enable\n"); - set_RFFC5071_ENBL(1); - rffc5071_regs_commit(); +void rffc5071_enable(rffc5071_driver_t* const drv) { + set_RFFC5071_ENBL(drv, 1); + rffc5071_regs_commit(drv); } #define LO_MAX 5400 @@ -409,7 +212,7 @@ void rffc5071_enable(void) { #define FREQ_ONE_MHZ (1000*1000) /* 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; uint16_t fvco; uint8_t fbkdiv; @@ -418,8 +221,6 @@ uint64_t rffc5071_config_synth_int(uint16_t lo) { uint16_t p1nmsb; uint8_t p1nlsb; - LOG("# config_synth_int\n"); - /* Calculate n_lo */ uint8_t n_lo = 0; uint16_t x = LO_MAX / lo; @@ -438,10 +239,10 @@ uint64_t rffc5071_config_synth_int(uint16_t lo) { * and will be unaffected. */ if (fvco > 3200) { fbkdiv = 4; - set_RFFC5071_PLLCPL(3); + set_RFFC5071_PLLCPL(drv, 3); } else { fbkdiv = 2; - set_RFFC5071_PLLCPL(2); + set_RFFC5071_PLLCPL(drv, 2); } 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) / (lodiv * (1 << 24ULL)); - LOG("# lo=%d n_lo=%d lodiv=%d fvco=%d fbkdiv=%d n=%d tune_freq_hz=%d\n", - lo, n_lo, lodiv, fvco, fbkdiv, n, tune_freq); /* Path 1 */ - set_RFFC5071_P1LODIV(n_lo); - set_RFFC5071_P1N(n); - set_RFFC5071_P1PRESC(fbkdiv >> 1); - set_RFFC5071_P1NMSB(p1nmsb); - set_RFFC5071_P1NLSB(p1nlsb); + set_RFFC5071_P1LODIV(drv, n_lo); + set_RFFC5071_P1N(drv, n); + set_RFFC5071_P1PRESC(drv, fbkdiv >> 1); + set_RFFC5071_P1NMSB(drv, p1nmsb); + set_RFFC5071_P1NLSB(drv, p1nlsb); /* Path 2 */ - set_RFFC5071_P2LODIV(n_lo); - set_RFFC5071_P2N(n); - set_RFFC5071_P2PRESC(fbkdiv >> 1); - set_RFFC5071_P2NMSB(p1nmsb); - set_RFFC5071_P2NLSB(p1nlsb); + set_RFFC5071_P2LODIV(drv, n_lo); + set_RFFC5071_P2N(drv, n); + set_RFFC5071_P2PRESC(drv, fbkdiv >> 1); + set_RFFC5071_P2NMSB(drv, p1nmsb); + set_RFFC5071_P2NLSB(drv, p1nlsb); - rffc5071_regs_commit(); + rffc5071_regs_commit(drv); return tune_freq_hz; } /* !!!!!!!!!!! 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; - rffc5071_disable(); - tune_freq = rffc5071_config_synth_int(mhz); - rffc5071_enable(); + rffc5071_disable(drv); + tune_freq = rffc5071_config_synth_int(drv, mhz); + rffc5071_enable(drv); 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. */ - set_RFFC5071_P1GPO(gpo); - set_RFFC5071_P2GPO(gpo); + set_RFFC5071_P1GPO(drv, 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 diff --git a/firmware/common/rffc5071.h b/firmware/common/rffc5071.h index 98c31a3e..cedb6988 100644 --- a/firmware/common/rffc5071.h +++ b/firmware/common/rffc5071.h @@ -23,43 +23,49 @@ #ifndef __RFFC5071_H #define __RFFC5071_H +#include + +#include "spi_bus.h" +#include "gpio.h" + /* 31 registers, each containing 16 bits of data. */ #define RFFC5071_NUM_REGS 31 -extern uint16_t rffc5071_regs[RFFC5071_NUM_REGS]; -extern uint32_t rffc5071_regs_dirty; - -#define RFFC5071_REG_SET_CLEAN(r) rffc5071_regs_dirty &= ~(1UL<regs_dirty &= ~(1UL<<_r)) +#define RFFC5071_REG_SET_DIRTY(_d, _r) (_d->regs_dirty |= (1UL<<_r)) + #define RFFC5071_READBACK_REG 31 /* 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, * l=length (bits) */ #define __MREG__(n,r,o,l) \ -static inline uint16_t get_##n(void) { \ - return (rffc5071_regs[r] >> o) & ((1L<regs[r] >> o) & ((1L<regs[r] &= (uint16_t)(~(((1L<regs[r] |= (uint16_t)(((v&((1L< + * + * 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 +#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); + } +} diff --git a/firmware/common/rffc5071_spi.h b/firmware/common/rffc5071_spi.h new file mode 100644 index 00000000..8b577910 --- /dev/null +++ b/firmware/common/rffc5071_spi.h @@ -0,0 +1,41 @@ +/* + * Copyright 2012 Michael Ossmann + * Copyright 2014 Jared Boone + * + * This file is part of HackRF. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __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 diff --git a/firmware/common/rom_iap.c b/firmware/common/rom_iap.c index f7a4420c..011e6523 100644 --- a/firmware/common/rom_iap.c +++ b/firmware/common/rom_iap.c @@ -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 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) { @@ -92,7 +93,7 @@ isp_iap_ret_code_t iap_cmd_call(iap_cmd_res_t* iap_cmd_res) /* Only 64bits used */ iap_cmd_res->status_res.iap_result[0] = 0; iap_cmd_res->status_res.iap_result[1] = 0; - w25q80bv_get_unique_id( (w25q80bv_unique_id_t*)&iap_cmd_res->status_res.iap_result[2] ); + 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; break; diff --git a/firmware/common/sgpio.c b/firmware/common/sgpio.c index 4c87bb44..075b6eaf 100644 --- a/firmware/common/sgpio.c +++ b/firmware/common/sgpio.c @@ -20,7 +20,6 @@ * Boston, MA 02110-1301, USA. */ -#include #include #include @@ -28,9 +27,7 @@ #include -static bool sgpio_slice_mode_multislice = true; - -void sgpio_configure_pin_functions() { +void sgpio_configure_pin_functions(sgpio_config_t* const config) { scu_pinmux(SCU_PINMUX_SGPIO0, SCU_GPIO_FAST | SCU_CONF_FUNCTION3); scu_pinmux(SCU_PINMUX_SGPIO1, SCU_GPIO_FAST | SCU_CONF_FUNCTION3); scu_pinmux(SCU_PINMUX_SGPIO2, SCU_GPIO_FAST | SCU_CONF_FUNCTION2); @@ -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_SGPIO15, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); /* GPIO5[14] */ - sgpio_cpld_stream_rx_set_decimation(1); - sgpio_cpld_stream_rx_set_q_invert(0); + sgpio_cpld_stream_rx_set_decimation(config, 1); + sgpio_cpld_stream_rx_set_q_invert(config, 0); - GPIO_DIR(GPIO0) |= GPIOPIN13; - GPIO_DIR(GPIO5) |= GPIOPIN14 | GPIOPIN13 | GPIOPIN12; -} - - -void sgpio_test_interface() { - const uint_fast8_t host_clock_sgpio_pin = 8; // Input - const uint_fast8_t host_capture_sgpio_pin = 9; // Input - const uint_fast8_t host_disable_sgpio_pin = 10; // Output - const uint_fast8_t host_direction_sgpio_pin = 11; // Output - - SGPIO_GPIO_OENREG = 0; // All inputs for the moment. - - // Disable all counters during configuration - SGPIO_CTRL_ENABLE = 0; - - // Make all SGPIO controlled by SGPIO's "GPIO" registers - for (uint_fast8_t i = 0; i < 16; i++) { - SGPIO_OUT_MUX_CFG(i) = - SGPIO_OUT_MUX_CFG_P_OE_CFG(0) - | SGPIO_OUT_MUX_CFG_P_OUT_CFG(4); - } - - // Set SGPIO output values. - SGPIO_GPIO_OUTREG = - (1L << host_direction_sgpio_pin) - | (1L << host_disable_sgpio_pin); - - // Enable SGPIO pin outputs. - SGPIO_GPIO_OENREG = - (1L << host_direction_sgpio_pin) - | (1L << host_disable_sgpio_pin) - | (0L << host_capture_sgpio_pin) - | (0L << host_clock_sgpio_pin) - | (0xFF << 0); - - // Configure SGPIO slices. - - // Enable codec data stream. - SGPIO_GPIO_OUTREG &= ~(1L << host_disable_sgpio_pin); - - while (1) { - for (uint_fast8_t i = 0; i < 8; i++) { - SGPIO_GPIO_OUTREG ^= (1L << i); - } - } + gpio_output(config->gpio_rx_q_invert); + gpio_output(config->gpio_rx_decimation[0]); + gpio_output(config->gpio_rx_decimation[1]); + gpio_output(config->gpio_rx_decimation[2]); } void sgpio_set_slice_mode( + sgpio_config_t* const config, 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) */ void sgpio_configure( + sgpio_config_t* const config, const sgpio_direction_t direction ) { // Disable all counters during configuration @@ -167,7 +124,7 @@ void sgpio_configure( ; const uint_fast8_t output_multiplexing_mode = - sgpio_slice_mode_multislice ? 11 : 9; + config->slice_mode_multislice ? 11 : 9; /* SGPIO0 to SGPIO7 */ for(uint_fast8_t i=0; i<8; i++) { // SGPIO pin 0 outputs slice A bit "i". @@ -189,9 +146,9 @@ void sgpio_configure( }; const uint_fast8_t slice_gpdma = SGPIO_SLICE_H; - const uint_fast8_t pos = sgpio_slice_mode_multislice ? 0x1f : 0x03; - const bool single_slice = !sgpio_slice_mode_multislice; - const uint_fast8_t slice_count = sgpio_slice_mode_multislice ? 8 : 1; + const uint_fast8_t pos = config->slice_mode_multislice ? 0x1f : 0x03; + const bool single_slice = !config->slice_mode_multislice; + 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; uint32_t slice_enable_mask = 0; @@ -236,7 +193,7 @@ void sgpio_configure( 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_CONCAT_ORDER(0) /* Self-loop */ | SGPIO_MUX_CFG_CONCAT_ENABLE(1) @@ -274,21 +231,24 @@ void sgpio_configure( 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. 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. 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 */ } -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]: * 111: decimate by 1 (skip_n=0, skip no samples) * 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) */ const uint_fast8_t skip_n = n - 1; - GPIO_SET(GPIO5) = GPIOPIN14 | GPIOPIN13 | GPIOPIN12; - GPIO_CLR(GPIO5) = (skip_n & 7) << 12; + gpio_write(config->gpio_rx_decimation[0], (skip_n & 1) == 0); + 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); } -void sgpio_cpld_stream_rx_set_q_invert(const uint_fast8_t invert) { - if( invert ) { - GPIO_SET(GPIO0) = GPIOPIN13; - } else { - GPIO_CLR(GPIO0) = GPIOPIN13; - } +void sgpio_cpld_stream_rx_set_q_invert(sgpio_config_t* const config, const uint_fast8_t invert) { + gpio_write(config->gpio_rx_q_invert, invert); } diff --git a/firmware/common/sgpio.h b/firmware/common/sgpio.h index c7c13f8c..46681afe 100644 --- a/firmware/common/sgpio.h +++ b/firmware/common/sgpio.h @@ -22,26 +22,39 @@ #ifndef __SGPIO_H__ #define __SGPIO_H__ -#include +#include +#include + +#include + +#include "gpio.h" typedef enum { SGPIO_DIRECTION_RX, SGPIO_DIRECTION_TX, } sgpio_direction_t; - -void sgpio_configure_pin_functions(); -void sgpio_test_interface(); + +typedef struct sgpio_config_t { + 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( + sgpio_config_t* const config, const bool multi_slice ); void sgpio_configure( + sgpio_config_t* const config, const sgpio_direction_t direction ); -void sgpio_cpld_stream_enable(); -void sgpio_cpld_stream_disable(); -bool sgpio_cpld_stream_is_enabled(); +void sgpio_cpld_stream_enable(sgpio_config_t* const config); +void sgpio_cpld_stream_disable(sgpio_config_t* const config); +bool sgpio_cpld_stream_is_enabled(sgpio_config_t* const config); -bool sgpio_cpld_stream_rx_set_decimation(const uint_fast8_t n); -void sgpio_cpld_stream_rx_set_q_invert(const uint_fast8_t invert); +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(sgpio_config_t* const config, const uint_fast8_t invert); #endif//__SGPIO_H__ diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index 58b614dc..36730930 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -21,73 +21,50 @@ */ #include "si5351c.h" -#include enum pll_sources active_clock_source; -/* FIXME return i2c0 status from each function */ - /* write to single register */ -void si5351c_write_single(uint8_t reg, uint8_t val) +void si5351c_write_single(si5351c_driver_t* const drv, uint8_t reg, uint8_t val) { - i2c0_tx_start(); - i2c0_tx_byte(SI5351C_I2C_ADDR | I2C_WRITE); - i2c0_tx_byte(reg); - i2c0_tx_byte(val); - i2c0_stop(); + const uint8_t data_tx[] = { reg, val }; + si5351c_write(drv, data_tx, 2); } /* 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; - - /* set register address with write */ - i2c0_tx_start(); - i2c0_tx_byte(SI5351C_I2C_ADDR | I2C_WRITE); - i2c0_tx_byte(reg); - - /* read the value */ - i2c0_tx_start(); - i2c0_tx_byte(SI5351C_I2C_ADDR | I2C_READ); - val = i2c0_rx_byte(); - i2c0_stop(); - - return val; + const uint8_t data_tx[] = { reg }; + uint8_t data_rx[] = { 0x00 }; + i2c_bus_transfer(drv->bus, drv->i2c_address, data_tx, 1, data_rx, 1); + return data_rx[0]; } /* * Write to one or more contiguous registers. data[0] should be the first * register number, one or more values follow. */ -void si5351c_write(uint8_t* const data, const uint_fast8_t data_count) +void si5351c_write(si5351c_driver_t* const drv, const uint8_t* const data, const size_t data_count) { - uint_fast8_t i; - - i2c0_tx_start(); - i2c0_tx_byte(SI5351C_I2C_ADDR | I2C_WRITE); - - for (i = 0; i < data_count; i++) - i2c0_tx_byte(data[i]); - i2c0_stop(); + i2c_bus_transfer(drv->bus, drv->i2c_address, data, data_count, NULL, 0); } /* Disable all CLKx outputs. */ -void si5351c_disable_all_outputs() +void si5351c_disable_all_outputs(si5351c_driver_t* const drv) { uint8_t data[] = { 3, 0xFF }; - si5351c_write(data, sizeof(data)); + si5351c_write(drv, data, sizeof(data)); } /* 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 }; - si5351c_write(data, sizeof(data)); + si5351c_write(drv, data, sizeof(data)); } /* 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 , 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_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 * 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 }; - si5351c_write(data, sizeof(data)); + si5351c_write(drv, data, sizeof(data)); } /* * Register 187: Fanout Enable * 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 }; - 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) * 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 }; - si5351c_write(data, sizeof(data)); + si5351c_write(drv, data, sizeof(data)); } /* 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 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 */ data[0] = 34; 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 */ 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 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), (p2 >> 8) & 0xFF, (p2 >> 0) & 0xFF }; - si5351c_write(data, sizeof(data)); + si5351c_write(drv, data, sizeof(data)); } #ifdef JELLYBEAN @@ -232,15 +210,15 @@ void si5351c_configure_multisynth(const uint_fast8_t ms_number, * CLK5_SRC=3 (MS5 as input source) * 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 }; - si5351c_write(data, sizeof(data)); + si5351c_write(drv, data, sizeof(data)); } #endif #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; @@ -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_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 /* 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 }; - 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}; if(ms_number < 8){ data[0] = 16 + ms_number; - data[1] = si5351c_read_single(data[0]); + data[1] = si5351c_read_single(drv, data[0]); if(on) data[1] |= SI5351C_CLK_INT_MODE; else 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; } -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) { /* CLKIN not detected */ if (active_clock_source == PLL_SOURCE_CLKIN) { - si5351c_set_clock_source(PLL_SOURCE_XTAL); + si5351c_set_clock_source(drv, PLL_SOURCE_XTAL); } } else { /* CLKIN detected */ if (active_clock_source == PLL_SOURCE_XTAL) { - si5351c_set_clock_source(PLL_SOURCE_CLKIN); + si5351c_set_clock_source(drv, PLL_SOURCE_CLKIN); } } } diff --git a/firmware/common/si5351c.h b/firmware/common/si5351c.h index b62279d7..d10a0a93 100644 --- a/firmware/common/si5351c.h +++ b/firmware/common/si5351c.h @@ -30,8 +30,9 @@ extern "C" #include +#include "i2c_bus.h" + #define SI_INTDIV(x) (x*128-512) -#define SI5351C_I2C_ADDR (0x60 << 1) #define SI5351C_CLK_POWERDOWN (1<<7) #define SI5351C_CLK_INT_MODE (1<<6) @@ -62,26 +63,32 @@ enum pll_sources { PLL_SOURCE_CLKIN = 1, }; -void si5351c_disable_all_outputs(); -void si5351c_disable_oeb_pin_control(); -void si5351c_power_down_all_clocks(); -void si5351c_set_crystal_configuration(); -void si5351c_enable_xo_and_ms_fanout(); -void si5351c_configure_pll_sources(void); -void si5351c_configure_pll_multisynth(void); -void si5351c_reset_pll(void); -void si5351c_configure_multisynth(const uint_fast8_t ms_number, +typedef struct { + i2c_bus_t* const bus; + uint8_t i2c_address; +} si5351c_driver_t; + +void si5351c_disable_all_outputs(si5351c_driver_t* const drv); +void si5351c_disable_oeb_pin_control(si5351c_driver_t* const drv); +void si5351c_power_down_all_clocks(si5351c_driver_t* const drv); +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 uint_fast8_t r_div); -void si5351c_configure_clock_control(const enum pll_sources source); -void si5351c_enable_clock_outputs(); -void si5351c_set_int_mode(const uint_fast8_t ms_number, const uint_fast8_t on); +void si5351c_configure_clock_control(si5351c_driver_t* const drv, const enum pll_sources source); +void si5351c_enable_clock_outputs(si5351c_driver_t* const drv); +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); -uint8_t si5351c_read_single(uint8_t reg); -void si5351c_write(uint8_t* const data, const uint_fast8_t data_count); -void si5351c_set_clock_source(const enum pll_sources source); -void si5351c_activate_best_clock_source(void); +void si5351c_write_single(si5351c_driver_t* const drv, uint8_t reg, uint8_t val); +uint8_t si5351c_read_single(si5351c_driver_t* const drv, uint8_t reg); +void si5351c_write(si5351c_driver_t* const drv, const uint8_t* const data, const size_t data_count); #ifdef __cplusplus } diff --git a/firmware/common/spi_bus.c b/firmware/common/spi_bus.c new file mode 100644 index 00000000..7bf942c9 --- /dev/null +++ b/firmware/common/spi_bus.c @@ -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); +} diff --git a/firmware/common/spi_bus.h b/firmware/common/spi_bus.h new file mode 100644 index 00000000..e1257d41 --- /dev/null +++ b/firmware/common/spi_bus.h @@ -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 + +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__*/ diff --git a/firmware/common/spi_ssp.c b/firmware/common/spi_ssp.c new file mode 100644 index 00000000..7a1e2ea8 --- /dev/null +++ b/firmware/common/spi_ssp.c @@ -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 +#include + +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; igpio_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); +} diff --git a/firmware/common/spi_ssp.h b/firmware/common/spi_ssp.h new file mode 100644 index 00000000..2b2f884f --- /dev/null +++ b/firmware/common/spi_ssp.h @@ -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 +#include + +#include "spi_bus.h" + +#include "gpio.h" + +#include + +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__*/ diff --git a/firmware/common/streaming.c b/firmware/common/streaming.c index 32dbb295..07db7b64 100644 --- a/firmware/common/streaming.c +++ b/firmware/common/streaming.c @@ -25,18 +25,16 @@ #include #include -#include - -void baseband_streaming_enable() { +void baseband_streaming_enable(sgpio_config_t* const sgpio_config) { nvic_set_priority(NVIC_SGPIO_IRQ, 0); nvic_enable_irq(NVIC_SGPIO_IRQ); SGPIO_SET_EN_1 = (1 << SGPIO_SLICE_A); - sgpio_cpld_stream_enable(); + sgpio_cpld_stream_enable(sgpio_config); } -void baseband_streaming_disable() { - sgpio_cpld_stream_disable(); +void baseband_streaming_disable(sgpio_config_t* const sgpio_config) { + sgpio_cpld_stream_disable(sgpio_config); nvic_disable_irq(NVIC_SGPIO_IRQ); } \ No newline at end of file diff --git a/firmware/common/streaming.h b/firmware/common/streaming.h index 1f234127..4f26cd10 100644 --- a/firmware/common/streaming.h +++ b/firmware/common/streaming.h @@ -23,7 +23,9 @@ #ifndef __STREAMING_H__ #define __STREAMING_H__ -void baseband_streaming_enable(); -void baseband_streaming_disable(); +#include + +void baseband_streaming_enable(sgpio_config_t* const sgpio_config); +void baseband_streaming_disable(sgpio_config_t* const sgpio_config); #endif/*__STREAMING_H__*/ diff --git a/firmware/common/tuning.c b/firmware/common/tuning.c index 6bbe4cd1..166f910c 100644 --- a/firmware/common/tuning.c +++ b/firmware/common/tuning.c @@ -22,6 +22,7 @@ #include "tuning.h" +#include #include #include #include @@ -62,25 +63,25 @@ bool set_freq(const uint64_t freq) success = true; - const max2837_mode_t prior_max2837_mode = max2837_mode(); - max2837_mode_standby(); + const max2837_mode_t prior_max2837_mode = max2837_mode(&max2837); + max2837_set_mode(&max2837, MAX2837_MODE_STANDBY); 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 */ max2837_freq_nominal_hz = 2650000000 - (freq / 7); RFFC5071_freq_mhz = (max2837_freq_nominal_hz / FREQ_ONE_MHZ) + freq_mhz; /* Set Freq and read real freq */ - real_RFFC5071_freq_hz = rffc5071_set_frequency(RFFC5071_freq_mhz); - max2837_set_frequency(real_RFFC5071_freq_hz - freq); - sgpio_cpld_stream_rx_set_q_invert(1); + real_RFFC5071_freq_hz = rffc5071_set_frequency(&rffc5072, RFFC5071_freq_mhz); + max2837_set_frequency(&max2837, real_RFFC5071_freq_hz - freq); + sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 1); }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; /* RFFC5071_freq_mhz <= not used in Bypass mode */ - max2837_set_frequency(MAX2837_freq_hz); - sgpio_cpld_stream_rx_set_q_invert(0); + max2837_set_frequency(&max2837, MAX2837_freq_hz); + sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 0); }else if( (freq_mhz >= MIN_HP_FREQ_MHZ) && (freq_mhz <= MAX_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 */ 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); /* Set Freq and read real freq */ - real_RFFC5071_freq_hz = rffc5071_set_frequency(RFFC5071_freq_mhz); - max2837_set_frequency(freq - real_RFFC5071_freq_hz); - sgpio_cpld_stream_rx_set_q_invert(0); + real_RFFC5071_freq_hz = rffc5071_set_frequency(&rffc5072, RFFC5071_freq_mhz); + max2837_set_frequency(&max2837, freq - real_RFFC5071_freq_hz); + sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 0); }else { /* Error freq_mhz too high */ success = false; } - max2837_set_mode(prior_max2837_mode); + max2837_set_mode(&max2837, prior_max2837_mode); if( success ) { 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; } - rf_path_set_filter(path); - max2837_set_frequency(if_freq_hz); + rf_path_set_filter(&rf_path, path); + max2837_set_frequency(&max2837, 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 { - sgpio_cpld_stream_rx_set_q_invert(0); + sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 0); } 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; } diff --git a/firmware/common/w25q80bv.c b/firmware/common/w25q80bv.c index f49ffe3f..b9f6880d 100644 --- a/firmware/common/w25q80bv.c +++ b/firmware/common/w25q80bv.c @@ -1,6 +1,7 @@ /* * Copyright 2013 Michael Ossmann * Copyright 2013 Benjamin Vernoux + * Copyright 2014 Jared Boone, ShareBrained Technology * * This file is part of HackRF. * @@ -27,183 +28,139 @@ */ #include +#include + #include "w25q80bv.h" -#include "hackrf_core.h" -#include -#include -#include -#include + +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + +#define W25Q80BV_READ_DATA 0x03 +#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. * SSP0_SSEL is controlled by GPIO in order to handle various transfer lengths. */ - -void w25q80bv_setup(void) +void w25q80bv_setup(w25q80bv_driver_t* const drv) { uint8_t device_id; - const uint8_t serial_clock_rate = 2; - const uint8_t clock_prescale_rate = 2; - /* Reset SPIFI peripheral before to Erase/Write SPIFI memory through SPI */ - RESET_CTRL1 = RESET_CTRL1_SPIFI_RST; - - /* Init SPIFI GPIO to Normal GPIO */ - scu_pinmux(P3_3, (SCU_SSP_IO | SCU_CONF_FUNCTION2)); // P3_3 SPIFI_SCK => SSP0_SCK - scu_pinmux(P3_4, (SCU_GPIO_FAST | SCU_CONF_FUNCTION0)); // P3_4 SPIFI SPIFI_SIO3 IO3 => GPIO1[14] - scu_pinmux(P3_5, (SCU_GPIO_FAST | SCU_CONF_FUNCTION0)); // P3_5 SPIFI SPIFI_SIO2 IO2 => GPIO1[15] - scu_pinmux(P3_6, (SCU_GPIO_FAST | SCU_CONF_FUNCTION0)); // P3_6 SPIFI SPIFI_MISO IO1 => GPIO0[6] - scu_pinmux(P3_7, (SCU_GPIO_FAST | SCU_CONF_FUNCTION4)); // P3_7 SPIFI SPIFI_MOSI IO0 => GPIO5[10] - scu_pinmux(P3_8, (SCU_GPIO_FAST | SCU_CONF_FUNCTION4)); // P3_8 SPIFI SPIFI_CS => GPIO5[11] - - /* configure SSP pins */ - scu_pinmux(SCU_SSP0_MISO, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); - scu_pinmux(SCU_SSP0_MOSI, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); - scu_pinmux(SCU_SSP0_SCK, (SCU_SSP_IO | SCU_CONF_FUNCTION2)); + drv->page_len = 256U; + drv->num_pages = 4096U; + drv->num_bytes = 1048576U; - /* 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); + drv->target_init(drv); device_id = 0; 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; - - gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL); - ssp_transfer(SSP0_NUM, W25Q80BV_READ_STATUS1); - value = ssp_transfer(SSP0_NUM, 0xFF); - gpio_set(PORT_SSP0_SSEL, PIN_SSP0_SSEL); - - return value; + uint8_t data[] = { W25Q80BV_READ_STATUS1, 0xFF }; + spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data)); + return data[1]; } /* 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; - - gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL); - ssp_transfer(SSP0_NUM, W25Q80BV_DEVICE_ID); - - /* Read 3 dummy bytes */ - value = ssp_transfer(SSP0_NUM, 0xFF); - value = ssp_transfer(SSP0_NUM, 0xFF); - value = ssp_transfer(SSP0_NUM, 0xFF); - /* Read Device ID shall return 0x13 for W25Q80BV */ - value = ssp_transfer(SSP0_NUM, 0xFF); - - gpio_set(PORT_SSP0_SSEL, PIN_SSP0_SSEL); - - return value; + uint8_t data[] = { + W25Q80BV_DEVICE_ID, + 0xFF, 0xFF, 0xFF, 0xFF + }; + spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data)); + return data[4]; } -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 value; + uint8_t data[] = { + 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); - ssp_transfer(SSP0_NUM, W25Q80BV_UNIQUE_ID); - - /* Read 4 dummy bytes */ - for(i=0; i<4; i++) - value = ssp_transfer(SSP0_NUM, 0xFF); - - /* Read Unique ID 64bits (8*8) */ - for(i=0; i<8; i++) - { - value = ssp_transfer(SSP0_NUM, 0xFF); - unique_id->id_8b[i] = value; + for(size_t i=0; i<8; i++) { + unique_id->id_8b[i] = data[5+i]; } - - 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(); - gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL); - ssp_transfer(SSP0_NUM, W25Q80BV_WRITE_ENABLE); - gpio_set(PORT_SSP0_SSEL, PIN_SSP0_SSEL); + w25q80bv_wait_while_busy(drv); + + uint8_t data[] = { W25Q80BV_WRITE_ENABLE }; + 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; device_id = 0; while(device_id != W25Q80BV_DEVICE_ID_RES) { - device_id = w25q80bv_get_device_id(); + device_id = w25q80bv_get_device_id(drv); } - w25q80bv_write_enable(); - w25q80bv_wait_while_busy(); - gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL); - ssp_transfer(SSP0_NUM, W25Q80BV_CHIP_ERASE); - gpio_set(PORT_SSP0_SSEL, PIN_SSP0_SSEL); + w25q80bv_write_enable(drv); + w25q80bv_wait_while_busy(drv); + + uint8_t data[] = { W25Q80BV_CHIP_ERASE }; + spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data)); } /* 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 */ - if (((addr & 0xFF) + len) > W25Q80BV_PAGE_LEN) + if (((addr & 0xFF) + len) > drv->page_len) return; /* do nothing if we would overflow the flash */ - if (addr > (W25Q80BV_NUM_BYTES - len)) + if (addr > (drv->num_bytes - len)) return; - w25q80bv_write_enable(); - w25q80bv_wait_while_busy(); + w25q80bv_write_enable(drv); + w25q80bv_wait_while_busy(drv); - gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL); - ssp_transfer(SSP0_NUM, W25Q80BV_PAGE_PROGRAM); - ssp_transfer(SSP0_NUM, (addr & 0xFF0000) >> 16); - ssp_transfer(SSP0_NUM, (addr & 0xFF00) >> 8); - ssp_transfer(SSP0_NUM, addr & 0xFF); - for (i = 0; i < len; i++) - ssp_transfer(SSP0_NUM, data[i]); - gpio_set(PORT_SSP0_SSEL, PIN_SSP0_SSEL); + uint8_t header[] = { + W25Q80BV_PAGE_PROGRAM, + (addr & 0xFF0000) >> 16, + (addr & 0xFF00) >> 8, + addr & 0xFF + }; + + 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 */ -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; uint8_t device_id; @@ -211,36 +168,36 @@ void w25q80bv_program(uint32_t addr, uint32_t len, const uint8_t* data) device_id = 0; 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 */ - if ((len > W25Q80BV_NUM_BYTES) || (addr > W25Q80BV_NUM_BYTES) - || ((addr + len) > W25Q80BV_NUM_BYTES)) + if ((len > drv->num_bytes) || (addr > drv->num_bytes) + || ((addr + len) > drv->num_bytes)) return; /* 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) first_block_len = 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; data += first_block_len; len -= first_block_len; } /* one page at a time on boundaries */ - while (len >= W25Q80BV_PAGE_LEN) { - w25q80bv_page_program(addr, W25Q80BV_PAGE_LEN, data); - addr += W25Q80BV_PAGE_LEN; - data += W25Q80BV_PAGE_LEN; - len -= W25Q80BV_PAGE_LEN; + while (len >= drv->page_len) { + w25q80bv_page_program(drv, addr, drv->page_len, data); + addr += drv->page_len; + data += drv->page_len; + len -= drv->page_len; } /* handle end not at page boundary */ if (len) { - w25q80bv_page_program(addr, len, data); + w25q80bv_page_program(drv, addr, len, data); } } diff --git a/firmware/common/w25q80bv.h b/firmware/common/w25q80bv.h index 5eda749d..18ac481d 100644 --- a/firmware/common/w25q80bv.h +++ b/firmware/common/w25q80bv.h @@ -1,6 +1,7 @@ /* * Copyright 2013 Michael Ossmann * Copyright 2013 Benjamin Vernoux + * Copyright 2014 Jared Boone, ShareBrained Technology * * This file is part of HackRF. * @@ -23,23 +24,11 @@ #ifndef __W25Q80BV_H__ #define __W25Q80BV_H__ -#define W25Q80BV_PAGE_LEN 256U -#define W25Q80BV_NUM_PAGES 4096U -#define W25Q80BV_NUM_BYTES 1048576U +#include +#include -#define W25Q80BV_READ_DATA 0x03 -#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 */ +#include "spi_bus.h" +#include "gpio.h" typedef union { @@ -48,11 +37,24 @@ typedef union uint8_t id_8b[8]; /* 8*8bits 64bits Unique ID */ } w25q80bv_unique_id_t; -void w25q80bv_setup(void); -void w25q80bv_chip_erase(void); -void w25q80bv_program(uint32_t addr, uint32_t len, const uint8_t* data); -uint8_t w25q80bv_get_device_id(void); -void w25q80bv_get_unique_id(w25q80bv_unique_id_t* unique_id); +struct w25q80bv_driver_t; +typedef struct w25q80bv_driver_t w25q80bv_driver_t; + +struct w25q80bv_driver_t { + spi_bus_t* bus; + 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(uint32_t addr, uint32_t len, uint8_t* const data); #endif//__W25Q80BV_H__ diff --git a/firmware/common/w25q80bv_target.c b/firmware/common/w25q80bv_target.c new file mode 100644 index 00000000..087d6822 --- /dev/null +++ b/firmware/common/w25q80bv_target.c @@ -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 +#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); +} diff --git a/firmware/common/w25q80bv_target.h b/firmware/common/w25q80bv_target.h new file mode 100644 index 00000000..e36f94ae --- /dev/null +++ b/firmware/common/w25q80bv_target.h @@ -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__*/ diff --git a/firmware/common/xapp058/micro.c b/firmware/common/xapp058/micro.c index 501d1024..c94bc77a 100644 --- a/firmware/common/xapp058/micro.c +++ b/firmware/common/xapp058/micro.c @@ -197,7 +197,7 @@ typedef struct tagSXsvfInfo } SXsvfInfo; /* 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 ============================================================================*/ -int xsvfDoIllegalCmd( SXsvfInfo* pXsvfInfo ); /* Illegal command function */ -int xsvfDoXCOMPLETE( SXsvfInfo* pXsvfInfo ); -int xsvfDoXTDOMASK( SXsvfInfo* pXsvfInfo ); -int xsvfDoXSIR( SXsvfInfo* pXsvfInfo ); -int xsvfDoXSIR2( SXsvfInfo* pXsvfInfo ); -int xsvfDoXSDR( SXsvfInfo* pXsvfInfo ); -int xsvfDoXRUNTEST( SXsvfInfo* pXsvfInfo ); -int xsvfDoXREPEAT( SXsvfInfo* pXsvfInfo ); -int xsvfDoXSDRSIZE( SXsvfInfo* pXsvfInfo ); -int xsvfDoXSDRTDO( SXsvfInfo* pXsvfInfo ); -int xsvfDoXSETSDRMASKS( SXsvfInfo* pXsvfInfo ); -int xsvfDoXSDRINC( SXsvfInfo* pXsvfInfo ); -int xsvfDoXSDRBCE( SXsvfInfo* pXsvfInfo ); -int xsvfDoXSDRTDOBCE( SXsvfInfo* pXsvfInfo ); -int xsvfDoXSTATE( SXsvfInfo* pXsvfInfo ); -int xsvfDoXENDXR( SXsvfInfo* pXsvfInfo ); -int xsvfDoXCOMMENT( SXsvfInfo* pXsvfInfo ); -int xsvfDoXWAIT( SXsvfInfo* pXsvfInfo ); +int xsvfDoIllegalCmd( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo ); /* Illegal command function */ +int xsvfDoXCOMPLETE( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo ); +int xsvfDoXTDOMASK( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo ); +int xsvfDoXSIR( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo ); +int xsvfDoXSIR2( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo ); +int xsvfDoXSDR( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo ); +int xsvfDoXRUNTEST( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo ); +int xsvfDoXREPEAT( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo ); +int xsvfDoXSDRSIZE( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo ); +int xsvfDoXSDRTDO( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo ); +int xsvfDoXSETSDRMASKS( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo ); +int xsvfDoXSDRINC( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo ); +int xsvfDoXSDRBCE( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo ); +int xsvfDoXSDRTDOBCE( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo ); +int xsvfDoXSTATE( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo ); +int xsvfDoXENDXR( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo ); +int xsvfDoXCOMMENT( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo ); +int xsvfDoXWAIT( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo ); /* Insert new command functions here */ /*============================================================================ @@ -476,11 +476,11 @@ short xsvfGetAsNumBytes( long lNumBits ) * Parameters: sTms - new TMS value. * Returns: void. *****************************************************************************/ -void xsvfTmsTransition( short sTms ) +void xsvfTmsTransition(jtag_gpio_t* const gpio, short sTms ) { - setPort( TMS, sTms ); - setPort( TCK, 0 ); - setPort( TCK, 1 ); + setPort(gpio, TMS, sTms ); + setPort(gpio, TCK, 0 ); + setPort(gpio, TCK, 1 ); } /***************************************************************************** @@ -496,7 +496,8 @@ void xsvfTmsTransition( short sTms ) * ucTargetState - New target TAP state. * Returns: int - 0 = success; otherwise error. *****************************************************************************/ -int xsvfGotoTapState( unsigned char* pucTapState, +int xsvfGotoTapState( jtag_gpio_t* const gpio, + unsigned char* pucTapState, unsigned char ucTargetState ) { int i; @@ -506,11 +507,11 @@ int xsvfGotoTapState( unsigned char* pucTapState, if ( ucTargetState == XTAPSTATE_RESET ) { /* If RESET, always perform TMS reset sequence to reset/sync TAPs */ - xsvfTmsTransition( 1 ); + xsvfTmsTransition( gpio, 1 ); for ( i = 0; i < 5; ++i ) { - setPort( TCK, 0 ); - setPort( TCK, 1 ); + setPort(gpio, TCK, 0 ); + setPort(gpio, TCK, 1 ); } *pucTapState = XTAPSTATE_RESET; 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 */ if ( ucTargetState == XTAPSTATE_PAUSEDR ) { - xsvfTmsTransition( 1 ); + xsvfTmsTransition( gpio, 1 ); *pucTapState = XTAPSTATE_EXIT2DR; XSVFDBG_PRINTF1( 3, " TAP State = %s\n", xsvf_pzTapState[ *pucTapState ] ); } else if ( ucTargetState == XTAPSTATE_PAUSEIR ) { - xsvfTmsTransition( 1 ); + xsvfTmsTransition( gpio, 1 ); *pucTapState = XTAPSTATE_EXIT2IR; XSVFDBG_PRINTF1( 3, " TAP State = %s\n", xsvf_pzTapState[ *pucTapState ] ); @@ -552,138 +553,138 @@ int xsvfGotoTapState( unsigned char* pucTapState, switch ( *pucTapState ) { case XTAPSTATE_RESET: - xsvfTmsTransition( 0 ); + xsvfTmsTransition( gpio, 0 ); *pucTapState = XTAPSTATE_RUNTEST; break; case XTAPSTATE_RUNTEST: - xsvfTmsTransition( 1 ); + xsvfTmsTransition( gpio, 1 ); *pucTapState = XTAPSTATE_SELECTDR; break; case XTAPSTATE_SELECTDR: if ( ucTargetState >= XTAPSTATE_IRSTATES ) { - xsvfTmsTransition( 1 ); + xsvfTmsTransition( gpio, 1 ); *pucTapState = XTAPSTATE_SELECTIR; } else { - xsvfTmsTransition( 0 ); + xsvfTmsTransition( gpio, 0 ); *pucTapState = XTAPSTATE_CAPTUREDR; } break; case XTAPSTATE_CAPTUREDR: if ( ucTargetState == XTAPSTATE_SHIFTDR ) { - xsvfTmsTransition( 0 ); + xsvfTmsTransition( gpio, 0 ); *pucTapState = XTAPSTATE_SHIFTDR; } else { - xsvfTmsTransition( 1 ); + xsvfTmsTransition( gpio, 1 ); *pucTapState = XTAPSTATE_EXIT1DR; } break; case XTAPSTATE_SHIFTDR: - xsvfTmsTransition( 1 ); + xsvfTmsTransition( gpio, 1 ); *pucTapState = XTAPSTATE_EXIT1DR; break; case XTAPSTATE_EXIT1DR: if ( ucTargetState == XTAPSTATE_PAUSEDR ) { - xsvfTmsTransition( 0 ); + xsvfTmsTransition( gpio, 0 ); *pucTapState = XTAPSTATE_PAUSEDR; } else { - xsvfTmsTransition( 1 ); + xsvfTmsTransition( gpio, 1 ); *pucTapState = XTAPSTATE_UPDATEDR; } break; case XTAPSTATE_PAUSEDR: - xsvfTmsTransition( 1 ); + xsvfTmsTransition( gpio, 1 ); *pucTapState = XTAPSTATE_EXIT2DR; break; case XTAPSTATE_EXIT2DR: if ( ucTargetState == XTAPSTATE_SHIFTDR ) { - xsvfTmsTransition( 0 ); + xsvfTmsTransition( gpio, 0 ); *pucTapState = XTAPSTATE_SHIFTDR; } else { - xsvfTmsTransition( 1 ); + xsvfTmsTransition( gpio, 1 ); *pucTapState = XTAPSTATE_UPDATEDR; } break; case XTAPSTATE_UPDATEDR: if ( ucTargetState == XTAPSTATE_RUNTEST ) { - xsvfTmsTransition( 0 ); + xsvfTmsTransition( gpio, 0 ); *pucTapState = XTAPSTATE_RUNTEST; } else { - xsvfTmsTransition( 1 ); + xsvfTmsTransition( gpio, 1 ); *pucTapState = XTAPSTATE_SELECTDR; } break; case XTAPSTATE_SELECTIR: - xsvfTmsTransition( 0 ); + xsvfTmsTransition( gpio, 0 ); *pucTapState = XTAPSTATE_CAPTUREIR; break; case XTAPSTATE_CAPTUREIR: if ( ucTargetState == XTAPSTATE_SHIFTIR ) { - xsvfTmsTransition( 0 ); + xsvfTmsTransition( gpio, 0 ); *pucTapState = XTAPSTATE_SHIFTIR; } else { - xsvfTmsTransition( 1 ); + xsvfTmsTransition( gpio, 1 ); *pucTapState = XTAPSTATE_EXIT1IR; } break; case XTAPSTATE_SHIFTIR: - xsvfTmsTransition( 1 ); + xsvfTmsTransition( gpio, 1 ); *pucTapState = XTAPSTATE_EXIT1IR; break; case XTAPSTATE_EXIT1IR: if ( ucTargetState == XTAPSTATE_PAUSEIR ) { - xsvfTmsTransition( 0 ); + xsvfTmsTransition( gpio, 0 ); *pucTapState = XTAPSTATE_PAUSEIR; } else { - xsvfTmsTransition( 1 ); + xsvfTmsTransition( gpio, 1 ); *pucTapState = XTAPSTATE_UPDATEIR; } break; case XTAPSTATE_PAUSEIR: - xsvfTmsTransition( 1 ); + xsvfTmsTransition( gpio, 1 ); *pucTapState = XTAPSTATE_EXIT2IR; break; case XTAPSTATE_EXIT2IR: if ( ucTargetState == XTAPSTATE_SHIFTIR ) { - xsvfTmsTransition( 0 ); + xsvfTmsTransition( gpio, 0 ); *pucTapState = XTAPSTATE_SHIFTIR; } else { - xsvfTmsTransition( 1 ); + xsvfTmsTransition( gpio, 1 ); *pucTapState = XTAPSTATE_UPDATEIR; } break; case XTAPSTATE_UPDATEIR: if ( ucTargetState == XTAPSTATE_RUNTEST ) { - xsvfTmsTransition( 0 ); + xsvfTmsTransition( gpio, 0 ); *pucTapState = XTAPSTATE_RUNTEST; } else { - xsvfTmsTransition( 1 ); + xsvfTmsTransition( gpio, 1 ); *pucTapState = XTAPSTATE_SELECTDR; } break; @@ -714,7 +715,8 @@ int xsvfGotoTapState( unsigned char* pucTapState, * iExitShift - 1=exit at end of shift; 0=stay in Shift-DR. * Returns: void. *****************************************************************************/ -void xsvfShiftOnly( long lNumBits, +void xsvfShiftOnly( jtag_gpio_t* const gpio, + long lNumBits, lenVal* plvTdi, lenVal* plvTdoCaptured, int iExitShift ) @@ -749,25 +751,25 @@ void xsvfShiftOnly( long lNumBits, if ( iExitShift && !lNumBits ) { /* Exit Shift-DR state */ - setPort( TMS, 1 ); + setPort(gpio, TMS, 1 ); } /* Set the new TDI value */ - setPort( TDI, (short)(ucTdiByte & 1) ); + setPort(gpio, TDI, (short)(ucTdiByte & 1) ); ucTdiByte >>= 1; /* Set TCK low */ - setPort( TCK, 0 ); + setPort(gpio, TCK, 0 ); if ( pucTdo ) { /* Save the TDO value */ - ucTdoBit = readTDOBit(); + ucTdoBit = readTDOBit(gpio); ucTdoByte |= ( ucTdoBit << i ); } /* Set TCK high */ - setPort( TCK, 1 ); + setPort(gpio, TCK, 1 ); } /* Save the TDO byte value */ @@ -802,7 +804,8 @@ void xsvfShiftOnly( long lNumBits, * Skip the waitTime() if plvTdoMask->val[0:plvTdoMask->len-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, long lNumBits, lenVal* plvTdi, @@ -837,9 +840,9 @@ int xsvfShift( unsigned char* pucTapState, if ( lRunTestTime ) { /* Wait for prespecified XRUNTEST time */ - xsvfGotoTapState( pucTapState, XTAPSTATE_RUNTEST ); + xsvfGotoTapState( gpio, pucTapState, XTAPSTATE_RUNTEST ); XSVFDBG_PRINTF1( 3, " Wait = %ld usec\n", lRunTestTime ); - waitTime( lRunTestTime ); + waitTime( gpio, lRunTestTime ); } } else @@ -847,10 +850,10 @@ int xsvfShift( unsigned char* pucTapState, do { /* Goto Shift-DR or Shift-IR */ - xsvfGotoTapState( pucTapState, ucStartState ); + xsvfGotoTapState( gpio, pucTapState, ucStartState ); /* Shift TDI and capture TDO */ - xsvfShiftOnly( lNumBits, plvTdi, plvTdoCaptured, iExitShift ); + xsvfShiftOnly( gpio, lNumBits, plvTdi, plvTdoCaptured, iExitShift ); if ( plvTdoExpected ) { @@ -880,24 +883,24 @@ int xsvfShift( unsigned char* pucTapState, XSVFDBG_PRINTF( 4, "\n"); XSVFDBG_PRINTF1( 3, " Retry #%d\n", ( ucRepeat + 1 ) ); /* Do exception handling retry - ShiftDR only */ - xsvfGotoTapState( pucTapState, XTAPSTATE_PAUSEDR ); + xsvfGotoTapState( gpio, pucTapState, XTAPSTATE_PAUSEDR ); /* Shift 1 extra bit */ - xsvfGotoTapState( pucTapState, XTAPSTATE_SHIFTDR ); + xsvfGotoTapState( gpio, pucTapState, XTAPSTATE_SHIFTDR ); /* Increment RUNTEST time by an additional 25% */ lRunTestTime += ( lRunTestTime >> 2 ); } else { /* Do normal exit from Shift-XR */ - xsvfGotoTapState( pucTapState, ucEndState ); + xsvfGotoTapState( gpio, pucTapState, ucEndState ); } if ( lRunTestTime ) { /* Wait for prespecified XRUNTEST time */ - xsvfGotoTapState( pucTapState, XTAPSTATE_RUNTEST ); + xsvfGotoTapState( gpio, pucTapState, XTAPSTATE_RUNTEST ); XSVFDBG_PRINTF1( 3, " Wait = %ld usec\n", lRunTestTime ); - waitTime( lRunTestTime ); + waitTime( gpio, lRunTestTime ); } } } while ( iMismatch && ( ucRepeat++ < ucMaxRepeat ) ); @@ -941,7 +944,8 @@ int xsvfShift( unsigned char* pucTapState, * ucMaxRepeat - maximum xc9500/xl retries. * Returns: int - 0 = success; otherwise TDO mismatch. *****************************************************************************/ -int xsvfBasicXSDRTDO( unsigned char* pucTapState, +int xsvfBasicXSDRTDO( jtag_gpio_t* const gpio, + unsigned char* pucTapState, long lShiftLengthBits, short sShiftLengthBytes, lenVal* plvTdi, @@ -957,7 +961,7 @@ int xsvfBasicXSDRTDO( unsigned char* pucTapState, { readVal( plvTdoExpected, sShiftLengthBytes ); } - return( xsvfShift( pucTapState, XTAPSTATE_SHIFTDR, lShiftLengthBits, + return( xsvfShift( gpio, pucTapState, XTAPSTATE_SHIFTDR, lShiftLengthBits, plvTdi, plvTdoCaptured, plvTdoExpected, plvTdoMask, ucEndState, lRunTestTime, ucMaxRepeat ) ); } @@ -1052,8 +1056,9 @@ void xsvfDoSDRMasking( lenVal* plvTdi, * Parameters: pXsvfInfo - XSVF information pointer. * 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", ((unsigned int)(pXsvfInfo->ucCommand)), ((pXsvfInfo->ucCommand < XLASTCMD) @@ -1070,8 +1075,9 @@ int xsvfDoIllegalCmd( SXsvfInfo* pXsvfInfo ) * Parameters: pXsvfInfo - XSVF information pointer. * 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; return( XSVF_ERROR_NONE ); } @@ -1083,8 +1089,9 @@ int xsvfDoXCOMPLETE( SXsvfInfo* pXsvfInfo ) * Parameters: pXsvfInfo - XSVF information pointer. * 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 ); XSVFDBG_PRINTF( 4, " TDO Mask = "); XSVFDBG_PRINTLENVAL( 4, &(pXsvfInfo->lvTdoMask) ); @@ -1101,7 +1108,7 @@ int xsvfDoXTDOMASK( SXsvfInfo* pXsvfInfo ) * Parameters: pXsvfInfo - XSVF information pointer. * Returns: int - 0 = success; non-zero = error. *****************************************************************************/ -int xsvfDoXSIR( SXsvfInfo* pXsvfInfo ) +int xsvfDoXSIR( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo ) { unsigned char ucShiftIrBits; short sShiftIrBytes; @@ -1123,7 +1130,7 @@ int xsvfDoXSIR( SXsvfInfo* pXsvfInfo ) readVal( &(pXsvfInfo->lvTdi), xsvfGetAsNumBytes( ucShiftIrBits ) ); /* Shift the data */ - iErrorCode = xsvfShift( &(pXsvfInfo->ucTapState), XTAPSTATE_SHIFTIR, + iErrorCode = xsvfShift( gpio, &(pXsvfInfo->ucTapState), XTAPSTATE_SHIFTIR, ucShiftIrBits, &(pXsvfInfo->lvTdi), /*plvTdoCaptured*/0, /*plvTdoExpected*/0, /*plvTdoMask*/0, pXsvfInfo->ucEndIR, @@ -1146,7 +1153,7 @@ int xsvfDoXSIR( SXsvfInfo* pXsvfInfo ) * Parameters: pXsvfInfo - XSVF information pointer. * Returns: int - 0 = success; non-zero = error. *****************************************************************************/ -int xsvfDoXSIR2( SXsvfInfo* pXsvfInfo ) +int xsvfDoXSIR2( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo ) { long lShiftIrBits; short sShiftIrBytes; @@ -1168,7 +1175,7 @@ int xsvfDoXSIR2( SXsvfInfo* pXsvfInfo ) readVal( &(pXsvfInfo->lvTdi), xsvfGetAsNumBytes( lShiftIrBits ) ); /* Shift the data */ - iErrorCode = xsvfShift( &(pXsvfInfo->ucTapState), XTAPSTATE_SHIFTIR, + iErrorCode = xsvfShift( gpio, &(pXsvfInfo->ucTapState), XTAPSTATE_SHIFTIR, lShiftIrBits, &(pXsvfInfo->lvTdi), /*plvTdoCaptured*/0, /*plvTdoExpected*/0, /*plvTdoMask*/0, pXsvfInfo->ucEndIR, @@ -1192,12 +1199,12 @@ int xsvfDoXSIR2( SXsvfInfo* pXsvfInfo ) * Parameters: pXsvfInfo - XSVF information pointer. * Returns: int - 0 = success; non-zero = error. *****************************************************************************/ -int xsvfDoXSDR( SXsvfInfo* pXsvfInfo ) +int xsvfDoXSDR( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo ) { int iErrorCode; readVal( &(pXsvfInfo->lvTdi), pXsvfInfo->sShiftLengthBytes ); /* use TDOExpected from last XSDRTDO instruction */ - iErrorCode = xsvfShift( &(pXsvfInfo->ucTapState), XTAPSTATE_SHIFTDR, + iErrorCode = xsvfShift( gpio, &(pXsvfInfo->ucTapState), XTAPSTATE_SHIFTDR, pXsvfInfo->lShiftLengthBits, &(pXsvfInfo->lvTdi), &(pXsvfInfo->lvTdoCaptured), &(pXsvfInfo->lvTdoExpected), @@ -1217,8 +1224,9 @@ int xsvfDoXSDR( SXsvfInfo* pXsvfInfo ) * Parameters: pXsvfInfo - XSVF information pointer. * 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 ); pXsvfInfo->lRunTestTime = value( &(pXsvfInfo->lvTdi) ); XSVFDBG_PRINTF1( 3, " XRUNTEST = %ld\n", pXsvfInfo->lRunTestTime ); @@ -1232,8 +1240,9 @@ int xsvfDoXRUNTEST( SXsvfInfo* pXsvfInfo ) * Parameters: pXsvfInfo - XSVF information pointer. * 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) ); XSVFDBG_PRINTF1( 3, " XREPEAT = %d\n", ((unsigned int)(pXsvfInfo->ucMaxRepeat)) ); @@ -1247,8 +1256,9 @@ int xsvfDoXREPEAT( SXsvfInfo* pXsvfInfo ) * Parameters: pXsvfInfo - XSVF information pointer. * Returns: int - 0 = success; non-zero = error. *****************************************************************************/ -int xsvfDoXSDRSIZE( SXsvfInfo* pXsvfInfo ) +int xsvfDoXSDRSIZE( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo ) { + (void)gpio; int iErrorCode; iErrorCode = XSVF_ERROR_NONE; readVal( &(pXsvfInfo->lvTdi), 4 ); @@ -1272,10 +1282,10 @@ int xsvfDoXSDRSIZE( SXsvfInfo* pXsvfInfo ) * Parameters: pXsvfInfo - XSVF information pointer. * Returns: int - 0 = success; non-zero = error. *****************************************************************************/ -int xsvfDoXSDRTDO( SXsvfInfo* pXsvfInfo ) +int xsvfDoXSDRTDO( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo ) { int iErrorCode; - iErrorCode = xsvfBasicXSDRTDO( &(pXsvfInfo->ucTapState), + iErrorCode = xsvfBasicXSDRTDO( gpio, &(pXsvfInfo->ucTapState), pXsvfInfo->lShiftLengthBits, pXsvfInfo->sShiftLengthBytes, &(pXsvfInfo->lvTdi), @@ -1303,8 +1313,9 @@ int xsvfDoXSDRTDO( SXsvfInfo* pXsvfInfo ) * Returns: int - 0 = success; non-zero = error. *****************************************************************************/ #ifdef XSVF_SUPPORT_COMPRESSION -int xsvfDoXSETSDRMASKS( SXsvfInfo* pXsvfInfo ) +int xsvfDoXSETSDRMASKS( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo ) { + (void)gpio; /* read the addressMask */ readVal( &(pXsvfInfo->lvAddressMask), pXsvfInfo->sShiftLengthBytes ); /* read the dataMask */ @@ -1338,7 +1349,7 @@ int xsvfDoXSETSDRMASKS( SXsvfInfo* pXsvfInfo ) * Returns: int - 0 = success; non-zero = error. *****************************************************************************/ #ifdef XSVF_SUPPORT_COMPRESSION -int xsvfDoXSDRINC( SXsvfInfo* pXsvfInfo ) +int xsvfDoXSDRINC( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo ) { int iErrorCode; int iDataMaskLen; @@ -1347,7 +1358,7 @@ int xsvfDoXSDRINC( SXsvfInfo* pXsvfInfo ) unsigned char i; readVal( &(pXsvfInfo->lvTdi), pXsvfInfo->sShiftLengthBytes ); - iErrorCode = xsvfShift( &(pXsvfInfo->ucTapState), XTAPSTATE_SHIFTDR, + iErrorCode = xsvfShift( gpio, &(pXsvfInfo->ucTapState), XTAPSTATE_SHIFTDR, pXsvfInfo->lShiftLengthBits, &(pXsvfInfo->lvTdi), &(pXsvfInfo->lvTdoCaptured), &(pXsvfInfo->lvTdoExpected), @@ -1379,7 +1390,7 @@ int xsvfDoXSDRINC( SXsvfInfo* pXsvfInfo ) &(pXsvfInfo->lvNextData), &(pXsvfInfo->lvAddressMask), &(pXsvfInfo->lvDataMask) ); - iErrorCode = xsvfShift( &(pXsvfInfo->ucTapState), + iErrorCode = xsvfShift( gpio, &(pXsvfInfo->ucTapState), XTAPSTATE_SHIFTDR, pXsvfInfo->lShiftLengthBits, &(pXsvfInfo->lvTdi), @@ -1410,13 +1421,13 @@ int xsvfDoXSDRINC( SXsvfInfo* pXsvfInfo ) * Parameters: pXsvfInfo - XSVF information pointer. * Returns: int - 0 = success; non-zero = error. *****************************************************************************/ -int xsvfDoXSDRBCE( SXsvfInfo* pXsvfInfo ) +int xsvfDoXSDRBCE( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo ) { unsigned char ucEndDR; int iErrorCode; ucEndDR = (unsigned char)(( pXsvfInfo->ucCommand == XSDRE ) ? pXsvfInfo->ucEndDR : XTAPSTATE_SHIFTDR); - iErrorCode = xsvfBasicXSDRTDO( &(pXsvfInfo->ucTapState), + iErrorCode = xsvfBasicXSDRTDO( gpio, &(pXsvfInfo->ucTapState), pXsvfInfo->lShiftLengthBits, pXsvfInfo->sShiftLengthBytes, &(pXsvfInfo->lvTdi), @@ -1441,13 +1452,13 @@ int xsvfDoXSDRBCE( SXsvfInfo* pXsvfInfo ) * Parameters: pXsvfInfo - XSVF information pointer. * Returns: int - 0 = success; non-zero = error. *****************************************************************************/ -int xsvfDoXSDRTDOBCE( SXsvfInfo* pXsvfInfo ) +int xsvfDoXSDRTDOBCE( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo ) { unsigned char ucEndDR; int iErrorCode; ucEndDR = (unsigned char)(( pXsvfInfo->ucCommand == XSDRTDOE ) ? pXsvfInfo->ucEndDR : XTAPSTATE_SHIFTDR); - iErrorCode = xsvfBasicXSDRTDO( &(pXsvfInfo->ucTapState), + iErrorCode = xsvfBasicXSDRTDO( gpio, &(pXsvfInfo->ucTapState), pXsvfInfo->lShiftLengthBits, pXsvfInfo->sShiftLengthBytes, &(pXsvfInfo->lvTdi), @@ -1470,12 +1481,12 @@ int xsvfDoXSDRTDOBCE( SXsvfInfo* pXsvfInfo ) * Parameters: pXsvfInfo - XSVF information pointer. * Returns: int - 0 = success; non-zero = error. *****************************************************************************/ -int xsvfDoXSTATE( SXsvfInfo* pXsvfInfo ) +int xsvfDoXSTATE( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo ) { unsigned char ucNextState; int iErrorCode; readByte( &ucNextState ); - iErrorCode = xsvfGotoTapState( &(pXsvfInfo->ucTapState), ucNextState ); + iErrorCode = xsvfGotoTapState( gpio, &(pXsvfInfo->ucTapState), ucNextState ); if ( iErrorCode != XSVF_ERROR_NONE ) { pXsvfInfo->iErrorCode = iErrorCode; @@ -1492,8 +1503,9 @@ int xsvfDoXSTATE( SXsvfInfo* pXsvfInfo ) * Parameters: pXsvfInfo - XSVF information pointer. * Returns: int - 0 = success; non-zero = error. *****************************************************************************/ -int xsvfDoXENDXR( SXsvfInfo* pXsvfInfo ) +int xsvfDoXENDXR( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo ) { + (void)gpio; int iErrorCode; unsigned char ucEndState; @@ -1549,8 +1561,10 @@ int xsvfDoXENDXR( SXsvfInfo* pXsvfInfo ) * Parameters: pXsvfInfo - XSVF information pointer. * 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 */ /* Otherwise, read through the comment to the end '\0' and ignore */ unsigned char ucText; @@ -1587,7 +1601,7 @@ int xsvfDoXCOMMENT( SXsvfInfo* pXsvfInfo ) * Parameters: pXsvfInfo - XSVF information pointer. * 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 ucEndState; @@ -1611,16 +1625,16 @@ int xsvfDoXWAIT( SXsvfInfo* pXsvfInfo ) /* If not already in , go to */ if ( pXsvfInfo->ucTapState != ucWaitState ) { - xsvfGotoTapState( &(pXsvfInfo->ucTapState), ucWaitState ); + xsvfGotoTapState( gpio, &(pXsvfInfo->ucTapState), ucWaitState ); } /* Wait for microseconds */ - waitTime( lWaitTime ); + waitTime( gpio, lWaitTime ); /* If not already in , go to */ if ( pXsvfInfo->ucTapState != ucEndState ) { - xsvfGotoTapState( &(pXsvfInfo->ucTapState), ucEndState ); + xsvfGotoTapState( gpio, &(pXsvfInfo->ucTapState), ucEndState ); } return( XSVF_ERROR_NONE ); @@ -1641,7 +1655,7 @@ int xsvfDoXWAIT( SXsvfInfo* pXsvfInfo ) * Parameters: pXsvfInfo - ptr to the XSVF information. * Returns: int - 0 = success; otherwise error. *****************************************************************************/ -int xsvfInitialize( SXsvfInfo* pXsvfInfo ) +int xsvfInitialize( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo ) { /* Initialize values */ pXsvfInfo->iErrorCode = xsvfInfoInit( pXsvfInfo ); @@ -1649,7 +1663,7 @@ int xsvfInitialize( SXsvfInfo* pXsvfInfo ) if ( !pXsvfInfo->iErrorCode ) { /* Initialize the TAPs */ - pXsvfInfo->iErrorCode = xsvfGotoTapState( &(pXsvfInfo->ucTapState), + pXsvfInfo->iErrorCode = xsvfGotoTapState( gpio, &(pXsvfInfo->ucTapState), XTAPSTATE_RESET ); } @@ -1666,7 +1680,7 @@ int xsvfInitialize( SXsvfInfo* pXsvfInfo ) * Parameters: pXsvfInfo - ptr to the XSVF information. * Returns: int - 0 = success; otherwise error. *****************************************************************************/ -int xsvfRun( SXsvfInfo* pXsvfInfo ) +int xsvfRun( jtag_gpio_t* const gpio, SXsvfInfo* pXsvfInfo ) { /* Process the XSVF commands */ if ( (!pXsvfInfo->iErrorCode) && (!pXsvfInfo->ucComplete) ) @@ -1682,12 +1696,12 @@ int xsvfRun( SXsvfInfo* pXsvfInfo ) xsvf_pzCommandName[pXsvfInfo->ucCommand] ); /* If your compiler cannot take this form, then convert to a switch statement */ - xsvf_pfDoCmd[ pXsvfInfo->ucCommand ]( pXsvfInfo ); + xsvf_pfDoCmd[ pXsvfInfo->ucCommand ]( gpio, pXsvfInfo ); } else { /* Illegal command value. Func sets error code. */ - xsvfDoIllegalCmd( pXsvfInfo ); + xsvfDoIllegalCmd( gpio, pXsvfInfo ); } } @@ -1717,15 +1731,15 @@ void xsvfCleanup( SXsvfInfo* pXsvfInfo ) * Parameters: none. * Returns: int - Legacy result values: 1 == success; 0 == failed. *****************************************************************************/ -int xsvfExecute() +int xsvfExecute(jtag_gpio_t* const gpio) { SXsvfInfo xsvfInfo; - xsvfInitialize( &xsvfInfo ); + xsvfInitialize( gpio, &xsvfInfo ); while ( !xsvfInfo.iErrorCode && (!xsvfInfo.ucComplete) ) { - xsvfRun( &xsvfInfo ); + xsvfRun( gpio, &xsvfInfo ); } if ( xsvfInfo.iErrorCode ) diff --git a/firmware/common/xapp058/micro.h b/firmware/common/xapp058/micro.h index 75258053..21ded729 100644 --- a/firmware/common/xapp058/micro.h +++ b/firmware/common/xapp058/micro.h @@ -13,6 +13,8 @@ #ifndef XSVF_MICRO_H #define XSVF_MICRO_H +#include "cpld_jtag.h" + /* Legacy error codes for xsvfExecute from original XSVF player v2.0 */ #define XSVF_LEGACY_SUCCESS 1 #define XSVF_LEGACY_ERROR 0 @@ -36,7 +38,7 @@ * Parameters: none. * Returns: int - For error codes see above. *****************************************************************************/ -extern int xsvfExecute(); +extern int xsvfExecute(jtag_gpio_t* const gpio); #endif /* XSVF_MICRO_H */ diff --git a/firmware/common/xapp058/ports.c b/firmware/common/xapp058/ports.c index 029ee0ca..336c83cf 100644 --- a/firmware/common/xapp058/ports.c +++ b/firmware/common/xapp058/ports.c @@ -13,7 +13,8 @@ #include "hackrf_core.h" #include "cpld_jtag.h" -#include + +#include "gpio.h" 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).*/ /* 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 (val) - gpio_set(PORT_CPLD_TMS, PIN_CPLD_TMS); + gpio_set(gpio->gpio_tms); else - gpio_clear(PORT_CPLD_TMS, PIN_CPLD_TMS); + gpio_clear(gpio->gpio_tms); } if (p==TDI) { if (val) - gpio_set(PORT_CPLD_TDI, PIN_CPLD_TDI); + gpio_set(gpio->gpio_tdi); else - gpio_clear(PORT_CPLD_TDI, PIN_CPLD_TDI); + gpio_clear(gpio->gpio_tdi); } if (p==TCK) { if (val) - gpio_set(PORT_CPLD_TCK, PIN_CPLD_TCK); + gpio_set(gpio->gpio_tck); else - gpio_clear(PORT_CPLD_TCK, PIN_CPLD_TCK); + gpio_clear(gpio->gpio_tck); } /* 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. */ -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); - setPort(TCK,1); /* set the TCK port to high */ + setPort(gpio, TCK,1); /* set the TCK port to high */ delay_jtag(200); } @@ -81,10 +82,10 @@ void readByte(unsigned char *data) /* readTDOBit: Implement to return the current value of the JTAG TDO signal.*/ /* read the TDO bit from port */ -unsigned char readTDOBit() +unsigned char readTDOBit(jtag_gpio_t* const gpio) { delay_jtag(2000); - return CPLD_TDO_STATE; + return gpio_read(gpio->gpio_tdo);; } /* waitTime: Implement as follows: */ @@ -96,7 +97,7 @@ unsigned char readTDOBit() /* RECOMMENDED IMPLEMENTATION: Pulse TCK at least microsec times AND */ /* continue pulsing TCK until the microsec wait */ /* 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 */ long tckCycles = microsec * tckCyclesPerMicrosec; @@ -108,6 +109,6 @@ void waitTime(long microsec) in order to satisfy the microsec wait time requirement. */ for ( i = 0; i < tckCycles; ++i ) { - pulseClock(); + pulseClock(gpio); } } diff --git a/firmware/common/xapp058/ports.h b/firmware/common/xapp058/ports.h index e09d95e6..5b23c3f8 100644 --- a/firmware/common/xapp058/ports.h +++ b/firmware/common/xapp058/ports.h @@ -7,6 +7,8 @@ #ifndef ports_dot_h #define ports_dot_h +#include "cpld_jtag.h" + /* these constants are used to send the appropriate ports to setPort */ /* they should be enumerated types, but some of the microcontroller */ /* compilers don't like enumerated types */ @@ -15,17 +17,17 @@ #define TDI (short) 2 /* 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 */ -extern unsigned char readTDOBit(); +extern unsigned char readTDOBit(jtag_gpio_t* const gpio); /* 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 */ extern void readByte(unsigned char *data); -extern void waitTime(long microsec); +extern void waitTime(jtag_gpio_t* const gpio, long microsec); #endif diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index df5d5c96..8ea1e6e6 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -135,8 +135,18 @@ macro(DeclareTargets) ${PATH_HACKRF_FIRMWARE_COMMON}/rf_path.c ${PATH_HACKRF_FIRMWARE_COMMON}/si5351c.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_target.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 ) diff --git a/firmware/hackrf_usb/CMakeLists.txt b/firmware/hackrf_usb/CMakeLists.txt index a4a0b0ee..10ee4ffb 100644 --- a/firmware/hackrf_usb/CMakeLists.txt +++ b/firmware/hackrf_usb/CMakeLists.txt @@ -44,7 +44,6 @@ set(SRC_M4 usb_api_transceiver.c "${PATH_HACKRF_FIRMWARE_COMMON}/usb_queue.c" "${PATH_HACKRF_FIRMWARE_COMMON}/fault_handler.c" - "${PATH_HACKRF_FIRMWARE_COMMON}/w25q80bv.c" "${PATH_HACKRF_FIRMWARE_COMMON}/cpld_jtag.c" "${PATH_HACKRF_FIRMWARE_COMMON}/xapp058/lenval.c" "${PATH_HACKRF_FIRMWARE_COMMON}/xapp058/micro.c" diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 5f793966..ea3104d3 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -24,7 +24,6 @@ #include -#include #include #include @@ -43,16 +42,13 @@ #include "usb_api_spiflash.h" #include "usb_api_transceiver.h" -#include "rf_path.h" #include "sgpio_isr.h" #include "usb_bulk_buffer.h" -#include "si5351c.h" -#include "w25q80bv.h" static volatile transceiver_mode_t _transceiver_mode = TRANSCEIVER_MODE_OFF; void set_transceiver_mode(const transceiver_mode_t new_transceiver_mode) { - baseband_streaming_disable(); + baseband_streaming_disable(&sgpio_config); usb_endpoint_disable(&usb_endpoint_bulk_in); 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; if( _transceiver_mode == TRANSCEIVER_MODE_RX ) { - gpio_clear(PORT_LED1_3, PIN_LED3); - gpio_set(PORT_LED1_3, PIN_LED2); + led_off(LED3); + led_on(LED2); 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; } else if (_transceiver_mode == TRANSCEIVER_MODE_TX) { - gpio_clear(PORT_LED1_3, PIN_LED2); - gpio_set(PORT_LED1_3, PIN_LED3); + led_off(LED2); + led_on(LED3); 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; } else { - gpio_clear(PORT_LED1_3, PIN_LED2); - gpio_clear(PORT_LED1_3, PIN_LED3); - rf_path_set_direction(RF_PATH_DIRECTION_OFF); + led_off(LED2); + led_off(LED3); + rf_path_set_direction(&rf_path, RF_PATH_DIRECTION_OFF); vector_table.irq[NVIC_SGPIO_IRQ] = sgpio_isr_rx; } if( _transceiver_mode != TRANSCEIVER_MODE_OFF ) { - si5351c_activate_best_clock_source(); - baseband_streaming_enable(); + si5351c_activate_best_clock_source(&clock_gen); + baseband_streaming_enable(&sgpio_config); } } @@ -179,7 +175,7 @@ void usb_configuration_changed( if( device->configuration->number == 1 ) { // transceiver configuration cpu_clock_pll1_max_speed(); - gpio_set(PORT_LED1_3, PIN_LED1); + led_on(LED1); } else if( device->configuration->number == 2 ) { // CPLD update configuration cpu_clock_pll1_max_speed(); @@ -188,7 +184,7 @@ void usb_configuration_changed( } else { /* Configuration number equal 0 means usb bus reset. */ cpu_clock_pll1_low_speed(); - gpio_clear(PORT_LED1_3, PIN_LED1); + led_off(LED1); } } @@ -247,9 +243,7 @@ int main(void) { usb_run(&usb_device); - ssp1_init(); - - rf_path_init(); + rf_path_init(&rf_path); unsigned int phase = 0; while(true) { diff --git a/firmware/hackrf_usb/usb_api_cpld.c b/firmware/hackrf_usb/usb_api_cpld.c index cc9daa0f..3b5b8c91 100644 --- a/firmware/hackrf_usb/usb_api_cpld.c +++ b/firmware/hackrf_usb/usb_api_cpld.c @@ -22,8 +22,6 @@ #include "usb_api_cpld.h" -#include - #include #include #include @@ -63,7 +61,6 @@ static void refill_cpld_buffer(void) void cpld_update(void) { #define WAIT_LOOP_DELAY (6000000) - #define ALL_LEDS (PIN_LED1|PIN_LED2|PIN_LED3) int i; int error; @@ -72,7 +69,7 @@ void cpld_update(void) refill_cpld_buffer(); - error = cpld_jtag_program(sizeof(cpld_xsvf_buffer), + error = cpld_jtag_program(&jtag_cpld, sizeof(cpld_xsvf_buffer), cpld_xsvf_buffer, refill_cpld_buffer); if(error == 0) @@ -80,17 +77,21 @@ void cpld_update(void) /* blink LED1, LED2, and LED3 on success */ 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. */ __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. */ __asm__("nop"); } }else { /* LED3 (Red) steady on error */ - gpio_set(PORT_LED1_3, PIN_LED3); /* LEDs on */ + led_on(LED3); while (1); } } diff --git a/firmware/hackrf_usb/usb_api_register.c b/firmware/hackrf_usb/usb_api_register.c index d822c924..373354d9 100644 --- a/firmware/hackrf_usb/usb_api_register.c +++ b/firmware/hackrf_usb/usb_api_register.c @@ -22,14 +22,16 @@ #include "usb_api_register.h" +#include #include #include -#include #include #include #include +#include + usb_request_status_t usb_vendor_request_write_max2837( usb_endpoint_t* const endpoint, 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( endpoint->setup.index < MAX2837_NUM_REGS ) { 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); 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( 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[1] = value >> 8; 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( endpoint->setup.index < 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); 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( 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; usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1, NULL, NULL); @@ -113,7 +115,7 @@ usb_request_status_t usb_vendor_request_write_rffc5071( { 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); 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 ) { - value = rffc5071_reg_read(endpoint->setup.index); + value = rffc5071_reg_read(&rffc5072, endpoint->setup.index); endpoint->buffer[0] = value & 0xff; endpoint->buffer[1] = value >> 8; usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 2, diff --git a/firmware/hackrf_usb/usb_api_spiflash.c b/firmware/hackrf_usb/usb_api_spiflash.c index 96072394..ff429099 100644 --- a/firmware/hackrf_usb/usb_api_spiflash.c +++ b/firmware/hackrf_usb/usb_api_spiflash.c @@ -26,16 +26,21 @@ #include +#include + #include -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_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { if (stage == USB_TRANSFER_STAGE_SETUP) { + spi_bus_start(spi_flash.bus, &ssp_config_w25q80bv); + w25q80bv_setup(&spi_flash); /* only chip erase is implemented */ - w25q80bv_chip_erase(); + w25q80bv_chip_erase(&spi_flash); usb_transfer_schedule_ack(endpoint->in); } return USB_REQUEST_STATUS_OK; @@ -50,23 +55,25 @@ usb_request_status_t usb_vendor_request_write_spiflash( if (stage == USB_TRANSFER_STAGE_SETUP) { addr = (endpoint->setup.value << 16) | endpoint->setup.index; len = endpoint->setup.length; - if ((len > W25Q80BV_PAGE_LEN) || (addr > W25Q80BV_NUM_BYTES) - || ((addr + len) > W25Q80BV_NUM_BYTES)) { + if ((len > spi_flash.page_len) || (addr > spi_flash.num_bytes) + || ((addr + len) > spi_flash.num_bytes)) { return USB_REQUEST_STATUS_STALL; } else { usb_transfer_schedule_block(endpoint->out, &spiflash_buffer[0], len, NULL, NULL); + spi_bus_start(spi_flash.bus, &ssp_config_w25q80bv); + w25q80bv_setup(&spi_flash); return USB_REQUEST_STATUS_OK; } } else if (stage == USB_TRANSFER_STAGE_DATA) { addr = (endpoint->setup.value << 16) | endpoint->setup.index; len = endpoint->setup.length; /* This check is redundant but makes me feel better. */ - if ((len > W25Q80BV_PAGE_LEN) || (addr > W25Q80BV_NUM_BYTES) - || ((addr + len) > W25Q80BV_NUM_BYTES)) { + if ((len > spi_flash.page_len) || (addr > spi_flash.num_bytes) + || ((addr + len) > spi_flash.num_bytes)) { return USB_REQUEST_STATUS_STALL; } else { - w25q80bv_program(addr, len, &spiflash_buffer[0]); + w25q80bv_program(&spi_flash, addr, len, &spiflash_buffer[0]); usb_transfer_schedule_ack(endpoint->in); return USB_REQUEST_STATUS_OK; } @@ -85,8 +92,8 @@ usb_request_status_t usb_vendor_request_read_spiflash( { addr = (endpoint->setup.value << 16) | endpoint->setup.index; len = endpoint->setup.length; - if ((len > W25Q80BV_PAGE_LEN) || (addr > W25Q80BV_NUM_BYTES) - || ((addr + len) > W25Q80BV_NUM_BYTES)) { + if ((len > spi_flash.page_len) || (addr > spi_flash.num_bytes) + || ((addr + len) > spi_flash.num_bytes)) { return USB_REQUEST_STATUS_STALL; } else { w25q80bv_read(addr, len, &spiflash_buffer[0]); @@ -99,8 +106,8 @@ usb_request_status_t usb_vendor_request_read_spiflash( addr = (endpoint->setup.value << 16) | endpoint->setup.index; len = endpoint->setup.length; /* This check is redundant but makes me feel better. */ - if ((len > W25Q80BV_PAGE_LEN) || (addr > W25Q80BV_NUM_BYTES) - || ((addr + len) > W25Q80BV_NUM_BYTES)) + if ((len > spi_flash.page_len) || (addr > spi_flash.num_bytes) + || ((addr + len) > spi_flash.num_bytes)) { return USB_REQUEST_STATUS_STALL; } else diff --git a/firmware/hackrf_usb/usb_api_transceiver.c b/firmware/hackrf_usb/usb_api_transceiver.c index 7ab06376..e8bac410 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.c +++ b/firmware/hackrf_usb/usb_api_transceiver.c @@ -22,8 +22,6 @@ #include "usb_api_transceiver.h" -#include - #include #include #include @@ -125,11 +123,11 @@ usb_request_status_t usb_vendor_request_set_amp_enable( if (stage == USB_TRANSFER_STAGE_SETUP) { switch (endpoint->setup.value) { case 0: - rf_path_set_lna(0); + rf_path_set_lna(&rf_path, 0); usb_transfer_schedule_ack(endpoint->in); return USB_REQUEST_STATUS_OK; case 1: - rf_path_set_lna(1); + rf_path_set_lna(&rf_path, 1); usb_transfer_schedule_ack(endpoint->in); return USB_REQUEST_STATUS_OK; default: @@ -145,7 +143,7 @@ usb_request_status_t usb_vendor_request_set_lna_gain( const usb_transfer_stage_t stage) { 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; usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1, 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) { 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; usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1, 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) { 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; usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1, NULL, NULL); @@ -189,11 +187,11 @@ usb_request_status_t usb_vendor_request_set_antenna_enable( if (stage == USB_TRANSFER_STAGE_SETUP) { switch (endpoint->setup.value) { case 0: - rf_path_set_antenna(0); + rf_path_set_antenna(&rf_path, 0); usb_transfer_schedule_ack(endpoint->in); return USB_REQUEST_STATUS_OK; case 1: - rf_path_set_antenna(1); + rf_path_set_antenna(&rf_path, 1); usb_transfer_schedule_ack(endpoint->in); return USB_REQUEST_STATUS_OK; default: diff --git a/firmware/libopencm3 b/firmware/libopencm3 index 854c112a..10503c7c 160000 --- a/firmware/libopencm3 +++ b/firmware/libopencm3 @@ -1 +1 @@ -Subproject commit 854c112a0ea7b27e85a15345507c8a2e13e76607 +Subproject commit 10503c7cc19647393d98cc66c3dbaf20bd634494 diff --git a/firmware/mixertx/mixertx.c b/firmware/mixertx/mixertx.c index 363859f5..a6c2024a 100644 --- a/firmware/mixertx/mixertx.c +++ b/firmware/mixertx/mixertx.c @@ -19,14 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#include -#include -#include -#include - #include "hackrf_core.h" -#include "max2837.h" -#include "rffc5071.h" int main(void) { @@ -38,21 +31,20 @@ int main(void) enable_rf_power(); #endif cpu_clock_init(); - ssp1_init(); - gpio_set(PORT_LED1_3, (PIN_LED1)); /* LED1 on */ + led_on(LED1); ssp1_set_mode_max2837(); - max2837_setup(); - rffc5071_setup(); - gpio_set(PORT_LED1_3, (PIN_LED2)); /* LED2 on */ + max2837_setup(&max2837); + rffc5071_setup(&rffc5072); + led_on(LED2); - max2837_set_frequency(freq); - max2837_start(); - max2837_tx(); - gpio_set(PORT_LED1_3, (PIN_LED3)); /* LED3 on */ + max2837_set_frequency(&max2837, freq); + max2837_start(&max2837); + max2837_tx(&max2837); + led_on(LED3); while (1); - max2837_stop(); + max2837_stop(&max2837); return 0; } diff --git a/firmware/sgpio-rx/sgpio-rx.c b/firmware/sgpio-rx/sgpio-rx.c index dbee1d3f..3d9154ce 100644 --- a/firmware/sgpio-rx/sgpio-rx.c +++ b/firmware/sgpio-rx/sgpio-rx.c @@ -20,17 +20,14 @@ * Boston, MA 02110-1301, USA. */ -#include #include #include -#include -#include #include void tx_test() { - sgpio_set_slice_mode(false); - sgpio_configure(TRANSCEIVER_MODE_TX); + sgpio_set_slice_mode(&sgpio_config, false); + sgpio_configure(&sgpio_config, TRANSCEIVER_MODE_TX); // LSB goes out first, samples are 0x volatile uint32_t buffer[] = { @@ -41,7 +38,7 @@ void tx_test() { }; uint32_t i = 0; - sgpio_cpld_stream_enable(); + sgpio_cpld_stream_enable(&sgpio_config); while(true) { while(SGPIO_STATUS_1 == 0); @@ -51,20 +48,20 @@ void tx_test() { } void rx_test() { - sgpio_set_slice_mode(false); - sgpio_configure(TRANSCEIVER_MODE_RX); + sgpio_set_slice_mode(&sgpio_config, false); + sgpio_configure(&sgpio_config, TRANSCEIVER_MODE_RX); volatile uint32_t buffer[4096]; uint32_t i = 0; int16_t magsq; 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(SGPIO_STATUS_1 == 0); - gpio_set(PORT_LED1_3, (PIN_LED1)); /* LED1 on */ + led_on(LED1); SGPIO_CLR_STATUS_1 = 1; buffer[i & 4095] = SGPIO_REG_SS(SGPIO_SLICE_A); @@ -79,9 +76,9 @@ void rx_test() { /* illuminate LED3 only when magsq exceeds threshold */ if (magsq > 0x3c00) - gpio_set(PORT_LED1_3, (PIN_LED3)); /* LED3 on */ + led_on(LED3); else - gpio_clear(PORT_LED1_3, (PIN_LED3)); /* LED3 off */ + led_off(LED3); i++; } } @@ -96,14 +93,13 @@ int main(void) { enable_rf_power(); #endif cpu_clock_init(); - ssp1_init(); - rf_path_init(); - rf_path_set_direction(RF_PATH_DIRECTION_RX); + rf_path_init(&rf_path); + rf_path_set_direction(&rf_path, RF_PATH_DIRECTION_RX); set_freq(freq); rx_test(); - gpio_set(PORT_LED1_3, (PIN_LED2)); /* LED2 on */ + led_on(LED2); while (1) { diff --git a/firmware/sgpio/sgpio_test.c b/firmware/sgpio/sgpio_test.c index 6e391c10..8215983e 100644 --- a/firmware/sgpio/sgpio_test.c +++ b/firmware/sgpio/sgpio_test.c @@ -19,22 +19,15 @@ * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ - -#include -#include #include -#include -#include #include -#include -#include volatile uint32_t buffer[4096]; void tx_test() { - sgpio_set_slice_mode(false); - sgpio_configure(TRANSCEIVER_MODE_TX); + sgpio_set_slice_mode(&sgpio_config, false); + sgpio_configure(&sgpio_config, TRANSCEIVER_MODE_TX); // LSB goes out first, samples are 0x buffer[0] = 0xda808080; @@ -44,7 +37,7 @@ void tx_test() { uint32_t i = 0; - sgpio_cpld_stream_enable(); + sgpio_cpld_stream_enable(&sgpio_config); while(true) { while(SGPIO_STATUS_1 == 0); @@ -54,12 +47,12 @@ void tx_test() { } void rx_test() { - sgpio_set_slice_mode(false); - sgpio_configure(TRANSCEIVER_MODE_RX); + sgpio_set_slice_mode(&sgpio_config, false); + sgpio_configure(&sgpio_config, TRANSCEIVER_MODE_RX); uint32_t i = 0; - sgpio_cpld_stream_enable(); + sgpio_cpld_stream_enable(&sgpio_config); while(true) { while(SGPIO_STATUS_1 == 0); @@ -72,12 +65,12 @@ int main(void) { pin_setup(); enable_1v8_power(); cpu_clock_init(); - ssp1_init(); - gpio_set(PORT_LED1_3, PIN_LED1); + led_on(LED1); ssp1_set_mode_max5864(); - max5864_xcvr(); + max5864_setup(&max5864); + max5864_xcvr(&max5864); while (1) { diff --git a/firmware/sgpio_passthrough/sgpio_passthrough.c b/firmware/sgpio_passthrough/sgpio_passthrough.c index 8e4d38d5..57810ee6 100644 --- a/firmware/sgpio_passthrough/sgpio_passthrough.c +++ b/firmware/sgpio_passthrough/sgpio_passthrough.c @@ -21,11 +21,8 @@ * Boston, MA 02110-1301, USA. */ -#include #include #include -#include -#include #include @@ -353,8 +350,7 @@ int main(void) pin_setup(); enable_1v8_power(); cpu_clock_init(); - ssp1_init(); - gpio_set(PORT_LED1_3, PIN_LED1); + led_on(LED1); //test_sgpio_sliceA_D(); test_sgpio_interface(); diff --git a/firmware/simpletx/simpletx.c b/firmware/simpletx/simpletx.c index 04efb686..900d876e 100644 --- a/firmware/simpletx/simpletx.c +++ b/firmware/simpletx/simpletx.c @@ -19,13 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#include -#include -#include -#include - #include "hackrf_core.h" -#include "max2837.h" int main(void) { @@ -37,19 +31,18 @@ int main(void) enable_rf_power(); #endif cpu_clock_init(); - ssp1_init(); - gpio_set(PORT_LED1_3, (PIN_LED1)); /* LED1 on */ + led_on(LED1); ssp1_set_mode_max2837(); - max2837_setup(); - gpio_set(PORT_LED1_3, (PIN_LED2)); /* LED2 on */ - max2837_set_frequency(freq); - max2837_start(); - max2837_tx(); - gpio_set(PORT_LED1_3, (PIN_LED3)); /* LED3 on */ + max2837_setup(&max2837); + led_on(LED2); + max2837_set_frequency(&max2837, freq); + max2837_start(&max2837); + max2837_tx(&max2837); + led_on(LED3); while (1); - max2837_stop(); + max2837_stop(&max2837); return 0; } diff --git a/firmware/spiflash/spiflash.c b/firmware/spiflash/spiflash.c index e1ae772e..73185b77 100644 --- a/firmware/spiflash/spiflash.c +++ b/firmware/spiflash/spiflash.c @@ -19,11 +19,7 @@ * Boston, MA 02110-1301, USA. */ -#include -#include - #include "hackrf_core.h" -#include "w25q80bv.h" int main(void) { @@ -39,17 +35,19 @@ int main(void) /* program test data to SPI flash */ for (i = 0; i < 515; i++) buf[i] = (i * 3) & 0xFF; - w25q80bv_setup(); - w25q80bv_chip_erase(); - w25q80bv_program(790, 515, &buf[0]); + w25q80bv_setup(&w25q80bv); + w25q80bv_chip_erase(&w25q80bv); + w25q80bv_program(&w25q80bv, 790, 515, &buf[0]); /* blink LED1 and LED3 */ 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. */ __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. */ __asm__("nop"); } diff --git a/firmware/startup/startup.c b/firmware/startup/startup.c index b6d0be65..3dfe78a5 100644 --- a/firmware/startup/startup.c +++ b/firmware/startup/startup.c @@ -19,10 +19,6 @@ * Boston, MA 02110-1301, USA. */ -#include -#include -#include - #include "hackrf_core.h" int main(void) @@ -35,23 +31,27 @@ int main(void) 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) { - gpio_set(PORT_LED1_3, (PIN_LED1)); /* LEDs on */ + led_on(LED1); for (i = 0; i < 2000000; i++) /* Wait a bit. */ __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. */ __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. */ __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. */ __asm__("nop"); } diff --git a/firmware/startup_systick/startup_systick.c b/firmware/startup_systick/startup_systick.c index d4c8517e..57fcb91e 100644 --- a/firmware/startup_systick/startup_systick.c +++ b/firmware/startup_systick/startup_systick.c @@ -19,9 +19,6 @@ * Boston, MA 02110-1301, USA. */ -#include -#include -#include #include #include #include @@ -139,19 +136,21 @@ int main(void) 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) { - gpio_set(PORT_LED1_3, (PIN_LED1)); /* LED1 on */ - gpio_set(PORT_LED1_3, (PIN_LED2)); /* LED2 on */ - gpio_set(PORT_LED1_3, (PIN_LED3)); /* LED3 on */ + led_on(LED1); + led_on(LED2); + led_on(LED3); sys_tick_wait_time_ms(500); - gpio_clear(PORT_LED1_3, (PIN_LED3)); /* LED3 off */ - gpio_clear(PORT_LED1_3, (PIN_LED2)); /* LED2 off */ - gpio_clear(PORT_LED1_3, (PIN_LED1)); /* LED1 off */ + led_off(LED1); + led_off(LED2); + led_off(LED3); sys_tick_wait_time_ms(500); } diff --git a/firmware/startup_systick_perfo/perf_mips.c b/firmware/startup_systick_perfo/perf_mips.c index a798b6ff..ea9c9d83 100644 --- a/firmware/startup_systick_perfo/perf_mips.c +++ b/firmware/startup_systick_perfo/perf_mips.c @@ -19,9 +19,6 @@ * Boston, MA 02110-1301, USA. */ -#include -#include -#include #include #include #include diff --git a/firmware/startup_systick_perfo/startup_systick.c b/firmware/startup_systick_perfo/startup_systick.c index 26c1fcc0..f07982be 100644 --- a/firmware/startup_systick_perfo/startup_systick.c +++ b/firmware/startup_systick_perfo/startup_systick.c @@ -19,9 +19,6 @@ * Boston, MA 02110-1301, USA. */ -#include -#include -#include #include #include #include @@ -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_1000_nop_asm(); -#define LED1_TOGGLE() (gpio_toggle(PORT_LED1_3, (PIN_LED1))) +#define LED1_TOGGLE() (led_toggle(LED1)) int main(void) { @@ -152,7 +149,7 @@ int main(void) 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 */ LED1_TOGGLE(); @@ -192,15 +189,15 @@ LED1_TOGGLE(); /* Test finished fast blink */ while (1) { - gpio_set(PORT_LED1_3, (PIN_LED1)); /* LED1 on */ - gpio_set(PORT_LED1_3, (PIN_LED2)); /* LED2 on */ - gpio_set(PORT_LED1_3, (PIN_LED3)); /* LED3 on */ + led_on(LED1); + led_on(LED2); + led_on(LED3); sys_tick_wait_time_ms(250); - gpio_clear(PORT_LED1_3, (PIN_LED3)); /* LED3 off */ - gpio_clear(PORT_LED1_3, (PIN_LED2)); /* LED2 off */ - gpio_clear(PORT_LED1_3, (PIN_LED1)); /* LED1 off */ + led_off(LED1); + led_off(LED2); + led_off(LED3); sys_tick_wait_time_ms(250); }