From 0bf84d974e94d4f612a1287b0a8901af4f729503 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 4 Nov 2014 09:58:31 -0800 Subject: [PATCH 01/46] Si5351C: Extract low-level driver code. --- firmware/common/hackrf_core.c | 1 + firmware/common/si5351c.c | 50 +---------------- firmware/common/si5351c.h | 5 -- firmware/common/si5351c_drv.c | 74 ++++++++++++++++++++++++++ firmware/common/si5351c_drv.h | 41 ++++++++++++++ firmware/hackrf-common.cmake | 1 + firmware/hackrf_usb/usb_api_register.c | 2 +- 7 files changed, 120 insertions(+), 54 deletions(-) create mode 100644 firmware/common/si5351c_drv.c create mode 100644 firmware/common/si5351c_drv.h diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index b862ba4f..cd1c8005 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -23,6 +23,7 @@ #include "hackrf_core.h" #include "si5351c.h" +#include "si5351c_drv.h" #include "max2837.h" #include "rffc5071.h" #include "sgpio.h" diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index 58b614dc..3be5041a 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -21,57 +21,11 @@ */ #include "si5351c.h" -#include + +#include "si5351c_drv.h" enum pll_sources active_clock_source; -/* FIXME return i2c0 status from each function */ - -/* write to single register */ -void si5351c_write_single(uint8_t reg, uint8_t val) -{ - i2c0_tx_start(); - i2c0_tx_byte(SI5351C_I2C_ADDR | I2C_WRITE); - i2c0_tx_byte(reg); - i2c0_tx_byte(val); - i2c0_stop(); -} - -/* read single register */ -uint8_t si5351c_read_single(uint8_t reg) -{ - uint8_t val; - - /* set register address with write */ - i2c0_tx_start(); - i2c0_tx_byte(SI5351C_I2C_ADDR | I2C_WRITE); - i2c0_tx_byte(reg); - - /* read the value */ - i2c0_tx_start(); - i2c0_tx_byte(SI5351C_I2C_ADDR | I2C_READ); - val = i2c0_rx_byte(); - i2c0_stop(); - - return val; -} - -/* - * Write to one or more contiguous registers. data[0] should be the first - * register number, one or more values follow. - */ -void si5351c_write(uint8_t* const data, const uint_fast8_t data_count) -{ - uint_fast8_t i; - - i2c0_tx_start(); - i2c0_tx_byte(SI5351C_I2C_ADDR | I2C_WRITE); - - for (i = 0; i < data_count; i++) - i2c0_tx_byte(data[i]); - i2c0_stop(); -} - /* Disable all CLKx outputs. */ void si5351c_disable_all_outputs() { diff --git a/firmware/common/si5351c.h b/firmware/common/si5351c.h index b62279d7..fcc2d2b8 100644 --- a/firmware/common/si5351c.h +++ b/firmware/common/si5351c.h @@ -31,7 +31,6 @@ extern "C" #include #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) @@ -76,10 +75,6 @@ void si5351c_configure_multisynth(const uint_fast8_t ms_number, void si5351c_configure_clock_control(const enum pll_sources source); void si5351c_enable_clock_outputs(); void si5351c_set_int_mode(const uint_fast8_t ms_number, const uint_fast8_t on); - -void si5351c_write_single(uint8_t reg, uint8_t val); -uint8_t si5351c_read_single(uint8_t reg); -void si5351c_write(uint8_t* const data, const uint_fast8_t data_count); void si5351c_set_clock_source(const enum pll_sources source); void si5351c_activate_best_clock_source(void); diff --git a/firmware/common/si5351c_drv.c b/firmware/common/si5351c_drv.c new file mode 100644 index 00000000..e63912c1 --- /dev/null +++ b/firmware/common/si5351c_drv.c @@ -0,0 +1,74 @@ +/* + * 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 "si5351c_drv.h" + +#include + +#define SI5351C_I2C_ADDR (0x60 << 1) + +/* FIXME return i2c0 status from each function */ + +/* write to single register */ +void si5351c_write_single(uint8_t reg, uint8_t val) +{ + i2c0_tx_start(); + i2c0_tx_byte(SI5351C_I2C_ADDR | I2C_WRITE); + i2c0_tx_byte(reg); + i2c0_tx_byte(val); + i2c0_stop(); +} + +/* read single register */ +uint8_t si5351c_read_single(uint8_t reg) +{ + uint8_t val; + + /* set register address with write */ + i2c0_tx_start(); + i2c0_tx_byte(SI5351C_I2C_ADDR | I2C_WRITE); + i2c0_tx_byte(reg); + + /* read the value */ + i2c0_tx_start(); + i2c0_tx_byte(SI5351C_I2C_ADDR | I2C_READ); + val = i2c0_rx_byte(); + i2c0_stop(); + + return val; +} + +/* + * Write to one or more contiguous registers. data[0] should be the first + * register number, one or more values follow. + */ +void si5351c_write(uint8_t* const data, const uint_fast8_t data_count) +{ + uint_fast8_t i; + + i2c0_tx_start(); + i2c0_tx_byte(SI5351C_I2C_ADDR | I2C_WRITE); + + for (i = 0; i < data_count; i++) + i2c0_tx_byte(data[i]); + i2c0_stop(); +} diff --git a/firmware/common/si5351c_drv.h b/firmware/common/si5351c_drv.h new file mode 100644 index 00000000..501b221e --- /dev/null +++ b/firmware/common/si5351c_drv.h @@ -0,0 +1,41 @@ +/* + * 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. + */ + +#ifndef __SI5351C_DRV_H +#define __SI5351C_DRV_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include + +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); + +#ifdef __cplusplus +} +#endif + +#endif /* __SI5351C_DRV_H */ diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index df5d5c96..9b4fb9a9 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -134,6 +134,7 @@ macro(DeclareTargets) ${PATH_HACKRF_FIRMWARE_COMMON}/sgpio.c ${PATH_HACKRF_FIRMWARE_COMMON}/rf_path.c ${PATH_HACKRF_FIRMWARE_COMMON}/si5351c.c + ${PATH_HACKRF_FIRMWARE_COMMON}/si5351c_drv.c ${PATH_HACKRF_FIRMWARE_COMMON}/max2837.c ${PATH_HACKRF_FIRMWARE_COMMON}/max5864.c ${PATH_HACKRF_FIRMWARE_COMMON}/rffc5071.c diff --git a/firmware/hackrf_usb/usb_api_register.c b/firmware/hackrf_usb/usb_api_register.c index d822c924..9478e7c1 100644 --- a/firmware/hackrf_usb/usb_api_register.c +++ b/firmware/hackrf_usb/usb_api_register.c @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include From 3bc41f1480401ea09b49bd1c06bfb28865b8b148 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 4 Nov 2014 10:45:24 -0800 Subject: [PATCH 02/46] Si5351C: Un-singleton the high- and low-level drivers. Proper. --- firmware/common/hackrf_core.c | 61 ++++++++++++----------- firmware/common/hackrf_core.h | 4 ++ firmware/common/si5351c.c | 69 +++++++++++++------------- firmware/common/si5351c.h | 31 ++++++------ firmware/common/si5351c_drv.c | 14 +++--- firmware/common/si5351c_drv.h | 10 ++-- firmware/hackrf_usb/hackrf_usb.c | 2 +- firmware/hackrf_usb/usb_api_register.c | 6 +-- 8 files changed, 106 insertions(+), 91 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index cd1c8005..792beec3 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -23,7 +23,6 @@ #include "hackrf_core.h" #include "si5351c.h" -#include "si5351c_drv.h" #include "max2837.h" #include "rffc5071.h" #include "sgpio.h" @@ -36,6 +35,10 @@ #define WAIT_CPU_CLOCK_INIT_DELAY (10000) +si5351c_driver_t clock_gen = { + .i2c_address = 0x60, +}; + void delay(uint32_t duration) { uint32_t i; @@ -119,9 +122,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; @@ -129,13 +132,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; } @@ -175,13 +178,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 @@ -238,13 +241,13 @@ 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 @@ -267,13 +270,13 @@ void cpu_clock_init(void) i2c0_init(15); - si5351c_disable_all_outputs(); - si5351c_disable_oeb_pin_control(); - si5351c_power_down_all_clocks(); - si5351c_set_crystal_configuration(); - si5351c_enable_xo_and_ms_fanout(); - si5351c_configure_pll_sources(); - si5351c_configure_pll_multisynth(); + 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 /* @@ -289,13 +292,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) @@ -312,28 +315,28 @@ 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 */ diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index 8ce6c943..7ad1ad50 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -32,6 +32,8 @@ extern "C" #include #include +#include "si5351c_drv.h" + /* hardware identification number */ #define BOARD_ID_JELLYBEAN 0 #define BOARD_ID_JAWBREAKER 1 @@ -350,6 +352,8 @@ typedef enum { void delay(uint32_t duration); +extern si5351c_driver_t clock_gen; + void cpu_clock_init(void); void cpu_clock_pll1_low_speed(void); void cpu_clock_pll1_max_speed(void); diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index 3be5041a..f6b4483a 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -27,21 +27,21 @@ enum pll_sources active_clock_source; /* 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 @@ -53,7 +53,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)); } /* @@ -61,20 +61,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)); } /* @@ -83,34 +83,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) { @@ -137,7 +138,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 @@ -186,15 +187,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; @@ -215,54 +216,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 fcc2d2b8..7151f990 100644 --- a/firmware/common/si5351c.h +++ b/firmware/common/si5351c.h @@ -30,6 +30,8 @@ extern "C" #include +#include "si5351c_drv.h" + #define SI_INTDIV(x) (x*128-512) #define SI5351C_CLK_POWERDOWN (1<<7) @@ -61,22 +63,23 @@ 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, +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_set_clock_source(const enum pll_sources source); -void si5351c_activate_best_clock_source(void); +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); #ifdef __cplusplus } diff --git a/firmware/common/si5351c_drv.c b/firmware/common/si5351c_drv.c index e63912c1..4cb58cd6 100644 --- a/firmware/common/si5351c_drv.c +++ b/firmware/common/si5351c_drv.c @@ -29,28 +29,28 @@ /* 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((drv->i2c_address << 1) | I2C_WRITE); i2c0_tx_byte(reg); i2c0_tx_byte(val); i2c0_stop(); } /* read single register */ -uint8_t si5351c_read_single(uint8_t reg) +uint8_t 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((drv->i2c_address << 1) | I2C_WRITE); i2c0_tx_byte(reg); /* read the value */ i2c0_tx_start(); - i2c0_tx_byte(SI5351C_I2C_ADDR | I2C_READ); + i2c0_tx_byte((drv->i2c_address << 1) | I2C_READ); val = i2c0_rx_byte(); i2c0_stop(); @@ -61,12 +61,12 @@ uint8_t si5351c_read_single(uint8_t reg) * 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, uint8_t* const data, const uint_fast8_t data_count) { uint_fast8_t i; i2c0_tx_start(); - i2c0_tx_byte(SI5351C_I2C_ADDR | I2C_WRITE); + i2c0_tx_byte((drv->i2c_address << 1) | I2C_WRITE); for (i = 0; i < data_count; i++) i2c0_tx_byte(data[i]); diff --git a/firmware/common/si5351c_drv.h b/firmware/common/si5351c_drv.h index 501b221e..61c6f374 100644 --- a/firmware/common/si5351c_drv.h +++ b/firmware/common/si5351c_drv.h @@ -30,9 +30,13 @@ extern "C" #include -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); +typedef struct { + uint8_t i2c_address; +} si5351c_driver_t; + +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, uint8_t* const data, const uint_fast8_t data_count); #ifdef __cplusplus } diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 42fc4482..0ed260c5 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -75,7 +75,7 @@ void set_transceiver_mode(const transceiver_mode_t new_transceiver_mode) { } if( _transceiver_mode != TRANSCEIVER_MODE_OFF ) { - si5351c_activate_best_clock_source(); + si5351c_activate_best_clock_source(&clock_gen); baseband_streaming_enable(); } } diff --git a/firmware/hackrf_usb/usb_api_register.c b/firmware/hackrf_usb/usb_api_register.c index 9478e7c1..35b9e012 100644 --- a/firmware/hackrf_usb/usb_api_register.c +++ b/firmware/hackrf_usb/usb_api_register.c @@ -22,9 +22,9 @@ #include "usb_api_register.h" +#include #include #include -#include #include #include @@ -75,7 +75,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 +92,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); From 4f3cae2e4192dcb17452fef32d10aa8b64ca2cf0 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 4 Nov 2014 11:16:14 -0800 Subject: [PATCH 03/46] MAX2837: Extract hardware/bus dependent stuff into separate layer. Conflicts: firmware/CMakeLists.txt firmware/hackrf_usb/Makefile firmware/mixertx/Makefile firmware/sgpio/CMakeLists.txt firmware/simpletx/Makefile firmware/spiflash/CMakeLists.txt firmware/startup/Makefile firmware/startup_systick/Makefile firmware/startup_systick_perfo/Makefile --- firmware/common/max2837.c | 155 +++++---------------------------- firmware/common/max2837.h | 34 +++++--- firmware/common/max2837_drv.c | 159 ++++++++++++++++++++++++++++++++++ firmware/common/max2837_drv.h | 45 ++++++++++ firmware/hackrf-common.cmake | 1 + 5 files changed, 253 insertions(+), 141 deletions(-) create mode 100644 firmware/common/max2837_drv.c create mode 100644 firmware/common/max2837_drv.h diff --git a/firmware/common/max2837.c b/firmware/common/max2837.c index 020763d6..73d9e1cd 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 @@ -9,6 +31,7 @@ #include #include #include "max2837.h" +#include "max2837_drv.h" #include "max2837_regs.def" // private register def macros #if (defined DEBUG || defined BUS_PIRATE) @@ -16,9 +39,6 @@ #define LOG printf #else #define LOG(x,...) -#include -#include -#include #include "hackrf_core.h" #endif @@ -85,51 +105,7 @@ void max2837_init(void) void max2837_setup(void) { LOG("# max2837_setup\n"); -#if !defined TEST - /* Configure XCVR_CTL GPIO pins. */ -#ifdef JELLYBEAN - scu_pinmux(SCU_XCVR_RXHP, SCU_GPIO_FAST); - scu_pinmux(SCU_XCVR_B1, SCU_GPIO_FAST); - scu_pinmux(SCU_XCVR_B2, SCU_GPIO_FAST); - scu_pinmux(SCU_XCVR_B3, SCU_GPIO_FAST); - scu_pinmux(SCU_XCVR_B4, SCU_GPIO_FAST); - scu_pinmux(SCU_XCVR_B5, SCU_GPIO_FAST); - scu_pinmux(SCU_XCVR_B6, SCU_GPIO_FAST); - scu_pinmux(SCU_XCVR_B7, SCU_GPIO_FAST); -#endif - scu_pinmux(SCU_XCVR_ENABLE, SCU_GPIO_FAST); - scu_pinmux(SCU_XCVR_RXENABLE, SCU_GPIO_FAST); - scu_pinmux(SCU_XCVR_TXENABLE, SCU_GPIO_FAST); - - /* Set GPIO pins as outputs. */ - GPIO2_DIR |= (PIN_XCVR_ENABLE | PIN_XCVR_RXENABLE | PIN_XCVR_TXENABLE); -#ifdef JELLYBEAN - GPIO_DIR(PORT_XCVR_RXHP) |= PIN_XCVR_RXHP; - GPIO_DIR(PORT_XCVR_B) |= - PIN_XCVR_B1 - | PIN_XCVR_B2 - | PIN_XCVR_B3 - | PIN_XCVR_B4 - | PIN_XCVR_B5 - | PIN_XCVR_B6 - | PIN_XCVR_B7 - ; -#endif - - max2837_mode_shutdown(); -#ifdef JELLYBEAN - gpio_set(PORT_XCVR_RXHP, PIN_XCVR_RXHP); - gpio_set(PORT_XCVR_B, - PIN_XCVR_B1 - | PIN_XCVR_B2 - | PIN_XCVR_B3 - | PIN_XCVR_B4 - | PIN_XCVR_B5 - | PIN_XCVR_B6 - | PIN_XCVR_B7 - ); -#endif -#endif + max2837_pin_config(); max2837_init(); LOG("# max2837_init done\n"); @@ -159,29 +135,6 @@ void max2837_setup(void) max2837_regs_commit(); } -/* SPI register read. */ -uint16_t max2837_spi_read(uint8_t r) { - gpio_clear(PORT_XCVR_CS, PIN_XCVR_CS); - const uint16_t value = ssp_transfer(SSP1_NUM, (uint16_t)((1 << 15) | (r << 10))); - gpio_set(PORT_XCVR_CS, PIN_XCVR_CS); - return value & 0x3ff; -} - -/* SPI register write */ -void max2837_spi_write(uint8_t r, uint16_t v) { - -#ifdef BUS_PIRATE - LOG("{0x%02x 0x%02x]\n", 0x00 | ((uint16_t)r<<2) | ((v>>8) & 0x3), - v & 0xff); -#elif DEBUG - LOG("0x%03x -> reg%d\n", v, r); -#else - gpio_clear(PORT_XCVR_CS, PIN_XCVR_CS); - ssp_transfer(SSP1_NUM, (uint16_t)((r << 10) | (v & 0x3ff))); - gpio_set(PORT_XCVR_CS, PIN_XCVR_CS); -#endif -} - uint16_t max2837_reg_read(uint8_t r) { if ((max2837_regs_dirty >> r) & 0x1) { @@ -197,12 +150,6 @@ void max2837_reg_write(uint8_t r, uint16_t v) MAX2837_REG_SET_CLEAN(r); } -/* This functions should not be needed, and might be confusing. DELETE. */ -void max2837_regs_read(void) -{ - ; -} - static inline void max2837_reg_commit(uint8_t r) { max2837_reg_write(r,max2837_regs[r]); @@ -218,60 +165,6 @@ void max2837_regs_commit(void) } } -void max2837_mode_shutdown(void) { - /* All circuit blocks are powered down, except the 4-wire serial bus - * and its internal programmable registers. - */ - gpio_clear(PORT_XCVR_ENABLE, - (PIN_XCVR_ENABLE | PIN_XCVR_RXENABLE | PIN_XCVR_TXENABLE)); -} - -void max2837_mode_standby(void) { - /* Used to enable the frequency synthesizer block while the rest of the - * device is powered down. In this mode, PLL, VCO, and LO generator - * are on, so that Tx or Rx modes can be quickly enabled from this mode. - * These and other blocks can be selectively enabled in this mode. - */ - gpio_clear(PORT_XCVR_ENABLE, (PIN_XCVR_RXENABLE | PIN_XCVR_TXENABLE)); - gpio_set(PORT_XCVR_ENABLE, PIN_XCVR_ENABLE); -} - -void max2837_mode_tx(void) { - /* All Tx circuit blocks are powered on. The external PA is powered on - * after a programmable delay using the on-chip PA bias DAC. The slow- - * charging Rx circuits are in a precharged “idle-off” state for fast - * Tx-to-Rx turnaround time. - */ - gpio_clear(PORT_XCVR_ENABLE, PIN_XCVR_RXENABLE); - gpio_set(PORT_XCVR_ENABLE, - (PIN_XCVR_ENABLE | PIN_XCVR_TXENABLE)); -} - -void max2837_mode_rx(void) { - /* All Rx circuit blocks are powered on and active. Antenna signal is - * applied; RF is downconverted, filtered, and buffered at Rx BB I and Q - * outputs. The slow- charging Tx circuits are in a precharged “idle-off” - * state for fast Rx-to-Tx turnaround time. - */ - gpio_clear(PORT_XCVR_ENABLE, PIN_XCVR_TXENABLE); - gpio_set(PORT_XCVR_ENABLE, - (PIN_XCVR_ENABLE | PIN_XCVR_RXENABLE)); -} - -max2837_mode_t max2837_mode(void) { - if( gpio_get(PORT_XCVR_ENABLE, PIN_XCVR_ENABLE) ) { - if( gpio_get(PORT_XCVR_ENABLE, PIN_XCVR_TXENABLE) ) { - return MAX2837_MODE_TX; - } else if( gpio_get(PORT_XCVR_ENABLE, PIN_XCVR_RXENABLE) ) { - return MAX2837_MODE_RX; - } else { - return MAX2837_MODE_STANDBY; - } - } else { - return MAX2837_MODE_SHUTDOWN; - } -} - void max2837_set_mode(const max2837_mode_t new_mode) { switch(new_mode) { case MAX2837_MODE_SHUTDOWN: diff --git a/firmware/common/max2837.h b/firmware/common/max2837.h index 582a0966..d1563d86 100644 --- a/firmware/common/max2837.h +++ b/firmware/common/max2837.h @@ -1,9 +1,33 @@ +/* + * 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 +#include "max2837_drv.h" + /* TODO - make this a private header for max2837.c only, make new max2837.h */ /* 32 registers, each containing 10 bits of data. */ @@ -29,21 +53,11 @@ extern uint16_t max2837_reg_read(uint8_t r); * clean. */ extern void max2837_reg_write(uint8_t r, uint16_t v); -/* Read all registers from chip and copy to memory. Mark all clean. */ -extern void max2837_regs_read(void); - /* Write all dirty registers via SPI from memory. Mark all clean. Some * operations require registers to be written in a certain order. Use * provided routines for those operations. */ extern void max2837_regs_commit(void); -typedef enum { - MAX2837_MODE_SHUTDOWN, - MAX2837_MODE_STANDBY, - MAX2837_MODE_TX, - MAX2837_MODE_RX -} max2837_mode_t; - void max2837_mode_shutdown(void); void max2837_mode_standby(void); void max2837_mode_tx(void); diff --git a/firmware/common/max2837_drv.c b/firmware/common/max2837_drv.c new file mode 100644 index 00000000..235869c1 --- /dev/null +++ b/firmware/common/max2837_drv.c @@ -0,0 +1,159 @@ +/* + * 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. + */ + +#include "max2837_drv.h" + +#if (defined DEBUG || defined BUS_PIRATE) +#include +#define LOG printf +#else +#define LOG(x,...) +#include +#include +#include +#include "hackrf_core.h" +#endif + +void max2837_pin_config(void) { +#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 +} + +void max2837_mode_shutdown(void) { + /* All circuit blocks are powered down, except the 4-wire serial bus + * and its internal programmable registers. + */ + gpio_clear(PORT_XCVR_ENABLE, + (PIN_XCVR_ENABLE | PIN_XCVR_RXENABLE | PIN_XCVR_TXENABLE)); +} + +void max2837_mode_standby(void) { + /* Used to enable the frequency synthesizer block while the rest of the + * device is powered down. In this mode, PLL, VCO, and LO generator + * are on, so that Tx or Rx modes can be quickly enabled from this mode. + * These and other blocks can be selectively enabled in this mode. + */ + gpio_clear(PORT_XCVR_ENABLE, (PIN_XCVR_RXENABLE | PIN_XCVR_TXENABLE)); + gpio_set(PORT_XCVR_ENABLE, PIN_XCVR_ENABLE); +} + +void max2837_mode_tx(void) { + /* All Tx circuit blocks are powered on. The external PA is powered on + * after a programmable delay using the on-chip PA bias DAC. The slow- + * charging Rx circuits are in a precharged “idle-off” state for fast + * Tx-to-Rx turnaround time. + */ + gpio_clear(PORT_XCVR_ENABLE, PIN_XCVR_RXENABLE); + gpio_set(PORT_XCVR_ENABLE, + (PIN_XCVR_ENABLE | PIN_XCVR_TXENABLE)); +} + +void max2837_mode_rx(void) { + /* All Rx circuit blocks are powered on and active. Antenna signal is + * applied; RF is downconverted, filtered, and buffered at Rx BB I and Q + * outputs. The slow- charging Tx circuits are in a precharged “idle-off” + * state for fast Rx-to-Tx turnaround time. + */ + gpio_clear(PORT_XCVR_ENABLE, PIN_XCVR_TXENABLE); + gpio_set(PORT_XCVR_ENABLE, + (PIN_XCVR_ENABLE | PIN_XCVR_RXENABLE)); +} + +max2837_mode_t max2837_mode(void) { + if( gpio_get(PORT_XCVR_ENABLE, PIN_XCVR_ENABLE) ) { + if( gpio_get(PORT_XCVR_ENABLE, PIN_XCVR_TXENABLE) ) { + return MAX2837_MODE_TX; + } else if( gpio_get(PORT_XCVR_ENABLE, PIN_XCVR_RXENABLE) ) { + return MAX2837_MODE_RX; + } else { + return MAX2837_MODE_STANDBY; + } + } else { + return MAX2837_MODE_SHUTDOWN; + } +} + +/* SPI register read. */ +uint16_t max2837_spi_read(uint8_t r) { + gpio_clear(PORT_XCVR_CS, PIN_XCVR_CS); + const uint16_t value = ssp_transfer(SSP1_NUM, (uint16_t)((1 << 15) | (r << 10))); + gpio_set(PORT_XCVR_CS, PIN_XCVR_CS); + return value & 0x3ff; +} + +/* SPI register write */ +void max2837_spi_write(uint8_t r, uint16_t v) { + +#ifdef BUS_PIRATE + LOG("{0x%02x 0x%02x]\n", 0x00 | ((uint16_t)r<<2) | ((v>>8) & 0x3), + v & 0xff); +#elif DEBUG + LOG("0x%03x -> reg%d\n", v, r); +#else + gpio_clear(PORT_XCVR_CS, PIN_XCVR_CS); + ssp_transfer(SSP1_NUM, (uint16_t)((r << 10) | (v & 0x3ff))); + gpio_set(PORT_XCVR_CS, PIN_XCVR_CS); +#endif +} diff --git a/firmware/common/max2837_drv.h b/firmware/common/max2837_drv.h new file mode 100644 index 00000000..a2d61253 --- /dev/null +++ b/firmware/common/max2837_drv.h @@ -0,0 +1,45 @@ +/* + * 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_DRV_H +#define __MAX2837_DRV_H + +#include + +typedef enum { + MAX2837_MODE_SHUTDOWN, + MAX2837_MODE_STANDBY, + MAX2837_MODE_TX, + MAX2837_MODE_RX +} max2837_mode_t; + +void max2837_pin_config(void); +void max2837_mode_shutdown(void); +void max2837_mode_standby(void); +void max2837_mode_tx(void); +void max2837_mode_rx(void); +max2837_mode_t max2837_mode(void); + +uint16_t max2837_spi_read(uint8_t r); +void max2837_spi_write(uint8_t r, uint16_t v); + +#endif // __MAX2837_DRV_H diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index df5d5c96..091f9d43 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -135,6 +135,7 @@ 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_drv.c ${PATH_HACKRF_FIRMWARE_COMMON}/max5864.c ${PATH_HACKRF_FIRMWARE_COMMON}/rffc5071.c m0_bin.s From 453f622b749fdbb6a373094cd7b3599d36b33d71 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 4 Nov 2014 12:15:03 -0800 Subject: [PATCH 04/46] MAX2837: De-singleton the driver. Conflicts: firmware/common/hackrf_core.c firmware/common/hackrf_core.h --- firmware/common/hackrf_core.c | 4 +- firmware/common/hackrf_core.h | 3 + firmware/common/max2837.c | 171 +++++++++++----------- firmware/common/max2837.h | 50 ++----- firmware/common/max2837_drv.c | 25 ++-- firmware/common/max2837_drv.h | 25 +++- firmware/common/max2837_regs.def | 15 +- firmware/common/rf_path.c | 10 +- firmware/common/tuning.c | 15 +- firmware/hackrf_usb/usb_api_register.c | 6 +- firmware/hackrf_usb/usb_api_transceiver.c | 6 +- firmware/mixertx/mixertx.c | 10 +- firmware/simpletx/simpletx.c | 10 +- 13 files changed, 177 insertions(+), 173 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index b862ba4f..201fe367 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -35,6 +35,8 @@ #define WAIT_CPU_CLOCK_INIT_DELAY (10000) +max2837_driver_t max2837; + void delay(uint32_t duration) { uint32_t i; @@ -250,7 +252,7 @@ bool sample_rate_set(const uint32_t sample_rate_hz) { } bool baseband_filter_bandwidth_set(const uint32_t bandwidth_hz) { - return max2837_set_lpf_bandwidth(bandwidth_hz); + return max2837_set_lpf_bandwidth(&max2837, bandwidth_hz); } /* clock startup for Jellybean with Lemondrop attached diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index 8ce6c943..74652cd2 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -32,6 +32,8 @@ extern "C" #include #include +#include "max2837_drv.h" + /* hardware identification number */ #define BOARD_ID_JELLYBEAN 0 #define BOARD_ID_JAWBREAKER 1 @@ -349,6 +351,7 @@ typedef enum { } transceiver_mode_t; void delay(uint32_t duration); +extern max2837_driver_t max2837; void cpu_clock_init(void); void cpu_clock_pll1_low_speed(void); diff --git a/firmware/common/max2837.c b/firmware/common/max2837.c index 73d9e1cd..835751c0 100644 --- a/firmware/common/max2837.c +++ b/firmware/common/max2837.c @@ -43,7 +43,7 @@ #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 */ @@ -82,105 +82,100 @@ 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) +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; + 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"); - max2837_pin_config(); + max2837_pin_config(drv); - max2837_init(); + max2837_init(drv); LOG("# max2837_init done\n"); /* Use SPI control instead of B1-B7 pins for gain settings. */ - set_MAX2837_TXVGA_GAIN_SPI_EN(1); - set_MAX2837_TXVGA_GAIN_MSB_SPI_EN(1); + set_MAX2837_TXVGA_GAIN_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); } -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_spi_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_spi_write(drv, r, v); + MAX2837_REG_SET_CLEAN(drv, r); } -static inline void max2837_reg_commit(uint8_t r) +static inline void max2837_reg_commit(max2837_driver_t* const drv, uint8_t r) { - max2837_reg_write(r,max2837_regs[r]); + max2837_reg_write(drv, r, drv->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_set_mode(const max2837_mode_t new_mode) { +void max2837_set_mode(max2837_driver_t* const drv, const max2837_mode_t new_mode) { switch(new_mode) { case MAX2837_MODE_SHUTDOWN: - max2837_mode_shutdown(); + max2837_mode_shutdown(drv); break; case MAX2837_MODE_STANDBY: - max2837_mode_standby(); + max2837_mode_standby(drv); break; case MAX2837_MODE_TX: - max2837_mode_tx(); + max2837_mode_tx(drv); break; case MAX2837_MODE_RX: - max2837_mode_rx(); + max2837_mode_rx(drv); break; default: @@ -188,50 +183,50 @@ void max2837_set_mode(const max2837_mode_t new_mode) { } } -void max2837_start(void) +void max2837_start(max2837_driver_t* const drv) { LOG("# max2837_start\n"); - set_MAX2837_EN_SPI(1); - max2837_regs_commit(); + set_MAX2837_EN_SPI(drv, 1); + max2837_regs_commit(drv); #if !defined TEST - max2837_mode_standby(); + max2837_mode_standby(drv); #endif } -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(); + set_MAX2837_ModeCtrl(drv, MAX2837_ModeCtrl_TxLPF); + max2837_regs_commit(drv); + max2837_mode_tx(drv); #endif } -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(); + set_MAX2837_ModeCtrl(drv, MAX2837_ModeCtrl_RxLPF); + max2837_regs_commit(drv); #if !defined TEST - max2837_mode_rx(); + max2837_mode_rx(drv); #endif } -void max2837_stop(void) +void max2837_stop(max2837_driver_t* const drv) { LOG("# max2837_stop\n"); - set_MAX2837_EN_SPI(0); - max2837_regs_commit(); + set_MAX2837_EN_SPI(drv, 0); + max2837_regs_commit(drv); #if !defined TEST - max2837_mode_shutdown(); + max2837_mode_shutdown(drv); #endif } -void max2837_set_frequency(uint32_t freq) +void max2837_set_frequency(max2837_driver_t* const drv, uint32_t freq) { uint8_t band; uint8_t lna_band; @@ -278,19 +273,19 @@ void max2837_set_frequency(uint32_t freq) 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 { @@ -318,7 +313,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 ) { @@ -328,15 +323,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: @@ -360,21 +355,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; @@ -383,18 +378,18 @@ 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(); + max2837_setup(drv); + max2837_set_frequency(drv, 2441000000); + max2837_start(drv); + max2837_tx(drv); + max2837_stop(drv); } #endif //TEST diff --git a/firmware/common/max2837.h b/firmware/common/max2837.h index d1563d86..b4fdeb48 100644 --- a/firmware/common/max2837.h +++ b/firmware/common/max2837.h @@ -28,57 +28,39 @@ #include "max2837_drv.h" -/* TODO - make this a private header for max2837.c only, make new max2837.h */ - -/* 32 registers, each containing 10 bits of data. */ -#define MAX2837_NUM_REGS 32 -#define MAX2837_DATA_REGS_MAX_VALUE 1024 - -/* TODO - these externs will be local to max2837.c ... don't define here? */ -extern uint16_t max2837_regs[MAX2837_NUM_REGS]; -extern uint32_t max2837_regs_dirty; - -#define MAX2837_REG_SET_CLEAN(r) max2837_regs_dirty &= ~(1UL<>8) & 0x3), diff --git a/firmware/common/max2837_drv.h b/firmware/common/max2837_drv.h index a2d61253..c7f1062e 100644 --- a/firmware/common/max2837_drv.h +++ b/firmware/common/max2837_drv.h @@ -25,6 +25,10 @@ #include +/* 32 registers, each containing 10 bits of data. */ +#define MAX2837_NUM_REGS 32 +#define MAX2837_DATA_REGS_MAX_VALUE 1024 + typedef enum { MAX2837_MODE_SHUTDOWN, MAX2837_MODE_STANDBY, @@ -32,14 +36,19 @@ typedef enum { MAX2837_MODE_RX } max2837_mode_t; -void max2837_pin_config(void); -void max2837_mode_shutdown(void); -void max2837_mode_standby(void); -void max2837_mode_tx(void); -void max2837_mode_rx(void); -max2837_mode_t max2837_mode(void); +typedef struct { + uint16_t regs[MAX2837_NUM_REGS]; + uint32_t regs_dirty; +} max2837_driver_t; -uint16_t max2837_spi_read(uint8_t r); -void max2837_spi_write(uint8_t r, uint16_t v); +void max2837_pin_config(max2837_driver_t* const drv); +void max2837_mode_shutdown(max2837_driver_t* const drv); +void max2837_mode_standby(max2837_driver_t* const drv); +void max2837_mode_tx(max2837_driver_t* const drv); +void max2837_mode_rx(max2837_driver_t* const drv); +max2837_mode_t max2837_mode(max2837_driver_t* const drv); + +uint16_t max2837_spi_read(max2837_driver_t* const drv, uint8_t r); +void max2837_spi_write(max2837_driver_t* const drv, uint8_t r, uint16_t v); #endif // __MAX2837_DRV_H diff --git a/firmware/common/max2837_regs.def b/firmware/common/max2837_regs.def index 0247afad..0aa2f9e5 100644 --- a/firmware/common/max2837_regs.def +++ b/firmware/common/max2837_regs.def @@ -9,19 +9,22 @@ * (structs). This may be used in firmware, or on host predefined * register loads. */ +#define MAX2837_REG_SET_CLEAN(_d, _r) (_d->regs_dirty &= ~(1UL<<_r)) +#define MAX2837_REG_SET_DIRTY(_d, _r) (_d->regs_dirty |= (1UL<<_r)) + /* On set_, register is always set dirty, even if nothing * 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< #include #include #include @@ -62,8 +63,8 @@ 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_mode_standby(&max2837); if(freq_mhz < MAX_LP_FREQ_MHZ) { rf_path_set_filter(RF_PATH_FILTER_LOW_PASS); @@ -72,14 +73,14 @@ bool set_freq(const uint64_t freq) 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); + max2837_set_frequency(&max2837, real_RFFC5071_freq_hz - freq); sgpio_cpld_stream_rx_set_q_invert(1); }else if( (freq_mhz >= MIN_BYPASS_FREQ_MHZ) && (freq_mhz < MAX_BYPASS_FREQ_MHZ) ) { rf_path_set_filter(RF_PATH_FILTER_BYPASS); MAX2837_freq_hz = (freq_mhz * FREQ_ONE_MHZ) + freq_hz; /* RFFC5071_freq_mhz <= not used in Bypass mode */ - max2837_set_frequency(MAX2837_freq_hz); + max2837_set_frequency(&max2837, MAX2837_freq_hz); sgpio_cpld_stream_rx_set_q_invert(0); }else if( (freq_mhz >= MIN_HP_FREQ_MHZ) && (freq_mhz <= MAX_HP_FREQ_MHZ) ) { @@ -97,14 +98,14 @@ bool set_freq(const uint64_t freq) 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); + max2837_set_frequency(&max2837, freq - real_RFFC5071_freq_hz); sgpio_cpld_stream_rx_set_q_invert(0); }else { /* Error freq_mhz too high */ success = false; } - max2837_set_mode(prior_max2837_mode); + max2837_set_mode(&max2837, prior_max2837_mode); if( success ) { freq_cache = freq; } @@ -129,7 +130,7 @@ bool set_freq_explicit(const uint64_t if_freq_hz, const uint64_t lo_freq_hz, } rf_path_set_filter(path); - max2837_set_frequency(if_freq_hz); + max2837_set_frequency(&max2837, if_freq_hz); if (lo_freq_hz > if_freq_hz) { sgpio_cpld_stream_rx_set_q_invert(1); } else { diff --git a/firmware/hackrf_usb/usb_api_register.c b/firmware/hackrf_usb/usb_api_register.c index d822c924..3dfb5a49 100644 --- a/firmware/hackrf_usb/usb_api_register.c +++ b/firmware/hackrf_usb/usb_api_register.c @@ -30,6 +30,8 @@ #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, diff --git a/firmware/hackrf_usb/usb_api_transceiver.c b/firmware/hackrf_usb/usb_api_transceiver.c index 7ab06376..b2297dbc 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.c +++ b/firmware/hackrf_usb/usb_api_transceiver.c @@ -145,7 +145,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 +159,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 +173,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); diff --git a/firmware/mixertx/mixertx.c b/firmware/mixertx/mixertx.c index 363859f5..ba3c6482 100644 --- a/firmware/mixertx/mixertx.c +++ b/firmware/mixertx/mixertx.c @@ -43,16 +43,16 @@ int main(void) gpio_set(PORT_LED1_3, (PIN_LED1)); /* LED1 on */ ssp1_set_mode_max2837(); - max2837_setup(); + max2837_setup(&max2837); rffc5071_setup(); gpio_set(PORT_LED1_3, (PIN_LED2)); /* LED2 on */ - max2837_set_frequency(freq); - max2837_start(); - max2837_tx(); + max2837_set_frequency(&max2837, freq); + max2837_start(&max2837); + max2837_tx(&max2837); gpio_set(PORT_LED1_3, (PIN_LED3)); /* LED3 on */ while (1); - max2837_stop(); + max2837_stop(&max2837); return 0; } diff --git a/firmware/simpletx/simpletx.c b/firmware/simpletx/simpletx.c index 04efb686..d6f9072d 100644 --- a/firmware/simpletx/simpletx.c +++ b/firmware/simpletx/simpletx.c @@ -42,14 +42,14 @@ int main(void) gpio_set(PORT_LED1_3, (PIN_LED1)); /* LED1 on */ ssp1_set_mode_max2837(); - max2837_setup(); + max2837_setup(&max2837); gpio_set(PORT_LED1_3, (PIN_LED2)); /* LED2 on */ - max2837_set_frequency(freq); - max2837_start(); - max2837_tx(); + max2837_set_frequency(&max2837, freq); + max2837_start(&max2837); + max2837_tx(&max2837); gpio_set(PORT_LED1_3, (PIN_LED3)); /* LED3 on */ while (1); - max2837_stop(); + max2837_stop(&max2837); return 0; } From 0c69d0a7f7c78b306cbf22de58d9b63eba856350 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 4 Nov 2014 12:35:38 -0800 Subject: [PATCH 05/46] RFFC5071: Separate hardware-specific code. Conflicts: firmware/CMakeLists.txt firmware/hackrf_usb/Makefile firmware/mixertx/Makefile firmware/sgpio/CMakeLists.txt firmware/simpletx/Makefile firmware/spiflash/CMakeLists.txt firmware/startup/Makefile firmware/startup_systick/Makefile firmware/startup_systick_perfo/Makefile --- firmware/common/rffc5071.c | 198 +--------------------------- firmware/common/rffc5071_drv.c | 229 +++++++++++++++++++++++++++++++++ firmware/common/rffc5071_drv.h | 31 +++++ firmware/hackrf-common.cmake | 1 + 4 files changed, 263 insertions(+), 196 deletions(-) create mode 100644 firmware/common/rffc5071_drv.c create mode 100644 firmware/common/rffc5071_drv.h diff --git a/firmware/common/rffc5071.c b/firmware/common/rffc5071.c index 96745eb4..1384a8c7 100644 --- a/firmware/common/rffc5071.c +++ b/firmware/common/rffc5071.c @@ -34,6 +34,7 @@ #include #include #include "rffc5071.h" +#include "rffc5071_drv.h" #include "rffc5071_regs.def" // private register def macros #if (defined DEBUG) @@ -41,9 +42,6 @@ #define LOG printf #else #define LOG(x,...) -#include -#include -#include #include "hackrf_core.h" #endif @@ -105,25 +103,8 @@ void rffc5071_setup(void) { rffc5071_init(); LOG("# rffc5071_setup\n"); -#if !defined TEST - /* Configure GPIO pins. */ - scu_pinmux(SCU_MIXER_ENX, SCU_GPIO_FAST); - scu_pinmux(SCU_MIXER_SCLK, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - scu_pinmux(SCU_MIXER_SDATA, SCU_GPIO_FAST); - scu_pinmux(SCU_MIXER_RESETX, SCU_GPIO_FAST); - /* Set GPIO pins as outputs. */ - GPIO_DIR(PORT_MIXER_ENX) |= PIN_MIXER_ENX; - GPIO_DIR(PORT_MIXER_SCLK) |= PIN_MIXER_SCLK; - GPIO_DIR(PORT_MIXER_SDATA) |= PIN_MIXER_SDATA; - GPIO_DIR(PORT_MIXER_RESETX) |= PIN_MIXER_RESETX; - - /* set to known state */ - gpio_set(PORT_MIXER_ENX, PIN_MIXER_ENX); /* active low */ - gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA); - gpio_set(PORT_MIXER_RESETX, PIN_MIXER_RESETX); /* active low */ -#endif + rffc5071_pin_config(); /* initial setup */ /* put zeros in freq contol registers */ @@ -152,181 +133,6 @@ void rffc5071_setup(void) rffc5071_regs_commit(); } -void serial_delay(void) -{ - uint32_t i; - - for (i = 0; i < 2; i++) - __asm__("nop"); -} - -/* SPI register read. - * - * Send 9 bits: - * first bit is ignored, - * second bit is one for read operation, - * next 7 bits are register address. - * Then receive 16 bits (register value). - */ -uint16_t rffc5071_spi_read(uint8_t r) { - - int bits = 9; - int msb = 1 << (bits -1); - uint32_t data = 0x80 | (r & 0x7f); - -#if DEBUG - LOG("reg%d = 0\n", r); - return 0; -#else - /* make sure everything is starting in the correct state */ - gpio_set(PORT_MIXER_ENX, PIN_MIXER_ENX); - gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA); - - /* - * The device requires two clocks while ENX is high before a serial - * transaction. This is not clearly documented. - */ - serial_delay(); - gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - - serial_delay(); - gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - - serial_delay(); - gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - - serial_delay(); - gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - - /* start transaction by bringing ENX low */ - gpio_clear(PORT_MIXER_ENX, PIN_MIXER_ENX); - - while (bits--) { - if (data & msb) - gpio_set(PORT_MIXER_SDATA, PIN_MIXER_SDATA); - else - gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA); - data <<= 1; - - serial_delay(); - gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - - serial_delay(); - gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - } - - serial_delay(); - gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - - serial_delay(); - gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - - bits = 16; - data = 0; - /* set SDATA line as input */ - GPIO_DIR(PORT_MIXER_SDATA) &= ~PIN_MIXER_SDATA; - - while (bits--) { - data <<= 1; - - serial_delay(); - gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - - serial_delay(); - gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - if (MIXER_SDATA_STATE) - data |= 1; - } - /* set SDATA line as output */ - GPIO_DIR(PORT_MIXER_SDATA) |= PIN_MIXER_SDATA; - - serial_delay(); - gpio_set(PORT_MIXER_ENX, PIN_MIXER_ENX); - - /* - * The device requires a clock while ENX is high after a serial - * transaction. This is not clearly documented. - */ - gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - - serial_delay(); - gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - - return data; -#endif /* DEBUG */ -} - -/* SPI register write - * - * Send 25 bits: - * first bit is ignored, - * second bit is zero for write operation, - * next 7 bits are register address, - * next 16 bits are register value. - */ -void rffc5071_spi_write(uint8_t r, uint16_t v) { - -#if DEBUG - LOG("0x%04x -> reg%d\n", v, r); -#else - - int bits = 25; - int msb = 1 << (bits -1); - uint32_t data = ((r & 0x7f) << 16) | v; - - /* make sure everything is starting in the correct state */ - gpio_set(PORT_MIXER_ENX, PIN_MIXER_ENX); - gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA); - - /* - * The device requires two clocks while ENX is high before a serial - * transaction. This is not clearly documented. - */ - serial_delay(); - gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - - serial_delay(); - gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - - serial_delay(); - gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - - serial_delay(); - gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - - /* start transaction by bringing ENX low */ - gpio_clear(PORT_MIXER_ENX, PIN_MIXER_ENX); - - while (bits--) { - if (data & msb) - gpio_set(PORT_MIXER_SDATA, PIN_MIXER_SDATA); - else - gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA); - data <<= 1; - - serial_delay(); - gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - - serial_delay(); - gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - } - - gpio_set(PORT_MIXER_ENX, PIN_MIXER_ENX); - - /* - * The device requires a clock while ENX is high after a serial - * transaction. This is not clearly documented. - */ - serial_delay(); - gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - - serial_delay(); - gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); -#endif -} - uint16_t rffc5071_reg_read(uint8_t r) { /* Readback register is not cached. */ diff --git a/firmware/common/rffc5071_drv.c b/firmware/common/rffc5071_drv.c new file mode 100644 index 00000000..4642e386 --- /dev/null +++ b/firmware/common/rffc5071_drv.c @@ -0,0 +1,229 @@ +/* + * 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. + */ + +#if (defined DEBUG) +#include +#define LOG printf +#else +#define LOG(x,...) +#include +#include +#include +#include "hackrf_core.h" +#endif + +void rffc5071_pin_config() { +#if !defined TEST + /* Configure GPIO pins. */ + scu_pinmux(SCU_MIXER_ENX, SCU_GPIO_FAST); + scu_pinmux(SCU_MIXER_SCLK, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu_pinmux(SCU_MIXER_SDATA, SCU_GPIO_FAST); + scu_pinmux(SCU_MIXER_RESETX, SCU_GPIO_FAST); + + /* Set GPIO pins as outputs. */ + GPIO_DIR(PORT_MIXER_ENX) |= PIN_MIXER_ENX; + GPIO_DIR(PORT_MIXER_SCLK) |= PIN_MIXER_SCLK; + GPIO_DIR(PORT_MIXER_SDATA) |= PIN_MIXER_SDATA; + GPIO_DIR(PORT_MIXER_RESETX) |= PIN_MIXER_RESETX; + + /* set to known state */ + gpio_set(PORT_MIXER_ENX, PIN_MIXER_ENX); /* active low */ + gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); + gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA); + gpio_set(PORT_MIXER_RESETX, PIN_MIXER_RESETX); /* active low */ +#endif +} + +static void serial_delay(void) +{ + uint32_t i; + + for (i = 0; i < 2; i++) + __asm__("nop"); +} + +/* SPI register read. + * + * Send 9 bits: + * first bit is ignored, + * second bit is one for read operation, + * next 7 bits are register address. + * Then receive 16 bits (register value). + */ +uint16_t rffc5071_spi_read(uint8_t r) { + + int bits = 9; + int msb = 1 << (bits -1); + uint32_t data = 0x80 | (r & 0x7f); + +#if DEBUG + LOG("reg%d = 0\n", r); + return 0; +#else + /* make sure everything is starting in the correct state */ + gpio_set(PORT_MIXER_ENX, PIN_MIXER_ENX); + gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); + gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA); + + /* + * The device requires two clocks while ENX is high before a serial + * transaction. This is not clearly documented. + */ + serial_delay(); + gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); + + serial_delay(); + gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); + + serial_delay(); + gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); + + serial_delay(); + gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); + + /* start transaction by bringing ENX low */ + gpio_clear(PORT_MIXER_ENX, PIN_MIXER_ENX); + + while (bits--) { + if (data & msb) + gpio_set(PORT_MIXER_SDATA, PIN_MIXER_SDATA); + else + gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA); + data <<= 1; + + serial_delay(); + gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); + + serial_delay(); + gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); + } + + serial_delay(); + gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); + + serial_delay(); + gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); + + bits = 16; + data = 0; + /* set SDATA line as input */ + GPIO_DIR(PORT_MIXER_SDATA) &= ~PIN_MIXER_SDATA; + + while (bits--) { + data <<= 1; + + serial_delay(); + gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); + + serial_delay(); + gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); + if (MIXER_SDATA_STATE) + data |= 1; + } + /* set SDATA line as output */ + GPIO_DIR(PORT_MIXER_SDATA) |= PIN_MIXER_SDATA; + + serial_delay(); + gpio_set(PORT_MIXER_ENX, PIN_MIXER_ENX); + + /* + * The device requires a clock while ENX is high after a serial + * transaction. This is not clearly documented. + */ + gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); + + serial_delay(); + gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); + + return data; +#endif /* DEBUG */ +} + +/* SPI register write + * + * Send 25 bits: + * first bit is ignored, + * second bit is zero for write operation, + * next 7 bits are register address, + * next 16 bits are register value. + */ +void rffc5071_spi_write(uint8_t r, uint16_t v) { + +#if DEBUG + LOG("0x%04x -> reg%d\n", v, r); +#else + + int bits = 25; + int msb = 1 << (bits -1); + uint32_t data = ((r & 0x7f) << 16) | v; + + /* make sure everything is starting in the correct state */ + gpio_set(PORT_MIXER_ENX, PIN_MIXER_ENX); + gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); + gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA); + + /* + * The device requires two clocks while ENX is high before a serial + * transaction. This is not clearly documented. + */ + serial_delay(); + gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); + + serial_delay(); + gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); + + serial_delay(); + gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); + + serial_delay(); + gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); + + /* start transaction by bringing ENX low */ + gpio_clear(PORT_MIXER_ENX, PIN_MIXER_ENX); + + while (bits--) { + if (data & msb) + gpio_set(PORT_MIXER_SDATA, PIN_MIXER_SDATA); + else + gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA); + data <<= 1; + + serial_delay(); + gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); + + serial_delay(); + gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); + } + + gpio_set(PORT_MIXER_ENX, PIN_MIXER_ENX); + + /* + * The device requires a clock while ENX is high after a serial + * transaction. This is not clearly documented. + */ + serial_delay(); + gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); + + serial_delay(); + gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); +#endif +} diff --git a/firmware/common/rffc5071_drv.h b/firmware/common/rffc5071_drv.h new file mode 100644 index 00000000..eea5ee50 --- /dev/null +++ b/firmware/common/rffc5071_drv.h @@ -0,0 +1,31 @@ +/* + * 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_DRV_H +#define __RFFC5071_DRV_H + +void rffc5071_pin_config(); + +uint16_t rffc5071_spi_read(uint8_t r); +void rffc5071_spi_write(uint8_t r, uint16_t v); + +#endif // __RFFC5071_DRV_H diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index 091f9d43..cf4d0182 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -138,6 +138,7 @@ macro(DeclareTargets) ${PATH_HACKRF_FIRMWARE_COMMON}/max2837_drv.c ${PATH_HACKRF_FIRMWARE_COMMON}/max5864.c ${PATH_HACKRF_FIRMWARE_COMMON}/rffc5071.c + ${PATH_HACKRF_FIRMWARE_COMMON}/rffc5071_drv.c m0_bin.s ) From d55bd529e2b95e487852ac54625800ffbbd69e1f Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 4 Nov 2014 13:05:07 -0800 Subject: [PATCH 06/46] RFFC507x: De-singleton the driver code. --- firmware/common/hackrf_core.c | 2 + firmware/common/hackrf_core.h | 2 + firmware/common/rf_path.c | 28 ++-- firmware/common/rffc5071.c | 191 ++++++++++++------------- firmware/common/rffc5071.h | 33 ++--- firmware/common/rffc5071_drv.c | 11 +- firmware/common/rffc5071_drv.h | 14 +- firmware/common/rffc5071_regs.def | 15 +- firmware/common/tuning.c | 6 +- firmware/hackrf_usb/usb_api_register.c | 4 +- firmware/mixertx/mixertx.c | 2 +- 11 files changed, 158 insertions(+), 150 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 201fe367..db5029ad 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -37,6 +37,8 @@ max2837_driver_t max2837; +rffc5071_driver_t rffc5072; + void delay(uint32_t duration) { uint32_t i; diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index 74652cd2..afa3379d 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -33,6 +33,7 @@ extern "C" #include #include "max2837_drv.h" +#include "rffc5071_drv.h" /* hardware identification number */ #define BOARD_ID_JELLYBEAN 0 @@ -352,6 +353,7 @@ typedef enum { void delay(uint32_t duration); extern max2837_driver_t max2837; +extern rffc5071_driver_t rffc5072; void cpu_clock_init(void); void cpu_clock_pll1_low_speed(void); diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index 14353363..071564da 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -149,16 +149,16 @@ static void switchctrl_set_hackrf_one(uint8_t ctrl) { gpio_set(PORT_NO_RX_AMP_PWR, PIN_NO_RX_AMP_PWR); if (ctrl & SWITCHCTRL_ANT_PWR) { - rffc5071_set_gpo(0x00); /* turn on antenna power by clearing GPO1 */ + 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) { #ifdef JAWBREAKER - rffc5071_set_gpo(gpo); + rffc5071_set_gpo(&rffc5072, gpo); #elif HACKRF_ONE switchctrl_set_hackrf_one(gpo); #else @@ -215,7 +215,7 @@ void rf_path_init(void) { max2837_setup(&max2837); max2837_start(&max2837); - rffc5071_setup(); + rffc5071_setup(&rffc5072); switchctrl_set(switchctrl); } @@ -229,11 +229,11 @@ void rf_path_set_direction(const rf_path_direction_t direction) { /* TX amplifier is in path, be sure to enable TX amplifier. */ switchctrl &= ~SWITCHCTRL_NO_TX_AMP_PWR; } - rffc5071_tx(); + rffc5071_tx(&rffc5072); if( switchctrl & SWITCHCTRL_MIX_BYPASS ) { - rffc5071_disable(); + rffc5071_disable(&rffc5072); } else { - rffc5071_enable(); + rffc5071_enable(&rffc5072); } ssp1_set_mode_max5864(); max5864_tx(); @@ -248,11 +248,11 @@ void rf_path_set_direction(const rf_path_direction_t direction) { /* RX amplifier is in path, be sure to enable RX amplifier. */ switchctrl &= ~SWITCHCTRL_NO_RX_AMP_PWR; } - rffc5071_rx(); + rffc5071_rx(&rffc5072); if( switchctrl & SWITCHCTRL_MIX_BYPASS ) { - rffc5071_disable(); + rffc5071_disable(&rffc5072); } else { - rffc5071_enable(); + rffc5071_enable(&rffc5072); } ssp1_set_mode_max5864(); max5864_rx(); @@ -268,7 +268,7 @@ void rf_path_set_direction(const rf_path_direction_t direction) { #endif /* Set RF path to receive direction when "off" */ switchctrl &= ~SWITCHCTRL_TX; - rffc5071_disable(); + rffc5071_disable(&rffc5072); ssp1_set_mode_max5864(); max5864_standby(); ssp1_set_mode_max2837(); @@ -285,18 +285,18 @@ void rf_path_set_filter(const rf_path_filter_t filter) { default: case RF_PATH_FILTER_BYPASS: switchctrl |= SWITCHCTRL_MIX_BYPASS; - rffc5071_disable(); + rffc5071_disable(&rffc5072); break; case RF_PATH_FILTER_LOW_PASS: switchctrl &= ~(SWITCHCTRL_HP | SWITCHCTRL_MIX_BYPASS); - rffc5071_enable(); + rffc5071_enable(&rffc5072); break; case RF_PATH_FILTER_HIGH_PASS: switchctrl &= ~SWITCHCTRL_MIX_BYPASS; switchctrl |= SWITCHCTRL_HP; - rffc5071_enable(); + rffc5071_enable(&rffc5072); break; } diff --git a/firmware/common/rffc5071.c b/firmware/common/rffc5071.c index 1384a8c7..6234a318 100644 --- a/firmware/common/rffc5071.c +++ b/firmware/common/rffc5071.c @@ -46,7 +46,7 @@ #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 */ @@ -79,135 +79,130 @@ 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(); + rffc5071_init(drv); LOG("# rffc5071_setup\n"); - rffc5071_pin_config(); + rffc5071_pin_config(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); } -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) { +void rffc5071_tx(rffc5071_driver_t* const drv) { 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(); + 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) { +void rffc5071_rx(rffc5071_driver_t* const drv) { 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(); + 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) { +void rffc5071_rxtx(rffc5071_driver_t* const drv) { LOG("# rfc5071_rxtx\n"); - set_RFFC5071_ENBL(0); - set_RFFC5071_FULLD(1); /* mixer 1 and mixer 2 (RXTX) */ - rffc5071_regs_commit(); + 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) { +void rffc5071_disable(rffc5071_driver_t* const drv) { LOG("# rfc5071_disable\n"); - set_RFFC5071_ENBL(0); - rffc5071_regs_commit(); + set_RFFC5071_ENBL(drv, 0); + rffc5071_regs_commit(drv); } -void rffc5071_enable(void) { +void rffc5071_enable(rffc5071_driver_t* const drv) { LOG("# rfc5071_enable\n"); - set_RFFC5071_ENBL(1); - rffc5071_regs_commit(); + set_RFFC5071_ENBL(drv, 1); + rffc5071_regs_commit(drv); } #define LO_MAX 5400 @@ -215,7 +210,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; @@ -244,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) ; @@ -262,59 +257,59 @@ uint64_t rffc5071_config_synth_int(uint16_t lo) { 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(); + rffc5071_setup(drv); + rffc5071_tx(drv, 0); + rffc5071_set_frequency(drv, 500, 0); + rffc5071_set_frequency(drv, 525, 0); + rffc5071_set_frequency(drv, 550, 0); + rffc5071_set_frequency(drv, 1500, 0); + rffc5071_set_frequency(drv, 1525, 0); + rffc5071_set_frequency(drv, 1550, 0); + rffc5071_disable(drv); + rffc5071_rx(drv, 0); + rffc5071_disable(drv); + rffc5071_rxtx(drv); + rffc5071_disable(drv); } #endif //TEST diff --git a/firmware/common/rffc5071.h b/firmware/common/rffc5071.h index 98c31a3e..7b2a7801 100644 --- a/firmware/common/rffc5071.h +++ b/firmware/common/rffc5071.h @@ -23,43 +23,38 @@ #ifndef __RFFC5071_H #define __RFFC5071_H -/* 31 registers, each containing 16 bits of data. */ -#define RFFC5071_NUM_REGS 31 +#include -extern uint16_t rffc5071_regs[RFFC5071_NUM_REGS]; -extern uint32_t rffc5071_regs_dirty; - -#define RFFC5071_REG_SET_CLEAN(r) rffc5071_regs_dirty &= ~(1UL< reg%d\n", v, r); #else diff --git a/firmware/common/rffc5071_drv.h b/firmware/common/rffc5071_drv.h index eea5ee50..441071ad 100644 --- a/firmware/common/rffc5071_drv.h +++ b/firmware/common/rffc5071_drv.h @@ -23,9 +23,17 @@ #ifndef __RFFC5071_DRV_H #define __RFFC5071_DRV_H -void rffc5071_pin_config(); +/* 31 registers, each containing 16 bits of data. */ +#define RFFC5071_NUM_REGS 31 -uint16_t rffc5071_spi_read(uint8_t r); -void rffc5071_spi_write(uint8_t r, uint16_t v); +typedef struct { + uint16_t regs[RFFC5071_NUM_REGS]; + uint32_t regs_dirty; +} rffc5071_driver_t; + +void rffc5071_pin_config(rffc5071_driver_t* const drv); + +uint16_t rffc5071_spi_read(rffc5071_driver_t* const drv, uint8_t r); +void rffc5071_spi_write(rffc5071_driver_t* const drv, uint8_t r, uint16_t v); #endif // __RFFC5071_DRV_H diff --git a/firmware/common/rffc5071_regs.def b/firmware/common/rffc5071_regs.def index d17a064f..ae45a677 100644 --- a/firmware/common/rffc5071_regs.def +++ b/firmware/common/rffc5071_regs.def @@ -23,6 +23,9 @@ #ifndef __RFFC5071_REGS_DEF #define __RFFC5071_REGS_DEF +#define RFFC5071_REG_SET_CLEAN(_d, _r) (_d->regs_dirty &= ~(1UL<<_r)) +#define RFFC5071_REG_SET_DIRTY(_d, _r) (_d->regs_dirty |= (1UL<<_r)) + #define RFFC5071_READBACK_REG 31 /* 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<= MIN_BYPASS_FREQ_MHZ) && (freq_mhz < MAX_BYPASS_FREQ_MHZ) ) @@ -97,7 +97,7 @@ bool set_freq(const uint64_t freq) rf_path_set_filter(RF_PATH_FILTER_HIGH_PASS); RFFC5071_freq_mhz = freq_mhz - (max2837_freq_nominal_hz / FREQ_ONE_MHZ); /* Set Freq and read real freq */ - real_RFFC5071_freq_hz = rffc5071_set_frequency(RFFC5071_freq_mhz); + 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(0); }else @@ -137,7 +137,7 @@ bool set_freq_explicit(const uint64_t if_freq_hz, const uint64_t lo_freq_hz, sgpio_cpld_stream_rx_set_q_invert(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/hackrf_usb/usb_api_register.c b/firmware/hackrf_usb/usb_api_register.c index 3dfb5a49..c8b8678a 100644 --- a/firmware/hackrf_usb/usb_api_register.c +++ b/firmware/hackrf_usb/usb_api_register.c @@ -115,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; } @@ -134,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/mixertx/mixertx.c b/firmware/mixertx/mixertx.c index ba3c6482..c7150d57 100644 --- a/firmware/mixertx/mixertx.c +++ b/firmware/mixertx/mixertx.c @@ -44,7 +44,7 @@ int main(void) ssp1_set_mode_max2837(); max2837_setup(&max2837); - rffc5071_setup(); + rffc5071_setup(&rffc5072); gpio_set(PORT_LED1_3, (PIN_LED2)); /* LED2 on */ max2837_set_frequency(&max2837, freq); From 4ac2be5304b433cac4859cc709cc46b6e0cf3cca Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 4 Nov 2014 16:33:09 -0800 Subject: [PATCH 07/46] W25Q80BV: Extract hardware-specific code into separate layer. Conflicts: firmware/hackrf_usb/Makefile --- firmware/common/w25q80bv.c | 107 +++++++++-------------------- firmware/common/w25q80bv.h | 1 + firmware/common/w25q80bv_drv.c | 88 ++++++++++++++++++++++++ firmware/common/w25q80bv_drv.h | 35 ++++++++++ firmware/hackrf_usb/CMakeLists.txt | 1 + 5 files changed, 157 insertions(+), 75 deletions(-) create mode 100644 firmware/common/w25q80bv_drv.c create mode 100644 firmware/common/w25q80bv_drv.h diff --git a/firmware/common/w25q80bv.c b/firmware/common/w25q80bv.c index 2b391d9d..fc440e6f 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. * @@ -28,11 +29,7 @@ #include #include "w25q80bv.h" -#include "hackrf_core.h" -#include -#include -#include -#include +#include "w25q80bv_drv.h" /* * Set up pins for GPIO and SPI control, configure SSP0 peripheral for SPI. @@ -42,48 +39,8 @@ void w25q80bv_setup(void) { uint8_t device_id; - const uint8_t serial_clock_rate = 2; - const uint8_t clock_prescale_rate = 2; - /* Reset SPIFI peripheral before to Erase/Write SPIFI memory through SPI */ - RESET_CTRL1 = RESET_CTRL1_SPIFI_RST; - - /* Init SPIFI GPIO to Normal GPIO */ - scu_pinmux(P3_3, (SCU_SSP_IO | SCU_CONF_FUNCTION2)); // P3_3 SPIFI_SCK => SSP0_SCK - scu_pinmux(P3_4, (SCU_GPIO_FAST | SCU_CONF_FUNCTION0)); // P3_4 SPIFI SPIFI_SIO3 IO3 => GPIO1[14] - scu_pinmux(P3_5, (SCU_GPIO_FAST | SCU_CONF_FUNCTION0)); // P3_5 SPIFI SPIFI_SIO2 IO2 => GPIO1[15] - scu_pinmux(P3_6, (SCU_GPIO_FAST | SCU_CONF_FUNCTION0)); // P3_6 SPIFI SPIFI_MISO IO1 => GPIO0[6] - scu_pinmux(P3_7, (SCU_GPIO_FAST | SCU_CONF_FUNCTION4)); // P3_7 SPIFI SPIFI_MOSI IO0 => GPIO5[10] - scu_pinmux(P3_8, (SCU_GPIO_FAST | SCU_CONF_FUNCTION4)); // P3_8 SPIFI SPIFI_CS => GPIO5[11] - - /* configure SSP pins */ - scu_pinmux(SCU_SSP0_MISO, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); - scu_pinmux(SCU_SSP0_MOSI, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); - scu_pinmux(SCU_SSP0_SCK, (SCU_SSP_IO | SCU_CONF_FUNCTION2)); - - /* configure GPIO pins */ - scu_pinmux(SCU_FLASH_HOLD, SCU_GPIO_FAST); - scu_pinmux(SCU_FLASH_WP, SCU_GPIO_FAST); - scu_pinmux(SCU_SSP0_SSEL, (SCU_GPIO_FAST | SCU_CONF_FUNCTION4)); - - /* drive SSEL, HOLD, and WP pins high */ - gpio_set(PORT_FLASH, (PIN_FLASH_HOLD | PIN_FLASH_WP)); - gpio_set(PORT_SSP0_SSEL, PIN_SSP0_SSEL); - - /* Set GPIO pins as outputs. */ - GPIO1_DIR |= (PIN_FLASH_HOLD | PIN_FLASH_WP); - GPIO5_DIR |= PIN_SSP0_SSEL; - - /* initialize SSP0 */ - ssp_init(SSP0_NUM, - SSP_DATA_8BITS, - SSP_FRAME_SPI, - SSP_CPOL_0_CPHA_0, - serial_clock_rate, - clock_prescale_rate, - SSP_MODE_NORMAL, - SSP_MASTER, - SSP_SLAVE_OUT_ENABLE); + w25q80bv_spi_init(); device_id = 0; while(device_id != W25Q80BV_DEVICE_ID_RES) @@ -96,10 +53,10 @@ uint8_t w25q80bv_get_status(void) { uint8_t value; - gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL); - ssp_transfer(SSP0_NUM, W25Q80BV_READ_STATUS1); - value = ssp_transfer(SSP0_NUM, 0xFF); - gpio_set(PORT_SSP0_SSEL, PIN_SSP0_SSEL); + w25q80bv_spi_select(); + w25q80bv_spi_transfer(W25Q80BV_READ_STATUS1); + value = w25q80bv_spi_transfer(0xFF); + w25q80bv_spi_unselect(); return value; } @@ -109,17 +66,17 @@ uint8_t w25q80bv_get_device_id(void) { uint8_t value; - gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL); - ssp_transfer(SSP0_NUM, W25Q80BV_DEVICE_ID); + w25q80bv_spi_select(); + w25q80bv_spi_transfer(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); + value = w25q80bv_spi_transfer(0xFF); + value = w25q80bv_spi_transfer(0xFF); + value = w25q80bv_spi_transfer(0xFF); /* Read Device ID shall return 0x13 for W25Q80BV */ - value = ssp_transfer(SSP0_NUM, 0xFF); + value = w25q80bv_spi_transfer(0xFF); - gpio_set(PORT_SSP0_SSEL, PIN_SSP0_SSEL); + w25q80bv_spi_unselect(); return value; } @@ -129,21 +86,21 @@ void w25q80bv_get_unique_id(w25q80bv_unique_id_t* unique_id) int i; uint8_t value; - gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL); - ssp_transfer(SSP0_NUM, W25Q80BV_UNIQUE_ID); + w25q80bv_spi_select(); + w25q80bv_spi_transfer(W25Q80BV_UNIQUE_ID); /* Read 4 dummy bytes */ for(i=0; i<4; i++) - value = ssp_transfer(SSP0_NUM, 0xFF); + value = w25q80bv_spi_transfer(0xFF); /* Read Unique ID 64bits (8*8) */ for(i=0; i<8; i++) { - value = ssp_transfer(SSP0_NUM, 0xFF); + value = w25q80bv_spi_transfer(0xFF); unique_id->id_8b[i] = value; } - gpio_set(PORT_SSP0_SSEL, PIN_SSP0_SSEL); + w25q80bv_spi_unselect(); } void w25q80bv_wait_while_busy(void) @@ -154,9 +111,9 @@ void w25q80bv_wait_while_busy(void) void w25q80bv_write_enable(void) { w25q80bv_wait_while_busy(); - gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL); - ssp_transfer(SSP0_NUM, W25Q80BV_WRITE_ENABLE); - gpio_set(PORT_SSP0_SSEL, PIN_SSP0_SSEL); + w25q80bv_spi_select(); + w25q80bv_spi_transfer(W25Q80BV_WRITE_ENABLE); + w25q80bv_spi_unselect(); } void w25q80bv_chip_erase(void) @@ -171,9 +128,9 @@ void w25q80bv_chip_erase(void) 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_spi_select(); + w25q80bv_spi_transfer(W25Q80BV_CHIP_ERASE); + w25q80bv_spi_unselect(); } /* write up a 256 byte page or partial page */ @@ -192,14 +149,14 @@ void w25q80bv_page_program(const uint32_t addr, const uint16_t len, const uint8_ w25q80bv_write_enable(); w25q80bv_wait_while_busy(); - gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL); - ssp_transfer(SSP0_NUM, W25Q80BV_PAGE_PROGRAM); - ssp_transfer(SSP0_NUM, (addr & 0xFF0000) >> 16); - ssp_transfer(SSP0_NUM, (addr & 0xFF00) >> 8); - ssp_transfer(SSP0_NUM, addr & 0xFF); + w25q80bv_spi_select(); + w25q80bv_spi_transfer(W25Q80BV_PAGE_PROGRAM); + w25q80bv_spi_transfer((addr & 0xFF0000) >> 16); + w25q80bv_spi_transfer((addr & 0xFF00) >> 8); + w25q80bv_spi_transfer(addr & 0xFF); for (i = 0; i < len; i++) - ssp_transfer(SSP0_NUM, data[i]); - gpio_set(PORT_SSP0_SSEL, PIN_SSP0_SSEL); + w25q80bv_spi_transfer(data[i]); + w25q80bv_spi_unselect(); } /* write an arbitrary number of bytes */ diff --git a/firmware/common/w25q80bv.h b/firmware/common/w25q80bv.h index b11a466a..49a72334 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. * diff --git a/firmware/common/w25q80bv_drv.c b/firmware/common/w25q80bv_drv.c new file mode 100644 index 00000000..3ba1952a --- /dev/null +++ b/firmware/common/w25q80bv_drv.c @@ -0,0 +1,88 @@ +/* + * Copyright 2013 Michael Ossmann + * Copyright 2013 Benjamin Vernoux + * Copyright 2014 Jared Boone, ShareBrained Technology + * + * 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_drv.h" + +#include "hackrf_core.h" + +#include +#include +#include +#include + +void w25q80bv_spi_init(void) { + const uint8_t serial_clock_rate = 2; + const uint8_t clock_prescale_rate = 2; + + /* Reset SPIFI peripheral before to Erase/Write SPIFI memory through SPI */ + RESET_CTRL1 = RESET_CTRL1_SPIFI_RST; + + /* Init SPIFI GPIO to Normal GPIO */ + scu_pinmux(P3_3, (SCU_SSP_IO | SCU_CONF_FUNCTION2)); // P3_3 SPIFI_SCK => SSP0_SCK + scu_pinmux(P3_4, (SCU_GPIO_FAST | SCU_CONF_FUNCTION0)); // P3_4 SPIFI SPIFI_SIO3 IO3 => GPIO1[14] + scu_pinmux(P3_5, (SCU_GPIO_FAST | SCU_CONF_FUNCTION0)); // P3_5 SPIFI SPIFI_SIO2 IO2 => GPIO1[15] + scu_pinmux(P3_6, (SCU_GPIO_FAST | SCU_CONF_FUNCTION0)); // P3_6 SPIFI SPIFI_MISO IO1 => GPIO0[6] + scu_pinmux(P3_7, (SCU_GPIO_FAST | SCU_CONF_FUNCTION4)); // P3_7 SPIFI SPIFI_MOSI IO0 => GPIO5[10] + scu_pinmux(P3_8, (SCU_GPIO_FAST | SCU_CONF_FUNCTION4)); // P3_8 SPIFI SPIFI_CS => GPIO5[11] + + /* configure SSP pins */ + scu_pinmux(SCU_SSP0_MISO, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); + scu_pinmux(SCU_SSP0_MOSI, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); + scu_pinmux(SCU_SSP0_SCK, (SCU_SSP_IO | SCU_CONF_FUNCTION2)); + + /* configure GPIO pins */ + scu_pinmux(SCU_FLASH_HOLD, SCU_GPIO_FAST); + scu_pinmux(SCU_FLASH_WP, SCU_GPIO_FAST); + scu_pinmux(SCU_SSP0_SSEL, (SCU_GPIO_FAST | SCU_CONF_FUNCTION4)); + + /* drive SSEL, HOLD, and WP pins high */ + gpio_set(PORT_FLASH, (PIN_FLASH_HOLD | PIN_FLASH_WP)); + w25q80bv_spi_unselect(); + + /* 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); +} + +void w25q80bv_spi_select(void) { + gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL); +} + +void w25q80bv_spi_unselect(void) { + gpio_set(PORT_SSP0_SSEL, PIN_SSP0_SSEL); +} + +uint16_t w25q80bv_spi_transfer(const uint16_t tx_data) { + return ssp_transfer(SSP0_NUM, tx_data); +} diff --git a/firmware/common/w25q80bv_drv.h b/firmware/common/w25q80bv_drv.h new file mode 100644 index 00000000..459fb5ed --- /dev/null +++ b/firmware/common/w25q80bv_drv.h @@ -0,0 +1,35 @@ +/* + * Copyright 2013 Michael Ossmann + * Copyright 2013 Benjamin Vernoux + * Copyright 2014 Jared Boone, ShareBrained Technology + * + * 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_DRV_H__ +#define __W25Q80BV_DRV_H__ + +#include + +void w25q80bv_spi_init(void); + +void w25q80bv_spi_select(void); +uint16_t w25q80bv_spi_transfer(const uint16_t tx_data); +void w25q80bv_spi_unselect(void); + +#endif//__W25Q80BV_DRV_H__ diff --git a/firmware/hackrf_usb/CMakeLists.txt b/firmware/hackrf_usb/CMakeLists.txt index a4a0b0ee..e9653119 100644 --- a/firmware/hackrf_usb/CMakeLists.txt +++ b/firmware/hackrf_usb/CMakeLists.txt @@ -45,6 +45,7 @@ set(SRC_M4 "${PATH_HACKRF_FIRMWARE_COMMON}/usb_queue.c" "${PATH_HACKRF_FIRMWARE_COMMON}/fault_handler.c" "${PATH_HACKRF_FIRMWARE_COMMON}/w25q80bv.c" + "${PATH_HACKRF_FIRMWARE_COMMON}/w25q80bv_drv.c" "${PATH_HACKRF_FIRMWARE_COMMON}/cpld_jtag.c" "${PATH_HACKRF_FIRMWARE_COMMON}/xapp058/lenval.c" "${PATH_HACKRF_FIRMWARE_COMMON}/xapp058/micro.c" From 7639ef0e3ec27f8f6630d64eb8467a9d38b579ad Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 4 Nov 2014 16:49:03 -0800 Subject: [PATCH 08/46] W25Q80BV: De-singleton the driver. --- firmware/common/hackrf_core.c | 2 + firmware/common/hackrf_core.h | 2 + firmware/common/rom_iap.c | 4 +- firmware/common/w25q80bv.c | 102 ++++++++++++------------- firmware/common/w25q80bv.h | 12 +-- firmware/common/w25q80bv_drv.c | 13 ++-- firmware/common/w25q80bv_drv.h | 12 ++- firmware/hackrf_usb/usb_api_spiflash.c | 10 ++- 8 files changed, 86 insertions(+), 71 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index db5029ad..93bf8512 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -39,6 +39,8 @@ max2837_driver_t max2837; rffc5071_driver_t rffc5072; +w25q80bv_driver_t spi_flash; + void delay(uint32_t duration) { uint32_t i; diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index afa3379d..35fa1225 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -34,6 +34,7 @@ extern "C" #include "max2837_drv.h" #include "rffc5071_drv.h" +#include "w25q80bv_drv.h" /* hardware identification number */ #define BOARD_ID_JELLYBEAN 0 @@ -354,6 +355,7 @@ typedef enum { void delay(uint32_t duration); extern max2837_driver_t max2837; extern rffc5071_driver_t rffc5072; +extern w25q80bv_driver_t spi_flash; void cpu_clock_init(void); void cpu_clock_pll1_low_speed(void); diff --git a/firmware/common/rom_iap.c b/firmware/common/rom_iap.c index f7a4420c..4a92494c 100644 --- a/firmware/common/rom_iap.c +++ b/firmware/common/rom_iap.c @@ -77,7 +77,7 @@ 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(); + w25q80bv_setup(&spi_flash); switch(iap_cmd_res->cmd_param.command_code) { @@ -92,7 +92,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/w25q80bv.c b/firmware/common/w25q80bv.c index fc440e6f..a325b464 100644 --- a/firmware/common/w25q80bv.c +++ b/firmware/common/w25q80bv.c @@ -36,105 +36,105 @@ * 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; - w25q80bv_spi_init(); + w25q80bv_spi_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; - w25q80bv_spi_select(); - w25q80bv_spi_transfer(W25Q80BV_READ_STATUS1); - value = w25q80bv_spi_transfer(0xFF); - w25q80bv_spi_unselect(); + w25q80bv_spi_select(drv); + w25q80bv_spi_transfer(drv, W25Q80BV_READ_STATUS1); + value = w25q80bv_spi_transfer(drv, 0xFF); + w25q80bv_spi_unselect(drv); return value; } /* 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; - w25q80bv_spi_select(); - w25q80bv_spi_transfer(W25Q80BV_DEVICE_ID); + w25q80bv_spi_select(drv); + w25q80bv_spi_transfer(drv, W25Q80BV_DEVICE_ID); /* Read 3 dummy bytes */ - value = w25q80bv_spi_transfer(0xFF); - value = w25q80bv_spi_transfer(0xFF); - value = w25q80bv_spi_transfer(0xFF); + value = w25q80bv_spi_transfer(drv, 0xFF); + value = w25q80bv_spi_transfer(drv, 0xFF); + value = w25q80bv_spi_transfer(drv, 0xFF); /* Read Device ID shall return 0x13 for W25Q80BV */ - value = w25q80bv_spi_transfer(0xFF); + value = w25q80bv_spi_transfer(drv, 0xFF); - w25q80bv_spi_unselect(); + w25q80bv_spi_unselect(drv); return value; } -void w25q80bv_get_unique_id(w25q80bv_unique_id_t* unique_id) +void w25q80bv_get_unique_id(w25q80bv_driver_t* const drv, w25q80bv_unique_id_t* unique_id) { int i; uint8_t value; - w25q80bv_spi_select(); - w25q80bv_spi_transfer(W25Q80BV_UNIQUE_ID); + w25q80bv_spi_select(drv); + w25q80bv_spi_transfer(drv, W25Q80BV_UNIQUE_ID); /* Read 4 dummy bytes */ for(i=0; i<4; i++) - value = w25q80bv_spi_transfer(0xFF); + value = w25q80bv_spi_transfer(drv, 0xFF); /* Read Unique ID 64bits (8*8) */ for(i=0; i<8; i++) { - value = w25q80bv_spi_transfer(0xFF); + value = w25q80bv_spi_transfer(drv, 0xFF); unique_id->id_8b[i] = value; } - w25q80bv_spi_unselect(); + w25q80bv_spi_unselect(drv); } -void w25q80bv_wait_while_busy(void) +void w25q80bv_wait_while_busy(w25q80bv_driver_t* const drv) { - while (w25q80bv_get_status() & W25Q80BV_STATUS_BUSY); + while (w25q80bv_get_status(drv) & W25Q80BV_STATUS_BUSY); } -void w25q80bv_write_enable(void) +void w25q80bv_write_enable(w25q80bv_driver_t* const drv) { - w25q80bv_wait_while_busy(); - w25q80bv_spi_select(); - w25q80bv_spi_transfer(W25Q80BV_WRITE_ENABLE); - w25q80bv_spi_unselect(); + w25q80bv_wait_while_busy(drv); + w25q80bv_spi_select(drv); + w25q80bv_spi_transfer(drv, W25Q80BV_WRITE_ENABLE); + w25q80bv_spi_unselect(drv); } -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(); - w25q80bv_spi_select(); - w25q80bv_spi_transfer(W25Q80BV_CHIP_ERASE); - w25q80bv_spi_unselect(); + w25q80bv_write_enable(drv); + w25q80bv_wait_while_busy(drv); + w25q80bv_spi_select(drv); + w25q80bv_spi_transfer(drv, W25Q80BV_CHIP_ERASE); + w25q80bv_spi_unselect(drv); } /* 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) +void w25q80bv_page_program(w25q80bv_driver_t* const drv, const uint32_t addr, const uint16_t len, const uint8_t* data) { int i; @@ -146,21 +146,21 @@ void w25q80bv_page_program(const uint32_t addr, const uint16_t len, const uint8_ if (addr > (W25Q80BV_NUM_BYTES - len)) return; - w25q80bv_write_enable(); - w25q80bv_wait_while_busy(); + w25q80bv_write_enable(drv); + w25q80bv_wait_while_busy(drv); - w25q80bv_spi_select(); - w25q80bv_spi_transfer(W25Q80BV_PAGE_PROGRAM); - w25q80bv_spi_transfer((addr & 0xFF0000) >> 16); - w25q80bv_spi_transfer((addr & 0xFF00) >> 8); - w25q80bv_spi_transfer(addr & 0xFF); + w25q80bv_spi_select(drv); + w25q80bv_spi_transfer(drv, W25Q80BV_PAGE_PROGRAM); + w25q80bv_spi_transfer(drv, (addr & 0xFF0000) >> 16); + w25q80bv_spi_transfer(drv, (addr & 0xFF00) >> 8); + w25q80bv_spi_transfer(drv, addr & 0xFF); for (i = 0; i < len; i++) - w25q80bv_spi_transfer(data[i]); - w25q80bv_spi_unselect(); + w25q80bv_spi_transfer(drv, data[i]); + w25q80bv_spi_unselect(drv); } /* 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, const uint8_t* data) { uint16_t first_block_len; uint8_t device_id; @@ -168,7 +168,7 @@ 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 */ @@ -181,7 +181,7 @@ void w25q80bv_program(uint32_t addr, uint32_t len, const uint8_t* data) 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; @@ -189,7 +189,7 @@ void w25q80bv_program(uint32_t addr, uint32_t len, const uint8_t* data) /* one page at a time on boundaries */ while (len >= W25Q80BV_PAGE_LEN) { - w25q80bv_page_program(addr, W25Q80BV_PAGE_LEN, data); + w25q80bv_page_program(drv, addr, W25Q80BV_PAGE_LEN, data); addr += W25Q80BV_PAGE_LEN; data += W25Q80BV_PAGE_LEN; len -= W25Q80BV_PAGE_LEN; @@ -197,6 +197,6 @@ void w25q80bv_program(uint32_t addr, uint32_t len, const uint8_t* data) /* 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 49a72334..d58802d2 100644 --- a/firmware/common/w25q80bv.h +++ b/firmware/common/w25q80bv.h @@ -24,6 +24,8 @@ #ifndef __W25Q80BV_H__ #define __W25Q80BV_H__ +#include "w25q80bv_drv.h" + #define W25Q80BV_PAGE_LEN 256U #define W25Q80BV_NUM_PAGES 4096U #define W25Q80BV_NUM_BYTES 1048576U @@ -47,10 +49,10 @@ 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); +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, const 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); #endif//__W25Q80BV_H__ diff --git a/firmware/common/w25q80bv_drv.c b/firmware/common/w25q80bv_drv.c index 3ba1952a..3639f391 100644 --- a/firmware/common/w25q80bv_drv.c +++ b/firmware/common/w25q80bv_drv.c @@ -30,7 +30,7 @@ #include #include -void w25q80bv_spi_init(void) { +void w25q80bv_spi_init(w25q80bv_driver_t* const drv) { const uint8_t serial_clock_rate = 2; const uint8_t clock_prescale_rate = 2; @@ -57,7 +57,7 @@ void w25q80bv_spi_init(void) { /* drive SSEL, HOLD, and WP pins high */ gpio_set(PORT_FLASH, (PIN_FLASH_HOLD | PIN_FLASH_WP)); - w25q80bv_spi_unselect(); + w25q80bv_spi_unselect(drv); /* Set GPIO pins as outputs. */ GPIO1_DIR |= (PIN_FLASH_HOLD | PIN_FLASH_WP); @@ -75,14 +75,17 @@ void w25q80bv_spi_init(void) { SSP_SLAVE_OUT_ENABLE); } -void w25q80bv_spi_select(void) { +void w25q80bv_spi_select(w25q80bv_driver_t* const drv) { + (void)drv; gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL); } -void w25q80bv_spi_unselect(void) { +void w25q80bv_spi_unselect(w25q80bv_driver_t* const drv) { + (void)drv; gpio_set(PORT_SSP0_SSEL, PIN_SSP0_SSEL); } -uint16_t w25q80bv_spi_transfer(const uint16_t tx_data) { +uint16_t w25q80bv_spi_transfer(w25q80bv_driver_t* const drv, const uint16_t tx_data) { + (void)drv; return ssp_transfer(SSP0_NUM, tx_data); } diff --git a/firmware/common/w25q80bv_drv.h b/firmware/common/w25q80bv_drv.h index 459fb5ed..2d7e843e 100644 --- a/firmware/common/w25q80bv_drv.h +++ b/firmware/common/w25q80bv_drv.h @@ -26,10 +26,14 @@ #include -void w25q80bv_spi_init(void); +typedef struct { + /* Empty for now */ +} w25q80bv_driver_t; -void w25q80bv_spi_select(void); -uint16_t w25q80bv_spi_transfer(const uint16_t tx_data); -void w25q80bv_spi_unselect(void); +void w25q80bv_spi_init(w25q80bv_driver_t* const drv); + +void w25q80bv_spi_select(w25q80bv_driver_t* const drv); +uint16_t w25q80bv_spi_transfer(w25q80bv_driver_t* const drv, const uint16_t tx_data); +void w25q80bv_spi_unselect(w25q80bv_driver_t* const drv); #endif//__W25Q80BV_DRV_H__ diff --git a/firmware/hackrf_usb/usb_api_spiflash.c b/firmware/hackrf_usb/usb_api_spiflash.c index 93c12065..97b1771b 100644 --- a/firmware/hackrf_usb/usb_api_spiflash.c +++ b/firmware/hackrf_usb/usb_api_spiflash.c @@ -26,6 +26,8 @@ #include +#include + #include uint8_t spiflash_buffer[W25Q80BV_PAGE_LEN]; @@ -36,9 +38,9 @@ usb_request_status_t usb_vendor_request_erase_spiflash( //FIXME This should refuse to run if executing from SPI flash. if (stage == USB_TRANSFER_STAGE_SETUP) { - w25q80bv_setup(); + w25q80bv_setup(&spi_flash); /* only chip erase is implemented */ - w25q80bv_chip_erase(); + w25q80bv_chip_erase(&spi_flash); usb_transfer_schedule_ack(endpoint->in); //FIXME probably should undo w25q80bv_setup() } @@ -62,7 +64,7 @@ usb_request_status_t usb_vendor_request_write_spiflash( } else { usb_transfer_schedule_block(endpoint->out, &spiflash_buffer[0], len, NULL, NULL); - w25q80bv_setup(); + w25q80bv_setup(&spi_flash); return USB_REQUEST_STATUS_OK; } } else if (stage == USB_TRANSFER_STAGE_DATA) { @@ -73,7 +75,7 @@ usb_request_status_t usb_vendor_request_write_spiflash( || ((addr + len) > W25Q80BV_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); //FIXME probably should undo w25q80bv_setup() return USB_REQUEST_STATUS_OK; From 2dd0283549df3948d15469d69ba6b9ac8bae118d Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 4 Nov 2014 17:07:11 -0800 Subject: [PATCH 09/46] W25Q80BV: Make flash command details private. --- firmware/common/w25q80bv.c | 11 +++++++++++ firmware/common/w25q80bv.h | 12 ------------ 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/firmware/common/w25q80bv.c b/firmware/common/w25q80bv.c index a325b464..b9c54616 100644 --- a/firmware/common/w25q80bv.c +++ b/firmware/common/w25q80bv.c @@ -31,6 +31,17 @@ #include "w25q80bv.h" #include "w25q80bv_drv.h" +#define W25Q80BV_WRITE_ENABLE 0x06 +#define W25Q80BV_CHIP_ERASE 0xC7 +#define W25Q80BV_READ_STATUS1 0x05 +#define W25Q80BV_PAGE_PROGRAM 0x02 +#define W25Q80BV_DEVICE_ID 0xAB +#define W25Q80BV_UNIQUE_ID 0x4B + +#define W25Q80BV_STATUS_BUSY 0x01 + +#define W25Q80BV_DEVICE_ID_RES 0x13 /* Expected device_id for W25Q80BV */ + /* * 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. diff --git a/firmware/common/w25q80bv.h b/firmware/common/w25q80bv.h index d58802d2..0bcf6bf7 100644 --- a/firmware/common/w25q80bv.h +++ b/firmware/common/w25q80bv.h @@ -30,18 +30,6 @@ #define W25Q80BV_NUM_PAGES 4096U #define W25Q80BV_NUM_BYTES 1048576U -#define W25Q80BV_WRITE_ENABLE 0x06 -#define W25Q80BV_CHIP_ERASE 0xC7 -#define W25Q80BV_READ_STATUS1 0x05 -#define W25Q80BV_PAGE_PROGRAM 0x02 -#define W25Q80BV_DEVICE_ID 0xAB -#define W25Q80BV_UNIQUE_ID 0x4B - -#define W25Q80BV_STATUS_BUSY 0x01 - - -#define W25Q80BV_DEVICE_ID_RES 0x13 /* Expected device_id for W25Q80BV */ - typedef union { uint64_t id_64b; From 5a77d196ea548e702c61adaad257189e60620045 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 4 Nov 2014 17:38:43 -0800 Subject: [PATCH 10/46] W25Q80BV: Separate structures into algorithm and hardware access layers. Also extract #define constants for W25Q80BV into driver structure. Driver could eventually extend to other devices. --- firmware/common/hackrf_core.h | 2 +- firmware/common/w25q80bv.c | 84 ++++++++++++++------------ firmware/common/w25q80bv.h | 13 ++-- firmware/common/w25q80bv_drv.c | 16 ++--- firmware/common/w25q80bv_drv.h | 10 +-- firmware/hackrf_usb/usb_api_spiflash.c | 19 +++--- 6 files changed, 77 insertions(+), 67 deletions(-) diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index 35fa1225..67f1d720 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -34,7 +34,7 @@ extern "C" #include "max2837_drv.h" #include "rffc5071_drv.h" -#include "w25q80bv_drv.h" +#include "w25q80bv.h" /* hardware identification number */ #define BOARD_ID_JELLYBEAN 0 diff --git a/firmware/common/w25q80bv.c b/firmware/common/w25q80bv.c index b9c54616..fe64b957 100644 --- a/firmware/common/w25q80bv.c +++ b/firmware/common/w25q80bv.c @@ -51,7 +51,11 @@ void w25q80bv_setup(w25q80bv_driver_t* const drv) { uint8_t device_id; - w25q80bv_spi_init(drv); + drv->page_len = 256U; + drv->num_pages = 4096U; + drv->num_bytes = 1048576U; + + w25q80bv_spi_init(drv->hw); device_id = 0; while(device_id != W25Q80BV_DEVICE_ID_RES) @@ -64,10 +68,10 @@ uint8_t w25q80bv_get_status(w25q80bv_driver_t* const drv) { uint8_t value; - w25q80bv_spi_select(drv); - w25q80bv_spi_transfer(drv, W25Q80BV_READ_STATUS1); - value = w25q80bv_spi_transfer(drv, 0xFF); - w25q80bv_spi_unselect(drv); + w25q80bv_spi_select(drv->hw); + w25q80bv_spi_transfer(drv->hw, W25Q80BV_READ_STATUS1); + value = w25q80bv_spi_transfer(drv->hw, 0xFF); + w25q80bv_spi_unselect(drv->hw); return value; } @@ -77,17 +81,17 @@ uint8_t w25q80bv_get_device_id(w25q80bv_driver_t* const drv) { uint8_t value; - w25q80bv_spi_select(drv); - w25q80bv_spi_transfer(drv, W25Q80BV_DEVICE_ID); + w25q80bv_spi_select(drv->hw); + w25q80bv_spi_transfer(drv->hw, W25Q80BV_DEVICE_ID); /* Read 3 dummy bytes */ - value = w25q80bv_spi_transfer(drv, 0xFF); - value = w25q80bv_spi_transfer(drv, 0xFF); - value = w25q80bv_spi_transfer(drv, 0xFF); + value = w25q80bv_spi_transfer(drv->hw, 0xFF); + value = w25q80bv_spi_transfer(drv->hw, 0xFF); + value = w25q80bv_spi_transfer(drv->hw, 0xFF); /* Read Device ID shall return 0x13 for W25Q80BV */ - value = w25q80bv_spi_transfer(drv, 0xFF); + value = w25q80bv_spi_transfer(drv->hw, 0xFF); - w25q80bv_spi_unselect(drv); + w25q80bv_spi_unselect(drv->hw); return value; } @@ -97,21 +101,21 @@ void w25q80bv_get_unique_id(w25q80bv_driver_t* const drv, w25q80bv_unique_id_t* int i; uint8_t value; - w25q80bv_spi_select(drv); - w25q80bv_spi_transfer(drv, W25Q80BV_UNIQUE_ID); + w25q80bv_spi_select(drv->hw); + w25q80bv_spi_transfer(drv->hw, W25Q80BV_UNIQUE_ID); /* Read 4 dummy bytes */ for(i=0; i<4; i++) - value = w25q80bv_spi_transfer(drv, 0xFF); + value = w25q80bv_spi_transfer(drv->hw, 0xFF); /* Read Unique ID 64bits (8*8) */ for(i=0; i<8; i++) { - value = w25q80bv_spi_transfer(drv, 0xFF); + value = w25q80bv_spi_transfer(drv->hw, 0xFF); unique_id->id_8b[i] = value; } - w25q80bv_spi_unselect(drv); + w25q80bv_spi_unselect(drv->hw); } void w25q80bv_wait_while_busy(w25q80bv_driver_t* const drv) @@ -122,9 +126,9 @@ void w25q80bv_wait_while_busy(w25q80bv_driver_t* const drv) void w25q80bv_write_enable(w25q80bv_driver_t* const drv) { w25q80bv_wait_while_busy(drv); - w25q80bv_spi_select(drv); - w25q80bv_spi_transfer(drv, W25Q80BV_WRITE_ENABLE); - w25q80bv_spi_unselect(drv); + w25q80bv_spi_select(drv->hw); + w25q80bv_spi_transfer(drv->hw, W25Q80BV_WRITE_ENABLE); + w25q80bv_spi_unselect(drv->hw); } void w25q80bv_chip_erase(w25q80bv_driver_t* const drv) @@ -139,9 +143,9 @@ void w25q80bv_chip_erase(w25q80bv_driver_t* const drv) w25q80bv_write_enable(drv); w25q80bv_wait_while_busy(drv); - w25q80bv_spi_select(drv); - w25q80bv_spi_transfer(drv, W25Q80BV_CHIP_ERASE); - w25q80bv_spi_unselect(drv); + w25q80bv_spi_select(drv->hw); + w25q80bv_spi_transfer(drv->hw, W25Q80BV_CHIP_ERASE); + w25q80bv_spi_unselect(drv->hw); } /* write up a 256 byte page or partial page */ @@ -150,24 +154,24 @@ void w25q80bv_page_program(w25q80bv_driver_t* const drv, const uint32_t addr, co 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(drv); w25q80bv_wait_while_busy(drv); - w25q80bv_spi_select(drv); - w25q80bv_spi_transfer(drv, W25Q80BV_PAGE_PROGRAM); - w25q80bv_spi_transfer(drv, (addr & 0xFF0000) >> 16); - w25q80bv_spi_transfer(drv, (addr & 0xFF00) >> 8); - w25q80bv_spi_transfer(drv, addr & 0xFF); + w25q80bv_spi_select(drv->hw); + w25q80bv_spi_transfer(drv->hw, W25Q80BV_PAGE_PROGRAM); + w25q80bv_spi_transfer(drv->hw, (addr & 0xFF0000) >> 16); + w25q80bv_spi_transfer(drv->hw, (addr & 0xFF00) >> 8); + w25q80bv_spi_transfer(drv->hw, addr & 0xFF); for (i = 0; i < len; i++) - w25q80bv_spi_transfer(drv, data[i]); - w25q80bv_spi_unselect(drv); + w25q80bv_spi_transfer(drv->hw, data[i]); + w25q80bv_spi_unselect(drv->hw); } /* write an arbitrary number of bytes */ @@ -183,12 +187,12 @@ void w25q80bv_program(w25q80bv_driver_t* const drv, uint32_t addr, uint32_t len, } /* 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) { @@ -199,11 +203,11 @@ void w25q80bv_program(w25q80bv_driver_t* const drv, uint32_t addr, uint32_t len, } /* one page at a time on boundaries */ - while (len >= W25Q80BV_PAGE_LEN) { - w25q80bv_page_program(drv, 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 */ diff --git a/firmware/common/w25q80bv.h b/firmware/common/w25q80bv.h index 0bcf6bf7..cab8d686 100644 --- a/firmware/common/w25q80bv.h +++ b/firmware/common/w25q80bv.h @@ -24,11 +24,9 @@ #ifndef __W25Q80BV_H__ #define __W25Q80BV_H__ -#include "w25q80bv_drv.h" +#include -#define W25Q80BV_PAGE_LEN 256U -#define W25Q80BV_NUM_PAGES 4096U -#define W25Q80BV_NUM_BYTES 1048576U +#include "w25q80bv_drv.h" typedef union { @@ -37,6 +35,13 @@ typedef union uint8_t id_8b[8]; /* 8*8bits 64bits Unique ID */ } w25q80bv_unique_id_t; +typedef struct { + w25q80bv_hw_t* hw; + size_t page_len; + size_t num_pages; + size_t num_bytes; +} w25q80bv_driver_t; + 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, const uint8_t* data); diff --git a/firmware/common/w25q80bv_drv.c b/firmware/common/w25q80bv_drv.c index 3639f391..d0500b5d 100644 --- a/firmware/common/w25q80bv_drv.c +++ b/firmware/common/w25q80bv_drv.c @@ -30,7 +30,7 @@ #include #include -void w25q80bv_spi_init(w25q80bv_driver_t* const drv) { +void w25q80bv_spi_init(w25q80bv_hw_t* const hw) { const uint8_t serial_clock_rate = 2; const uint8_t clock_prescale_rate = 2; @@ -57,7 +57,7 @@ void w25q80bv_spi_init(w25q80bv_driver_t* const drv) { /* drive SSEL, HOLD, and WP pins high */ gpio_set(PORT_FLASH, (PIN_FLASH_HOLD | PIN_FLASH_WP)); - w25q80bv_spi_unselect(drv); + w25q80bv_spi_unselect(hw); /* Set GPIO pins as outputs. */ GPIO1_DIR |= (PIN_FLASH_HOLD | PIN_FLASH_WP); @@ -75,17 +75,17 @@ void w25q80bv_spi_init(w25q80bv_driver_t* const drv) { SSP_SLAVE_OUT_ENABLE); } -void w25q80bv_spi_select(w25q80bv_driver_t* const drv) { - (void)drv; +void w25q80bv_spi_select(w25q80bv_hw_t* const hw) { + (void)hw; gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL); } -void w25q80bv_spi_unselect(w25q80bv_driver_t* const drv) { - (void)drv; +void w25q80bv_spi_unselect(w25q80bv_hw_t* const hw) { + (void)hw; gpio_set(PORT_SSP0_SSEL, PIN_SSP0_SSEL); } -uint16_t w25q80bv_spi_transfer(w25q80bv_driver_t* const drv, const uint16_t tx_data) { - (void)drv; +uint16_t w25q80bv_spi_transfer(w25q80bv_hw_t* const hw, const uint16_t tx_data) { + (void)hw; return ssp_transfer(SSP0_NUM, tx_data); } diff --git a/firmware/common/w25q80bv_drv.h b/firmware/common/w25q80bv_drv.h index 2d7e843e..619e14ef 100644 --- a/firmware/common/w25q80bv_drv.h +++ b/firmware/common/w25q80bv_drv.h @@ -28,12 +28,12 @@ typedef struct { /* Empty for now */ -} w25q80bv_driver_t; +} w25q80bv_hw_t; -void w25q80bv_spi_init(w25q80bv_driver_t* const drv); +void w25q80bv_spi_init(w25q80bv_hw_t* const hw); -void w25q80bv_spi_select(w25q80bv_driver_t* const drv); -uint16_t w25q80bv_spi_transfer(w25q80bv_driver_t* const drv, const uint16_t tx_data); -void w25q80bv_spi_unselect(w25q80bv_driver_t* const drv); +void w25q80bv_spi_select(w25q80bv_hw_t* const hw); +uint16_t w25q80bv_spi_transfer(w25q80bv_hw_t* const hw, const uint16_t tx_data); +void w25q80bv_spi_unselect(w25q80bv_hw_t* const hw); #endif//__W25Q80BV_DRV_H__ diff --git a/firmware/hackrf_usb/usb_api_spiflash.c b/firmware/hackrf_usb/usb_api_spiflash.c index 97b1771b..a2368a91 100644 --- a/firmware/hackrf_usb/usb_api_spiflash.c +++ b/firmware/hackrf_usb/usb_api_spiflash.c @@ -30,7 +30,8 @@ #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) @@ -58,8 +59,8 @@ 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, @@ -71,8 +72,8 @@ usb_request_status_t usb_vendor_request_write_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 { w25q80bv_program(&spi_flash, addr, len, &spiflash_buffer[0]); @@ -97,8 +98,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 { /* TODO flush SPIFI "cache" before to read the SPIFI memory */ @@ -116,8 +117,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 From 466c6742481ce1f0865fbf9df87e288140cb5b65 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 4 Nov 2014 18:22:05 -0800 Subject: [PATCH 11/46] W25Q80BV: Un-const data argument to program function. --- firmware/common/w25q80bv.c | 2 +- firmware/common/w25q80bv.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/common/w25q80bv.c b/firmware/common/w25q80bv.c index fe64b957..e61da8a4 100644 --- a/firmware/common/w25q80bv.c +++ b/firmware/common/w25q80bv.c @@ -175,7 +175,7 @@ void w25q80bv_page_program(w25q80bv_driver_t* const drv, const uint32_t addr, co } /* write an arbitrary number of bytes */ -void w25q80bv_program(w25q80bv_driver_t* const drv, 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; diff --git a/firmware/common/w25q80bv.h b/firmware/common/w25q80bv.h index cab8d686..4eb028cd 100644 --- a/firmware/common/w25q80bv.h +++ b/firmware/common/w25q80bv.h @@ -44,7 +44,7 @@ typedef struct { 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, const uint8_t* data); +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); From 8edeaaa21e8c96b3c7683daa0b3c240b82d13b78 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 4 Nov 2014 18:25:00 -0800 Subject: [PATCH 12/46] W25Q80BV: Move SPI functions to top of file, since they're static and used later. --- firmware/common/w25q80bv_drv.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/firmware/common/w25q80bv_drv.c b/firmware/common/w25q80bv_drv.c index d0500b5d..1f55512f 100644 --- a/firmware/common/w25q80bv_drv.c +++ b/firmware/common/w25q80bv_drv.c @@ -30,6 +30,21 @@ #include #include +static void w25q80bv_spi_select(w25q80bv_hw_t* const hw) { + (void)hw; + gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL); +} + +static void w25q80bv_spi_unselect(w25q80bv_hw_t* const hw) { + (void)hw; + gpio_set(PORT_SSP0_SSEL, PIN_SSP0_SSEL); +} + +static uint16_t w25q80bv_spi_transfer(w25q80bv_hw_t* const hw, const uint16_t tx_data) { + (void)hw; + return ssp_transfer(SSP0_NUM, tx_data); +} + void w25q80bv_spi_init(w25q80bv_hw_t* const hw) { const uint8_t serial_clock_rate = 2; const uint8_t clock_prescale_rate = 2; @@ -74,18 +89,3 @@ void w25q80bv_spi_init(w25q80bv_hw_t* const hw) { SSP_MASTER, SSP_SLAVE_OUT_ENABLE); } - -void w25q80bv_spi_select(w25q80bv_hw_t* const hw) { - (void)hw; - gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL); -} - -void w25q80bv_spi_unselect(w25q80bv_hw_t* const hw) { - (void)hw; - gpio_set(PORT_SSP0_SSEL, PIN_SSP0_SSEL); -} - -uint16_t w25q80bv_spi_transfer(w25q80bv_hw_t* const hw, const uint16_t tx_data) { - (void)hw; - return ssp_transfer(SSP0_NUM, tx_data); -} From 6668c2706b92acb55e1cd77b4eeaf6d0b31464b9 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Tue, 4 Nov 2014 18:26:09 -0800 Subject: [PATCH 13/46] W25Q80BV: Consolidate API to perform entire transfers in one call. --- firmware/common/w25q80bv.c | 97 ++++++++++++++-------------------- firmware/common/w25q80bv_drv.c | 23 +++++++- firmware/common/w25q80bv_drv.h | 18 +++++-- 3 files changed, 75 insertions(+), 63 deletions(-) diff --git a/firmware/common/w25q80bv.c b/firmware/common/w25q80bv.c index e61da8a4..12941eb9 100644 --- a/firmware/common/w25q80bv.c +++ b/firmware/common/w25q80bv.c @@ -31,6 +31,8 @@ #include "w25q80bv.h" #include "w25q80bv_drv.h" +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + #define W25Q80BV_WRITE_ENABLE 0x06 #define W25Q80BV_CHIP_ERASE 0xC7 #define W25Q80BV_READ_STATUS1 0x05 @@ -55,7 +57,7 @@ void w25q80bv_setup(w25q80bv_driver_t* const drv) drv->num_pages = 4096U; drv->num_bytes = 1048576U; - w25q80bv_spi_init(drv->hw); + w25q80bv_hw_init(drv->hw); device_id = 0; while(device_id != W25Q80BV_DEVICE_ID_RES) @@ -66,56 +68,34 @@ void w25q80bv_setup(w25q80bv_driver_t* const drv) uint8_t w25q80bv_get_status(w25q80bv_driver_t* const drv) { - uint8_t value; - - w25q80bv_spi_select(drv->hw); - w25q80bv_spi_transfer(drv->hw, W25Q80BV_READ_STATUS1); - value = w25q80bv_spi_transfer(drv->hw, 0xFF); - w25q80bv_spi_unselect(drv->hw); - - return value; + uint8_t data[] = { W25Q80BV_READ_STATUS1, 0xFF }; + w25q80bv_hw_transfer(drv->hw, data, ARRAY_SIZE(data)); + return data[1]; } /* Release power down / Device ID */ uint8_t w25q80bv_get_device_id(w25q80bv_driver_t* const drv) { - uint8_t value; - - w25q80bv_spi_select(drv->hw); - w25q80bv_spi_transfer(drv->hw, W25Q80BV_DEVICE_ID); - - /* Read 3 dummy bytes */ - value = w25q80bv_spi_transfer(drv->hw, 0xFF); - value = w25q80bv_spi_transfer(drv->hw, 0xFF); - value = w25q80bv_spi_transfer(drv->hw, 0xFF); - /* Read Device ID shall return 0x13 for W25Q80BV */ - value = w25q80bv_spi_transfer(drv->hw, 0xFF); - - w25q80bv_spi_unselect(drv->hw); - - return value; + uint8_t data[] = { + W25Q80BV_DEVICE_ID, + 0xFF, 0xFF, 0xFF, 0xFF + }; + w25q80bv_hw_transfer(drv->hw, data, ARRAY_SIZE(data)); + return data[4]; } 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 + }; + w25q80bv_hw_transfer(drv->hw, data, ARRAY_SIZE(data)); - w25q80bv_spi_select(drv->hw); - w25q80bv_spi_transfer(drv->hw, W25Q80BV_UNIQUE_ID); - - /* Read 4 dummy bytes */ - for(i=0; i<4; i++) - value = w25q80bv_spi_transfer(drv->hw, 0xFF); - - /* Read Unique ID 64bits (8*8) */ - for(i=0; i<8; i++) - { - value = w25q80bv_spi_transfer(drv->hw, 0xFF); - unique_id->id_8b[i] = value; + for(size_t i=0; i<8; i++) { + unique_id->id_8b[i] = data[5+i]; } - - w25q80bv_spi_unselect(drv->hw); } void w25q80bv_wait_while_busy(w25q80bv_driver_t* const drv) @@ -126,9 +106,9 @@ void w25q80bv_wait_while_busy(w25q80bv_driver_t* const drv) void w25q80bv_write_enable(w25q80bv_driver_t* const drv) { w25q80bv_wait_while_busy(drv); - w25q80bv_spi_select(drv->hw); - w25q80bv_spi_transfer(drv->hw, W25Q80BV_WRITE_ENABLE); - w25q80bv_spi_unselect(drv->hw); + + uint8_t data[] = { W25Q80BV_WRITE_ENABLE }; + w25q80bv_hw_transfer(drv->hw, data, ARRAY_SIZE(data)); } void w25q80bv_chip_erase(w25q80bv_driver_t* const drv) @@ -143,16 +123,14 @@ void w25q80bv_chip_erase(w25q80bv_driver_t* const drv) w25q80bv_write_enable(drv); w25q80bv_wait_while_busy(drv); - w25q80bv_spi_select(drv->hw); - w25q80bv_spi_transfer(drv->hw, W25Q80BV_CHIP_ERASE); - w25q80bv_spi_unselect(drv->hw); + + uint8_t data[] = { W25Q80BV_CHIP_ERASE }; + w25q80bv_hw_transfer(drv->hw, data, ARRAY_SIZE(data)); } /* write up a 256 byte page or partial page */ -void w25q80bv_page_program(w25q80bv_driver_t* const drv, 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) > drv->page_len) return; @@ -164,14 +142,19 @@ void w25q80bv_page_program(w25q80bv_driver_t* const drv, const uint32_t addr, co w25q80bv_write_enable(drv); w25q80bv_wait_while_busy(drv); - w25q80bv_spi_select(drv->hw); - w25q80bv_spi_transfer(drv->hw, W25Q80BV_PAGE_PROGRAM); - w25q80bv_spi_transfer(drv->hw, (addr & 0xFF0000) >> 16); - w25q80bv_spi_transfer(drv->hw, (addr & 0xFF00) >> 8); - w25q80bv_spi_transfer(drv->hw, addr & 0xFF); - for (i = 0; i < len; i++) - w25q80bv_spi_transfer(drv->hw, data[i]); - w25q80bv_spi_unselect(drv->hw); + uint8_t header[] = { + W25Q80BV_PAGE_PROGRAM, + (addr & 0xFF0000) >> 16, + (addr & 0xFF00) >> 8, + addr & 0xFF + }; + + const w25q80bv_transfer_t transfers[] = { + { header, ARRAY_SIZE(header) }, + { data, len } + }; + + w25q80bv_hw_transfer_multiple(drv->hw, transfers, ARRAY_SIZE(transfers)); } /* write an arbitrary number of bytes */ diff --git a/firmware/common/w25q80bv_drv.c b/firmware/common/w25q80bv_drv.c index 1f55512f..c7d50bff 100644 --- a/firmware/common/w25q80bv_drv.c +++ b/firmware/common/w25q80bv_drv.c @@ -45,7 +45,7 @@ static uint16_t w25q80bv_spi_transfer(w25q80bv_hw_t* const hw, const uint16_t tx return ssp_transfer(SSP0_NUM, tx_data); } -void w25q80bv_spi_init(w25q80bv_hw_t* const hw) { +void w25q80bv_hw_init(w25q80bv_hw_t* const hw) { const uint8_t serial_clock_rate = 2; const uint8_t clock_prescale_rate = 2; @@ -89,3 +89,24 @@ void w25q80bv_spi_init(w25q80bv_hw_t* const hw) { SSP_MASTER, SSP_SLAVE_OUT_ENABLE); } + +void w25q80bv_hw_transfer_multiple( + w25q80bv_hw_t* const hw, + const w25q80bv_transfer_t* const transfers, + const size_t transfer_count +) { + w25q80bv_spi_select(hw); + for(size_t i=0; i +#include + +typedef struct { + uint8_t* const data; + const size_t count; +} w25q80bv_transfer_t; typedef struct { /* Empty for now */ } w25q80bv_hw_t; -void w25q80bv_spi_init(w25q80bv_hw_t* const hw); - -void w25q80bv_spi_select(w25q80bv_hw_t* const hw); -uint16_t w25q80bv_spi_transfer(w25q80bv_hw_t* const hw, const uint16_t tx_data); -void w25q80bv_spi_unselect(w25q80bv_hw_t* const hw); +void w25q80bv_hw_init(w25q80bv_hw_t* const hw); +void w25q80bv_hw_transfer(w25q80bv_hw_t* const hw, uint8_t* data, const size_t count); +void w25q80bv_hw_transfer_multiple( + w25q80bv_hw_t* const hw, + const w25q80bv_transfer_t* const transfers, + const size_t transfer_count +); #endif//__W25Q80BV_DRV_H__ From e2c33aac88d2fa42723db5a68960ad7dfa9f4f75 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Fri, 7 Nov 2014 11:12:41 -0800 Subject: [PATCH 14/46] MAX2837: Remove test code. Hardware abstraction should make for easier test harnessing in the future. --- firmware/common/max2837.c | 39 ----------------------------------- firmware/common/max2837_drv.c | 16 -------------- 2 files changed, 55 deletions(-) diff --git a/firmware/common/max2837.c b/firmware/common/max2837.c index 835751c0..f951dec0 100644 --- a/firmware/common/max2837.c +++ b/firmware/common/max2837.c @@ -34,13 +34,7 @@ #include "max2837_drv.h" #include "max2837_regs.def" // private register def macros -#if (defined DEBUG || defined BUS_PIRATE) -#include -#define LOG printf -#else -#define LOG(x,...) #include "hackrf_core.h" -#endif /* Default register values. */ static const uint16_t max2837_regs_default[MAX2837_NUM_REGS] = { @@ -85,7 +79,6 @@ static const uint16_t max2837_regs_default[MAX2837_NUM_REGS] = { /* Set up all registers according to defaults specified in docs. */ void max2837_init(max2837_driver_t* const drv) { - LOG("# max2837_init\n"); memcpy(drv->regs, max2837_regs_default, sizeof(drv->regs)); drv->regs_dirty = 0xffffffff; @@ -99,11 +92,9 @@ void max2837_init(max2837_driver_t* const drv) */ void max2837_setup(max2837_driver_t* const drv) { - LOG("# max2837_setup\n"); max2837_pin_config(drv); max2837_init(drv); - LOG("# max2837_init done\n"); /* Use SPI control instead of B1-B7 pins for gain settings. */ set_MAX2837_TXVGA_GAIN_SPI_EN(drv, 1); @@ -185,45 +176,30 @@ void max2837_set_mode(max2837_driver_t* const drv, const max2837_mode_t new_mode void max2837_start(max2837_driver_t* const drv) { - LOG("# max2837_start\n"); set_MAX2837_EN_SPI(drv, 1); max2837_regs_commit(drv); -#if !defined TEST max2837_mode_standby(drv); -#endif } void max2837_tx(max2837_driver_t* const drv) { - LOG("# max2837_tx\n"); -#if !defined TEST - set_MAX2837_ModeCtrl(drv, MAX2837_ModeCtrl_TxLPF); max2837_regs_commit(drv); max2837_mode_tx(drv); -#endif } void max2837_rx(max2837_driver_t* const drv) { - LOG("# max2837_rx\n"); - set_MAX2837_ModeCtrl(drv, MAX2837_ModeCtrl_RxLPF); max2837_regs_commit(drv); - -#if !defined TEST max2837_mode_rx(drv); -#endif } void max2837_stop(max2837_driver_t* const drv) { - LOG("# max2837_stop\n"); set_MAX2837_EN_SPI(drv, 0); max2837_regs_commit(drv); -#if !defined TEST max2837_mode_shutdown(drv); -#endif } void max2837_set_frequency(max2837_driver_t* const drv, uint32_t freq) @@ -254,9 +230,6 @@ void max2837_set_frequency(max2837_driver_t* const drv, 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; @@ -270,7 +243,6 @@ void max2837_set_frequency(max2837_driver_t* const drv, uint32_t freq) div_rem -= div_cmp; } } - LOG("# int %ld, frac %ld\n", div_int, div_frac); /* Band settings */ set_MAX2837_LOGEN_BSW(drv, band); @@ -382,14 +354,3 @@ bool max2837_set_txvga_gain(max2837_driver_t* const drv, const uint32_t gain_db) max2837_reg_commit(drv, 29); return true; } - -#ifdef TEST -int main(int ac, char **av) -{ - max2837_setup(drv); - max2837_set_frequency(drv, 2441000000); - max2837_start(drv); - max2837_tx(drv); - max2837_stop(drv); -} -#endif //TEST diff --git a/firmware/common/max2837_drv.c b/firmware/common/max2837_drv.c index 51adcd28..14df9f7c 100644 --- a/firmware/common/max2837_drv.c +++ b/firmware/common/max2837_drv.c @@ -22,19 +22,12 @@ #include "max2837_drv.h" -#if (defined DEBUG || defined BUS_PIRATE) -#include -#define LOG printf -#else -#define LOG(x,...) #include #include #include #include "hackrf_core.h" -#endif void max2837_pin_config(max2837_driver_t* const drv) { -#if !defined TEST /* Configure XCVR_CTL GPIO pins. */ #ifdef JELLYBEAN scu_pinmux(SCU_XCVR_RXHP, SCU_GPIO_FAST); @@ -78,7 +71,6 @@ void max2837_pin_config(max2837_driver_t* const drv) { | PIN_XCVR_B7 ); #endif -#endif } void max2837_mode_shutdown(max2837_driver_t* const drv) { @@ -152,15 +144,7 @@ uint16_t max2837_spi_read(max2837_driver_t* const drv, uint8_t r) { /* SPI register write */ void max2837_spi_write(max2837_driver_t* const drv, uint8_t r, uint16_t v) { (void)drv; - -#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 } From 55ed2c1affbd87de59274ced8676ee349fc2d6cd Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 8 Nov 2014 13:11:59 -0800 Subject: [PATCH 15/46] RFFC5071: Remove debug/test code. --- firmware/common/rffc5071.c | 36 ---------------------------------- firmware/common/rffc5071_drv.c | 18 ----------------- 2 files changed, 54 deletions(-) diff --git a/firmware/common/rffc5071.c b/firmware/common/rffc5071.c index 6234a318..ebda0c81 100644 --- a/firmware/common/rffc5071.c +++ b/firmware/common/rffc5071.c @@ -37,13 +37,7 @@ #include "rffc5071_drv.h" #include "rffc5071_regs.def" // private register def macros -#if (defined DEBUG) -#include -#define LOG printf -#else -#define LOG(x,...) #include "hackrf_core.h" -#endif /* Default register values. */ static const uint16_t rffc5071_regs_default[RFFC5071_NUM_REGS] = { @@ -82,7 +76,6 @@ static const uint16_t rffc5071_regs_default[RFFC5071_NUM_REGS] = { /* Set up all registers according to defaults specified in docs. */ void rffc5071_init(rffc5071_driver_t* const drv) { - LOG("# rffc5071_init\n"); memcpy(drv->regs, rffc5071_regs_default, sizeof(drv->regs)); drv->regs_dirty = 0x7fffffff; @@ -97,7 +90,6 @@ void rffc5071_init(rffc5071_driver_t* const drv) void rffc5071_setup(rffc5071_driver_t* const drv) { rffc5071_init(drv); - LOG("# rffc5071_setup\n"); rffc5071_pin_config(drv); @@ -165,7 +157,6 @@ void rffc5071_regs_commit(rffc5071_driver_t* const drv) } void rffc5071_tx(rffc5071_driver_t* const drv) { - LOG("# rffc5071_tx\n"); set_RFFC5071_ENBL(drv, 0); set_RFFC5071_FULLD(drv, 0); set_RFFC5071_MODE(drv, 1); /* mixer 2 used for both RX and TX */ @@ -173,7 +164,6 @@ void rffc5071_tx(rffc5071_driver_t* const drv) { } void rffc5071_rx(rffc5071_driver_t* const drv) { - LOG("# rfc5071_rx\n"); set_RFFC5071_ENBL(drv, 0); set_RFFC5071_FULLD(drv, 0); set_RFFC5071_MODE(drv, 1); /* mixer 2 used for both RX and TX */ @@ -185,7 +175,6 @@ void rffc5071_rx(rffc5071_driver_t* const drv) { * current hardware designs do not support full-duplex operation. */ void rffc5071_rxtx(rffc5071_driver_t* const drv) { - LOG("# rfc5071_rxtx\n"); set_RFFC5071_ENBL(drv, 0); set_RFFC5071_FULLD(drv, 1); /* mixer 1 and mixer 2 (RXTX) */ rffc5071_regs_commit(drv); @@ -194,13 +183,11 @@ void rffc5071_rxtx(rffc5071_driver_t* const drv) { } void rffc5071_disable(rffc5071_driver_t* const drv) { - LOG("# rfc5071_disable\n"); set_RFFC5071_ENBL(drv, 0); rffc5071_regs_commit(drv); } void rffc5071_enable(rffc5071_driver_t* const drv) { - LOG("# rfc5071_enable\n"); set_RFFC5071_ENBL(drv, 1); rffc5071_regs_commit(drv); } @@ -219,8 +206,6 @@ uint64_t rffc5071_config_synth_int(rffc5071_driver_t* const drv, 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; @@ -253,8 +238,6 @@ uint64_t rffc5071_config_synth_int(rffc5071_driver_t* const drv, 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(drv, n_lo); @@ -294,22 +277,3 @@ void rffc5071_set_gpo(rffc5071_driver_t* const drv, uint8_t gpo) rffc5071_regs_commit(drv); } - -#ifdef TEST -int main(int ac, char **av) -{ - rffc5071_setup(drv); - rffc5071_tx(drv, 0); - rffc5071_set_frequency(drv, 500, 0); - rffc5071_set_frequency(drv, 525, 0); - rffc5071_set_frequency(drv, 550, 0); - rffc5071_set_frequency(drv, 1500, 0); - rffc5071_set_frequency(drv, 1525, 0); - rffc5071_set_frequency(drv, 1550, 0); - rffc5071_disable(drv); - rffc5071_rx(drv, 0); - rffc5071_disable(drv); - rffc5071_rxtx(drv); - rffc5071_disable(drv); -} -#endif //TEST diff --git a/firmware/common/rffc5071_drv.c b/firmware/common/rffc5071_drv.c index ca7ce127..759e7c01 100644 --- a/firmware/common/rffc5071_drv.c +++ b/firmware/common/rffc5071_drv.c @@ -20,20 +20,13 @@ * Boston, MA 02110-1301, USA. */ -#if (defined DEBUG) -#include -#define LOG printf -#else -#define LOG(x,...) #include #include #include #include "hackrf_core.h" -#endif void rffc5071_pin_config(rffc5071_driver_t* const drv) { (void)drv; -#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); @@ -51,7 +44,6 @@ void rffc5071_pin_config(rffc5071_driver_t* const drv) { 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 } static void serial_delay(void) @@ -77,10 +69,6 @@ uint16_t rffc5071_spi_read(rffc5071_driver_t* const drv, uint8_t r) { 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); @@ -157,7 +145,6 @@ uint16_t rffc5071_spi_read(rffc5071_driver_t* const drv, uint8_t r) { gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); return data; -#endif /* DEBUG */ } /* SPI register write @@ -171,10 +158,6 @@ uint16_t rffc5071_spi_read(rffc5071_driver_t* const drv, uint8_t r) { void rffc5071_spi_write(rffc5071_driver_t* const drv, uint8_t r, uint16_t v) { (void)drv; -#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; @@ -228,5 +211,4 @@ void rffc5071_spi_write(rffc5071_driver_t* const drv, uint8_t r, uint16_t v) { serial_delay(); gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); -#endif } From e1d1274523a3eb55725764035b142973c30d8f29 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 8 Nov 2014 18:00:20 -0800 Subject: [PATCH 16/46] RFFC5071: Refactor a bunch. --- firmware/common/rffc5071.c | 15 +++ firmware/common/rffc5071_drv.c | 230 +++++++++++++-------------------- firmware/common/rffc5071_drv.h | 3 +- 3 files changed, 109 insertions(+), 139 deletions(-) diff --git a/firmware/common/rffc5071.c b/firmware/common/rffc5071.c index ebda0c81..1c1c69db 100644 --- a/firmware/common/rffc5071.c +++ b/firmware/common/rffc5071.c @@ -120,6 +120,21 @@ void rffc5071_setup(rffc5071_driver_t* const drv) rffc5071_regs_commit(drv); } +static uint16_t rffc5071_spi_read(rffc5071_driver_t* const drv, uint8_t r) { + (void)drv; + + uint16_t data[] = { 0x80 | (r & 0x7f), 0xffff }; + rffc5071_spi_transfer(drv, data, 2); + return data[1]; +} + +static void rffc5071_spi_write(rffc5071_driver_t* const drv, uint8_t r, uint16_t v) { + (void)drv; + + uint16_t data[] = { 0x00 | (r & 0x7f), v }; + rffc5071_spi_transfer(drv, data, 2); +} + uint16_t rffc5071_reg_read(rffc5071_driver_t* const drv, uint8_t r) { /* Readback register is not cached. */ diff --git a/firmware/common/rffc5071_drv.c b/firmware/common/rffc5071_drv.c index 759e7c01..81ee2976 100644 --- a/firmware/common/rffc5071_drv.c +++ b/firmware/common/rffc5071_drv.c @@ -25,35 +25,98 @@ #include #include "hackrf_core.h" -void rffc5071_pin_config(rffc5071_driver_t* const drv) { - (void)drv; - /* Configure GPIO pins. */ - scu_pinmux(SCU_MIXER_ENX, SCU_GPIO_FAST); +static void rffc5071_target_select() { + gpio_clear(PORT_MIXER_ENX, PIN_MIXER_ENX); +} + +static void rffc5071_target_unselect() { + gpio_set(PORT_MIXER_ENX, PIN_MIXER_ENX); +} + +static void rffc5071_spi_direction_out() { + GPIO_DIR(PORT_MIXER_SDATA) |= PIN_MIXER_SDATA; +} + +static void rffc5071_spi_direction_in() { + GPIO_DIR(PORT_MIXER_SDATA) &= ~PIN_MIXER_SDATA; +} + +static void rffc5071_spi_data_out(const bool bit) { + if (bit) + gpio_set(PORT_MIXER_SDATA, PIN_MIXER_SDATA); + else + gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA); +} + +static bool rffc5071_spi_data_in() { + return MIXER_SDATA_STATE; +} + +static void rffc5071_spi_init() { scu_pinmux(SCU_MIXER_SCLK, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); scu_pinmux(SCU_MIXER_SDATA, SCU_GPIO_FAST); + + GPIO_DIR(PORT_MIXER_SCLK) |= PIN_MIXER_SCLK; + rffc5071_spi_direction_out(); + + gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); + gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA); +} + +static void rffc5071_target_init() { + /* 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_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); + rffc5071_target_unselect(); gpio_set(PORT_MIXER_RESETX, PIN_MIXER_RESETX); /* active low */ } -static void serial_delay(void) -{ - uint32_t i; +void rffc5071_pin_config(rffc5071_driver_t* const drv) { + (void)drv; + + rffc5071_spi_init(); + rffc5071_target_init(); +} + +static void rffc5071_spi_serial_delay(void) { + volatile uint32_t i; for (i = 0; i < 2; i++) __asm__("nop"); } +static void rffc5071_spi_sck() { + rffc5071_spi_serial_delay(); + gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); + + rffc5071_spi_serial_delay(); + gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); +} + +static uint32_t rffc5071_spi_exchange_bit(const uint32_t bit) { + rffc5071_spi_data_out(bit); + rffc5071_spi_sck(); + return rffc5071_spi_data_in() ? 1 : 0; +} + +static uint32_t rffc5071_spi_exchange_word(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(t & msb); + } + + return t & ((1UL << count) - 1); +} + /* SPI register read. * * Send 9 bits: @@ -62,91 +125,6 @@ static void serial_delay(void) * next 7 bits are register address. * Then receive 16 bits (register value). */ -uint16_t rffc5071_spi_read(rffc5071_driver_t* const drv, uint8_t r) { - (void)drv; - - int bits = 9; - int msb = 1 << (bits -1); - uint32_t data = 0x80 | (r & 0x7f); - - /* 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; -} - /* SPI register write * * Send 25 bits: @@ -155,60 +133,38 @@ uint16_t rffc5071_spi_read(rffc5071_driver_t* const drv, uint8_t r) { * next 7 bits are register address, * next 16 bits are register value. */ -void rffc5071_spi_write(rffc5071_driver_t* const drv, uint8_t r, uint16_t v) { +void rffc5071_spi_transfer(rffc5071_driver_t* const drv, uint16_t* const data, const size_t count) { (void)drv; - - 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); + if( count != 2 ) { + return; + } + + 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. */ - serial_delay(); - gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); + rffc5071_spi_sck(); + rffc5071_spi_sck(); - serial_delay(); - gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); + rffc5071_target_select(); + data[0] = rffc5071_spi_exchange_word(data[0], 9); - 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); + if( direction_read ) { + rffc5071_spi_direction_in(); + rffc5071_spi_sck(); } + data[1] = rffc5071_spi_exchange_word(data[1], 16); + rffc5071_spi_direction_out(); - gpio_set(PORT_MIXER_ENX, PIN_MIXER_ENX); + rffc5071_spi_serial_delay(); + rffc5071_target_unselect(); /* * 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); + rffc5071_spi_sck(); } diff --git a/firmware/common/rffc5071_drv.h b/firmware/common/rffc5071_drv.h index 441071ad..a6823e2a 100644 --- a/firmware/common/rffc5071_drv.h +++ b/firmware/common/rffc5071_drv.h @@ -33,7 +33,6 @@ typedef struct { void rffc5071_pin_config(rffc5071_driver_t* const drv); -uint16_t rffc5071_spi_read(rffc5071_driver_t* const drv, uint8_t r); -void rffc5071_spi_write(rffc5071_driver_t* const drv, uint8_t r, uint16_t v); +void rffc5071_spi_transfer(rffc5071_driver_t* const drv, uint16_t* const data, const size_t count); #endif // __RFFC5071_DRV_H From 487b8cc16893ffbac136e827eb0a92b0b6987b98 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 8 Nov 2014 23:28:26 -0800 Subject: [PATCH 17/46] RFFC5071: Delay switching data direction until after target unselected. --- firmware/common/rffc5071_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/common/rffc5071_drv.c b/firmware/common/rffc5071_drv.c index 81ee2976..41d748cc 100644 --- a/firmware/common/rffc5071_drv.c +++ b/firmware/common/rffc5071_drv.c @@ -157,10 +157,10 @@ void rffc5071_spi_transfer(rffc5071_driver_t* const drv, uint16_t* const data, c rffc5071_spi_sck(); } data[1] = rffc5071_spi_exchange_word(data[1], 16); - rffc5071_spi_direction_out(); rffc5071_spi_serial_delay(); rffc5071_target_unselect(); + rffc5071_spi_direction_out(); /* * The device requires a clock while ENX is high after a serial From 69867bb637c9c4f4f80037b3d48f9b277151d684 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 9 Nov 2014 09:36:18 -0800 Subject: [PATCH 18/46] RFFC5071: Further refactoring to create common SPI interface. --- firmware/common/rffc5071.c | 6 +-- firmware/common/rffc5071_drv.c | 81 ++++++++++++++++++---------------- firmware/common/rffc5071_drv.h | 14 +++--- 3 files changed, 53 insertions(+), 48 deletions(-) diff --git a/firmware/common/rffc5071.c b/firmware/common/rffc5071.c index 1c1c69db..b5b28e39 100644 --- a/firmware/common/rffc5071.c +++ b/firmware/common/rffc5071.c @@ -91,7 +91,7 @@ void rffc5071_setup(rffc5071_driver_t* const drv) { rffc5071_init(drv); - rffc5071_pin_config(drv); + rffc5071_spi_init(drv->spi); /* initial setup */ /* put zeros in freq contol registers */ @@ -124,7 +124,7 @@ static uint16_t rffc5071_spi_read(rffc5071_driver_t* const drv, uint8_t r) { (void)drv; uint16_t data[] = { 0x80 | (r & 0x7f), 0xffff }; - rffc5071_spi_transfer(drv, data, 2); + rffc5071_spi_transfer(drv->spi, data, 2); return data[1]; } @@ -132,7 +132,7 @@ static void rffc5071_spi_write(rffc5071_driver_t* const drv, uint8_t r, uint16_t (void)drv; uint16_t data[] = { 0x00 | (r & 0x7f), v }; - rffc5071_spi_transfer(drv, data, 2); + rffc5071_spi_transfer(drv->spi, data, 2); } uint16_t rffc5071_reg_read(rffc5071_driver_t* const drv, uint8_t r) diff --git a/firmware/common/rffc5071_drv.c b/firmware/common/rffc5071_drv.c index 41d748cc..45f709c8 100644 --- a/firmware/common/rffc5071_drv.c +++ b/firmware/common/rffc5071_drv.c @@ -25,45 +25,51 @@ #include #include "hackrf_core.h" -static void rffc5071_target_select() { +static void rffc5071_spi_target_select(spi_t* const spi) { + (void)spi; gpio_clear(PORT_MIXER_ENX, PIN_MIXER_ENX); } -static void rffc5071_target_unselect() { +static void rffc5071_spi_target_unselect(spi_t* const spi) { + (void)spi; gpio_set(PORT_MIXER_ENX, PIN_MIXER_ENX); } -static void rffc5071_spi_direction_out() { +static void rffc5071_spi_direction_out(spi_t* const spi) { + (void)spi; GPIO_DIR(PORT_MIXER_SDATA) |= PIN_MIXER_SDATA; } -static void rffc5071_spi_direction_in() { +static void rffc5071_spi_direction_in(spi_t* const spi) { + (void)spi; GPIO_DIR(PORT_MIXER_SDATA) &= ~PIN_MIXER_SDATA; } -static void rffc5071_spi_data_out(const bool bit) { +static void rffc5071_spi_data_out(spi_t* const spi, const bool bit) { + (void)spi; if (bit) gpio_set(PORT_MIXER_SDATA, PIN_MIXER_SDATA); else gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA); } -static bool rffc5071_spi_data_in() { +static bool rffc5071_spi_data_in(spi_t* const spi) { + (void)spi; return MIXER_SDATA_STATE; } -static void rffc5071_spi_init() { +static void rffc5071_spi_bus_init(spi_t* const spi) { scu_pinmux(SCU_MIXER_SCLK, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); scu_pinmux(SCU_MIXER_SDATA, SCU_GPIO_FAST); GPIO_DIR(PORT_MIXER_SCLK) |= PIN_MIXER_SCLK; - rffc5071_spi_direction_out(); + rffc5071_spi_direction_out(spi); gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA); } -static void rffc5071_target_init() { +static void rffc5071_spi_target_init(spi_t* const spi) { /* Configure GPIO pins. */ scu_pinmux(SCU_MIXER_ENX, SCU_GPIO_FAST); scu_pinmux(SCU_MIXER_RESETX, SCU_GPIO_FAST); @@ -73,45 +79,44 @@ static void rffc5071_target_init() { GPIO_DIR(PORT_MIXER_RESETX) |= PIN_MIXER_RESETX; /* set to known state */ - rffc5071_target_unselect(); + rffc5071_spi_target_unselect(spi); gpio_set(PORT_MIXER_RESETX, PIN_MIXER_RESETX); /* active low */ } -void rffc5071_pin_config(rffc5071_driver_t* const drv) { - (void)drv; - - rffc5071_spi_init(); - rffc5071_target_init(); +void rffc5071_spi_init(spi_t* const spi) { + rffc5071_spi_bus_init(spi); + rffc5071_spi_target_init(spi); } -static void rffc5071_spi_serial_delay(void) { +static void rffc5071_spi_serial_delay(spi_t* const spi) { + (void)spi; volatile uint32_t i; for (i = 0; i < 2; i++) __asm__("nop"); } -static void rffc5071_spi_sck() { - rffc5071_spi_serial_delay(); +static void rffc5071_spi_sck(spi_t* const spi) { + rffc5071_spi_serial_delay(spi); gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - rffc5071_spi_serial_delay(); + rffc5071_spi_serial_delay(spi); gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); } -static uint32_t rffc5071_spi_exchange_bit(const uint32_t bit) { - rffc5071_spi_data_out(bit); - rffc5071_spi_sck(); - return rffc5071_spi_data_in() ? 1 : 0; +static uint32_t rffc5071_spi_exchange_bit(spi_t* const spi, const uint32_t bit) { + rffc5071_spi_data_out(spi, bit); + rffc5071_spi_sck(spi); + return rffc5071_spi_data_in(spi) ? 1 : 0; } -static uint32_t rffc5071_spi_exchange_word(const uint32_t data, const size_t count) { +static uint32_t rffc5071_spi_exchange_word(spi_t* const spi, 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(t & msb); + t = (t << 1) | rffc5071_spi_exchange_bit(spi, t & msb); } return t & ((1UL << count) - 1); @@ -133,9 +138,7 @@ static uint32_t rffc5071_spi_exchange_word(const uint32_t data, const size_t cou * next 7 bits are register address, * next 16 bits are register value. */ -void rffc5071_spi_transfer(rffc5071_driver_t* const drv, uint16_t* const data, const size_t count) { - (void)drv; - +void rffc5071_spi_transfer(spi_t* const spi, uint16_t* const data, const size_t count) { if( count != 2 ) { return; } @@ -146,25 +149,25 @@ void rffc5071_spi_transfer(rffc5071_driver_t* const drv, uint16_t* const data, c * The device requires two clocks while ENX is high before a serial * transaction. This is not clearly documented. */ - rffc5071_spi_sck(); - rffc5071_spi_sck(); + rffc5071_spi_sck(spi); + rffc5071_spi_sck(spi); - rffc5071_target_select(); - data[0] = rffc5071_spi_exchange_word(data[0], 9); + rffc5071_spi_target_select(spi); + data[0] = rffc5071_spi_exchange_word(spi, data[0], 9); if( direction_read ) { - rffc5071_spi_direction_in(); - rffc5071_spi_sck(); + rffc5071_spi_direction_in(spi); + rffc5071_spi_sck(spi); } - data[1] = rffc5071_spi_exchange_word(data[1], 16); + data[1] = rffc5071_spi_exchange_word(spi, data[1], 16); - rffc5071_spi_serial_delay(); - rffc5071_target_unselect(); - rffc5071_spi_direction_out(); + rffc5071_spi_serial_delay(spi); + rffc5071_spi_target_unselect(spi); + rffc5071_spi_direction_out(spi); /* * The device requires a clock while ENX is high after a serial * transaction. This is not clearly documented. */ - rffc5071_spi_sck(); + rffc5071_spi_sck(spi); } diff --git a/firmware/common/rffc5071_drv.h b/firmware/common/rffc5071_drv.h index a6823e2a..7c3ef5fc 100644 --- a/firmware/common/rffc5071_drv.h +++ b/firmware/common/rffc5071_drv.h @@ -20,19 +20,21 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __RFFC5071_DRV_H -#define __RFFC5071_DRV_H +#ifndef __RFFC5071_SPI_H +#define __RFFC5071_SPI_H + +#include "spi.h" /* 31 registers, each containing 16 bits of data. */ #define RFFC5071_NUM_REGS 31 typedef struct { + spi_t* const spi; uint16_t regs[RFFC5071_NUM_REGS]; uint32_t regs_dirty; } rffc5071_driver_t; -void rffc5071_pin_config(rffc5071_driver_t* const drv); +void rffc5071_spi_init(spi_t* const spi); +void rffc5071_spi_transfer(spi_t* const spi, uint16_t* const data, const size_t count); -void rffc5071_spi_transfer(rffc5071_driver_t* const drv, uint16_t* const data, const size_t count); - -#endif // __RFFC5071_DRV_H +#endif // __RFFC5071_SPI_H From 786a8fd2e18ec35944a242e475a69fbd663ba5e5 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 9 Nov 2014 09:39:28 -0800 Subject: [PATCH 19/46] RFFC5071: Rename rffc5071_drv->rffc5071_spi. --- firmware/common/hackrf_core.h | 2 +- firmware/common/rffc5071.c | 2 +- firmware/common/rffc5071.h | 2 +- firmware/common/{rffc5071_drv.c => rffc5071_spi.c} | 0 firmware/common/{rffc5071_drv.h => rffc5071_spi.h} | 0 firmware/hackrf-common.cmake | 2 +- 6 files changed, 4 insertions(+), 4 deletions(-) rename firmware/common/{rffc5071_drv.c => rffc5071_spi.c} (100%) rename firmware/common/{rffc5071_drv.h => rffc5071_spi.h} (100%) diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index 67f1d720..035a169e 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -33,7 +33,7 @@ extern "C" #include #include "max2837_drv.h" -#include "rffc5071_drv.h" +#include "rffc5071.h" #include "w25q80bv.h" /* hardware identification number */ diff --git a/firmware/common/rffc5071.c b/firmware/common/rffc5071.c index b5b28e39..a5e4e46e 100644 --- a/firmware/common/rffc5071.c +++ b/firmware/common/rffc5071.c @@ -34,7 +34,7 @@ #include #include #include "rffc5071.h" -#include "rffc5071_drv.h" +#include "rffc5071_spi.h" #include "rffc5071_regs.def" // private register def macros #include "hackrf_core.h" diff --git a/firmware/common/rffc5071.h b/firmware/common/rffc5071.h index 7b2a7801..c180ae84 100644 --- a/firmware/common/rffc5071.h +++ b/firmware/common/rffc5071.h @@ -25,7 +25,7 @@ #include -#include "rffc5071_drv.h" +#include "rffc5071_spi.h" /* Initialize chip. Call _setup() externally, as it calls _init(). */ extern void rffc5071_init(rffc5071_driver_t* const drv); diff --git a/firmware/common/rffc5071_drv.c b/firmware/common/rffc5071_spi.c similarity index 100% rename from firmware/common/rffc5071_drv.c rename to firmware/common/rffc5071_spi.c diff --git a/firmware/common/rffc5071_drv.h b/firmware/common/rffc5071_spi.h similarity index 100% rename from firmware/common/rffc5071_drv.h rename to firmware/common/rffc5071_spi.h diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index cf4d0182..3ea5a212 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -138,7 +138,7 @@ macro(DeclareTargets) ${PATH_HACKRF_FIRMWARE_COMMON}/max2837_drv.c ${PATH_HACKRF_FIRMWARE_COMMON}/max5864.c ${PATH_HACKRF_FIRMWARE_COMMON}/rffc5071.c - ${PATH_HACKRF_FIRMWARE_COMMON}/rffc5071_drv.c + ${PATH_HACKRF_FIRMWARE_COMMON}/rffc5071_spi.c m0_bin.s ) From f034bc82ca5c17647f0a1944943c293ae7aacb61 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 9 Nov 2014 10:50:32 -0800 Subject: [PATCH 20/46] RFFC5071: Further work abstracting SPI details out of driver. --- firmware/common/hackrf_core.c | 11 ++++++++- firmware/common/rffc5071.c | 7 +++--- firmware/common/rffc5071.h | 11 ++++++++- firmware/common/rffc5071_spi.c | 10 +++++++- firmware/common/rffc5071_spi.h | 12 ++------- firmware/common/spi.c | 34 +++++++++++++++++++++++++ firmware/common/spi.h | 45 ++++++++++++++++++++++++++++++++++ firmware/hackrf-common.cmake | 1 + 8 files changed, 114 insertions(+), 17 deletions(-) create mode 100644 firmware/common/spi.c create mode 100644 firmware/common/spi.h diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 93bf8512..651579bf 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -25,6 +25,7 @@ #include "si5351c.h" #include "max2837.h" #include "rffc5071.h" +#include "rffc5071_spi.h" #include "sgpio.h" #include "rf_path.h" #include @@ -37,9 +38,17 @@ max2837_driver_t max2837; -rffc5071_driver_t rffc5072; +spi_t rffc5071_spi = { + .init = rffc5071_spi_init, + .transfer = rffc5071_spi_transfer, + .transfer_gather = rffc5071_spi_transfer_gather, +}; w25q80bv_driver_t spi_flash; +rffc5071_driver_t rffc5072 = { + .spi = &rffc5071_spi, +}; + void delay(uint32_t duration) { diff --git a/firmware/common/rffc5071.c b/firmware/common/rffc5071.c index a5e4e46e..e9c1b72c 100644 --- a/firmware/common/rffc5071.c +++ b/firmware/common/rffc5071.c @@ -34,7 +34,6 @@ #include #include #include "rffc5071.h" -#include "rffc5071_spi.h" #include "rffc5071_regs.def" // private register def macros #include "hackrf_core.h" @@ -91,7 +90,7 @@ void rffc5071_setup(rffc5071_driver_t* const drv) { rffc5071_init(drv); - rffc5071_spi_init(drv->spi); + spi_init(drv->spi); /* initial setup */ /* put zeros in freq contol registers */ @@ -124,7 +123,7 @@ static uint16_t rffc5071_spi_read(rffc5071_driver_t* const drv, uint8_t r) { (void)drv; uint16_t data[] = { 0x80 | (r & 0x7f), 0xffff }; - rffc5071_spi_transfer(drv->spi, data, 2); + spi_transfer(drv->spi, data, 2); return data[1]; } @@ -132,7 +131,7 @@ static void rffc5071_spi_write(rffc5071_driver_t* const drv, uint8_t r, uint16_t (void)drv; uint16_t data[] = { 0x00 | (r & 0x7f), v }; - rffc5071_spi_transfer(drv->spi, data, 2); + spi_transfer(drv->spi, data, 2); } uint16_t rffc5071_reg_read(rffc5071_driver_t* const drv, uint8_t r) diff --git a/firmware/common/rffc5071.h b/firmware/common/rffc5071.h index c180ae84..18caf69f 100644 --- a/firmware/common/rffc5071.h +++ b/firmware/common/rffc5071.h @@ -25,7 +25,16 @@ #include -#include "rffc5071_spi.h" +#include "spi.h" + +/* 31 registers, each containing 16 bits of data. */ +#define RFFC5071_NUM_REGS 31 + +typedef struct { + spi_t* const spi; + uint16_t regs[RFFC5071_NUM_REGS]; + uint32_t regs_dirty; +} rffc5071_driver_t; /* Initialize chip. Call _setup() externally, as it calls _init(). */ extern void rffc5071_init(rffc5071_driver_t* const drv); diff --git a/firmware/common/rffc5071_spi.c b/firmware/common/rffc5071_spi.c index 45f709c8..1711c513 100644 --- a/firmware/common/rffc5071_spi.c +++ b/firmware/common/rffc5071_spi.c @@ -138,11 +138,13 @@ static uint32_t rffc5071_spi_exchange_word(spi_t* const spi, const uint32_t data * next 7 bits are register address, * next 16 bits are register value. */ -void rffc5071_spi_transfer(spi_t* const spi, uint16_t* const data, const size_t count) { +void rffc5071_spi_transfer(spi_t* const spi, void* const _data, const size_t count) { if( count != 2 ) { return; } + uint16_t* const data = _data; + const bool direction_read = (data[0] >> 7) & 1; /* @@ -171,3 +173,9 @@ void rffc5071_spi_transfer(spi_t* const spi, uint16_t* const data, const size_t */ rffc5071_spi_sck(spi); } + +void rffc5071_spi_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfer, const size_t count) { + if( count == 1 ) { + rffc5071_spi_transfer(spi, transfer[0].data, transfer[0].count); + } +} diff --git a/firmware/common/rffc5071_spi.h b/firmware/common/rffc5071_spi.h index 7c3ef5fc..d20fe152 100644 --- a/firmware/common/rffc5071_spi.h +++ b/firmware/common/rffc5071_spi.h @@ -25,16 +25,8 @@ #include "spi.h" -/* 31 registers, each containing 16 bits of data. */ -#define RFFC5071_NUM_REGS 31 - -typedef struct { - spi_t* const spi; - uint16_t regs[RFFC5071_NUM_REGS]; - uint32_t regs_dirty; -} rffc5071_driver_t; - void rffc5071_spi_init(spi_t* const spi); -void rffc5071_spi_transfer(spi_t* const spi, uint16_t* const data, const size_t count); +void rffc5071_spi_transfer(spi_t* const spi, void* const data, const size_t count); +void rffc5071_spi_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfer, const size_t count); #endif // __RFFC5071_SPI_H diff --git a/firmware/common/spi.c b/firmware/common/spi.c new file mode 100644 index 00000000..f743c0bc --- /dev/null +++ b/firmware/common/spi.c @@ -0,0 +1,34 @@ +/* + * 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.h" + +void spi_init(spi_t* const spi) { + spi->init(spi); +} + +void spi_transfer(spi_t* const spi, void* const data, const size_t count) { + spi->transfer(spi, data, count); +} + +void spi_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfers, const size_t count) { + spi->transfer_gather(spi, transfers, count); +} diff --git a/firmware/common/spi.h b/firmware/common/spi.h new file mode 100644 index 00000000..cad5f268 --- /dev/null +++ b/firmware/common/spi.h @@ -0,0 +1,45 @@ +/* + * 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_H__ +#define __SPI_H__ + +#include + +typedef struct { + void* const data; + const size_t count; +} spi_transfer_t; + +struct spi_t; +typedef struct spi_t spi_t; + +struct spi_t { + void (*init)(spi_t* const spi); + void (*transfer)(spi_t* const spi, void* const data, const size_t count); + void (*transfer_gather)(spi_t* const spi, const spi_transfer_t* const transfers, const size_t count); +}; + +void spi_init(spi_t* const spi); +void spi_transfer(spi_t* const spi, void* const data, const size_t count); +void spi_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfers, const size_t count); + +#endif/*__SPI_H__*/ diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index 3ea5a212..0973d7f0 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -139,6 +139,7 @@ macro(DeclareTargets) ${PATH_HACKRF_FIRMWARE_COMMON}/max5864.c ${PATH_HACKRF_FIRMWARE_COMMON}/rffc5071.c ${PATH_HACKRF_FIRMWARE_COMMON}/rffc5071_spi.c + ${PATH_HACKRF_FIRMWARE_COMMON}/spi.c m0_bin.s ) From 58e7ef4171f9c326803819ec52bd7a1f3525c9bd Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 9 Nov 2014 12:08:21 -0800 Subject: [PATCH 21/46] MAX2837: Refactoring toward abstracted SPI. Conflicts: firmware/common/hackrf_core.c firmware/common/hackrf_core.h firmware/common/tuning.c --- firmware/common/hackrf_core.c | 36 ++-------- firmware/common/hackrf_core.h | 2 +- firmware/common/max2837.c | 28 ++++++-- firmware/common/max2837.h | 20 +++++- firmware/common/max2837_spi.c | 70 +++++++++++++++++++ firmware/common/max2837_spi.h | 34 +++++++++ .../{max2837_drv.c => max2837_target.c} | 29 +++----- .../{max2837_drv.h => max2837_target.h} | 27 ++----- firmware/common/tuning.c | 1 + firmware/hackrf-common.cmake | 3 +- 10 files changed, 167 insertions(+), 83 deletions(-) create mode 100644 firmware/common/max2837_spi.c create mode 100644 firmware/common/max2837_spi.h rename firmware/common/{max2837_drv.c => max2837_target.c} (85%) rename firmware/common/{max2837_drv.h => max2837_target.h} (65%) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 651579bf..76a46347 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -24,6 +24,8 @@ #include "hackrf_core.h" #include "si5351c.h" #include "max2837.h" +#include "max2837_spi.h" +#include "max2837_target.h" #include "rffc5071.h" #include "rffc5071_spi.h" #include "sgpio.h" @@ -36,7 +38,10 @@ #define WAIT_CPU_CLOCK_INIT_DELAY (10000) -max2837_driver_t max2837; +max2837_driver_t max2837 = { + .spi = NULL, /* TODO */ +}; + spi_t rffc5071_spi = { .init = rffc5071_spi_init, @@ -528,38 +533,11 @@ void ssp1_init(void) 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); + max2837_spi_init(max2837.spi); } void ssp1_set_mode_max5864(void) diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index 035a169e..2eea5da4 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -32,7 +32,7 @@ extern "C" #include #include -#include "max2837_drv.h" +#include "max2837.h" #include "rffc5071.h" #include "w25q80bv.h" diff --git a/firmware/common/max2837.c b/firmware/common/max2837.c index f951dec0..1fa87755 100644 --- a/firmware/common/max2837.c +++ b/firmware/common/max2837.c @@ -31,7 +31,8 @@ #include #include #include "max2837.h" -#include "max2837_drv.h" +#include "max2837_spi.h" +#include "max2837_target.h" #include "max2837_regs.def" // private register def macros #include "hackrf_core.h" @@ -77,8 +78,12 @@ static const uint16_t max2837_regs_default[MAX2837_NUM_REGS] = { 0x000 }; /* 31 */ /* Set up all registers according to defaults specified in docs. */ -void max2837_init(max2837_driver_t* const drv) +static void max2837_init(max2837_driver_t* const drv) { + max2837_spi_init(drv->spi); + max2837_mode_shutdown(drv); + max2837_target_init(drv); + memcpy(drv->regs, max2837_regs_default, sizeof(drv->regs)); drv->regs_dirty = 0xffffffff; @@ -92,10 +97,8 @@ void max2837_init(max2837_driver_t* const drv) */ void max2837_setup(max2837_driver_t* const drv) { - max2837_pin_config(drv); - max2837_init(drv); - + /* Use SPI control instead of B1-B7 pins for gain settings. */ set_MAX2837_TXVGA_GAIN_SPI_EN(drv, 1); set_MAX2837_TXVGA_GAIN_MSB_SPI_EN(drv, 1); @@ -121,10 +124,21 @@ void max2837_setup(max2837_driver_t* const drv) max2837_regs_commit(drv); } +static uint16_t max2837_read(max2837_driver_t* const drv, uint8_t r) { + uint16_t value = (1 << 15) | (r << 10); + max2837_spi_transfer(drv->spi, &value, 1); + return value & 0x3ff; +} + +static void max2837_write(max2837_driver_t* const drv, uint8_t r, uint16_t v) { + uint16_t value = (r << 10) | (v & 0x3ff); + max2837_spi_transfer(drv->spi, &value, 1); +} + uint16_t max2837_reg_read(max2837_driver_t* const drv, uint8_t r) { if ((drv->regs_dirty >> r) & 0x1) { - drv->regs[r] = max2837_spi_read(drv, r); + drv->regs[r] = max2837_read(drv, r); }; return drv->regs[r]; } @@ -132,7 +146,7 @@ uint16_t max2837_reg_read(max2837_driver_t* const drv, uint8_t r) void max2837_reg_write(max2837_driver_t* const drv, uint8_t r, uint16_t v) { drv->regs[r] = v; - max2837_spi_write(drv, r, v); + max2837_write(drv, r, v); MAX2837_REG_SET_CLEAN(drv, r); } diff --git a/firmware/common/max2837.h b/firmware/common/max2837.h index b4fdeb48..42baa69e 100644 --- a/firmware/common/max2837.h +++ b/firmware/common/max2837.h @@ -26,10 +26,26 @@ #include #include -#include "max2837_drv.h" +#include "spi.h" + +/* 32 registers, each containing 10 bits of data. */ +#define MAX2837_NUM_REGS 32 +#define MAX2837_DATA_REGS_MAX_VALUE 1024 + +typedef enum { + MAX2837_MODE_SHUTDOWN, + MAX2837_MODE_STANDBY, + MAX2837_MODE_TX, + MAX2837_MODE_RX +} max2837_mode_t; + +typedef struct { + spi_t* const spi; + uint16_t regs[MAX2837_NUM_REGS]; + uint32_t regs_dirty; +} max2837_driver_t; /* Initialize chip. */ -extern void max2837_init(max2837_driver_t* const drv); extern void max2837_setup(max2837_driver_t* const drv); /* Read a register via SPI. Save a copy to memory and return diff --git a/firmware/common/max2837_spi.c b/firmware/common/max2837_spi.c new file mode 100644 index 00000000..f2fce0a1 --- /dev/null +++ b/firmware/common/max2837_spi.c @@ -0,0 +1,70 @@ +/* + * Copyright 2012 Will Code? (TODO: Proper attribution) + * 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 "max2837_spi.h" + +#include +#include +#include + +#include "hackrf_core.h" + +void max2837_spi_init(spi_t* const spi) { + (void)spi; + + /* 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); + + /* 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 max2837_spi_transfer(spi_t* const spi, void* const _data, const size_t count) { + (void)spi; + + uint16_t* const data = _data; + + gpio_clear(PORT_XCVR_CS, PIN_XCVR_CS); + for(size_t i=0; i #include #include #include "hackrf_core.h" -void max2837_pin_config(max2837_driver_t* const drv) { +void max2837_target_init(max2837_driver_t* const drv) { + (void)drv; + + 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 XCVR_CTL GPIO pins. */ #ifdef JELLYBEAN scu_pinmux(SCU_XCVR_RXHP, SCU_GPIO_FAST); @@ -58,7 +63,6 @@ void max2837_pin_config(max2837_driver_t* const drv) { ; #endif - max2837_mode_shutdown(drv); #ifdef JELLYBEAN gpio_set(PORT_XCVR_RXHP, PIN_XCVR_RXHP); gpio_set(PORT_XCVR_B, @@ -131,20 +135,3 @@ max2837_mode_t max2837_mode(max2837_driver_t* const drv) { return MAX2837_MODE_SHUTDOWN; } } - -/* SPI register read. */ -uint16_t max2837_spi_read(max2837_driver_t* const drv, uint8_t r) { - (void)drv; - gpio_clear(PORT_XCVR_CS, PIN_XCVR_CS); - const uint16_t value = ssp_transfer(SSP1_NUM, (uint16_t)((1 << 15) | (r << 10))); - gpio_set(PORT_XCVR_CS, PIN_XCVR_CS); - return value & 0x3ff; -} - -/* SPI register write */ -void max2837_spi_write(max2837_driver_t* const drv, uint8_t r, uint16_t v) { - (void)drv; - 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); -} diff --git a/firmware/common/max2837_drv.h b/firmware/common/max2837_target.h similarity index 65% rename from firmware/common/max2837_drv.h rename to firmware/common/max2837_target.h index c7f1062e..13a9a08e 100644 --- a/firmware/common/max2837_drv.h +++ b/firmware/common/max2837_target.h @@ -20,35 +20,18 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __MAX2837_DRV_H -#define __MAX2837_DRV_H +#ifndef __MAX2837_TARGET_H +#define __MAX2837_TARGET_H #include -/* 32 registers, each containing 10 bits of data. */ -#define MAX2837_NUM_REGS 32 -#define MAX2837_DATA_REGS_MAX_VALUE 1024 +#include "max2837.h" -typedef enum { - MAX2837_MODE_SHUTDOWN, - MAX2837_MODE_STANDBY, - MAX2837_MODE_TX, - MAX2837_MODE_RX -} max2837_mode_t; - -typedef struct { - uint16_t regs[MAX2837_NUM_REGS]; - uint32_t regs_dirty; -} max2837_driver_t; - -void max2837_pin_config(max2837_driver_t* const drv); +void max2837_target_init(max2837_driver_t* const drv); void max2837_mode_shutdown(max2837_driver_t* const drv); void max2837_mode_standby(max2837_driver_t* const drv); void max2837_mode_tx(max2837_driver_t* const drv); void max2837_mode_rx(max2837_driver_t* const drv); max2837_mode_t max2837_mode(max2837_driver_t* const drv); -uint16_t max2837_spi_read(max2837_driver_t* const drv, uint8_t r); -void max2837_spi_write(max2837_driver_t* const drv, uint8_t r, uint16_t v); - -#endif // __MAX2837_DRV_H +#endif // __MAX2837_TARGET_H diff --git a/firmware/common/tuning.c b/firmware/common/tuning.c index 07ed2479..74de0c7e 100644 --- a/firmware/common/tuning.c +++ b/firmware/common/tuning.c @@ -26,6 +26,7 @@ #include #include #include +#include "max2837_target.h" #define FREQ_ONE_MHZ (1000*1000) diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index 0973d7f0..72620aef 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -135,7 +135,8 @@ 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_drv.c + ${PATH_HACKRF_FIRMWARE_COMMON}/max2837_spi.c + ${PATH_HACKRF_FIRMWARE_COMMON}/max2837_target.c ${PATH_HACKRF_FIRMWARE_COMMON}/max5864.c ${PATH_HACKRF_FIRMWARE_COMMON}/rffc5071.c ${PATH_HACKRF_FIRMWARE_COMMON}/rffc5071_spi.c From 579f8212a652f305275c85abb0cdfdc6ddfc0112 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 9 Nov 2014 12:21:21 -0800 Subject: [PATCH 22/46] MAX2837: Finish SPI abstraction. Conflicts: firmware/common/hackrf_core.c --- firmware/common/hackrf_core.c | 10 ++++++++-- firmware/common/max2837.c | 7 +++---- firmware/common/max2837_spi.c | 19 ++++++++++++++----- firmware/common/max2837_spi.h | 1 + 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 76a46347..5cb7bd4f 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -38,8 +38,14 @@ #define WAIT_CPU_CLOCK_INIT_DELAY (10000) +spi_t max2837_spi = { + .init = max2837_spi_init, + .transfer = max2837_spi_transfer, + .transfer_gather = max2837_spi_transfer_gather, +}; + max2837_driver_t max2837 = { - .spi = NULL, /* TODO */ + .spi = &max2837_spi, }; @@ -537,7 +543,7 @@ void ssp1_init(void) void ssp1_set_mode_max2837(void) { - max2837_spi_init(max2837.spi); + spi_init(max2837.spi); } void ssp1_set_mode_max5864(void) diff --git a/firmware/common/max2837.c b/firmware/common/max2837.c index 1fa87755..fa3b9786 100644 --- a/firmware/common/max2837.c +++ b/firmware/common/max2837.c @@ -31,7 +31,6 @@ #include #include #include "max2837.h" -#include "max2837_spi.h" #include "max2837_target.h" #include "max2837_regs.def" // private register def macros @@ -80,7 +79,7 @@ static const uint16_t max2837_regs_default[MAX2837_NUM_REGS] = { /* Set up all registers according to defaults specified in docs. */ static void max2837_init(max2837_driver_t* const drv) { - max2837_spi_init(drv->spi); + spi_init(drv->spi); max2837_mode_shutdown(drv); max2837_target_init(drv); @@ -126,13 +125,13 @@ void max2837_setup(max2837_driver_t* const drv) static uint16_t max2837_read(max2837_driver_t* const drv, uint8_t r) { uint16_t value = (1 << 15) | (r << 10); - max2837_spi_transfer(drv->spi, &value, 1); + spi_transfer(drv->spi, &value, 1); return value & 0x3ff; } static void max2837_write(max2837_driver_t* const drv, uint8_t r, uint16_t v) { uint16_t value = (r << 10) | (v & 0x3ff); - max2837_spi_transfer(drv->spi, &value, 1); + spi_transfer(drv->spi, &value, 1); } uint16_t max2837_reg_read(max2837_driver_t* const drv, uint8_t r) diff --git a/firmware/common/max2837_spi.c b/firmware/common/max2837_spi.c index f2fce0a1..911fbbf6 100644 --- a/firmware/common/max2837_spi.c +++ b/firmware/common/max2837_spi.c @@ -57,14 +57,23 @@ void max2837_spi_init(spi_t* const spi) { scu_pinmux(SCU_SSP1_SCK, (SCU_SSP_IO | SCU_CONF_FUNCTION1)); } -void max2837_spi_transfer(spi_t* const spi, void* const _data, const size_t count) { +void max2837_spi_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfers, const size_t count) { (void)spi; - - uint16_t* const data = _data; gpio_clear(PORT_XCVR_CS, PIN_XCVR_CS); for(size_t i=0; i Date: Sun, 9 Nov 2014 13:48:15 -0800 Subject: [PATCH 23/46] MAX5864: Abstract SPI, extract target code --- firmware/common/hackrf_core.c | 49 ++++-------- firmware/common/hackrf_core.h | 3 +- firmware/common/max5864.c | 44 ++++++----- firmware/common/max5864.h | 20 +++-- firmware/common/max5864_spi.c | 78 +++++++++++++++++++ firmware/common/max5864_spi.h | 33 ++++++++ firmware/common/max5864_target.c | 38 +++++++++ firmware/common/max5864_target.h | 29 +++++++ firmware/common/rf_path.c | 9 ++- firmware/hackrf-common.cmake | 2 + firmware/hackrf_usb/hackrf_usb.c | 2 - firmware/mixertx/mixertx.c | 1 - firmware/sgpio-rx/sgpio-rx.c | 1 - firmware/sgpio/sgpio_test.c | 4 +- .../sgpio_passthrough/sgpio_passthrough.c | 1 - firmware/simpletx/simpletx.c | 1 - 16 files changed, 240 insertions(+), 75 deletions(-) create mode 100644 firmware/common/max5864_spi.c create mode 100644 firmware/common/max5864_spi.h create mode 100644 firmware/common/max5864_target.c create mode 100644 firmware/common/max5864_target.h diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 5cb7bd4f..a85984bc 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -26,6 +26,9 @@ #include "max2837.h" #include "max2837_spi.h" #include "max2837_target.h" +#include "max5864.h" +#include "max5864_spi.h" +#include "max5864_target.h" #include "rffc5071.h" #include "rffc5071_spi.h" #include "sgpio.h" @@ -48,6 +51,15 @@ max2837_driver_t max2837 = { .spi = &max2837_spi, }; +spi_t max5864_spi = { + .init = max5864_spi_init, + .transfer = max5864_spi_transfer, + .transfer_gather = max5864_spi_transfer_gather, +}; + +max5864_driver_t max5864 = { + .spi = &max5864_spi, +}; spi_t rffc5071_spi = { .init = rffc5071_spi_init, @@ -530,17 +542,6 @@ 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; -} - void ssp1_set_mode_max2837(void) { spi_init(max2837.spi); @@ -548,25 +549,7 @@ void ssp1_set_mode_max2837(void) 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_init(max5864.spi); } void pin_setup(void) { @@ -612,12 +595,6 @@ void pin_setup(void) { rf_path_pin_setup(); - /* Configure SSP1 Peripheral (to be moved later in SSP driver) */ - scu_pinmux(SCU_SSP1_MISO, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); - scu_pinmux(SCU_SSP1_MOSI, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); - scu_pinmux(SCU_SSP1_SCK, (SCU_SSP_IO | SCU_CONF_FUNCTION1)); - scu_pinmux(SCU_SSP1_SSEL, (SCU_SSP_IO | SCU_CONF_FUNCTION1)); - /* Configure external clock in */ scu_pinmux(SCU_PINMUX_GP_CLKIN, SCU_CLK_IN | SCU_CONF_FUNCTION1); diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index 2eea5da4..32356031 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -33,6 +33,7 @@ extern "C" #include #include "max2837.h" +#include "max5864.h" #include "rffc5071.h" #include "w25q80bv.h" @@ -354,13 +355,13 @@ typedef enum { void delay(uint32_t duration); extern max2837_driver_t max2837; +extern max5864_driver_t max5864; extern rffc5071_driver_t rffc5072; extern w25q80bv_driver_t spi_flash; 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); diff --git a/firmware/common/max5864.c b/firmware/common/max5864.c index 094ed700..773b0d2a 100644 --- a/firmware/common/max5864.c +++ b/firmware/common/max5864.c @@ -21,16 +21,20 @@ #include -#include -#include - -#include "hackrf_core.h" #include "max5864.h" +#include "max5864_target.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_transfer(drv->spi, &value, 1); +} + +void max5864_init(max5864_driver_t* const drv) { + spi_init(drv->spi); + max5864_target_init(drv); +} + +void max5864_setup(max5864_driver_t* const drv) { + max5864_init(drv); } /* Set MAX5864 operation mode to "Shutdown": @@ -39,9 +43,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 +54,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 +65,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 +76,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 +87,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 +98,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..0b5a8bb9 100644 --- a/firmware/common/max5864.h +++ b/firmware/common/max5864.h @@ -22,11 +22,19 @@ #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.h" + +typedef struct max5864_driver_t { + spi_t* const spi; +} max5864_driver_t; + +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_spi.c b/firmware/common/max5864_spi.c new file mode 100644 index 00000000..c30750ba --- /dev/null +++ b/firmware/common/max5864_spi.c @@ -0,0 +1,78 @@ +/* + * 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_spi.h" + +#include +#include +#include + +#include "hackrf_core.h" + +void max5864_spi_init(spi_t* const spi) { + (void)spi; + + /* 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); + + /* 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 max5864_spi_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfers, const size_t count) { + (void)spi; + + gpio_clear(PORT_AD_CS, PIN_AD_CS); + for(size_t i=0; i + +#include "spi.h" + +void max5864_spi_init(spi_t* const spi); +void max5864_spi_transfer(spi_t* const spi, void* const value, const size_t count); +void max5864_spi_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfers, const size_t count); + +#endif/*__MAX5864_SPI_H__*/ diff --git a/firmware/common/max5864_target.c b/firmware/common/max5864_target.c new file mode 100644 index 00000000..0c61f6f2 --- /dev/null +++ b/firmware/common/max5864_target.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 "max5864_target.h" + +#include +#include +#include "hackrf_core.h" + +void max5864_target_init(max5864_driver_t* const drv) { + (void)drv; + + /* + * 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; +} 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 071564da..589961aa 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -209,7 +209,8 @@ void rf_path_pin_setup() { void rf_path_init(void) { ssp1_set_mode_max5864(); - max5864_shutdown(); + max5864_setup(&max5864); + max5864_shutdown(&max5864); ssp1_set_mode_max2837(); max2837_setup(&max2837); @@ -236,7 +237,7 @@ void rf_path_set_direction(const rf_path_direction_t direction) { rffc5071_enable(&rffc5072); } ssp1_set_mode_max5864(); - max5864_tx(); + max5864_tx(&max5864); ssp1_set_mode_max2837(); max2837_tx(&max2837); sgpio_configure(SGPIO_DIRECTION_TX); @@ -255,7 +256,7 @@ void rf_path_set_direction(const rf_path_direction_t direction) { rffc5071_enable(&rffc5072); } ssp1_set_mode_max5864(); - max5864_rx(); + max5864_rx(&max5864); ssp1_set_mode_max2837(); max2837_rx(&max2837); sgpio_configure(SGPIO_DIRECTION_RX); @@ -270,7 +271,7 @@ void rf_path_set_direction(const rf_path_direction_t direction) { switchctrl &= ~SWITCHCTRL_TX; rffc5071_disable(&rffc5072); ssp1_set_mode_max5864(); - max5864_standby(); + max5864_standby(&max5864); ssp1_set_mode_max2837(); max2837_set_mode(&max2837, MAX2837_MODE_STANDBY); sgpio_configure(SGPIO_DIRECTION_RX); diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index 72620aef..ff5bcba0 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -138,6 +138,8 @@ macro(DeclareTargets) ${PATH_HACKRF_FIRMWARE_COMMON}/max2837_spi.c ${PATH_HACKRF_FIRMWARE_COMMON}/max2837_target.c ${PATH_HACKRF_FIRMWARE_COMMON}/max5864.c + ${PATH_HACKRF_FIRMWARE_COMMON}/max5864_spi.c + ${PATH_HACKRF_FIRMWARE_COMMON}/max5864_target.c ${PATH_HACKRF_FIRMWARE_COMMON}/rffc5071.c ${PATH_HACKRF_FIRMWARE_COMMON}/rffc5071_spi.c ${PATH_HACKRF_FIRMWARE_COMMON}/spi.c diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 42fc4482..2e6a4140 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -208,8 +208,6 @@ int main(void) { usb_run(&usb_device); - ssp1_init(); - rf_path_init(); unsigned int phase = 0; diff --git a/firmware/mixertx/mixertx.c b/firmware/mixertx/mixertx.c index c7150d57..e23e00d7 100644 --- a/firmware/mixertx/mixertx.c +++ b/firmware/mixertx/mixertx.c @@ -38,7 +38,6 @@ int main(void) enable_rf_power(); #endif cpu_clock_init(); - ssp1_init(); gpio_set(PORT_LED1_3, (PIN_LED1)); /* LED1 on */ diff --git a/firmware/sgpio-rx/sgpio-rx.c b/firmware/sgpio-rx/sgpio-rx.c index dbee1d3f..dca4c489 100644 --- a/firmware/sgpio-rx/sgpio-rx.c +++ b/firmware/sgpio-rx/sgpio-rx.c @@ -96,7 +96,6 @@ int main(void) { enable_rf_power(); #endif cpu_clock_init(); - ssp1_init(); rf_path_init(); rf_path_set_direction(RF_PATH_DIRECTION_RX); diff --git a/firmware/sgpio/sgpio_test.c b/firmware/sgpio/sgpio_test.c index 6e391c10..de3ee605 100644 --- a/firmware/sgpio/sgpio_test.c +++ b/firmware/sgpio/sgpio_test.c @@ -72,12 +72,12 @@ int main(void) { pin_setup(); enable_1v8_power(); cpu_clock_init(); - ssp1_init(); gpio_set(PORT_LED1_3, PIN_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..d1cc0491 100644 --- a/firmware/sgpio_passthrough/sgpio_passthrough.c +++ b/firmware/sgpio_passthrough/sgpio_passthrough.c @@ -353,7 +353,6 @@ int main(void) pin_setup(); enable_1v8_power(); cpu_clock_init(); - ssp1_init(); gpio_set(PORT_LED1_3, PIN_LED1); //test_sgpio_sliceA_D(); diff --git a/firmware/simpletx/simpletx.c b/firmware/simpletx/simpletx.c index d6f9072d..78178ee9 100644 --- a/firmware/simpletx/simpletx.c +++ b/firmware/simpletx/simpletx.c @@ -37,7 +37,6 @@ int main(void) enable_rf_power(); #endif cpu_clock_init(); - ssp1_init(); gpio_set(PORT_LED1_3, (PIN_LED1)); /* LED1 on */ From 20d6d5a5a241d2da1e44e3c48ed62f6daef34b67 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 9 Nov 2014 13:48:44 -0800 Subject: [PATCH 24/46] MAX2837: Header clean-up. --- firmware/common/max2837_spi.h | 1 - firmware/common/max2837_target.h | 2 -- 2 files changed, 3 deletions(-) diff --git a/firmware/common/max2837_spi.h b/firmware/common/max2837_spi.h index cb5b8fca..b3de6db3 100644 --- a/firmware/common/max2837_spi.h +++ b/firmware/common/max2837_spi.h @@ -23,7 +23,6 @@ #ifndef __MAX2837_SPI_H__ #define __MAX2837_SPI_H__ -#include "stdint.h" #include "stddef.h" #include "spi.h" diff --git a/firmware/common/max2837_target.h b/firmware/common/max2837_target.h index 13a9a08e..52d2565e 100644 --- a/firmware/common/max2837_target.h +++ b/firmware/common/max2837_target.h @@ -23,8 +23,6 @@ #ifndef __MAX2837_TARGET_H #define __MAX2837_TARGET_H -#include - #include "max2837.h" void max2837_target_init(max2837_driver_t* const drv); From 58e3465ce5a1be50c32eec5e5abf4314c9495bfe Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 9 Nov 2014 16:15:28 -0800 Subject: [PATCH 25/46] W25Q80BV: Finish abstracting SPI code. --- firmware/common/hackrf_core.c | 2 - firmware/common/hackrf_core.h | 2 - firmware/common/w25q80bv.c | 29 ++++--- firmware/common/w25q80bv.h | 7 +- .../common/{w25q80bv_drv.c => w25q80bv_spi.c} | 78 ++++++++----------- .../common/{w25q80bv_drv.h => w25q80bv_spi.h} | 26 ++----- firmware/hackrf_usb/CMakeLists.txt | 2 +- 7 files changed, 67 insertions(+), 79 deletions(-) rename firmware/common/{w25q80bv_drv.c => w25q80bv_spi.c} (78%) rename firmware/common/{w25q80bv_drv.h => w25q80bv_spi.h} (63%) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index a85984bc..d7c875be 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -67,12 +67,10 @@ spi_t rffc5071_spi = { .transfer_gather = rffc5071_spi_transfer_gather, }; -w25q80bv_driver_t spi_flash; rffc5071_driver_t rffc5072 = { .spi = &rffc5071_spi, }; - void delay(uint32_t duration) { uint32_t i; diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index 32356031..f9f8a93b 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -35,7 +35,6 @@ extern "C" #include "max2837.h" #include "max5864.h" #include "rffc5071.h" -#include "w25q80bv.h" /* hardware identification number */ #define BOARD_ID_JELLYBEAN 0 @@ -357,7 +356,6 @@ void delay(uint32_t duration); extern max2837_driver_t max2837; extern max5864_driver_t max5864; extern rffc5071_driver_t rffc5072; -extern w25q80bv_driver_t spi_flash; void cpu_clock_init(void); void cpu_clock_pll1_low_speed(void); diff --git a/firmware/common/w25q80bv.c b/firmware/common/w25q80bv.c index 12941eb9..e7596c0b 100644 --- a/firmware/common/w25q80bv.c +++ b/firmware/common/w25q80bv.c @@ -28,8 +28,9 @@ */ #include + #include "w25q80bv.h" -#include "w25q80bv_drv.h" +#include "w25q80bv_spi.h" #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) @@ -57,7 +58,7 @@ void w25q80bv_setup(w25q80bv_driver_t* const drv) drv->num_pages = 4096U; drv->num_bytes = 1048576U; - w25q80bv_hw_init(drv->hw); + spi_init(drv->spi); device_id = 0; while(device_id != W25Q80BV_DEVICE_ID_RES) @@ -69,7 +70,7 @@ void w25q80bv_setup(w25q80bv_driver_t* const drv) uint8_t w25q80bv_get_status(w25q80bv_driver_t* const drv) { uint8_t data[] = { W25Q80BV_READ_STATUS1, 0xFF }; - w25q80bv_hw_transfer(drv->hw, data, ARRAY_SIZE(data)); + spi_transfer(drv->spi, data, ARRAY_SIZE(data)); return data[1]; } @@ -80,7 +81,7 @@ uint8_t w25q80bv_get_device_id(w25q80bv_driver_t* const drv) W25Q80BV_DEVICE_ID, 0xFF, 0xFF, 0xFF, 0xFF }; - w25q80bv_hw_transfer(drv->hw, data, ARRAY_SIZE(data)); + spi_transfer(drv->spi, data, ARRAY_SIZE(data)); return data[4]; } @@ -91,7 +92,7 @@ void w25q80bv_get_unique_id(w25q80bv_driver_t* const drv, w25q80bv_unique_id_t* 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - w25q80bv_hw_transfer(drv->hw, data, ARRAY_SIZE(data)); + spi_transfer(drv->spi, data, ARRAY_SIZE(data)); for(size_t i=0; i<8; i++) { unique_id->id_8b[i] = data[5+i]; @@ -108,7 +109,7 @@ void w25q80bv_write_enable(w25q80bv_driver_t* const drv) w25q80bv_wait_while_busy(drv); uint8_t data[] = { W25Q80BV_WRITE_ENABLE }; - w25q80bv_hw_transfer(drv->hw, data, ARRAY_SIZE(data)); + spi_transfer(drv->spi, data, ARRAY_SIZE(data)); } void w25q80bv_chip_erase(w25q80bv_driver_t* const drv) @@ -125,7 +126,7 @@ void w25q80bv_chip_erase(w25q80bv_driver_t* const drv) w25q80bv_wait_while_busy(drv); uint8_t data[] = { W25Q80BV_CHIP_ERASE }; - w25q80bv_hw_transfer(drv->hw, data, ARRAY_SIZE(data)); + spi_transfer(drv->spi, data, ARRAY_SIZE(data)); } /* write up a 256 byte page or partial page */ @@ -149,12 +150,12 @@ static void w25q80bv_page_program(w25q80bv_driver_t* const drv, const uint32_t a addr & 0xFF }; - const w25q80bv_transfer_t transfers[] = { + const spi_transfer_t transfers[] = { { header, ARRAY_SIZE(header) }, { data, len } }; - w25q80bv_hw_transfer_multiple(drv->hw, transfers, ARRAY_SIZE(transfers)); + spi_transfer_gather(drv->spi, transfers, ARRAY_SIZE(transfers)); } /* write an arbitrary number of bytes */ @@ -198,3 +199,13 @@ void w25q80bv_program(w25q80bv_driver_t* const drv, uint32_t addr, uint32_t len, w25q80bv_page_program(drv, addr, len, data); } } + +spi_t w25q80bv_spi = { + .init = w25q80bv_spi_init, + .transfer = w25q80bv_spi_transfer, + .transfer_gather = w25q80bv_spi_transfer_gather, +}; + +w25q80bv_driver_t spi_flash = { + .spi = &w25q80bv_spi, +}; diff --git a/firmware/common/w25q80bv.h b/firmware/common/w25q80bv.h index 4eb028cd..9d31a286 100644 --- a/firmware/common/w25q80bv.h +++ b/firmware/common/w25q80bv.h @@ -24,9 +24,10 @@ #ifndef __W25Q80BV_H__ #define __W25Q80BV_H__ +#include #include -#include "w25q80bv_drv.h" +#include "spi.h" typedef union { @@ -36,7 +37,7 @@ typedef union } w25q80bv_unique_id_t; typedef struct { - w25q80bv_hw_t* hw; + spi_t* spi; size_t page_len; size_t num_pages; size_t num_bytes; @@ -48,4 +49,6 @@ void w25q80bv_program(w25q80bv_driver_t* const drv, uint32_t addr, uint32_t len, 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); +extern w25q80bv_driver_t spi_flash; + #endif//__W25Q80BV_H__ diff --git a/firmware/common/w25q80bv_drv.c b/firmware/common/w25q80bv_spi.c similarity index 78% rename from firmware/common/w25q80bv_drv.c rename to firmware/common/w25q80bv_spi.c index c7d50bff..d64e69ba 100644 --- a/firmware/common/w25q80bv_drv.c +++ b/firmware/common/w25q80bv_spi.c @@ -21,37 +21,35 @@ * Boston, MA 02110-1301, USA. */ -#include "w25q80bv_drv.h" +#include "w25q80bv_spi.h" + +#include +#include +#include +#include #include "hackrf_core.h" -#include -#include -#include -#include - -static void w25q80bv_spi_select(w25q80bv_hw_t* const hw) { - (void)hw; - gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL); -} - -static void w25q80bv_spi_unselect(w25q80bv_hw_t* const hw) { - (void)hw; - gpio_set(PORT_SSP0_SSEL, PIN_SSP0_SSEL); -} - -static uint16_t w25q80bv_spi_transfer(w25q80bv_hw_t* const hw, const uint16_t tx_data) { - (void)hw; - return ssp_transfer(SSP0_NUM, tx_data); -} - -void w25q80bv_hw_init(w25q80bv_hw_t* const hw) { +void w25q80bv_spi_init(spi_t* const spi) { + (void)spi; + 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; + /* 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); + /* 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] @@ -72,41 +70,33 @@ void w25q80bv_hw_init(w25q80bv_hw_t* const hw) { /* drive SSEL, HOLD, and WP pins high */ gpio_set(PORT_FLASH, (PIN_FLASH_HOLD | PIN_FLASH_WP)); - w25q80bv_spi_unselect(hw); + 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); } -void w25q80bv_hw_transfer_multiple( - w25q80bv_hw_t* const hw, - const w25q80bv_transfer_t* const transfers, +void w25q80bv_spi_transfer_gather( + spi_t* const spi, + const spi_transfer_t* const transfers, const size_t transfer_count ) { - w25q80bv_spi_select(hw); + (void)spi; + + gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL); for(size_t i=0; i #include -typedef struct { - uint8_t* const data; - const size_t count; -} w25q80bv_transfer_t; +#include "spi.h" -typedef struct { - /* Empty for now */ -} w25q80bv_hw_t; +void w25q80bv_spi_init(spi_t* const spi); +void w25q80bv_spi_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfers, const size_t transfer_count); +void w25q80bv_spi_transfer(spi_t* const spi, void* const data, const size_t count); -void w25q80bv_hw_init(w25q80bv_hw_t* const hw); -void w25q80bv_hw_transfer(w25q80bv_hw_t* const hw, uint8_t* data, const size_t count); -void w25q80bv_hw_transfer_multiple( - w25q80bv_hw_t* const hw, - const w25q80bv_transfer_t* const transfers, - const size_t transfer_count -); - -#endif//__W25Q80BV_DRV_H__ +#endif/*__W25Q80BV_SPI_H__*/ diff --git a/firmware/hackrf_usb/CMakeLists.txt b/firmware/hackrf_usb/CMakeLists.txt index e9653119..bf211f9c 100644 --- a/firmware/hackrf_usb/CMakeLists.txt +++ b/firmware/hackrf_usb/CMakeLists.txt @@ -45,7 +45,7 @@ set(SRC_M4 "${PATH_HACKRF_FIRMWARE_COMMON}/usb_queue.c" "${PATH_HACKRF_FIRMWARE_COMMON}/fault_handler.c" "${PATH_HACKRF_FIRMWARE_COMMON}/w25q80bv.c" - "${PATH_HACKRF_FIRMWARE_COMMON}/w25q80bv_drv.c" + "${PATH_HACKRF_FIRMWARE_COMMON}/w25q80bv_spi.c" "${PATH_HACKRF_FIRMWARE_COMMON}/cpld_jtag.c" "${PATH_HACKRF_FIRMWARE_COMMON}/xapp058/lenval.c" "${PATH_HACKRF_FIRMWARE_COMMON}/xapp058/micro.c" From b8421cc14fd73809571ff9940fecb80e5bf54d55 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sun, 9 Nov 2014 22:10:27 -0800 Subject: [PATCH 26/46] SSP1: Merge MAX2837 and MAX5864 SPI code to use single SPI interface. Conflicts: firmware/common/hackrf_core.c firmware/common/hackrf_core.h --- firmware/common/hackrf_core.c | 57 +++++++++---- firmware/common/hackrf_core.h | 6 ++ firmware/common/max2837.c | 2 +- firmware/common/max2837_spi.c | 79 ------------------- firmware/common/max2837_spi.h | 34 -------- firmware/common/max2837_target.c | 10 +++ firmware/common/max2837_target.h | 4 + firmware/common/max5864.c | 6 +- firmware/common/max5864_target.c | 10 +++ firmware/common/max5864_target.h | 3 + firmware/common/rffc5071.c | 2 +- firmware/common/rffc5071_spi.c | 3 +- firmware/common/rffc5071_spi.h | 2 +- firmware/common/spi.c | 4 +- firmware/common/spi.h | 5 +- firmware/common/{max5864_spi.c => spi_ssp1.c} | 55 ++++++------- firmware/common/{max5864_spi.h => spi_ssp1.h} | 23 ++++-- firmware/common/w25q80bv.c | 3 +- firmware/common/w25q80bv_spi.c | 3 +- firmware/common/w25q80bv_spi.h | 2 +- firmware/hackrf-common.cmake | 3 +- 21 files changed, 139 insertions(+), 177 deletions(-) delete mode 100644 firmware/common/max2837_spi.c delete mode 100644 firmware/common/max2837_spi.h rename firmware/common/{max5864_spi.c => spi_ssp1.c} (58%) rename firmware/common/{max5864_spi.h => spi_ssp1.h} (59%) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index d7c875be..9f2bb9bd 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -23,11 +23,10 @@ #include "hackrf_core.h" #include "si5351c.h" +#include "spi_ssp1.h" #include "max2837.h" -#include "max2837_spi.h" #include "max2837_target.h" #include "max5864.h" -#include "max5864_spi.h" #include "max5864_target.h" #include "rffc5071.h" #include "rffc5071_spi.h" @@ -41,27 +40,53 @@ #define WAIT_CPU_CLOCK_INIT_DELAY (10000) -spi_t max2837_spi = { - .init = max2837_spi_init, - .transfer = max2837_spi_transfer, - .transfer_gather = max2837_spi_transfer_gather, +const ssp1_config_t ssp1_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, + .select = max2837_target_spi_select, + .unselect = max2837_target_spi_unselect, +}; + +const ssp1_config_t ssp1_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, + .select = max5864_target_spi_select, + .unselect = max5864_target_spi_unselect, +}; + +spi_t spi_ssp1 = { + .config = &ssp1_config_max2837, + .init = spi_ssp1_init, + .transfer = spi_ssp1_transfer, + .transfer_gather = spi_ssp1_transfer_gather, }; max2837_driver_t max2837 = { - .spi = &max2837_spi, -}; - -spi_t max5864_spi = { - .init = max5864_spi_init, - .transfer = max5864_spi_transfer, - .transfer_gather = max5864_spi_transfer_gather, + .spi = &spi_ssp1, }; max5864_driver_t max5864 = { - .spi = &max5864_spi, + .spi = &spi_ssp1, }; spi_t rffc5071_spi = { + .config = NULL, .init = rffc5071_spi_init, .transfer = rffc5071_spi_transfer, .transfer_gather = rffc5071_spi_transfer_gather, @@ -542,12 +567,12 @@ void cpu_clock_pll1_max_speed(void) void ssp1_set_mode_max2837(void) { - spi_init(max2837.spi); + spi_init(max2837.spi, &ssp1_config_max2837); } void ssp1_set_mode_max5864(void) { - spi_init(max5864.spi); + spi_init(max5864.spi, &ssp1_config_max5864); } void pin_setup(void) { diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index f9f8a93b..daebe1b5 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -32,6 +32,8 @@ extern "C" #include #include +#include "spi_ssp1.h" + #include "max2837.h" #include "max5864.h" #include "rffc5071.h" @@ -353,6 +355,10 @@ typedef enum { } transceiver_mode_t; void delay(uint32_t duration); + +extern const ssp1_config_t ssp1_config_max2837; +extern const ssp1_config_t ssp1_config_max5864; + extern max2837_driver_t max2837; extern max5864_driver_t max5864; extern rffc5071_driver_t rffc5072; diff --git a/firmware/common/max2837.c b/firmware/common/max2837.c index fa3b9786..c667bbe3 100644 --- a/firmware/common/max2837.c +++ b/firmware/common/max2837.c @@ -79,7 +79,7 @@ static const uint16_t max2837_regs_default[MAX2837_NUM_REGS] = { /* Set up all registers according to defaults specified in docs. */ static void max2837_init(max2837_driver_t* const drv) { - spi_init(drv->spi); + spi_init(drv->spi, &ssp1_config_max2837); max2837_mode_shutdown(drv); max2837_target_init(drv); diff --git a/firmware/common/max2837_spi.c b/firmware/common/max2837_spi.c deleted file mode 100644 index 911fbbf6..00000000 --- a/firmware/common/max2837_spi.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2012 Will Code? (TODO: Proper attribution) - * 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 "max2837_spi.h" - -#include -#include -#include - -#include "hackrf_core.h" - -void max2837_spi_init(spi_t* const spi) { - (void)spi; - - /* 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); - - /* 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 max2837_spi_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfers, const size_t count) { - (void)spi; - - gpio_clear(PORT_XCVR_CS, PIN_XCVR_CS); - for(size_t i=0; ispi, &value, 1); } -void max5864_init(max5864_driver_t* const drv) { - spi_init(drv->spi); +static void max5864_init(max5864_driver_t* const drv) { + spi_init(drv->spi, &ssp1_config_max5864); max5864_target_init(drv); } diff --git a/firmware/common/max5864_target.c b/firmware/common/max5864_target.c index 0c61f6f2..d109f898 100644 --- a/firmware/common/max5864_target.c +++ b/firmware/common/max5864_target.c @@ -36,3 +36,13 @@ void max5864_target_init(max5864_driver_t* const drv) { GPIO_SET(PORT_AD_CS) = PIN_AD_CS; GPIO_DIR(PORT_AD_CS) |= PIN_AD_CS; } + +void max5864_target_spi_select(spi_t* const spi) { + (void)spi; + gpio_clear(PORT_AD_CS, PIN_AD_CS); +} + +void max5864_target_spi_unselect(spi_t* const spi) { + (void)spi; + gpio_set(PORT_AD_CS, PIN_AD_CS); +} diff --git a/firmware/common/max5864_target.h b/firmware/common/max5864_target.h index be684e2c..b5c7a060 100644 --- a/firmware/common/max5864_target.h +++ b/firmware/common/max5864_target.h @@ -23,7 +23,10 @@ #define __MAX5864_TARGET_H__ #include "max5864.h" +#include "spi.h" void max5864_target_init(max5864_driver_t* const drv); +void max5864_target_spi_select(spi_t* const spi); +void max5864_target_spi_unselect(spi_t* const spi); #endif/*__MAX5864_TARGET_H__*/ diff --git a/firmware/common/rffc5071.c b/firmware/common/rffc5071.c index e9c1b72c..54237b98 100644 --- a/firmware/common/rffc5071.c +++ b/firmware/common/rffc5071.c @@ -90,7 +90,7 @@ void rffc5071_setup(rffc5071_driver_t* const drv) { rffc5071_init(drv); - spi_init(drv->spi); + spi_init(drv->spi, NULL); /* initial setup */ /* put zeros in freq contol registers */ diff --git a/firmware/common/rffc5071_spi.c b/firmware/common/rffc5071_spi.c index 1711c513..74574902 100644 --- a/firmware/common/rffc5071_spi.c +++ b/firmware/common/rffc5071_spi.c @@ -83,7 +83,8 @@ static void rffc5071_spi_target_init(spi_t* const spi) { gpio_set(PORT_MIXER_RESETX, PIN_MIXER_RESETX); /* active low */ } -void rffc5071_spi_init(spi_t* const spi) { +void rffc5071_spi_init(spi_t* const spi, const void* const config) { + (void)config; rffc5071_spi_bus_init(spi); rffc5071_spi_target_init(spi); } diff --git a/firmware/common/rffc5071_spi.h b/firmware/common/rffc5071_spi.h index d20fe152..ba2eb44f 100644 --- a/firmware/common/rffc5071_spi.h +++ b/firmware/common/rffc5071_spi.h @@ -25,7 +25,7 @@ #include "spi.h" -void rffc5071_spi_init(spi_t* const spi); +void rffc5071_spi_init(spi_t* const spi, const void* const config); void rffc5071_spi_transfer(spi_t* const spi, void* const data, const size_t count); void rffc5071_spi_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfer, const size_t count); diff --git a/firmware/common/spi.c b/firmware/common/spi.c index f743c0bc..99076737 100644 --- a/firmware/common/spi.c +++ b/firmware/common/spi.c @@ -21,8 +21,8 @@ #include "spi.h" -void spi_init(spi_t* const spi) { - spi->init(spi); +void spi_init(spi_t* const spi, const void* const config) { + spi->init(spi, config); } void spi_transfer(spi_t* const spi, void* const data, const size_t count) { diff --git a/firmware/common/spi.h b/firmware/common/spi.h index cad5f268..d2ec2a46 100644 --- a/firmware/common/spi.h +++ b/firmware/common/spi.h @@ -33,12 +33,13 @@ struct spi_t; typedef struct spi_t spi_t; struct spi_t { - void (*init)(spi_t* const spi); + const void* config; + void (*init)(spi_t* const spi, const void* const config); void (*transfer)(spi_t* const spi, void* const data, const size_t count); void (*transfer_gather)(spi_t* const spi, const spi_transfer_t* const transfers, const size_t count); }; -void spi_init(spi_t* const spi); +void spi_init(spi_t* const spi, const void* const config); void spi_transfer(spi_t* const spi, void* const data, const size_t count); void spi_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfers, const size_t count); diff --git a/firmware/common/max5864_spi.c b/firmware/common/spi_ssp1.c similarity index 58% rename from firmware/common/max5864_spi.c rename to firmware/common/spi_ssp1.c index c30750ba..b0e6182a 100644 --- a/firmware/common/max5864_spi.c +++ b/firmware/common/spi_ssp1.c @@ -19,60 +19,61 @@ * Boston, MA 02110-1301, USA. */ -#include "max5864_spi.h" +#include "spi_ssp1.h" -#include #include #include #include "hackrf_core.h" -void max5864_spi_init(spi_t* const spi) { - (void)spi; +void spi_ssp1_init(spi_t* const spi, const void* const _config) { + const ssp1_config_t* const config = _config; - /* 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, + config->data_bits, SSP_FRAME_SPI, SSP_CPOL_0_CPHA_0, - serial_clock_rate, - clock_prescale_rate, + config->serial_clock_rate, + config->clock_prescale_rate, SSP_MODE_NORMAL, SSP_MASTER, SSP_SLAVE_OUT_ENABLE); + spi->config = config; + /* 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 max5864_spi_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfers, const size_t count) { - (void)spi; +void spi_ssp1_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfers, const size_t count) { + const ssp1_config_t* const config = spi->config; - gpio_clear(PORT_AD_CS, PIN_AD_CS); + const size_t word_size = (SSP1_CR0 & 0xf) + 1; + + config->select(spi); for(size_t i=0; i 8 ) { + uint16_t* const data = transfers[i].data; + for(size_t j=0; junselect(spi); } -void max5864_spi_transfer(spi_t* const spi, void* const data, const size_t count) { +void spi_ssp1_transfer(spi_t* const spi, void* const data, const size_t count) { const spi_transfer_t transfers[] = { { data, count }, }; - max5864_spi_transfer_gather(spi, transfers, 1); + spi_ssp1_transfer_gather(spi, transfers, 1); } diff --git a/firmware/common/max5864_spi.h b/firmware/common/spi_ssp1.h similarity index 59% rename from firmware/common/max5864_spi.h rename to firmware/common/spi_ssp1.h index 7ee4d651..b74aff40 100644 --- a/firmware/common/max5864_spi.h +++ b/firmware/common/spi_ssp1.h @@ -19,15 +19,26 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __MAX5864_SPI_H__ -#define __MAX5864_SPI_H__ +#ifndef __SPI_SSP1_H__ +#define __SPI_SSP1_H__ +#include #include #include "spi.h" -void max5864_spi_init(spi_t* const spi); -void max5864_spi_transfer(spi_t* const spi, void* const value, const size_t count); -void max5864_spi_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfers, const size_t count); +#include -#endif/*__MAX5864_SPI_H__*/ +typedef struct ssp1_config_t { + ssp_datasize_t data_bits; + uint8_t serial_clock_rate; + uint8_t clock_prescale_rate; + void (*select)(spi_t* const spi); + void (*unselect)(spi_t* const spi); +} ssp1_config_t; + +void spi_ssp1_init(spi_t* const spi, const void* const config); +void spi_ssp1_transfer(spi_t* const spi, void* const value, const size_t count); +void spi_ssp1_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfers, const size_t count); + +#endif/*__SPI_SSP1_H__*/ diff --git a/firmware/common/w25q80bv.c b/firmware/common/w25q80bv.c index e7596c0b..6f33edae 100644 --- a/firmware/common/w25q80bv.c +++ b/firmware/common/w25q80bv.c @@ -58,7 +58,7 @@ void w25q80bv_setup(w25q80bv_driver_t* const drv) drv->num_pages = 4096U; drv->num_bytes = 1048576U; - spi_init(drv->spi); + spi_init(drv->spi, NULL); device_id = 0; while(device_id != W25Q80BV_DEVICE_ID_RES) @@ -201,6 +201,7 @@ void w25q80bv_program(w25q80bv_driver_t* const drv, uint32_t addr, uint32_t len, } spi_t w25q80bv_spi = { + .config = NULL, .init = w25q80bv_spi_init, .transfer = w25q80bv_spi_transfer, .transfer_gather = w25q80bv_spi_transfer_gather, diff --git a/firmware/common/w25q80bv_spi.c b/firmware/common/w25q80bv_spi.c index d64e69ba..f51b7b13 100644 --- a/firmware/common/w25q80bv_spi.c +++ b/firmware/common/w25q80bv_spi.c @@ -30,8 +30,9 @@ #include "hackrf_core.h" -void w25q80bv_spi_init(spi_t* const spi) { +void w25q80bv_spi_init(spi_t* const spi, const void* const config) { (void)spi; + (void)config; const uint8_t serial_clock_rate = 2; const uint8_t clock_prescale_rate = 2; diff --git a/firmware/common/w25q80bv_spi.h b/firmware/common/w25q80bv_spi.h index c6c95026..dce1a029 100644 --- a/firmware/common/w25q80bv_spi.h +++ b/firmware/common/w25q80bv_spi.h @@ -28,7 +28,7 @@ #include "spi.h" -void w25q80bv_spi_init(spi_t* const spi); +void w25q80bv_spi_init(spi_t* const spi, const void* const config); void w25q80bv_spi_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfers, const size_t transfer_count); void w25q80bv_spi_transfer(spi_t* const spi, void* const data, const size_t count); diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index ff5bcba0..9d4d01ea 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -135,14 +135,13 @@ 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_spi.c ${PATH_HACKRF_FIRMWARE_COMMON}/max2837_target.c ${PATH_HACKRF_FIRMWARE_COMMON}/max5864.c - ${PATH_HACKRF_FIRMWARE_COMMON}/max5864_spi.c ${PATH_HACKRF_FIRMWARE_COMMON}/max5864_target.c ${PATH_HACKRF_FIRMWARE_COMMON}/rffc5071.c ${PATH_HACKRF_FIRMWARE_COMMON}/rffc5071_spi.c ${PATH_HACKRF_FIRMWARE_COMMON}/spi.c + ${PATH_HACKRF_FIRMWARE_COMMON}/spi_ssp1.c m0_bin.s ) From 79fd31d5d6bb84e62daac02df31fb879a8ed540b Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 10 Nov 2014 08:58:50 -0800 Subject: [PATCH 27/46] SSP1: Fix argument name to match SPI naming. --- firmware/common/spi_ssp1.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/common/spi_ssp1.h b/firmware/common/spi_ssp1.h index b74aff40..57bb493e 100644 --- a/firmware/common/spi_ssp1.h +++ b/firmware/common/spi_ssp1.h @@ -38,7 +38,7 @@ typedef struct ssp1_config_t { } ssp1_config_t; void spi_ssp1_init(spi_t* const spi, const void* const config); -void spi_ssp1_transfer(spi_t* const spi, void* const value, const size_t count); +void spi_ssp1_transfer(spi_t* const spi, void* const data, const size_t count); void spi_ssp1_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfers, const size_t count); #endif/*__SPI_SSP1_H__*/ From 21eb27c3f33787faea51dae0bf03f7771ca79887 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 10 Nov 2014 09:58:49 -0800 Subject: [PATCH 28/46] SSP0: Extract SPI interface from W25Q80BV code. --- firmware/common/hackrf_core.c | 22 ++++++ firmware/common/hackrf_core.h | 5 ++ .../common/{w25q80bv_spi.c => spi_ssp0.c} | 69 ++++++++++--------- firmware/common/spi_ssp0.h | 44 ++++++++++++ firmware/common/w25q80bv.c | 19 ++--- firmware/common/w25q80bv.h | 2 - firmware/common/w25q80bv_target.c | 48 +++++++++++++ .../{w25q80bv_spi.h => w25q80bv_target.h} | 19 +++-- firmware/hackrf-common.cmake | 3 + firmware/hackrf_usb/CMakeLists.txt | 2 - 10 files changed, 170 insertions(+), 63 deletions(-) rename firmware/common/{w25q80bv_spi.c => spi_ssp0.c} (68%) create mode 100644 firmware/common/spi_ssp0.h create mode 100644 firmware/common/w25q80bv_target.c rename firmware/common/{w25q80bv_spi.h => w25q80bv_target.h} (61%) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 9f2bb9bd..b5edabd9 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -23,6 +23,7 @@ #include "hackrf_core.h" #include "si5351c.h" +#include "spi_ssp0.h" #include "spi_ssp1.h" #include "max2837.h" #include "max2837_target.h" @@ -30,6 +31,8 @@ #include "max5864_target.h" #include "rffc5071.h" #include "rffc5071_spi.h" +#include "w25q80bv.h" +#include "w25q80bv_target.h" #include "sgpio.h" #include "rf_path.h" #include @@ -96,6 +99,25 @@ rffc5071_driver_t rffc5072 = { .spi = &rffc5071_spi, }; +const ssp0_config_t ssp0_config_w25q80bv = { + .data_bits = SSP_DATA_8BITS, + .serial_clock_rate = 2, + .clock_prescale_rate = 2, + .select = w25q80bv_target_spi_select, + .unselect = w25q80bv_target_spi_unselect, +}; + +spi_t spi_ssp0 = { + .config = &ssp0_config_w25q80bv, + .init = spi_ssp0_init, + .transfer = spi_ssp0_transfer, + .transfer_gather = spi_ssp0_transfer_gather, +}; + +w25q80bv_driver_t spi_flash = { + .spi = &spi_ssp0, +}; + void delay(uint32_t duration) { uint32_t i; diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index daebe1b5..53270f2f 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -32,11 +32,13 @@ extern "C" #include #include +#include "spi_ssp0.h" #include "spi_ssp1.h" #include "max2837.h" #include "max5864.h" #include "rffc5071.h" +#include "w25q80bv.h" /* hardware identification number */ #define BOARD_ID_JELLYBEAN 0 @@ -356,12 +358,15 @@ typedef enum { void delay(uint32_t duration); +/* TODO: Hide these configurations */ +extern const ssp0_config_t ssp0_config_w25q80bv; extern const ssp1_config_t ssp1_config_max2837; extern const ssp1_config_t ssp1_config_max5864; extern max2837_driver_t max2837; extern max5864_driver_t max5864; extern rffc5071_driver_t rffc5072; +extern w25q80bv_driver_t spi_flash; void cpu_clock_init(void); void cpu_clock_pll1_low_speed(void); diff --git a/firmware/common/w25q80bv_spi.c b/firmware/common/spi_ssp0.c similarity index 68% rename from firmware/common/w25q80bv_spi.c rename to firmware/common/spi_ssp0.c index f51b7b13..a875aa98 100644 --- a/firmware/common/w25q80bv_spi.c +++ b/firmware/common/spi_ssp0.c @@ -21,7 +21,7 @@ * Boston, MA 02110-1301, USA. */ -#include "w25q80bv_spi.h" +#include "spi_ssp0.h" #include #include @@ -30,26 +30,23 @@ #include "hackrf_core.h" -void w25q80bv_spi_init(spi_t* const spi, const void* const config) { - (void)spi; - (void)config; - - const uint8_t serial_clock_rate = 2; - const uint8_t clock_prescale_rate = 2; - +void spi_ssp0_init(spi_t* const spi, const void* const _config) { /* Reset SPIFI peripheral before to Erase/Write SPIFI memory through SPI */ RESET_CTRL1 = RESET_CTRL1_SPIFI_RST; - /* initialize SSP0 */ + const ssp0_config_t* const config = _config; + 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); + config->data_bits, + SSP_FRAME_SPI, + SSP_CPOL_0_CPHA_0, + config->serial_clock_rate, + config->clock_prescale_rate, + SSP_MODE_NORMAL, + SSP_MASTER, + SSP_SLAVE_OUT_ENABLE); + + spi->config = config; /* Init SPIFI GPIO to Normal GPIO */ scu_pinmux(P3_3, (SCU_SSP_IO | SCU_CONF_FUNCTION2)); // P3_3 SPIFI_SCK => SSP0_SCK @@ -67,37 +64,41 @@ void w25q80bv_spi_init(spi_t* const spi, const void* const config) { /* 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; } -void w25q80bv_spi_transfer_gather( - spi_t* const spi, - const spi_transfer_t* const transfers, - const size_t transfer_count -) { - (void)spi; +void spi_ssp0_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfers, const size_t count) { + const ssp0_config_t* const config = spi->config; - gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL); - for(size_t i=0; iselect(spi); + for(size_t i=0; i 8 ) { + uint16_t* const data = transfers[i].data; + for(size_t j=0; junselect(spi); } -void w25q80bv_spi_transfer(spi_t* const spi, void* const data, const size_t count) { +void spi_ssp0_transfer(spi_t* const spi, void* const data, const size_t count) { const spi_transfer_t transfers[] = { { data, count }, }; - w25q80bv_spi_transfer_gather(spi, transfers, 1); + spi_ssp0_transfer_gather(spi, transfers, 1); } diff --git a/firmware/common/spi_ssp0.h b/firmware/common/spi_ssp0.h new file mode 100644 index 00000000..adf420b2 --- /dev/null +++ b/firmware/common/spi_ssp0.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2014 Jared Boone, ShareBrained Technology + * + * 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_SSP0_H__ +#define __SPI_SSP0_H__ + +#include +#include + +#include "spi.h" + +#include + +typedef struct ssp0_config_t { + ssp_datasize_t data_bits; + uint8_t serial_clock_rate; + uint8_t clock_prescale_rate; + void (*select)(spi_t* const spi); + void (*unselect)(spi_t* const spi); +} ssp0_config_t; + +void spi_ssp0_init(spi_t* const spi, const void* const config); +void spi_ssp0_transfer(spi_t* const spi, void* const data, const size_t count); +void spi_ssp0_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfers, const size_t count); + +#endif/*__SPI_SSP0_H__*/ diff --git a/firmware/common/w25q80bv.c b/firmware/common/w25q80bv.c index 6f33edae..a03e30be 100644 --- a/firmware/common/w25q80bv.c +++ b/firmware/common/w25q80bv.c @@ -30,7 +30,9 @@ #include #include "w25q80bv.h" -#include "w25q80bv_spi.h" +#include "w25q80bv_target.h" + +#include "hackrf_core.h" #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) @@ -49,7 +51,6 @@ * 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(w25q80bv_driver_t* const drv) { uint8_t device_id; @@ -58,7 +59,8 @@ void w25q80bv_setup(w25q80bv_driver_t* const drv) drv->num_pages = 4096U; drv->num_bytes = 1048576U; - spi_init(drv->spi, NULL); + spi_init(drv->spi, &ssp0_config_w25q80bv); + w25q80bv_target_init(drv); device_id = 0; while(device_id != W25Q80BV_DEVICE_ID_RES) @@ -199,14 +201,3 @@ void w25q80bv_program(w25q80bv_driver_t* const drv, uint32_t addr, uint32_t len, w25q80bv_page_program(drv, addr, len, data); } } - -spi_t w25q80bv_spi = { - .config = NULL, - .init = w25q80bv_spi_init, - .transfer = w25q80bv_spi_transfer, - .transfer_gather = w25q80bv_spi_transfer_gather, -}; - -w25q80bv_driver_t spi_flash = { - .spi = &w25q80bv_spi, -}; diff --git a/firmware/common/w25q80bv.h b/firmware/common/w25q80bv.h index 9d31a286..89c82653 100644 --- a/firmware/common/w25q80bv.h +++ b/firmware/common/w25q80bv.h @@ -49,6 +49,4 @@ void w25q80bv_program(w25q80bv_driver_t* const drv, uint32_t addr, uint32_t len, 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); -extern w25q80bv_driver_t spi_flash; - #endif//__W25Q80BV_H__ diff --git a/firmware/common/w25q80bv_target.c b/firmware/common/w25q80bv_target.c new file mode 100644 index 00000000..e406bbe5 --- /dev/null +++ b/firmware/common/w25q80bv_target.c @@ -0,0 +1,48 @@ +/* + * 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 +#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; + + scu_pinmux(SCU_SSP0_SSEL, (SCU_GPIO_FAST | SCU_CONF_FUNCTION4)); + gpio_set(PORT_SSP0_SSEL, PIN_SSP0_SSEL); + GPIO5_DIR |= PIN_SSP0_SSEL; +} + +void w25q80bv_target_spi_select(spi_t* const spi) { + (void)spi; + gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL); +} + +void w25q80bv_target_spi_unselect(spi_t* const spi) { + (void)spi; + gpio_set(PORT_SSP0_SSEL, PIN_SSP0_SSEL); +} diff --git a/firmware/common/w25q80bv_spi.h b/firmware/common/w25q80bv_target.h similarity index 61% rename from firmware/common/w25q80bv_spi.h rename to firmware/common/w25q80bv_target.h index dce1a029..f8e7f05e 100644 --- a/firmware/common/w25q80bv_spi.h +++ b/firmware/common/w25q80bv_target.h @@ -1,7 +1,5 @@ /* - * Copyright 2013 Michael Ossmann - * Copyright 2013 Benjamin Vernoux - * Copyright 2014 Jared Boone, ShareBrained Technology + * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. * * This file is part of HackRF. * @@ -21,15 +19,14 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __W25Q80BV_SPI_H__ -#define __W25Q80BV_SPI_H__ - -#include +#ifndef __W25Q80BV_TARGET_H__ +#define __W25Q80BV_TARGET_H__ +#include "w25q80bv.h" #include "spi.h" -void w25q80bv_spi_init(spi_t* const spi, const void* const config); -void w25q80bv_spi_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfers, const size_t transfer_count); -void w25q80bv_spi_transfer(spi_t* const spi, void* const data, const size_t count); +void w25q80bv_target_init(w25q80bv_driver_t* const drv); +void w25q80bv_target_spi_select(spi_t* const spi); +void w25q80bv_target_spi_unselect(spi_t* const spi); -#endif/*__W25Q80BV_SPI_H__*/ +#endif/*__W25Q80BV_TARGET_H__*/ diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index 9d4d01ea..c412e121 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -140,7 +140,10 @@ macro(DeclareTargets) ${PATH_HACKRF_FIRMWARE_COMMON}/max5864_target.c ${PATH_HACKRF_FIRMWARE_COMMON}/rffc5071.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.c + ${PATH_HACKRF_FIRMWARE_COMMON}/spi_ssp0.c ${PATH_HACKRF_FIRMWARE_COMMON}/spi_ssp1.c m0_bin.s ) diff --git a/firmware/hackrf_usb/CMakeLists.txt b/firmware/hackrf_usb/CMakeLists.txt index bf211f9c..10ee4ffb 100644 --- a/firmware/hackrf_usb/CMakeLists.txt +++ b/firmware/hackrf_usb/CMakeLists.txt @@ -44,8 +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}/w25q80bv_spi.c" "${PATH_HACKRF_FIRMWARE_COMMON}/cpld_jtag.c" "${PATH_HACKRF_FIRMWARE_COMMON}/xapp058/lenval.c" "${PATH_HACKRF_FIRMWARE_COMMON}/xapp058/micro.c" From 264ee53d47f9b9064792aa3d21cff4c54747cf2e Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 10 Nov 2014 10:18:56 -0800 Subject: [PATCH 29/46] SPI: Move SCU/pin config to target layers. --- firmware/common/max2837_target.c | 7 ++++++- firmware/common/max5864_target.c | 5 +++++ firmware/common/spi_ssp0.c | 25 ------------------------- firmware/common/spi_ssp1.c | 6 ------ firmware/common/w25q80bv_target.c | 22 ++++++++++++++++++++++ 5 files changed, 33 insertions(+), 32 deletions(-) diff --git a/firmware/common/max2837_target.c b/firmware/common/max2837_target.c index a2c21e72..013c5c2d 100644 --- a/firmware/common/max2837_target.c +++ b/firmware/common/max2837_target.c @@ -28,7 +28,12 @@ void max2837_target_init(max2837_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)); + scu_pinmux(SCU_XCVR_CS, SCU_GPIO_FAST); GPIO_SET(PORT_XCVR_CS) = PIN_XCVR_CS; GPIO_DIR(PORT_XCVR_CS) |= PIN_XCVR_CS; diff --git a/firmware/common/max5864_target.c b/firmware/common/max5864_target.c index d109f898..1ca09d25 100644 --- a/firmware/common/max5864_target.c +++ b/firmware/common/max5864_target.c @@ -28,6 +28,11 @@ 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. diff --git a/firmware/common/spi_ssp0.c b/firmware/common/spi_ssp0.c index a875aa98..1b3ffce9 100644 --- a/firmware/common/spi_ssp0.c +++ b/firmware/common/spi_ssp0.c @@ -23,9 +23,7 @@ #include "spi_ssp0.h" -#include #include -#include #include #include "hackrf_core.h" @@ -47,29 +45,6 @@ void spi_ssp0_init(spi_t* const spi, const void* const _config) { SSP_SLAVE_OUT_ENABLE); spi->config = config; - - /* 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); - - /* drive SSEL, HOLD, and WP pins high */ - gpio_set(PORT_FLASH, (PIN_FLASH_HOLD | PIN_FLASH_WP)); - - /* Set GPIO pins as outputs. */ - GPIO1_DIR |= (PIN_FLASH_HOLD | PIN_FLASH_WP); } void spi_ssp0_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfers, const size_t count) { diff --git a/firmware/common/spi_ssp1.c b/firmware/common/spi_ssp1.c index b0e6182a..74453597 100644 --- a/firmware/common/spi_ssp1.c +++ b/firmware/common/spi_ssp1.c @@ -21,7 +21,6 @@ #include "spi_ssp1.h" -#include #include #include "hackrf_core.h" @@ -40,11 +39,6 @@ void spi_ssp1_init(spi_t* const spi, const void* const _config) { SSP_SLAVE_OUT_ENABLE); spi->config = config; - - /* 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 spi_ssp1_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfers, const size_t count) { diff --git a/firmware/common/w25q80bv_target.c b/firmware/common/w25q80bv_target.c index e406bbe5..8d07f66e 100644 --- a/firmware/common/w25q80bv_target.c +++ b/firmware/common/w25q80bv_target.c @@ -32,8 +32,30 @@ 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(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; } From 905cd2b9191193c65db03f8555cdf8f624522ba2 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 10 Nov 2014 10:57:36 -0800 Subject: [PATCH 30/46] SSP: Merge SSP0 and SSP1 code into single unit. Conflicts: firmware/common/hackrf_core.c --- firmware/common/hackrf_core.c | 37 ++++---- firmware/common/hackrf_core.h | 9 +- firmware/common/max2837.c | 2 +- firmware/common/max5864.c | 2 +- firmware/common/spi.h | 1 + firmware/common/spi_ssp.c | 102 ++++++++++++++++++++++ firmware/common/{spi_ssp1.h => spi_ssp.h} | 16 ++-- firmware/common/spi_ssp0.c | 79 ----------------- firmware/common/spi_ssp0.h | 44 ---------- firmware/common/spi_ssp1.c | 73 ---------------- firmware/common/w25q80bv.c | 2 +- firmware/hackrf-common.cmake | 3 +- 12 files changed, 141 insertions(+), 229 deletions(-) create mode 100644 firmware/common/spi_ssp.c rename firmware/common/{spi_ssp1.h => spi_ssp.h} (74%) delete mode 100644 firmware/common/spi_ssp0.c delete mode 100644 firmware/common/spi_ssp0.h delete mode 100644 firmware/common/spi_ssp1.c diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index b5edabd9..41b9fec0 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -23,8 +23,7 @@ #include "hackrf_core.h" #include "si5351c.h" -#include "spi_ssp0.h" -#include "spi_ssp1.h" +#include "spi_ssp.h" #include "max2837.h" #include "max2837_target.h" #include "max5864.h" @@ -43,7 +42,7 @@ #define WAIT_CPU_CLOCK_INIT_DELAY (10000) -const ssp1_config_t ssp1_config_max2837 = { +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 @@ -58,7 +57,7 @@ const ssp1_config_t ssp1_config_max2837 = { .unselect = max2837_target_spi_unselect, }; -const ssp1_config_t ssp1_config_max5864 = { +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 @@ -74,10 +73,11 @@ const ssp1_config_t ssp1_config_max5864 = { }; spi_t spi_ssp1 = { - .config = &ssp1_config_max2837, - .init = spi_ssp1_init, - .transfer = spi_ssp1_transfer, - .transfer_gather = spi_ssp1_transfer_gather, + .obj = (void*)SSP1_BASE, + .config = &ssp_config_max2837, + .init = spi_ssp_init, + .transfer = spi_ssp_transfer, + .transfer_gather = spi_ssp_transfer_gather, }; max2837_driver_t max2837 = { @@ -99,7 +99,7 @@ rffc5071_driver_t rffc5072 = { .spi = &rffc5071_spi, }; -const ssp0_config_t ssp0_config_w25q80bv = { +const ssp_config_t ssp_config_w25q80bv = { .data_bits = SSP_DATA_8BITS, .serial_clock_rate = 2, .clock_prescale_rate = 2, @@ -108,10 +108,11 @@ const ssp0_config_t ssp0_config_w25q80bv = { }; spi_t spi_ssp0 = { - .config = &ssp0_config_w25q80bv, - .init = spi_ssp0_init, - .transfer = spi_ssp0_transfer, - .transfer_gather = spi_ssp0_transfer_gather, + .obj = (void*)SSP0_BASE, + .config = &ssp_config_w25q80bv, + .init = spi_ssp_init, + .transfer = spi_ssp_transfer, + .transfer_gather = spi_ssp_transfer_gather, }; w25q80bv_driver_t spi_flash = { @@ -494,6 +495,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); } @@ -589,12 +596,12 @@ void cpu_clock_pll1_max_speed(void) void ssp1_set_mode_max2837(void) { - spi_init(max2837.spi, &ssp1_config_max2837); + spi_init(max2837.spi, &ssp_config_max2837); } void ssp1_set_mode_max5864(void) { - spi_init(max5864.spi, &ssp1_config_max5864); + spi_init(max5864.spi, &ssp_config_max5864); } void pin_setup(void) { diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index 53270f2f..2bda7e4c 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -32,8 +32,7 @@ extern "C" #include #include -#include "spi_ssp0.h" -#include "spi_ssp1.h" +#include "spi_ssp.h" #include "max2837.h" #include "max5864.h" @@ -359,9 +358,9 @@ typedef enum { void delay(uint32_t duration); /* TODO: Hide these configurations */ -extern const ssp0_config_t ssp0_config_w25q80bv; -extern const ssp1_config_t ssp1_config_max2837; -extern const ssp1_config_t ssp1_config_max5864; +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; diff --git a/firmware/common/max2837.c b/firmware/common/max2837.c index c667bbe3..9e49bad3 100644 --- a/firmware/common/max2837.c +++ b/firmware/common/max2837.c @@ -79,7 +79,7 @@ static const uint16_t max2837_regs_default[MAX2837_NUM_REGS] = { /* Set up all registers according to defaults specified in docs. */ static void max2837_init(max2837_driver_t* const drv) { - spi_init(drv->spi, &ssp1_config_max2837); + spi_init(drv->spi, &ssp_config_max2837); max2837_mode_shutdown(drv); max2837_target_init(drv); diff --git a/firmware/common/max5864.c b/firmware/common/max5864.c index c3cb456d..5e87f97f 100644 --- a/firmware/common/max5864.c +++ b/firmware/common/max5864.c @@ -31,7 +31,7 @@ static void max5864_write(max5864_driver_t* const drv, uint8_t value) { } static void max5864_init(max5864_driver_t* const drv) { - spi_init(drv->spi, &ssp1_config_max5864); + spi_init(drv->spi, &ssp_config_max5864); max5864_target_init(drv); } diff --git a/firmware/common/spi.h b/firmware/common/spi.h index d2ec2a46..5ec54446 100644 --- a/firmware/common/spi.h +++ b/firmware/common/spi.h @@ -33,6 +33,7 @@ struct spi_t; typedef struct spi_t spi_t; struct spi_t { + void* const obj; const void* config; void (*init)(spi_t* const spi, const void* const config); void (*transfer)(spi_t* const spi, void* const data, const size_t count); diff --git a/firmware/common/spi_ssp.c b/firmware/common/spi_ssp.c new file mode 100644 index 00000000..2c069f82 --- /dev/null +++ b/firmware/common/spi_ssp.c @@ -0,0 +1,102 @@ +/* + * 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_init(spi_t* const spi, const void* const _config) { + const ssp_config_t* const config = _config; + + if( spi->obj == (void*)SSP0_BASE ) { + /* Reset SPIFI peripheral before to Erase/Write SPIFI memory through SPI */ + RESET_CTRL1 = RESET_CTRL1_SPIFI_RST; + } + + SSP_CR1(spi->obj) = 0; + SSP_CPSR(spi->obj) = config->clock_prescale_rate; + SSP_CR0(spi->obj) = + (config->serial_clock_rate << 8) + | SSP_CPOL_0_CPHA_0 + | SSP_FRAME_SPI + | config->data_bits + ; + SSP_CR1(spi->obj) = + SSP_SLAVE_OUT_ENABLE + | SSP_MASTER + | SSP_ENABLE + | SSP_MODE_NORMAL + ; + + spi->config = config; +} + +static void spi_ssp_wait_for_tx_fifo_not_full(spi_t* const spi) { + while( (SSP_SR(spi->obj) & SSP_SR_TNF) == 0 ); +} + +static void spi_ssp_wait_for_rx_fifo_not_empty(spi_t* const spi) { + while( (SSP_SR(spi->obj) & SSP_SR_RNE) == 0 ); +} + +static void spi_ssp_wait_for_not_busy(spi_t* const spi) { + while( SSP_SR(spi->obj) & SSP_SR_BSY ); +} + +static uint32_t spi_ssp_transfer_word(spi_t* const spi, const uint32_t data) { + spi_ssp_wait_for_tx_fifo_not_full(spi); + SSP_DR(spi->obj) = data; + spi_ssp_wait_for_not_busy(spi); + spi_ssp_wait_for_rx_fifo_not_empty(spi); + return SSP_DR(spi->obj); +} + +void spi_ssp_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfers, const size_t count) { + const ssp_config_t* const config = spi->config; + + const bool word_size_u16 = (SSP_CR0(spi->obj) & 0xf) > SSP_DATA_8BITS; + + config->select(spi); + for(size_t i=0; iunselect(spi); +} + +void spi_ssp_transfer(spi_t* const spi, void* const data, const size_t count) { + const spi_transfer_t transfers[] = { + { data, count }, + }; + spi_ssp_transfer_gather(spi, transfers, 1); +} diff --git a/firmware/common/spi_ssp1.h b/firmware/common/spi_ssp.h similarity index 74% rename from firmware/common/spi_ssp1.h rename to firmware/common/spi_ssp.h index 57bb493e..481328f8 100644 --- a/firmware/common/spi_ssp1.h +++ b/firmware/common/spi_ssp.h @@ -19,8 +19,8 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __SPI_SSP1_H__ -#define __SPI_SSP1_H__ +#ifndef __SPI_SSP_H__ +#define __SPI_SSP_H__ #include #include @@ -29,16 +29,16 @@ #include -typedef struct ssp1_config_t { +typedef struct ssp_config_t { ssp_datasize_t data_bits; uint8_t serial_clock_rate; uint8_t clock_prescale_rate; void (*select)(spi_t* const spi); void (*unselect)(spi_t* const spi); -} ssp1_config_t; +} ssp_config_t; -void spi_ssp1_init(spi_t* const spi, const void* const config); -void spi_ssp1_transfer(spi_t* const spi, void* const data, const size_t count); -void spi_ssp1_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfers, const size_t count); +void spi_ssp_init(spi_t* const spi, const void* const config); +void spi_ssp_transfer(spi_t* const spi, void* const data, const size_t count); +void spi_ssp_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfers, const size_t count); -#endif/*__SPI_SSP1_H__*/ +#endif/*__SPI_SSP_H__*/ diff --git a/firmware/common/spi_ssp0.c b/firmware/common/spi_ssp0.c deleted file mode 100644 index 1b3ffce9..00000000 --- a/firmware/common/spi_ssp0.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2013 Michael Ossmann - * Copyright 2013 Benjamin Vernoux - * Copyright 2014 Jared Boone, ShareBrained Technology - * - * 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_ssp0.h" - -#include -#include - -#include "hackrf_core.h" - -void spi_ssp0_init(spi_t* const spi, const void* const _config) { - /* Reset SPIFI peripheral before to Erase/Write SPIFI memory through SPI */ - RESET_CTRL1 = RESET_CTRL1_SPIFI_RST; - - const ssp0_config_t* const config = _config; - - ssp_init(SSP0_NUM, - config->data_bits, - SSP_FRAME_SPI, - SSP_CPOL_0_CPHA_0, - config->serial_clock_rate, - config->clock_prescale_rate, - SSP_MODE_NORMAL, - SSP_MASTER, - SSP_SLAVE_OUT_ENABLE); - - spi->config = config; -} - -void spi_ssp0_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfers, const size_t count) { - const ssp0_config_t* const config = spi->config; - - const size_t word_size = (SSP0_CR0 & 0xf) + 1; - - config->select(spi); - for(size_t i=0; i 8 ) { - uint16_t* const data = transfers[i].data; - for(size_t j=0; junselect(spi); -} - -void spi_ssp0_transfer(spi_t* const spi, void* const data, const size_t count) { - const spi_transfer_t transfers[] = { - { data, count }, - }; - spi_ssp0_transfer_gather(spi, transfers, 1); -} diff --git a/firmware/common/spi_ssp0.h b/firmware/common/spi_ssp0.h deleted file mode 100644 index adf420b2..00000000 --- a/firmware/common/spi_ssp0.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2014 Jared Boone, ShareBrained Technology - * - * 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_SSP0_H__ -#define __SPI_SSP0_H__ - -#include -#include - -#include "spi.h" - -#include - -typedef struct ssp0_config_t { - ssp_datasize_t data_bits; - uint8_t serial_clock_rate; - uint8_t clock_prescale_rate; - void (*select)(spi_t* const spi); - void (*unselect)(spi_t* const spi); -} ssp0_config_t; - -void spi_ssp0_init(spi_t* const spi, const void* const config); -void spi_ssp0_transfer(spi_t* const spi, void* const data, const size_t count); -void spi_ssp0_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfers, const size_t count); - -#endif/*__SPI_SSP0_H__*/ diff --git a/firmware/common/spi_ssp1.c b/firmware/common/spi_ssp1.c deleted file mode 100644 index 74453597..00000000 --- a/firmware/common/spi_ssp1.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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_ssp1.h" - -#include - -#include "hackrf_core.h" - -void spi_ssp1_init(spi_t* const spi, const void* const _config) { - const ssp1_config_t* const config = _config; - - ssp_init(SSP1_NUM, - config->data_bits, - SSP_FRAME_SPI, - SSP_CPOL_0_CPHA_0, - config->serial_clock_rate, - config->clock_prescale_rate, - SSP_MODE_NORMAL, - SSP_MASTER, - SSP_SLAVE_OUT_ENABLE); - - spi->config = config; -} - -void spi_ssp1_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfers, const size_t count) { - const ssp1_config_t* const config = spi->config; - - const size_t word_size = (SSP1_CR0 & 0xf) + 1; - - config->select(spi); - for(size_t i=0; i 8 ) { - uint16_t* const data = transfers[i].data; - for(size_t j=0; junselect(spi); -} - -void spi_ssp1_transfer(spi_t* const spi, void* const data, const size_t count) { - const spi_transfer_t transfers[] = { - { data, count }, - }; - spi_ssp1_transfer_gather(spi, transfers, 1); -} diff --git a/firmware/common/w25q80bv.c b/firmware/common/w25q80bv.c index a03e30be..ad084950 100644 --- a/firmware/common/w25q80bv.c +++ b/firmware/common/w25q80bv.c @@ -59,7 +59,7 @@ void w25q80bv_setup(w25q80bv_driver_t* const drv) drv->num_pages = 4096U; drv->num_bytes = 1048576U; - spi_init(drv->spi, &ssp0_config_w25q80bv); + spi_init(drv->spi, &ssp_config_w25q80bv); w25q80bv_target_init(drv); device_id = 0; diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index c412e121..dd3fceb8 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -143,8 +143,7 @@ macro(DeclareTargets) ${PATH_HACKRF_FIRMWARE_COMMON}/w25q80bv.c ${PATH_HACKRF_FIRMWARE_COMMON}/w25q80bv_target.c ${PATH_HACKRF_FIRMWARE_COMMON}/spi.c - ${PATH_HACKRF_FIRMWARE_COMMON}/spi_ssp0.c - ${PATH_HACKRF_FIRMWARE_COMMON}/spi_ssp1.c + ${PATH_HACKRF_FIRMWARE_COMMON}/spi_ssp.c m0_bin.s ) From 6d57c08e28ee1e5519dbc39349b6918c584ab3d9 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 10 Nov 2014 12:40:11 -0800 Subject: [PATCH 31/46] MAX2837: Add virtual function for setting device mode. --- firmware/common/hackrf_core.c | 1 + firmware/common/max2837.c | 33 +++++++---------------- firmware/common/max2837.h | 2 ++ firmware/common/max2837_target.c | 46 ++++++++++++++++++-------------- firmware/common/max2837_target.h | 8 ++---- firmware/common/tuning.c | 2 +- 6 files changed, 41 insertions(+), 51 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 41b9fec0..b11cfa05 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -82,6 +82,7 @@ spi_t spi_ssp1 = { max2837_driver_t max2837 = { .spi = &spi_ssp1, + .set_mode = max2837_target_set_mode, }; max5864_driver_t max5864 = { diff --git a/firmware/common/max2837.c b/firmware/common/max2837.c index 9e49bad3..63bf7afc 100644 --- a/firmware/common/max2837.c +++ b/firmware/common/max2837.c @@ -80,8 +80,8 @@ static const uint16_t max2837_regs_default[MAX2837_NUM_REGS] = { static void max2837_init(max2837_driver_t* const drv) { spi_init(drv->spi, &ssp_config_max2837); - max2837_mode_shutdown(drv); max2837_target_init(drv); + max2837_set_mode(drv, MAX2837_MODE_SHUTDOWN); memcpy(drv->regs, max2837_regs_default, sizeof(drv->regs)); drv->regs_dirty = 0xffffffff; @@ -165,54 +165,39 @@ void max2837_regs_commit(max2837_driver_t* const drv) } void max2837_set_mode(max2837_driver_t* const drv, const max2837_mode_t new_mode) { - switch(new_mode) { - case MAX2837_MODE_SHUTDOWN: - max2837_mode_shutdown(drv); - break; - - case MAX2837_MODE_STANDBY: - max2837_mode_standby(drv); - break; - - case MAX2837_MODE_TX: - max2837_mode_tx(drv); - break; + drv->set_mode(drv, new_mode); +} - case MAX2837_MODE_RX: - max2837_mode_rx(drv); - break; - - default: - break; - } +max2837_mode_t max2837_mode(max2837_driver_t* const drv) { + return drv->mode; } void max2837_start(max2837_driver_t* const drv) { set_MAX2837_EN_SPI(drv, 1); max2837_regs_commit(drv); - max2837_mode_standby(drv); + max2837_set_mode(drv, MAX2837_MODE_STANDBY); } void max2837_tx(max2837_driver_t* const drv) { set_MAX2837_ModeCtrl(drv, MAX2837_ModeCtrl_TxLPF); max2837_regs_commit(drv); - max2837_mode_tx(drv); + max2837_set_mode(drv, MAX2837_MODE_TX); } void max2837_rx(max2837_driver_t* const drv) { set_MAX2837_ModeCtrl(drv, MAX2837_ModeCtrl_RxLPF); max2837_regs_commit(drv); - max2837_mode_rx(drv); + max2837_set_mode(drv, MAX2837_MODE_RX); } void max2837_stop(max2837_driver_t* const drv) { set_MAX2837_EN_SPI(drv, 0); max2837_regs_commit(drv); - max2837_mode_shutdown(drv); + max2837_set_mode(drv, MAX2837_MODE_SHUTDOWN); } void max2837_set_frequency(max2837_driver_t* const drv, uint32_t freq) diff --git a/firmware/common/max2837.h b/firmware/common/max2837.h index 42baa69e..9c8698fa 100644 --- a/firmware/common/max2837.h +++ b/firmware/common/max2837.h @@ -41,6 +41,8 @@ typedef enum { typedef struct { spi_t* const spi; + void (*set_mode)(max2837_driver_t* const drv, const max2837_mode_t new_mode); + max2837_mode_t mode; uint16_t regs[MAX2837_NUM_REGS]; uint32_t regs_dirty; } max2837_driver_t; diff --git a/firmware/common/max2837_target.c b/firmware/common/max2837_target.c index 013c5c2d..6701cf70 100644 --- a/firmware/common/max2837_target.c +++ b/firmware/common/max2837_target.c @@ -92,17 +92,16 @@ void max2837_target_spi_unselect(spi_t* const spi) { gpio_set(PORT_XCVR_CS, PIN_XCVR_CS); } -void max2837_mode_shutdown(max2837_driver_t* const drv) { - (void)drv; +static void max2837_target_mode_shutdown(max2837_driver_t* const drv) { /* 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)); + drv->mode = MAX2837_MODE_SHUTDOWN; } -void max2837_mode_standby(max2837_driver_t* const drv) { - (void)drv; +static void max2837_target_mode_standby(max2837_driver_t* const drv) { /* 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. @@ -110,10 +109,10 @@ void max2837_mode_standby(max2837_driver_t* const drv) { */ gpio_clear(PORT_XCVR_ENABLE, (PIN_XCVR_RXENABLE | PIN_XCVR_TXENABLE)); gpio_set(PORT_XCVR_ENABLE, PIN_XCVR_ENABLE); + drv->mode = MAX2837_MODE_STANDBY; } -void max2837_mode_tx(max2837_driver_t* const drv) { - (void)drv; +static void max2837_target_mode_tx(max2837_driver_t* const drv) { /* All Tx circuit blocks are powered on. The external PA is powered on * after a programmable delay using the on-chip PA bias DAC. The slow- * charging Rx circuits are in a precharged “idle-off” state for fast @@ -122,10 +121,10 @@ void max2837_mode_tx(max2837_driver_t* const drv) { gpio_clear(PORT_XCVR_ENABLE, PIN_XCVR_RXENABLE); gpio_set(PORT_XCVR_ENABLE, (PIN_XCVR_ENABLE | PIN_XCVR_TXENABLE)); + drv->mode = MAX2837_MODE_TX; } -void max2837_mode_rx(max2837_driver_t* const drv) { - (void)drv; +static void max2837_target_mode_rx(max2837_driver_t* const drv) { /* 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” @@ -134,19 +133,26 @@ void max2837_mode_rx(max2837_driver_t* const drv) { gpio_clear(PORT_XCVR_ENABLE, PIN_XCVR_TXENABLE); gpio_set(PORT_XCVR_ENABLE, (PIN_XCVR_ENABLE | PIN_XCVR_RXENABLE)); + drv->mode = MAX2837_MODE_RX; } -max2837_mode_t max2837_mode(max2837_driver_t* const drv) { - (void)drv; - 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_target_set_mode(max2837_driver_t* const drv, const max2837_mode_t new_mode) { + switch(new_mode) { + default: + case MAX2837_MODE_SHUTDOWN: + max2837_target_mode_shutdown(drv); + break; + + case MAX2837_MODE_STANDBY: + max2837_target_mode_standby(drv); + break; + + case MAX2837_MODE_TX: + max2837_target_mode_tx(drv); + break; + + case MAX2837_MODE_RX: + max2837_target_mode_rx(drv); + break; } } diff --git a/firmware/common/max2837_target.h b/firmware/common/max2837_target.h index b834ea7c..bb5200d0 100644 --- a/firmware/common/max2837_target.h +++ b/firmware/common/max2837_target.h @@ -27,13 +27,9 @@ #include "spi.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); + void max2837_target_spi_select(spi_t* const spi); void max2837_target_spi_unselect(spi_t* const spi); -void max2837_mode_shutdown(max2837_driver_t* const drv); -void max2837_mode_standby(max2837_driver_t* const drv); -void max2837_mode_tx(max2837_driver_t* const drv); -void max2837_mode_rx(max2837_driver_t* const drv); -max2837_mode_t max2837_mode(max2837_driver_t* const drv); - #endif // __MAX2837_TARGET_H diff --git a/firmware/common/tuning.c b/firmware/common/tuning.c index 74de0c7e..7cb8bdb5 100644 --- a/firmware/common/tuning.c +++ b/firmware/common/tuning.c @@ -65,7 +65,7 @@ bool set_freq(const uint64_t freq) success = true; const max2837_mode_t prior_max2837_mode = max2837_mode(&max2837); - max2837_mode_standby(&max2837); + max2837_set_mode(&max2837, MAX2837_MODE_STANDBY); if(freq_mhz < MAX_LP_FREQ_MHZ) { rf_path_set_filter(RF_PATH_FILTER_LOW_PASS); From 8ced9415c2bc4722e9eb324735d9b62f7407a899 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 10 Nov 2014 12:44:14 -0800 Subject: [PATCH 32/46] SPI: Remove MAX2837/5864, W25Q80BV driver dependence on target code. Conflicts: firmware/common/tuning.c --- firmware/common/hackrf_core.c | 3 +++ firmware/common/max2837.c | 3 +-- firmware/common/max2837.h | 8 ++++++-- firmware/common/max5864.c | 3 +-- firmware/common/max5864.h | 8 ++++++-- firmware/common/tuning.c | 1 - firmware/common/w25q80bv.c | 4 ++-- firmware/common/w25q80bv.h | 8 ++++++-- 8 files changed, 25 insertions(+), 13 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index b11cfa05..b1985b70 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -82,11 +82,13 @@ spi_t spi_ssp1 = { max2837_driver_t max2837 = { .spi = &spi_ssp1, + .target_init = max2837_target_init, .set_mode = max2837_target_set_mode, }; max5864_driver_t max5864 = { .spi = &spi_ssp1, + .target_init = max5864_target_init, }; spi_t rffc5071_spi = { @@ -118,6 +120,7 @@ spi_t spi_ssp0 = { w25q80bv_driver_t spi_flash = { .spi = &spi_ssp0, + .target_init = w25q80bv_target_init, }; void delay(uint32_t duration) diff --git a/firmware/common/max2837.c b/firmware/common/max2837.c index 63bf7afc..8f58595f 100644 --- a/firmware/common/max2837.c +++ b/firmware/common/max2837.c @@ -31,7 +31,6 @@ #include #include #include "max2837.h" -#include "max2837_target.h" #include "max2837_regs.def" // private register def macros #include "hackrf_core.h" @@ -80,7 +79,7 @@ static const uint16_t max2837_regs_default[MAX2837_NUM_REGS] = { static void max2837_init(max2837_driver_t* const drv) { spi_init(drv->spi, &ssp_config_max2837); - max2837_target_init(drv); + drv->target_init(drv); max2837_set_mode(drv, MAX2837_MODE_SHUTDOWN); memcpy(drv->regs, max2837_regs_default, sizeof(drv->regs)); diff --git a/firmware/common/max2837.h b/firmware/common/max2837.h index 9c8698fa..7ca45580 100644 --- a/firmware/common/max2837.h +++ b/firmware/common/max2837.h @@ -39,13 +39,17 @@ typedef enum { MAX2837_MODE_RX } max2837_mode_t; -typedef struct { +struct max2837_driver_t; +typedef struct max2837_driver_t max2837_driver_t; + +struct max2837_driver_t { spi_t* const spi; + void (*target_init)(max2837_driver_t* const drv); void (*set_mode)(max2837_driver_t* const drv, const max2837_mode_t new_mode); max2837_mode_t mode; uint16_t regs[MAX2837_NUM_REGS]; uint32_t regs_dirty; -} max2837_driver_t; +}; /* Initialize chip. */ extern void max2837_setup(max2837_driver_t* const drv); diff --git a/firmware/common/max5864.c b/firmware/common/max5864.c index 5e87f97f..13644862 100644 --- a/firmware/common/max5864.c +++ b/firmware/common/max5864.c @@ -22,7 +22,6 @@ #include #include "max5864.h" -#include "max5864_target.h" #include "hackrf_core.h" @@ -32,7 +31,7 @@ static void max5864_write(max5864_driver_t* const drv, uint8_t value) { static void max5864_init(max5864_driver_t* const drv) { spi_init(drv->spi, &ssp_config_max5864); - max5864_target_init(drv); + drv->target_init(drv); } void max5864_setup(max5864_driver_t* const drv) { diff --git a/firmware/common/max5864.h b/firmware/common/max5864.h index 0b5a8bb9..ae1d1b15 100644 --- a/firmware/common/max5864.h +++ b/firmware/common/max5864.h @@ -24,9 +24,13 @@ #include "spi.h" -typedef struct max5864_driver_t { +struct max5864_driver_t; +typedef struct max5864_driver_t max5864_driver_t; + +struct max5864_driver_t { spi_t* const spi; -} max5864_driver_t; + void (*target_init)(max5864_driver_t* const drv); +}; void max5864_setup(max5864_driver_t* const drv); diff --git a/firmware/common/tuning.c b/firmware/common/tuning.c index 7cb8bdb5..91cbfdb1 100644 --- a/firmware/common/tuning.c +++ b/firmware/common/tuning.c @@ -26,7 +26,6 @@ #include #include #include -#include "max2837_target.h" #define FREQ_ONE_MHZ (1000*1000) diff --git a/firmware/common/w25q80bv.c b/firmware/common/w25q80bv.c index ad084950..5b3984ab 100644 --- a/firmware/common/w25q80bv.c +++ b/firmware/common/w25q80bv.c @@ -28,9 +28,9 @@ */ #include +#include #include "w25q80bv.h" -#include "w25q80bv_target.h" #include "hackrf_core.h" @@ -60,7 +60,7 @@ void w25q80bv_setup(w25q80bv_driver_t* const drv) drv->num_bytes = 1048576U; spi_init(drv->spi, &ssp_config_w25q80bv); - w25q80bv_target_init(drv); + drv->target_init(drv); device_id = 0; while(device_id != W25Q80BV_DEVICE_ID_RES) diff --git a/firmware/common/w25q80bv.h b/firmware/common/w25q80bv.h index 89c82653..fab11bda 100644 --- a/firmware/common/w25q80bv.h +++ b/firmware/common/w25q80bv.h @@ -36,12 +36,16 @@ typedef union uint8_t id_8b[8]; /* 8*8bits 64bits Unique ID */ } w25q80bv_unique_id_t; -typedef struct { +struct w25q80bv_driver_t; +typedef struct w25q80bv_driver_t w25q80bv_driver_t; + +struct w25q80bv_driver_t { spi_t* spi; + void (*target_init)(w25q80bv_driver_t* const drv); size_t page_len; size_t num_pages; size_t num_bytes; -} w25q80bv_driver_t; +}; void w25q80bv_setup(w25q80bv_driver_t* const drv); void w25q80bv_chip_erase(w25q80bv_driver_t* const drv); From 569f320826a2dc4d431ec2cf92d0558caa2d2673 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 10 Nov 2014 14:48:42 -0800 Subject: [PATCH 33/46] SPI: Pull remaining hardware bits out of MAX2837/5864/W25Q80BV device drivers. --- firmware/common/hackrf_core.c | 3 +++ firmware/common/max2837.c | 3 --- firmware/common/max5864.c | 3 --- firmware/common/rffc5071.c | 2 -- firmware/common/rom_iap.c | 1 + firmware/common/w25q80bv.c | 3 --- firmware/hackrf_usb/usb_api_spiflash.c | 2 ++ 7 files changed, 6 insertions(+), 11 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index b1985b70..53817583 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -649,6 +649,9 @@ void pin_setup(void) { /* GPIO3[6] on P6_10 as output. */ GPIO3_DIR |= PIN_EN1V8; + spi_init(&spi_ssp1, &ssp_config_max2837); + spi_init(&rffc5071_spi, NULL); + rf_path_pin_setup(); /* Configure external clock in */ diff --git a/firmware/common/max2837.c b/firmware/common/max2837.c index 8f58595f..3105cc63 100644 --- a/firmware/common/max2837.c +++ b/firmware/common/max2837.c @@ -33,8 +33,6 @@ #include "max2837.h" #include "max2837_regs.def" // private register def macros -#include "hackrf_core.h" - /* Default register values. */ static const uint16_t max2837_regs_default[MAX2837_NUM_REGS] = { 0x150, /* 0 */ @@ -78,7 +76,6 @@ static const uint16_t max2837_regs_default[MAX2837_NUM_REGS] = { /* Set up all registers according to defaults specified in docs. */ static void max2837_init(max2837_driver_t* const drv) { - spi_init(drv->spi, &ssp_config_max2837); drv->target_init(drv); max2837_set_mode(drv, MAX2837_MODE_SHUTDOWN); diff --git a/firmware/common/max5864.c b/firmware/common/max5864.c index 13644862..40afd68d 100644 --- a/firmware/common/max5864.c +++ b/firmware/common/max5864.c @@ -23,14 +23,11 @@ #include "max5864.h" -#include "hackrf_core.h" - static void max5864_write(max5864_driver_t* const drv, uint8_t value) { spi_transfer(drv->spi, &value, 1); } static void max5864_init(max5864_driver_t* const drv) { - spi_init(drv->spi, &ssp_config_max5864); drv->target_init(drv); } diff --git a/firmware/common/rffc5071.c b/firmware/common/rffc5071.c index 54237b98..6f9bd106 100644 --- a/firmware/common/rffc5071.c +++ b/firmware/common/rffc5071.c @@ -90,8 +90,6 @@ void rffc5071_setup(rffc5071_driver_t* const drv) { rffc5071_init(drv); - spi_init(drv->spi, NULL); - /* initial setup */ /* put zeros in freq contol registers */ set_RFFC5071_P2N(drv, 0); diff --git a/firmware/common/rom_iap.c b/firmware/common/rom_iap.c index 4a92494c..f3917a03 100644 --- a/firmware/common/rom_iap.c +++ b/firmware/common/rom_iap.c @@ -77,6 +77,7 @@ 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 */ + spi_init(spi_flash.spi, &ssp_config_w25q80bv); w25q80bv_setup(&spi_flash); switch(iap_cmd_res->cmd_param.command_code) diff --git a/firmware/common/w25q80bv.c b/firmware/common/w25q80bv.c index 5b3984ab..6218e34d 100644 --- a/firmware/common/w25q80bv.c +++ b/firmware/common/w25q80bv.c @@ -32,8 +32,6 @@ #include "w25q80bv.h" -#include "hackrf_core.h" - #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) #define W25Q80BV_WRITE_ENABLE 0x06 @@ -59,7 +57,6 @@ void w25q80bv_setup(w25q80bv_driver_t* const drv) drv->num_pages = 4096U; drv->num_bytes = 1048576U; - spi_init(drv->spi, &ssp_config_w25q80bv); drv->target_init(drv); device_id = 0; diff --git a/firmware/hackrf_usb/usb_api_spiflash.c b/firmware/hackrf_usb/usb_api_spiflash.c index a2368a91..6b5efb26 100644 --- a/firmware/hackrf_usb/usb_api_spiflash.c +++ b/firmware/hackrf_usb/usb_api_spiflash.c @@ -39,6 +39,7 @@ usb_request_status_t usb_vendor_request_erase_spiflash( //FIXME This should refuse to run if executing from SPI flash. if (stage == USB_TRANSFER_STAGE_SETUP) { + spi_init(spi_flash.spi, &ssp_config_w25q80bv); w25q80bv_setup(&spi_flash); /* only chip erase is implemented */ w25q80bv_chip_erase(&spi_flash); @@ -65,6 +66,7 @@ usb_request_status_t usb_vendor_request_write_spiflash( } else { usb_transfer_schedule_block(endpoint->out, &spiflash_buffer[0], len, NULL, NULL); + spi_init(spi_flash.spi, &ssp_config_w25q80bv); w25q80bv_setup(&spi_flash); return USB_REQUEST_STATUS_OK; } From 81dfde2a2969021c7068dbe914505d395535d38f Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 10 Nov 2014 16:06:59 -0800 Subject: [PATCH 34/46] RFFC5071: Remove extraneous #include. --- firmware/common/rffc5071_spi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/firmware/common/rffc5071_spi.c b/firmware/common/rffc5071_spi.c index 74574902..5f69fb4e 100644 --- a/firmware/common/rffc5071_spi.c +++ b/firmware/common/rffc5071_spi.c @@ -20,7 +20,6 @@ * Boston, MA 02110-1301, USA. */ -#include #include #include #include "hackrf_core.h" From 721f74867779291e11dcf69ffe313b45213f84cf Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 12 Nov 2014 10:21:34 -0800 Subject: [PATCH 35/46] Si5351C: Change write data arg to be const. --- firmware/common/si5351c_drv.c | 2 +- firmware/common/si5351c_drv.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/common/si5351c_drv.c b/firmware/common/si5351c_drv.c index 4cb58cd6..4c17ae45 100644 --- a/firmware/common/si5351c_drv.c +++ b/firmware/common/si5351c_drv.c @@ -61,7 +61,7 @@ uint8_t si5351c_read_single(si5351c_driver_t* const drv, uint8_t reg) * Write to one or more contiguous registers. data[0] should be the first * register number, one or more values follow. */ -void si5351c_write(si5351c_driver_t* const drv, uint8_t* const data, const uint_fast8_t data_count) +void si5351c_write(si5351c_driver_t* const drv, const uint8_t* const data, const uint_fast8_t data_count) { uint_fast8_t i; diff --git a/firmware/common/si5351c_drv.h b/firmware/common/si5351c_drv.h index 61c6f374..2e94e0bd 100644 --- a/firmware/common/si5351c_drv.h +++ b/firmware/common/si5351c_drv.h @@ -36,7 +36,7 @@ typedef struct { 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, uint8_t* const data, const uint_fast8_t data_count); +void si5351c_write(si5351c_driver_t* const drv, const uint8_t* const data, const uint_fast8_t data_count); #ifdef __cplusplus } From 4ea0f28d14a086c64c7e9f04707910b8776b4f02 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 12 Nov 2014 10:23:00 -0800 Subject: [PATCH 36/46] SI5351C: Rewrite si5351c_write_single() to use si5351c_write(). --- firmware/common/si5351c_drv.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/firmware/common/si5351c_drv.c b/firmware/common/si5351c_drv.c index 4c17ae45..207269d6 100644 --- a/firmware/common/si5351c_drv.c +++ b/firmware/common/si5351c_drv.c @@ -31,11 +31,8 @@ /* write to single register */ void si5351c_write_single(si5351c_driver_t* const drv, uint8_t reg, uint8_t val) { - i2c0_tx_start(); - i2c0_tx_byte((drv->i2c_address << 1) | 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 */ From 35b549816a387d2c579a5d106720636f8ee78cbf Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 12 Nov 2014 10:37:58 -0800 Subject: [PATCH 37/46] Si5351C: Widen write() data_count argument type to size_t. --- firmware/common/si5351c_drv.c | 2 +- firmware/common/si5351c_drv.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/firmware/common/si5351c_drv.c b/firmware/common/si5351c_drv.c index 207269d6..85596839 100644 --- a/firmware/common/si5351c_drv.c +++ b/firmware/common/si5351c_drv.c @@ -58,7 +58,7 @@ uint8_t si5351c_read_single(si5351c_driver_t* const drv, uint8_t reg) * Write to one or more contiguous registers. data[0] should be the first * register number, one or more values follow. */ -void si5351c_write(si5351c_driver_t* const drv, const 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; diff --git a/firmware/common/si5351c_drv.h b/firmware/common/si5351c_drv.h index 2e94e0bd..147e91fa 100644 --- a/firmware/common/si5351c_drv.h +++ b/firmware/common/si5351c_drv.h @@ -29,6 +29,7 @@ extern "C" #endif #include +#include typedef struct { uint8_t i2c_address; @@ -36,7 +37,7 @@ typedef struct { 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 uint_fast8_t data_count); +void si5351c_write(si5351c_driver_t* const drv, const uint8_t* const data, const size_t data_count); #ifdef __cplusplus } From 080a1ba9ac97ef5817d0302f0a408d95403c058a Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 12 Nov 2014 10:45:26 -0800 Subject: [PATCH 38/46] Si5351C: Extract I2C code into single transfer function. --- firmware/common/si5351c_drv.c | 51 ++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/firmware/common/si5351c_drv.c b/firmware/common/si5351c_drv.c index 85596839..e2c87eff 100644 --- a/firmware/common/si5351c_drv.c +++ b/firmware/common/si5351c_drv.c @@ -28,6 +28,30 @@ /* FIXME return i2c0 status from each function */ +static void i2c0_transfer(si5351c_driver_t* const drv, + const uint_fast8_t address, + const uint8_t* const data_tx, const size_t count_tx, + uint8_t* const data_rx, const size_t count_rx +) { + (void)drv; + + i2c0_tx_start(); + i2c0_tx_byte((address << 1) | I2C_WRITE); + for(size_t i=0; ii2c_address << 1) | I2C_WRITE); - i2c0_tx_byte(reg); - - /* read the value */ - i2c0_tx_start(); - i2c0_tx_byte((drv->i2c_address << 1) | I2C_READ); - val = i2c0_rx_byte(); - i2c0_stop(); - - return val; + const uint8_t data_tx[] = { reg }; + uint8_t data_rx[] = { 0x00 }; + i2c0_transfer(drv, drv->i2c_address, data_tx, 1, data_rx, 1); + return data_rx[0]; } /* @@ -60,12 +74,5 @@ 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) { - uint_fast8_t i; - - i2c0_tx_start(); - i2c0_tx_byte((drv->i2c_address << 1) | I2C_WRITE); - - for (i = 0; i < data_count; i++) - i2c0_tx_byte(data[i]); - i2c0_stop(); + i2c0_transfer(drv, drv->i2c_address, data, data_count, NULL, 0); } From eb0dea483fa120fc8c4252ba0c7331879fe3d189 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 12 Nov 2014 13:56:58 -0800 Subject: [PATCH 39/46] I2C: Finish extracting from Si5351C code. --- firmware/common/hackrf_core.c | 31 +++++++++++++++++-- firmware/common/i2c_bus.c | 35 +++++++++++++++++++++ firmware/common/i2c_bus.h | 50 ++++++++++++++++++++++++++++++ firmware/common/i2c_lpc.c | 57 +++++++++++++++++++++++++++++++++++ firmware/common/i2c_lpc.h | 41 +++++++++++++++++++++++++ firmware/common/si5351c_drv.c | 34 ++------------------- firmware/common/si5351c_drv.h | 3 ++ firmware/hackrf-common.cmake | 2 ++ firmware/libopencm3 | 2 +- 9 files changed, 219 insertions(+), 36 deletions(-) create mode 100644 firmware/common/i2c_bus.c create mode 100644 firmware/common/i2c_bus.h create mode 100644 firmware/common/i2c_lpc.c create mode 100644 firmware/common/i2c_lpc.h diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 792beec3..a562f7c6 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -27,7 +27,8 @@ #include "rffc5071.h" #include "sgpio.h" #include "rf_path.h" -#include +#include "i2c_bus.h" +#include "i2c_lpc.h" #include #include #include @@ -35,7 +36,28 @@ #define WAIT_CPU_CLOCK_INIT_DELAY (10000) +i2c_bus_t i2c0 = { + .obj = (void*)I2C0_BASE, + .init = i2c_lpc_init, + .transfer = i2c_lpc_transfer, +}; + +i2c_bus_t i2c1 = { + .obj = (void*)I2C1_BASE, + .init = i2c_lpc_init, + .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, }; @@ -268,7 +290,7 @@ 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_init(clock_gen.bus, &i2c_config_si5351c_slow_clock); si5351c_disable_all_outputs(&clock_gen); si5351c_disable_oeb_pin_control(&clock_gen); @@ -340,7 +362,7 @@ void cpu_clock_init(void) //FIXME disable I2C /* Kick I2C0 down to 400kHz when we switch over to APB1 clock = 204MHz */ - i2c0_init(255); + i2c_bus_init(clock_gen.bus, &i2c_config_si5351c_fast_clock); /* * 12MHz clock is entering LPC XTAL1/OSC input now. On @@ -615,6 +637,9 @@ void pin_setup(void) { /* GPIO3[6] on P6_10 as output. */ GPIO3_DIR |= PIN_EN1V8; + /* enable input on SCL and SDA pins */ + SCU_SFSI2C0 = SCU_I2C0_NOMINAL; + rf_path_pin_setup(); /* Configure SSP1 Peripheral (to be moved later in SSP driver) */ diff --git a/firmware/common/i2c_bus.c b/firmware/common/i2c_bus.c new file mode 100644 index 00000000..6b60455a --- /dev/null +++ b/firmware/common/i2c_bus.c @@ -0,0 +1,35 @@ +/* + * 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_init(i2c_bus_t* const bus, const void* const config) { + bus->init(bus, config); +} + +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..784fb602 --- /dev/null +++ b/firmware/common/i2c_bus.h @@ -0,0 +1,50 @@ +/* + * 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 (*init)(i2c_bus_t* const bus, const void* const config); + 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_init(i2c_bus_t* const bus, const void* const config); +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..73c3e92c --- /dev/null +++ b/firmware/common/i2c_lpc.c @@ -0,0 +1,57 @@ +/* + * 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_init(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_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_init(i2c_bus_t* const bus, const void* const config); +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/si5351c_drv.c b/firmware/common/si5351c_drv.c index e2c87eff..2b788842 100644 --- a/firmware/common/si5351c_drv.c +++ b/firmware/common/si5351c_drv.c @@ -22,36 +22,6 @@ #include "si5351c_drv.h" -#include - -#define SI5351C_I2C_ADDR (0x60 << 1) - -/* FIXME return i2c0 status from each function */ - -static void i2c0_transfer(si5351c_driver_t* const drv, - const uint_fast8_t address, - const uint8_t* const data_tx, const size_t count_tx, - uint8_t* const data_rx, const size_t count_rx -) { - (void)drv; - - i2c0_tx_start(); - i2c0_tx_byte((address << 1) | I2C_WRITE); - for(size_t i=0; ii2c_address, data_tx, 1, data_rx, 1); + i2c_bus_transfer(drv->bus, drv->i2c_address, data_tx, 1, data_rx, 1); return data_rx[0]; } @@ -74,5 +44,5 @@ 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) { - i2c0_transfer(drv, drv->i2c_address, data, data_count, NULL, 0); + i2c_bus_transfer(drv->bus, drv->i2c_address, data, data_count, NULL, 0); } diff --git a/firmware/common/si5351c_drv.h b/firmware/common/si5351c_drv.h index 147e91fa..acb71459 100644 --- a/firmware/common/si5351c_drv.h +++ b/firmware/common/si5351c_drv.h @@ -31,7 +31,10 @@ extern "C" #include #include +#include "i2c_bus.h" + typedef struct { + i2c_bus_t* const bus; uint8_t i2c_address; } si5351c_driver_t; diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index 9b4fb9a9..decd2bed 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -138,6 +138,8 @@ macro(DeclareTargets) ${PATH_HACKRF_FIRMWARE_COMMON}/max2837.c ${PATH_HACKRF_FIRMWARE_COMMON}/max5864.c ${PATH_HACKRF_FIRMWARE_COMMON}/rffc5071.c + ${PATH_HACKRF_FIRMWARE_COMMON}/i2c_bus.c + ${PATH_HACKRF_FIRMWARE_COMMON}/i2c_lpc.c m0_bin.s ) diff --git a/firmware/libopencm3 b/firmware/libopencm3 index 854c112a..aec04e96 160000 --- a/firmware/libopencm3 +++ b/firmware/libopencm3 @@ -1 +1 @@ -Subproject commit 854c112a0ea7b27e85a15345507c8a2e13e76607 +Subproject commit aec04e962c2264877580be30fe1e1178ce3f568c From 28d629e0993985430284e2c4625af4c45d55ac0e Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 12 Nov 2014 18:32:00 -0800 Subject: [PATCH 40/46] Si5351C: Bring I2C wrapper into main driver. --- firmware/common/hackrf_core.h | 2 +- firmware/common/si5351c.c | 27 +++++++++++++++++-- firmware/common/si5351c.h | 11 +++++++- firmware/common/si5351c_drv.c | 48 ---------------------------------- firmware/common/si5351c_drv.h | 49 ----------------------------------- firmware/hackrf-common.cmake | 1 - 6 files changed, 36 insertions(+), 102 deletions(-) delete mode 100644 firmware/common/si5351c_drv.c delete mode 100644 firmware/common/si5351c_drv.h diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index 7ad1ad50..ae7c7a2d 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -32,7 +32,7 @@ extern "C" #include #include -#include "si5351c_drv.h" +#include "si5351c.h" /* hardware identification number */ #define BOARD_ID_JELLYBEAN 0 diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index f6b4483a..36730930 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -22,10 +22,33 @@ #include "si5351c.h" -#include "si5351c_drv.h" - enum pll_sources active_clock_source; +/* write to single register */ +void si5351c_write_single(si5351c_driver_t* const drv, uint8_t reg, uint8_t val) +{ + const uint8_t data_tx[] = { reg, val }; + si5351c_write(drv, data_tx, 2); +} + +/* read single register */ +uint8_t si5351c_read_single(si5351c_driver_t* const drv, uint8_t reg) +{ + 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(si5351c_driver_t* const drv, const uint8_t* const data, const size_t data_count) +{ + i2c_bus_transfer(drv->bus, drv->i2c_address, data, data_count, NULL, 0); +} + /* Disable all CLKx outputs. */ void si5351c_disable_all_outputs(si5351c_driver_t* const drv) { diff --git a/firmware/common/si5351c.h b/firmware/common/si5351c.h index 7151f990..d10a0a93 100644 --- a/firmware/common/si5351c.h +++ b/firmware/common/si5351c.h @@ -30,7 +30,7 @@ extern "C" #include -#include "si5351c_drv.h" +#include "i2c_bus.h" #define SI_INTDIV(x) (x*128-512) @@ -63,6 +63,11 @@ enum pll_sources { PLL_SOURCE_CLKIN = 1, }; +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); @@ -81,6 +86,10 @@ void si5351c_set_int_mode(si5351c_driver_t* const drv, const uint_fast8_t ms_num 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(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 } #endif diff --git a/firmware/common/si5351c_drv.c b/firmware/common/si5351c_drv.c deleted file mode 100644 index 2b788842..00000000 --- a/firmware/common/si5351c_drv.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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 "si5351c_drv.h" - -/* write to single register */ -void si5351c_write_single(si5351c_driver_t* const drv, uint8_t reg, uint8_t val) -{ - const uint8_t data_tx[] = { reg, val }; - si5351c_write(drv, data_tx, 2); -} - -/* read single register */ -uint8_t si5351c_read_single(si5351c_driver_t* const drv, uint8_t reg) -{ - 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(si5351c_driver_t* const drv, const uint8_t* const data, const size_t data_count) -{ - i2c_bus_transfer(drv->bus, drv->i2c_address, data, data_count, NULL, 0); -} diff --git a/firmware/common/si5351c_drv.h b/firmware/common/si5351c_drv.h deleted file mode 100644 index acb71459..00000000 --- a/firmware/common/si5351c_drv.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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. - */ - -#ifndef __SI5351C_DRV_H -#define __SI5351C_DRV_H - -#ifdef __cplusplus -extern "C" -{ -#endif - -#include -#include - -#include "i2c_bus.h" - -typedef struct { - i2c_bus_t* const bus; - uint8_t i2c_address; -} si5351c_driver_t; - -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 -} -#endif - -#endif /* __SI5351C_DRV_H */ diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index decd2bed..b7a0ec91 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -134,7 +134,6 @@ macro(DeclareTargets) ${PATH_HACKRF_FIRMWARE_COMMON}/sgpio.c ${PATH_HACKRF_FIRMWARE_COMMON}/rf_path.c ${PATH_HACKRF_FIRMWARE_COMMON}/si5351c.c - ${PATH_HACKRF_FIRMWARE_COMMON}/si5351c_drv.c ${PATH_HACKRF_FIRMWARE_COMMON}/max2837.c ${PATH_HACKRF_FIRMWARE_COMMON}/max5864.c ${PATH_HACKRF_FIRMWARE_COMMON}/rffc5071.c From 05b8c4c153c3b0af583ad36fb0fd8a98c90f795c Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 13 Nov 2014 09:51:48 -0800 Subject: [PATCH 41/46] SPI: Interface: Rename init()->start(), add stop(). --- firmware/common/hackrf_core.c | 17 ++++++++++------- firmware/common/rffc5071_spi.c | 6 +++++- firmware/common/rffc5071_spi.h | 3 ++- firmware/common/rom_iap.c | 2 +- firmware/common/spi.c | 8 ++++++-- firmware/common/spi.h | 6 ++++-- firmware/common/spi_ssp.c | 6 +++++- firmware/common/spi_ssp.h | 3 ++- firmware/hackrf_usb/usb_api_spiflash.c | 4 ++-- 9 files changed, 37 insertions(+), 18 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 53817583..6cf6b3bc 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -75,7 +75,8 @@ const ssp_config_t ssp_config_max5864 = { spi_t spi_ssp1 = { .obj = (void*)SSP1_BASE, .config = &ssp_config_max2837, - .init = spi_ssp_init, + .start = spi_ssp_start, + .stop = spi_ssp_stop, .transfer = spi_ssp_transfer, .transfer_gather = spi_ssp_transfer_gather, }; @@ -93,7 +94,8 @@ max5864_driver_t max5864 = { spi_t rffc5071_spi = { .config = NULL, - .init = rffc5071_spi_init, + .start = rffc5071_spi_start, + .stop = rffc5071_spi_stop, .transfer = rffc5071_spi_transfer, .transfer_gather = rffc5071_spi_transfer_gather, }; @@ -113,7 +115,8 @@ const ssp_config_t ssp_config_w25q80bv = { spi_t spi_ssp0 = { .obj = (void*)SSP0_BASE, .config = &ssp_config_w25q80bv, - .init = spi_ssp_init, + .start = spi_ssp_start, + .stop = spi_ssp_stop, .transfer = spi_ssp_transfer, .transfer_gather = spi_ssp_transfer_gather, }; @@ -600,12 +603,12 @@ void cpu_clock_pll1_max_speed(void) void ssp1_set_mode_max2837(void) { - spi_init(max2837.spi, &ssp_config_max2837); + spi_start(max2837.spi, &ssp_config_max2837); } void ssp1_set_mode_max5864(void) { - spi_init(max5864.spi, &ssp_config_max5864); + spi_start(max5864.spi, &ssp_config_max5864); } void pin_setup(void) { @@ -649,8 +652,8 @@ void pin_setup(void) { /* GPIO3[6] on P6_10 as output. */ GPIO3_DIR |= PIN_EN1V8; - spi_init(&spi_ssp1, &ssp_config_max2837); - spi_init(&rffc5071_spi, NULL); + spi_start(&spi_ssp1, &ssp_config_max2837); + spi_start(&rffc5071_spi, NULL); rf_path_pin_setup(); diff --git a/firmware/common/rffc5071_spi.c b/firmware/common/rffc5071_spi.c index 5f69fb4e..b587fef4 100644 --- a/firmware/common/rffc5071_spi.c +++ b/firmware/common/rffc5071_spi.c @@ -82,12 +82,16 @@ static void rffc5071_spi_target_init(spi_t* const spi) { gpio_set(PORT_MIXER_RESETX, PIN_MIXER_RESETX); /* active low */ } -void rffc5071_spi_init(spi_t* const spi, const void* const config) { +void rffc5071_spi_start(spi_t* const spi, const void* const config) { (void)config; rffc5071_spi_bus_init(spi); rffc5071_spi_target_init(spi); } +void rffc5071_spi_stop(spi_t* const spi) { + (void)spi; +} + static void rffc5071_spi_serial_delay(spi_t* const spi) { (void)spi; volatile uint32_t i; diff --git a/firmware/common/rffc5071_spi.h b/firmware/common/rffc5071_spi.h index ba2eb44f..930d7283 100644 --- a/firmware/common/rffc5071_spi.h +++ b/firmware/common/rffc5071_spi.h @@ -25,7 +25,8 @@ #include "spi.h" -void rffc5071_spi_init(spi_t* const spi, const void* const config); +void rffc5071_spi_start(spi_t* const spi, const void* const config); +void rffc5071_spi_stop(spi_t* const spi); void rffc5071_spi_transfer(spi_t* const spi, void* const data, const size_t count); void rffc5071_spi_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfer, const size_t count); diff --git a/firmware/common/rom_iap.c b/firmware/common/rom_iap.c index f3917a03..6807378a 100644 --- a/firmware/common/rom_iap.c +++ b/firmware/common/rom_iap.c @@ -77,7 +77,7 @@ 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 */ - spi_init(spi_flash.spi, &ssp_config_w25q80bv); + spi_start(spi_flash.spi, &ssp_config_w25q80bv); w25q80bv_setup(&spi_flash); switch(iap_cmd_res->cmd_param.command_code) diff --git a/firmware/common/spi.c b/firmware/common/spi.c index 99076737..9c0ff72b 100644 --- a/firmware/common/spi.c +++ b/firmware/common/spi.c @@ -21,8 +21,12 @@ #include "spi.h" -void spi_init(spi_t* const spi, const void* const config) { - spi->init(spi, config); +void spi_start(spi_t* const spi, const void* const config) { + spi->start(spi, config); +} + +void spi_stop(spi_t* const spi) { + spi->stop(spi); } void spi_transfer(spi_t* const spi, void* const data, const size_t count) { diff --git a/firmware/common/spi.h b/firmware/common/spi.h index 5ec54446..dfdca0e8 100644 --- a/firmware/common/spi.h +++ b/firmware/common/spi.h @@ -35,12 +35,14 @@ typedef struct spi_t spi_t; struct spi_t { void* const obj; const void* config; - void (*init)(spi_t* const spi, const void* const config); + void (*start)(spi_t* const spi, const void* const config); + void (*stop)(spi_t* const spi); void (*transfer)(spi_t* const spi, void* const data, const size_t count); void (*transfer_gather)(spi_t* const spi, const spi_transfer_t* const transfers, const size_t count); }; -void spi_init(spi_t* const spi, const void* const config); +void spi_start(spi_t* const spi, const void* const config); +void spi_stop(spi_t* const spi); void spi_transfer(spi_t* const spi, void* const data, const size_t count); void spi_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfers, const size_t count); diff --git a/firmware/common/spi_ssp.c b/firmware/common/spi_ssp.c index 2c069f82..2a93ad31 100644 --- a/firmware/common/spi_ssp.c +++ b/firmware/common/spi_ssp.c @@ -24,7 +24,7 @@ #include #include -void spi_ssp_init(spi_t* const spi, const void* const _config) { +void spi_ssp_start(spi_t* const spi, const void* const _config) { const ssp_config_t* const config = _config; if( spi->obj == (void*)SSP0_BASE ) { @@ -50,6 +50,10 @@ void spi_ssp_init(spi_t* const spi, const void* const _config) { spi->config = config; } +void spi_ssp_stop(spi_t* const spi) { + SSP_CR1(spi->obj) = 0; +} + static void spi_ssp_wait_for_tx_fifo_not_full(spi_t* const spi) { while( (SSP_SR(spi->obj) & SSP_SR_TNF) == 0 ); } diff --git a/firmware/common/spi_ssp.h b/firmware/common/spi_ssp.h index 481328f8..ef2d77cf 100644 --- a/firmware/common/spi_ssp.h +++ b/firmware/common/spi_ssp.h @@ -37,7 +37,8 @@ typedef struct ssp_config_t { void (*unselect)(spi_t* const spi); } ssp_config_t; -void spi_ssp_init(spi_t* const spi, const void* const config); +void spi_ssp_start(spi_t* const spi, const void* const config); +void spi_ssp_stop(spi_t* const spi); void spi_ssp_transfer(spi_t* const spi, void* const data, const size_t count); void spi_ssp_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfers, const size_t count); diff --git a/firmware/hackrf_usb/usb_api_spiflash.c b/firmware/hackrf_usb/usb_api_spiflash.c index 6b5efb26..225bf0de 100644 --- a/firmware/hackrf_usb/usb_api_spiflash.c +++ b/firmware/hackrf_usb/usb_api_spiflash.c @@ -39,7 +39,7 @@ usb_request_status_t usb_vendor_request_erase_spiflash( //FIXME This should refuse to run if executing from SPI flash. if (stage == USB_TRANSFER_STAGE_SETUP) { - spi_init(spi_flash.spi, &ssp_config_w25q80bv); + spi_start(spi_flash.spi, &ssp_config_w25q80bv); w25q80bv_setup(&spi_flash); /* only chip erase is implemented */ w25q80bv_chip_erase(&spi_flash); @@ -66,7 +66,7 @@ usb_request_status_t usb_vendor_request_write_spiflash( } else { usb_transfer_schedule_block(endpoint->out, &spiflash_buffer[0], len, NULL, NULL); - spi_init(spi_flash.spi, &ssp_config_w25q80bv); + spi_start(spi_flash.spi, &ssp_config_w25q80bv); w25q80bv_setup(&spi_flash); return USB_REQUEST_STATUS_OK; } From ea136038a91de6d0585f05e9fffdbbd8ff1d4e84 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 13 Nov 2014 10:16:39 -0800 Subject: [PATCH 42/46] SPI: Rename spi_t to spi_bus_t to match I2C naming. --- firmware/common/hackrf_core.c | 22 +++--- firmware/common/max2837.c | 4 +- firmware/common/max2837.h | 4 +- firmware/common/max2837_target.c | 8 +-- firmware/common/max2837_target.h | 6 +- firmware/common/max5864.c | 2 +- firmware/common/max5864.h | 4 +- firmware/common/max5864_target.c | 8 +-- firmware/common/max5864_target.h | 6 +- firmware/common/rffc5071.c | 4 +- firmware/common/rffc5071.h | 4 +- firmware/common/rffc5071_spi.c | 92 +++++++++++++------------- firmware/common/rffc5071_spi.h | 10 +-- firmware/common/rom_iap.c | 2 +- firmware/common/{spi.c => spi_bus.c} | 18 ++--- firmware/common/{spi.h => spi_bus.h} | 28 ++++---- firmware/common/spi_ssp.c | 60 ++++++++--------- firmware/common/spi_ssp.h | 14 ++-- firmware/common/w25q80bv.c | 12 ++-- firmware/common/w25q80bv.h | 4 +- firmware/common/w25q80bv_target.c | 8 +-- firmware/common/w25q80bv_target.h | 6 +- firmware/hackrf-common.cmake | 2 +- firmware/hackrf_usb/usb_api_spiflash.c | 4 +- 24 files changed, 166 insertions(+), 166 deletions(-) rename firmware/common/{spi.c => spi_bus.c} (65%) rename firmware/common/{spi.h => spi_bus.h} (57%) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index 6cf6b3bc..a1ad6008 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -72,7 +72,7 @@ const ssp_config_t ssp_config_max5864 = { .unselect = max5864_target_spi_unselect, }; -spi_t spi_ssp1 = { +spi_bus_t spi_bus_ssp1 = { .obj = (void*)SSP1_BASE, .config = &ssp_config_max2837, .start = spi_ssp_start, @@ -82,17 +82,17 @@ spi_t spi_ssp1 = { }; max2837_driver_t max2837 = { - .spi = &spi_ssp1, + .bus = &spi_bus_ssp1, .target_init = max2837_target_init, .set_mode = max2837_target_set_mode, }; max5864_driver_t max5864 = { - .spi = &spi_ssp1, + .bus = &spi_bus_ssp1, .target_init = max5864_target_init, }; -spi_t rffc5071_spi = { +spi_bus_t spi_bus_rffc5071 = { .config = NULL, .start = rffc5071_spi_start, .stop = rffc5071_spi_stop, @@ -101,7 +101,7 @@ spi_t rffc5071_spi = { }; rffc5071_driver_t rffc5072 = { - .spi = &rffc5071_spi, + .bus = &spi_bus_rffc5071, }; const ssp_config_t ssp_config_w25q80bv = { @@ -112,7 +112,7 @@ const ssp_config_t ssp_config_w25q80bv = { .unselect = w25q80bv_target_spi_unselect, }; -spi_t spi_ssp0 = { +spi_bus_t spi_bus_ssp0 = { .obj = (void*)SSP0_BASE, .config = &ssp_config_w25q80bv, .start = spi_ssp_start, @@ -122,7 +122,7 @@ spi_t spi_ssp0 = { }; w25q80bv_driver_t spi_flash = { - .spi = &spi_ssp0, + .bus = &spi_bus_ssp0, .target_init = w25q80bv_target_init, }; @@ -603,12 +603,12 @@ void cpu_clock_pll1_max_speed(void) void ssp1_set_mode_max2837(void) { - spi_start(max2837.spi, &ssp_config_max2837); + spi_bus_start(max2837.bus, &ssp_config_max2837); } void ssp1_set_mode_max5864(void) { - spi_start(max5864.spi, &ssp_config_max5864); + spi_bus_start(max5864.bus, &ssp_config_max5864); } void pin_setup(void) { @@ -652,8 +652,8 @@ void pin_setup(void) { /* GPIO3[6] on P6_10 as output. */ GPIO3_DIR |= PIN_EN1V8; - spi_start(&spi_ssp1, &ssp_config_max2837); - spi_start(&rffc5071_spi, NULL); + spi_bus_start(&spi_bus_ssp1, &ssp_config_max2837); + spi_bus_start(&spi_bus_rffc5071, NULL); rf_path_pin_setup(); diff --git a/firmware/common/max2837.c b/firmware/common/max2837.c index 3105cc63..d99b740f 100644 --- a/firmware/common/max2837.c +++ b/firmware/common/max2837.c @@ -121,13 +121,13 @@ void max2837_setup(max2837_driver_t* const drv) static uint16_t max2837_read(max2837_driver_t* const drv, uint8_t r) { uint16_t value = (1 << 15) | (r << 10); - spi_transfer(drv->spi, &value, 1); + spi_bus_transfer(drv->bus, &value, 1); return value & 0x3ff; } static void max2837_write(max2837_driver_t* const drv, uint8_t r, uint16_t v) { uint16_t value = (r << 10) | (v & 0x3ff); - spi_transfer(drv->spi, &value, 1); + spi_bus_transfer(drv->bus, &value, 1); } uint16_t max2837_reg_read(max2837_driver_t* const drv, uint8_t r) diff --git a/firmware/common/max2837.h b/firmware/common/max2837.h index 7ca45580..b3414e08 100644 --- a/firmware/common/max2837.h +++ b/firmware/common/max2837.h @@ -26,7 +26,7 @@ #include #include -#include "spi.h" +#include "spi_bus.h" /* 32 registers, each containing 10 bits of data. */ #define MAX2837_NUM_REGS 32 @@ -43,7 +43,7 @@ struct max2837_driver_t; typedef struct max2837_driver_t max2837_driver_t; struct max2837_driver_t { - spi_t* const spi; + spi_bus_t* const bus; void (*target_init)(max2837_driver_t* const drv); void (*set_mode)(max2837_driver_t* const drv, const max2837_mode_t new_mode); max2837_mode_t mode; diff --git a/firmware/common/max2837_target.c b/firmware/common/max2837_target.c index 6701cf70..2a2f7b2d 100644 --- a/firmware/common/max2837_target.c +++ b/firmware/common/max2837_target.c @@ -82,13 +82,13 @@ void max2837_target_init(max2837_driver_t* const drv) { #endif } -void max2837_target_spi_select(spi_t* const spi) { - (void)spi; +void max2837_target_spi_select(spi_bus_t* const bus) { + (void)bus; gpio_clear(PORT_XCVR_CS, PIN_XCVR_CS); } -void max2837_target_spi_unselect(spi_t* const spi) { - (void)spi; +void max2837_target_spi_unselect(spi_bus_t* const bus) { + (void)bus; gpio_set(PORT_XCVR_CS, PIN_XCVR_CS); } diff --git a/firmware/common/max2837_target.h b/firmware/common/max2837_target.h index bb5200d0..cc578ed3 100644 --- a/firmware/common/max2837_target.h +++ b/firmware/common/max2837_target.h @@ -24,12 +24,12 @@ #define __MAX2837_TARGET_H #include "max2837.h" -#include "spi.h" +#include "spi_bus.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); -void max2837_target_spi_select(spi_t* const spi); -void max2837_target_spi_unselect(spi_t* const spi); +void max2837_target_spi_select(spi_bus_t* const bus); +void max2837_target_spi_unselect(spi_bus_t* const bus); #endif // __MAX2837_TARGET_H diff --git a/firmware/common/max5864.c b/firmware/common/max5864.c index 40afd68d..ed704a2d 100644 --- a/firmware/common/max5864.c +++ b/firmware/common/max5864.c @@ -24,7 +24,7 @@ #include "max5864.h" static void max5864_write(max5864_driver_t* const drv, uint8_t value) { - spi_transfer(drv->spi, &value, 1); + spi_bus_transfer(drv->bus, &value, 1); } static void max5864_init(max5864_driver_t* const drv) { diff --git a/firmware/common/max5864.h b/firmware/common/max5864.h index ae1d1b15..aba4357d 100644 --- a/firmware/common/max5864.h +++ b/firmware/common/max5864.h @@ -22,13 +22,13 @@ #ifndef __MAX5864_H #define __MAX5864_H -#include "spi.h" +#include "spi_bus.h" struct max5864_driver_t; typedef struct max5864_driver_t max5864_driver_t; struct max5864_driver_t { - spi_t* const spi; + spi_bus_t* const bus; void (*target_init)(max5864_driver_t* const drv); }; diff --git a/firmware/common/max5864_target.c b/firmware/common/max5864_target.c index 1ca09d25..1b92baa3 100644 --- a/firmware/common/max5864_target.c +++ b/firmware/common/max5864_target.c @@ -42,12 +42,12 @@ void max5864_target_init(max5864_driver_t* const drv) { GPIO_DIR(PORT_AD_CS) |= PIN_AD_CS; } -void max5864_target_spi_select(spi_t* const spi) { - (void)spi; +void max5864_target_spi_select(spi_bus_t* const bus) { + (void)bus; gpio_clear(PORT_AD_CS, PIN_AD_CS); } -void max5864_target_spi_unselect(spi_t* const spi) { - (void)spi; +void max5864_target_spi_unselect(spi_bus_t* const bus) { + (void)bus; gpio_set(PORT_AD_CS, PIN_AD_CS); } diff --git a/firmware/common/max5864_target.h b/firmware/common/max5864_target.h index b5c7a060..c98eef7d 100644 --- a/firmware/common/max5864_target.h +++ b/firmware/common/max5864_target.h @@ -23,10 +23,10 @@ #define __MAX5864_TARGET_H__ #include "max5864.h" -#include "spi.h" +#include "spi_bus.h" void max5864_target_init(max5864_driver_t* const drv); -void max5864_target_spi_select(spi_t* const spi); -void max5864_target_spi_unselect(spi_t* const spi); +void max5864_target_spi_select(spi_bus_t* const bus); +void max5864_target_spi_unselect(spi_bus_t* const bus); #endif/*__MAX5864_TARGET_H__*/ diff --git a/firmware/common/rffc5071.c b/firmware/common/rffc5071.c index 6f9bd106..1905c503 100644 --- a/firmware/common/rffc5071.c +++ b/firmware/common/rffc5071.c @@ -121,7 +121,7 @@ static uint16_t rffc5071_spi_read(rffc5071_driver_t* const drv, uint8_t r) { (void)drv; uint16_t data[] = { 0x80 | (r & 0x7f), 0xffff }; - spi_transfer(drv->spi, data, 2); + spi_bus_transfer(drv->bus, data, 2); return data[1]; } @@ -129,7 +129,7 @@ static void rffc5071_spi_write(rffc5071_driver_t* const drv, uint8_t r, uint16_t (void)drv; uint16_t data[] = { 0x00 | (r & 0x7f), v }; - spi_transfer(drv->spi, data, 2); + spi_bus_transfer(drv->bus, data, 2); } uint16_t rffc5071_reg_read(rffc5071_driver_t* const drv, uint8_t r) diff --git a/firmware/common/rffc5071.h b/firmware/common/rffc5071.h index 18caf69f..37d69afe 100644 --- a/firmware/common/rffc5071.h +++ b/firmware/common/rffc5071.h @@ -25,13 +25,13 @@ #include -#include "spi.h" +#include "spi_bus.h" /* 31 registers, each containing 16 bits of data. */ #define RFFC5071_NUM_REGS 31 typedef struct { - spi_t* const spi; + spi_bus_t* const bus; uint16_t regs[RFFC5071_NUM_REGS]; uint32_t regs_dirty; } rffc5071_driver_t; diff --git a/firmware/common/rffc5071_spi.c b/firmware/common/rffc5071_spi.c index b587fef4..6036bb04 100644 --- a/firmware/common/rffc5071_spi.c +++ b/firmware/common/rffc5071_spi.c @@ -24,51 +24,51 @@ #include #include "hackrf_core.h" -static void rffc5071_spi_target_select(spi_t* const spi) { - (void)spi; +static void rffc5071_spi_target_select(spi_bus_t* const bus) { + (void)bus; gpio_clear(PORT_MIXER_ENX, PIN_MIXER_ENX); } -static void rffc5071_spi_target_unselect(spi_t* const spi) { - (void)spi; +static void rffc5071_spi_target_unselect(spi_bus_t* const bus) { + (void)bus; gpio_set(PORT_MIXER_ENX, PIN_MIXER_ENX); } -static void rffc5071_spi_direction_out(spi_t* const spi) { - (void)spi; +static void rffc5071_spi_direction_out(spi_bus_t* const bus) { + (void)bus; GPIO_DIR(PORT_MIXER_SDATA) |= PIN_MIXER_SDATA; } -static void rffc5071_spi_direction_in(spi_t* const spi) { - (void)spi; +static void rffc5071_spi_direction_in(spi_bus_t* const bus) { + (void)bus; GPIO_DIR(PORT_MIXER_SDATA) &= ~PIN_MIXER_SDATA; } -static void rffc5071_spi_data_out(spi_t* const spi, const bool bit) { - (void)spi; +static void rffc5071_spi_data_out(spi_bus_t* const bus, const bool bit) { + (void)bus; if (bit) gpio_set(PORT_MIXER_SDATA, PIN_MIXER_SDATA); else gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA); } -static bool rffc5071_spi_data_in(spi_t* const spi) { - (void)spi; +static bool rffc5071_spi_data_in(spi_bus_t* const bus) { + (void)bus; return MIXER_SDATA_STATE; } -static void rffc5071_spi_bus_init(spi_t* const spi) { +static void rffc5071_spi_bus_init(spi_bus_t* const bus) { scu_pinmux(SCU_MIXER_SCLK, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); scu_pinmux(SCU_MIXER_SDATA, SCU_GPIO_FAST); GPIO_DIR(PORT_MIXER_SCLK) |= PIN_MIXER_SCLK; - rffc5071_spi_direction_out(spi); + rffc5071_spi_direction_out(bus); gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA); } -static void rffc5071_spi_target_init(spi_t* const spi) { +static void rffc5071_spi_target_init(spi_bus_t* const bus) { /* Configure GPIO pins. */ scu_pinmux(SCU_MIXER_ENX, SCU_GPIO_FAST); scu_pinmux(SCU_MIXER_RESETX, SCU_GPIO_FAST); @@ -78,49 +78,49 @@ static void rffc5071_spi_target_init(spi_t* const spi) { GPIO_DIR(PORT_MIXER_RESETX) |= PIN_MIXER_RESETX; /* set to known state */ - rffc5071_spi_target_unselect(spi); + rffc5071_spi_target_unselect(bus); gpio_set(PORT_MIXER_RESETX, PIN_MIXER_RESETX); /* active low */ } -void rffc5071_spi_start(spi_t* const spi, const void* const config) { +void rffc5071_spi_start(spi_bus_t* const bus, const void* const config) { (void)config; - rffc5071_spi_bus_init(spi); - rffc5071_spi_target_init(spi); + rffc5071_spi_bus_init(bus); + rffc5071_spi_target_init(bus); } -void rffc5071_spi_stop(spi_t* const spi) { - (void)spi; +void rffc5071_spi_stop(spi_bus_t* const bus) { + (void)bus; } -static void rffc5071_spi_serial_delay(spi_t* const spi) { - (void)spi; +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_t* const spi) { - rffc5071_spi_serial_delay(spi); +static void rffc5071_spi_sck(spi_bus_t* const bus) { + rffc5071_spi_serial_delay(bus); gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - rffc5071_spi_serial_delay(spi); + rffc5071_spi_serial_delay(bus); gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); } -static uint32_t rffc5071_spi_exchange_bit(spi_t* const spi, const uint32_t bit) { - rffc5071_spi_data_out(spi, bit); - rffc5071_spi_sck(spi); - return rffc5071_spi_data_in(spi) ? 1 : 0; +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_t* const spi, const uint32_t data, const size_t count) { +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(spi, t & msb); + t = (t << 1) | rffc5071_spi_exchange_bit(bus, t & msb); } return t & ((1UL << count) - 1); @@ -142,7 +142,7 @@ static uint32_t rffc5071_spi_exchange_word(spi_t* const spi, const uint32_t data * next 7 bits are register address, * next 16 bits are register value. */ -void rffc5071_spi_transfer(spi_t* const spi, void* const _data, const size_t count) { +void rffc5071_spi_transfer(spi_bus_t* const bus, void* const _data, const size_t count) { if( count != 2 ) { return; } @@ -155,31 +155,31 @@ void rffc5071_spi_transfer(spi_t* const spi, void* const _data, const size_t cou * The device requires two clocks while ENX is high before a serial * transaction. This is not clearly documented. */ - rffc5071_spi_sck(spi); - rffc5071_spi_sck(spi); + rffc5071_spi_sck(bus); + rffc5071_spi_sck(bus); - rffc5071_spi_target_select(spi); - data[0] = rffc5071_spi_exchange_word(spi, data[0], 9); + rffc5071_spi_target_select(bus); + data[0] = rffc5071_spi_exchange_word(bus, data[0], 9); if( direction_read ) { - rffc5071_spi_direction_in(spi); - rffc5071_spi_sck(spi); + rffc5071_spi_direction_in(bus); + rffc5071_spi_sck(bus); } - data[1] = rffc5071_spi_exchange_word(spi, data[1], 16); + data[1] = rffc5071_spi_exchange_word(bus, data[1], 16); - rffc5071_spi_serial_delay(spi); - rffc5071_spi_target_unselect(spi); - rffc5071_spi_direction_out(spi); + 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(spi); + rffc5071_spi_sck(bus); } -void rffc5071_spi_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfer, const size_t count) { +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(spi, transfer[0].data, transfer[0].count); + rffc5071_spi_transfer(bus, transfer[0].data, transfer[0].count); } } diff --git a/firmware/common/rffc5071_spi.h b/firmware/common/rffc5071_spi.h index 930d7283..8214aa31 100644 --- a/firmware/common/rffc5071_spi.h +++ b/firmware/common/rffc5071_spi.h @@ -23,11 +23,11 @@ #ifndef __RFFC5071_SPI_H #define __RFFC5071_SPI_H -#include "spi.h" +#include "spi_bus.h" -void rffc5071_spi_start(spi_t* const spi, const void* const config); -void rffc5071_spi_stop(spi_t* const spi); -void rffc5071_spi_transfer(spi_t* const spi, void* const data, const size_t count); -void rffc5071_spi_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfer, const size_t count); +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 6807378a..011e6523 100644 --- a/firmware/common/rom_iap.c +++ b/firmware/common/rom_iap.c @@ -77,7 +77,7 @@ 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 */ - spi_start(spi_flash.spi, &ssp_config_w25q80bv); + spi_bus_start(spi_flash.bus, &ssp_config_w25q80bv); w25q80bv_setup(&spi_flash); switch(iap_cmd_res->cmd_param.command_code) diff --git a/firmware/common/spi.c b/firmware/common/spi_bus.c similarity index 65% rename from firmware/common/spi.c rename to firmware/common/spi_bus.c index 9c0ff72b..7bf942c9 100644 --- a/firmware/common/spi.c +++ b/firmware/common/spi_bus.c @@ -19,20 +19,20 @@ * Boston, MA 02110-1301, USA. */ -#include "spi.h" +#include "spi_bus.h" -void spi_start(spi_t* const spi, const void* const config) { - spi->start(spi, config); +void spi_bus_start(spi_bus_t* const bus, const void* const config) { + bus->start(bus, config); } -void spi_stop(spi_t* const spi) { - spi->stop(spi); +void spi_bus_stop(spi_bus_t* const bus) { + bus->stop(bus); } -void spi_transfer(spi_t* const spi, void* const data, const size_t count) { - spi->transfer(spi, data, count); +void spi_bus_transfer(spi_bus_t* const bus, void* const data, const size_t count) { + bus->transfer(bus, data, count); } -void spi_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfers, const size_t count) { - spi->transfer_gather(spi, transfers, 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.h b/firmware/common/spi_bus.h similarity index 57% rename from firmware/common/spi.h rename to firmware/common/spi_bus.h index dfdca0e8..e1257d41 100644 --- a/firmware/common/spi.h +++ b/firmware/common/spi_bus.h @@ -19,8 +19,8 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __SPI_H__ -#define __SPI_H__ +#ifndef __SPI_BUS_H__ +#define __SPI_BUS_H__ #include @@ -29,21 +29,21 @@ typedef struct { const size_t count; } spi_transfer_t; -struct spi_t; -typedef struct spi_t spi_t; +struct spi_bus_t; +typedef struct spi_bus_t spi_bus_t; -struct spi_t { +struct spi_bus_t { void* const obj; const void* config; - void (*start)(spi_t* const spi, const void* const config); - void (*stop)(spi_t* const spi); - void (*transfer)(spi_t* const spi, void* const data, const size_t count); - void (*transfer_gather)(spi_t* const spi, const spi_transfer_t* const transfers, const size_t count); + 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_start(spi_t* const spi, const void* const config); -void spi_stop(spi_t* const spi); -void spi_transfer(spi_t* const spi, void* const data, const size_t count); -void spi_transfer_gather(spi_t* const spi, 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_H__*/ +#endif/*__SPI_BUS_H__*/ diff --git a/firmware/common/spi_ssp.c b/firmware/common/spi_ssp.c index 2a93ad31..9b5a3e86 100644 --- a/firmware/common/spi_ssp.c +++ b/firmware/common/spi_ssp.c @@ -24,83 +24,83 @@ #include #include -void spi_ssp_start(spi_t* const spi, const void* const _config) { +void spi_ssp_start(spi_bus_t* const bus, const void* const _config) { const ssp_config_t* const config = _config; - if( spi->obj == (void*)SSP0_BASE ) { + if( bus->obj == (void*)SSP0_BASE ) { /* Reset SPIFI peripheral before to Erase/Write SPIFI memory through SPI */ RESET_CTRL1 = RESET_CTRL1_SPIFI_RST; } - SSP_CR1(spi->obj) = 0; - SSP_CPSR(spi->obj) = config->clock_prescale_rate; - SSP_CR0(spi->obj) = + 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(spi->obj) = + SSP_CR1(bus->obj) = SSP_SLAVE_OUT_ENABLE | SSP_MASTER | SSP_ENABLE | SSP_MODE_NORMAL ; - spi->config = config; + bus->config = config; } -void spi_ssp_stop(spi_t* const spi) { - SSP_CR1(spi->obj) = 0; +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_t* const spi) { - while( (SSP_SR(spi->obj) & SSP_SR_TNF) == 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_t* const spi) { - while( (SSP_SR(spi->obj) & SSP_SR_RNE) == 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_t* const spi) { - while( SSP_SR(spi->obj) & SSP_SR_BSY ); +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_t* const spi, const uint32_t data) { - spi_ssp_wait_for_tx_fifo_not_full(spi); - SSP_DR(spi->obj) = data; - spi_ssp_wait_for_not_busy(spi); - spi_ssp_wait_for_rx_fifo_not_empty(spi); - return SSP_DR(spi->obj); +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_t* const spi, const spi_transfer_t* const transfers, const size_t count) { - const ssp_config_t* const config = spi->config; +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(spi->obj) & 0xf) > SSP_DATA_8BITS; + const bool word_size_u16 = (SSP_CR0(bus->obj) & 0xf) > SSP_DATA_8BITS; - config->select(spi); + config->select(bus); for(size_t i=0; iunselect(spi); + config->unselect(bus); } -void spi_ssp_transfer(spi_t* const spi, void* const data, const size_t count) { +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(spi, transfers, 1); + spi_ssp_transfer_gather(bus, transfers, 1); } diff --git a/firmware/common/spi_ssp.h b/firmware/common/spi_ssp.h index ef2d77cf..8cff3dbe 100644 --- a/firmware/common/spi_ssp.h +++ b/firmware/common/spi_ssp.h @@ -25,7 +25,7 @@ #include #include -#include "spi.h" +#include "spi_bus.h" #include @@ -33,13 +33,13 @@ typedef struct ssp_config_t { ssp_datasize_t data_bits; uint8_t serial_clock_rate; uint8_t clock_prescale_rate; - void (*select)(spi_t* const spi); - void (*unselect)(spi_t* const spi); + void (*select)(spi_bus_t* const bus); + void (*unselect)(spi_bus_t* const bus); } ssp_config_t; -void spi_ssp_start(spi_t* const spi, const void* const config); -void spi_ssp_stop(spi_t* const spi); -void spi_ssp_transfer(spi_t* const spi, void* const data, const size_t count); -void spi_ssp_transfer_gather(spi_t* const spi, const spi_transfer_t* const transfers, const size_t count); +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/w25q80bv.c b/firmware/common/w25q80bv.c index 6218e34d..572cc1f2 100644 --- a/firmware/common/w25q80bv.c +++ b/firmware/common/w25q80bv.c @@ -69,7 +69,7 @@ void w25q80bv_setup(w25q80bv_driver_t* const drv) uint8_t w25q80bv_get_status(w25q80bv_driver_t* const drv) { uint8_t data[] = { W25Q80BV_READ_STATUS1, 0xFF }; - spi_transfer(drv->spi, data, ARRAY_SIZE(data)); + spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data)); return data[1]; } @@ -80,7 +80,7 @@ uint8_t w25q80bv_get_device_id(w25q80bv_driver_t* const drv) W25Q80BV_DEVICE_ID, 0xFF, 0xFF, 0xFF, 0xFF }; - spi_transfer(drv->spi, data, ARRAY_SIZE(data)); + spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data)); return data[4]; } @@ -91,7 +91,7 @@ void w25q80bv_get_unique_id(w25q80bv_driver_t* const drv, w25q80bv_unique_id_t* 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - spi_transfer(drv->spi, data, ARRAY_SIZE(data)); + spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data)); for(size_t i=0; i<8; i++) { unique_id->id_8b[i] = data[5+i]; @@ -108,7 +108,7 @@ void w25q80bv_write_enable(w25q80bv_driver_t* const drv) w25q80bv_wait_while_busy(drv); uint8_t data[] = { W25Q80BV_WRITE_ENABLE }; - spi_transfer(drv->spi, data, ARRAY_SIZE(data)); + spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data)); } void w25q80bv_chip_erase(w25q80bv_driver_t* const drv) @@ -125,7 +125,7 @@ void w25q80bv_chip_erase(w25q80bv_driver_t* const drv) w25q80bv_wait_while_busy(drv); uint8_t data[] = { W25Q80BV_CHIP_ERASE }; - spi_transfer(drv->spi, data, ARRAY_SIZE(data)); + spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data)); } /* write up a 256 byte page or partial page */ @@ -154,7 +154,7 @@ static void w25q80bv_page_program(w25q80bv_driver_t* const drv, const uint32_t a { data, len } }; - spi_transfer_gather(drv->spi, transfers, ARRAY_SIZE(transfers)); + spi_bus_transfer_gather(drv->bus, transfers, ARRAY_SIZE(transfers)); } /* write an arbitrary number of bytes */ diff --git a/firmware/common/w25q80bv.h b/firmware/common/w25q80bv.h index fab11bda..c9018e2c 100644 --- a/firmware/common/w25q80bv.h +++ b/firmware/common/w25q80bv.h @@ -27,7 +27,7 @@ #include #include -#include "spi.h" +#include "spi_bus.h" typedef union { @@ -40,7 +40,7 @@ struct w25q80bv_driver_t; typedef struct w25q80bv_driver_t w25q80bv_driver_t; struct w25q80bv_driver_t { - spi_t* spi; + spi_bus_t* bus; void (*target_init)(w25q80bv_driver_t* const drv); size_t page_len; size_t num_pages; diff --git a/firmware/common/w25q80bv_target.c b/firmware/common/w25q80bv_target.c index 8d07f66e..6e6ee478 100644 --- a/firmware/common/w25q80bv_target.c +++ b/firmware/common/w25q80bv_target.c @@ -59,12 +59,12 @@ void w25q80bv_target_init(w25q80bv_driver_t* const drv) { GPIO5_DIR |= PIN_SSP0_SSEL; } -void w25q80bv_target_spi_select(spi_t* const spi) { - (void)spi; +void w25q80bv_target_spi_select(spi_bus_t* const bus) { + (void)bus; gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL); } -void w25q80bv_target_spi_unselect(spi_t* const spi) { - (void)spi; +void w25q80bv_target_spi_unselect(spi_bus_t* const bus) { + (void)bus; gpio_set(PORT_SSP0_SSEL, PIN_SSP0_SSEL); } diff --git a/firmware/common/w25q80bv_target.h b/firmware/common/w25q80bv_target.h index f8e7f05e..2d9e1f33 100644 --- a/firmware/common/w25q80bv_target.h +++ b/firmware/common/w25q80bv_target.h @@ -23,10 +23,10 @@ #define __W25Q80BV_TARGET_H__ #include "w25q80bv.h" -#include "spi.h" +#include "spi_bus.h" void w25q80bv_target_init(w25q80bv_driver_t* const drv); -void w25q80bv_target_spi_select(spi_t* const spi); -void w25q80bv_target_spi_unselect(spi_t* const spi); +void w25q80bv_target_spi_select(spi_bus_t* const bus); +void w25q80bv_target_spi_unselect(spi_bus_t* const bus); #endif/*__W25Q80BV_TARGET_H__*/ diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index dd3fceb8..f585181a 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -142,7 +142,7 @@ macro(DeclareTargets) ${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.c + ${PATH_HACKRF_FIRMWARE_COMMON}/spi_bus.c ${PATH_HACKRF_FIRMWARE_COMMON}/spi_ssp.c m0_bin.s ) diff --git a/firmware/hackrf_usb/usb_api_spiflash.c b/firmware/hackrf_usb/usb_api_spiflash.c index 225bf0de..34456781 100644 --- a/firmware/hackrf_usb/usb_api_spiflash.c +++ b/firmware/hackrf_usb/usb_api_spiflash.c @@ -39,7 +39,7 @@ usb_request_status_t usb_vendor_request_erase_spiflash( //FIXME This should refuse to run if executing from SPI flash. if (stage == USB_TRANSFER_STAGE_SETUP) { - spi_start(spi_flash.spi, &ssp_config_w25q80bv); + spi_bus_start(spi_flash.bus, &ssp_config_w25q80bv); w25q80bv_setup(&spi_flash); /* only chip erase is implemented */ w25q80bv_chip_erase(&spi_flash); @@ -66,7 +66,7 @@ usb_request_status_t usb_vendor_request_write_spiflash( } else { usb_transfer_schedule_block(endpoint->out, &spiflash_buffer[0], len, NULL, NULL); - spi_start(spi_flash.spi, &ssp_config_w25q80bv); + spi_bus_start(spi_flash.bus, &ssp_config_w25q80bv); w25q80bv_setup(&spi_flash); return USB_REQUEST_STATUS_OK; } From 02cc5814b15dfc666d6a0bcdedaec4583a659550 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 13 Nov 2014 10:32:38 -0800 Subject: [PATCH 43/46] I2C: Interface: Rename init()->start(), add stop(). --- firmware/common/hackrf_core.c | 10 ++++++---- firmware/common/i2c_bus.c | 8 ++++++-- firmware/common/i2c_bus.h | 6 ++++-- firmware/common/i2c_lpc.c | 7 ++++++- firmware/common/i2c_lpc.h | 3 ++- firmware/libopencm3 | 2 +- 6 files changed, 25 insertions(+), 11 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index a562f7c6..1af5e823 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -38,13 +38,15 @@ i2c_bus_t i2c0 = { .obj = (void*)I2C0_BASE, - .init = i2c_lpc_init, + .start = i2c_lpc_start, + .stop = i2c_lpc_stop, .transfer = i2c_lpc_transfer, }; i2c_bus_t i2c1 = { .obj = (void*)I2C1_BASE, - .init = i2c_lpc_init, + .start = i2c_lpc_start, + .stop = i2c_lpc_stop, .transfer = i2c_lpc_transfer, }; @@ -290,7 +292,7 @@ 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); - i2c_bus_init(clock_gen.bus, &i2c_config_si5351c_slow_clock); + i2c_bus_start(clock_gen.bus, &i2c_config_si5351c_slow_clock); si5351c_disable_all_outputs(&clock_gen); si5351c_disable_oeb_pin_control(&clock_gen); @@ -362,7 +364,7 @@ void cpu_clock_init(void) //FIXME disable I2C /* Kick I2C0 down to 400kHz when we switch over to APB1 clock = 204MHz */ - i2c_bus_init(clock_gen.bus, &i2c_config_si5351c_fast_clock); + i2c_bus_start(clock_gen.bus, &i2c_config_si5351c_fast_clock); /* * 12MHz clock is entering LPC XTAL1/OSC input now. On diff --git a/firmware/common/i2c_bus.c b/firmware/common/i2c_bus.c index 6b60455a..7b5497e0 100644 --- a/firmware/common/i2c_bus.c +++ b/firmware/common/i2c_bus.c @@ -21,8 +21,12 @@ #include "i2c_bus.h" -void i2c_bus_init(i2c_bus_t* const bus, const void* const config) { - bus->init(bus, config); +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( diff --git a/firmware/common/i2c_bus.h b/firmware/common/i2c_bus.h index 784fb602..04b83499 100644 --- a/firmware/common/i2c_bus.h +++ b/firmware/common/i2c_bus.h @@ -30,7 +30,8 @@ typedef struct i2c_bus_t i2c_bus_t; struct i2c_bus_t { void* const obj; - void (*init)(i2c_bus_t* const bus, const void* const config); + 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, @@ -39,7 +40,8 @@ struct i2c_bus_t { ); }; -void i2c_bus_init(i2c_bus_t* const bus, const void* const config); +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, diff --git a/firmware/common/i2c_lpc.c b/firmware/common/i2c_lpc.c index 73c3e92c..f7bf4393 100644 --- a/firmware/common/i2c_lpc.c +++ b/firmware/common/i2c_lpc.c @@ -26,13 +26,18 @@ /* FIXME return i2c0 status from each function */ -void i2c_lpc_init(i2c_bus_t* const bus, const void* const _config) { +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, diff --git a/firmware/common/i2c_lpc.h b/firmware/common/i2c_lpc.h index 16c04a22..32c79fcd 100644 --- a/firmware/common/i2c_lpc.h +++ b/firmware/common/i2c_lpc.h @@ -31,7 +31,8 @@ typedef struct i2c_lpc_config_t { const uint16_t duty_cycle_count; } i2c_lpc_config_t; -void i2c_lpc_init(i2c_bus_t* const bus, const void* const config); +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, diff --git a/firmware/libopencm3 b/firmware/libopencm3 index aec04e96..10503c7c 160000 --- a/firmware/libopencm3 +++ b/firmware/libopencm3 @@ -1 +1 @@ -Subproject commit aec04e962c2264877580be30fe1e1178ce3f568c +Subproject commit 10503c7cc19647393d98cc66c3dbaf20bd634494 From 7eee145365134586ec2f67d87f3a4edd81cff3c2 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Thu, 13 Nov 2014 16:12:54 -0800 Subject: [PATCH 44/46] Add "pin" interface to abstract GPIO pins. --- firmware/common/pin.h | 37 +++++++++++++++++++++++++ firmware/common/pin_lpc.c | 52 ++++++++++++++++++++++++++++++++++++ firmware/common/pin_lpc.h | 41 ++++++++++++++++++++++++++++ firmware/hackrf-common.cmake | 1 + 4 files changed, 131 insertions(+) create mode 100644 firmware/common/pin.h create mode 100644 firmware/common/pin_lpc.c create mode 100644 firmware/common/pin_lpc.h diff --git a/firmware/common/pin.h b/firmware/common/pin.h new file mode 100644 index 00000000..7c6c4df1 --- /dev/null +++ b/firmware/common/pin.h @@ -0,0 +1,37 @@ +/* + * 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 __PIN_H__ +#define __PIN_H__ + +#include + +typedef const struct pin_t* pin_t; + +void pin_set(pin_t pin); +void pin_clear(pin_t pin); +void pin_toggle(pin_t pin); +void pin_output(pin_t pin); +void pin_input(pin_t pin); +void pin_write(pin_t pin, const bool value); +bool pin_read(pin_t pin); + +#endif/*__PIN_H__*/ diff --git a/firmware/common/pin_lpc.c b/firmware/common/pin_lpc.c new file mode 100644 index 00000000..a8ba5549 --- /dev/null +++ b/firmware/common/pin_lpc.c @@ -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. + */ + +#include "pin_lpc.h" + +#include + +void pin_set(pin_t pin) { + GPIO_SET(pin->gpio) = pin->mask; +} + +void pin_clear(pin_t pin) { + GPIO_CLR(pin->gpio) = pin->mask; +} + +void pin_toggle(pin_t pin) { + GPIO_NOT(pin->gpio) = pin->mask; +} + +void pin_output(pin_t pin) { + GPIO_DIR(pin->gpio) |= pin->mask; +} + +void pin_input(pin_t pin) { + GPIO_DIR(pin->gpio) &= ~pin->mask; +} + +void pin_write(pin_t pin, const bool value) { + MMIO32(pin->gpio_w) = value; +} + +bool pin_read(pin_t pin) { + return MMIO32(pin->gpio_w); +} diff --git a/firmware/common/pin_lpc.h b/firmware/common/pin_lpc.h new file mode 100644 index 00000000..56f3e572 --- /dev/null +++ b/firmware/common/pin_lpc.h @@ -0,0 +1,41 @@ +/* + * 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 __PIN_LPC_H__ +#define __PIN_LPC_H__ + +#include + +#include "pin.h" + +struct pin_t { + uint32_t gpio; + uint32_t mask; + uint32_t gpio_w; +}; + +#define PIN_LPC(_port_num, _pin_num) { \ + .gpio = (GPIO0) + (_port_num) * 4, \ + .mask = (1UL << (_pin_num)), \ + .gpio_w = GPIO_PORT_BASE + 0x1000 + ((_port_num) * 0x80) + ((_pin_num) * 4), \ +}; + +#endif/*__PIN_LPC_H__*/ diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index e39343f6..2e496b43 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -146,6 +146,7 @@ macro(DeclareTargets) ${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}/pin_lpc.c m0_bin.s ) From 5363ec36726050e19c32bdc82424578989f6ee52 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Sat, 15 Nov 2014 16:21:10 -0800 Subject: [PATCH 45/46] Use new GPIO API to abstract GPIO in various drivers. Had to do it all at once due to name conflicts with API exposed in libopencm3. Quite invasive patch! Also precipitated an LED API... --- firmware/blinky/blinky.c | 21 +- firmware/common/cpld_jtag.c | 31 ++- firmware/common/cpld_jtag.h | 16 +- firmware/common/{pin.h => gpio.h} | 23 +- firmware/common/{pin_lpc.c => gpio_lpc.c} | 38 +-- firmware/common/gpio_lpc.h | 70 ++++++ firmware/common/hackrf_core.c | 237 +++++++++++++++--- firmware/common/hackrf_core.h | 152 ++--------- firmware/common/max2837.h | 14 ++ firmware/common/max2837_target.c | 123 +++------ firmware/common/max2837_target.h | 4 - firmware/common/max5864_target.c | 13 - firmware/common/max5864_target.h | 3 - firmware/common/pin_lpc.h | 41 --- firmware/common/rf_path.c | 177 ++++++------- firmware/common/rf_path.h | 35 ++- firmware/common/rffc5071.c | 3 + firmware/common/rffc5071.h | 2 + firmware/common/rffc5071_spi.c | 54 ++-- firmware/common/rffc5071_spi.h | 8 + firmware/common/sgpio.c | 97 ++----- firmware/common/sgpio.h | 31 ++- firmware/common/spi_ssp.c | 7 +- firmware/common/spi_ssp.h | 5 +- firmware/common/streaming.c | 10 +- firmware/common/streaming.h | 6 +- firmware/common/tuning.c | 18 +- firmware/common/w25q80bv.h | 3 + firmware/common/w25q80bv_target.c | 19 +- firmware/common/w25q80bv_target.h | 3 - firmware/common/xapp058/micro.c | 234 +++++++++-------- firmware/common/xapp058/micro.h | 4 +- firmware/common/xapp058/ports.c | 31 +-- firmware/common/xapp058/ports.h | 10 +- firmware/hackrf-common.cmake | 2 +- firmware/hackrf_usb/hackrf_usb.c | 31 ++- firmware/hackrf_usb/usb_api_cpld.c | 15 +- firmware/hackrf_usb/usb_api_transceiver.c | 10 +- firmware/mixertx/mixertx.c | 13 +- firmware/sgpio-rx/sgpio-rx.c | 29 +-- firmware/sgpio/sgpio_test.c | 21 +- .../sgpio_passthrough/sgpio_passthrough.c | 5 +- firmware/simpletx/simpletx.c | 12 +- firmware/spiflash/spiflash.c | 16 +- firmware/startup/startup.c | 18 +- firmware/startup_systick/startup_systick.c | 19 +- firmware/startup_systick_perfo/perf_mips.c | 3 - .../startup_systick_perfo/startup_systick.c | 19 +- 48 files changed, 886 insertions(+), 870 deletions(-) rename firmware/common/{pin.h => gpio.h} (71%) rename firmware/common/{pin_lpc.c => gpio_lpc.c} (60%) create mode 100644 firmware/common/gpio_lpc.h delete mode 100644 firmware/common/pin_lpc.h 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/pin.h b/firmware/common/gpio.h similarity index 71% rename from firmware/common/pin.h rename to firmware/common/gpio.h index 7c6c4df1..fe60ff61 100644 --- a/firmware/common/pin.h +++ b/firmware/common/gpio.h @@ -19,19 +19,20 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __PIN_H__ -#define __PIN_H__ +#ifndef __GPIO_H__ +#define __GPIO_H__ #include -typedef const struct pin_t* pin_t; +typedef const struct gpio_t* gpio_t; -void pin_set(pin_t pin); -void pin_clear(pin_t pin); -void pin_toggle(pin_t pin); -void pin_output(pin_t pin); -void pin_input(pin_t pin); -void pin_write(pin_t pin, const bool value); -bool pin_read(pin_t pin); +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/*__PIN_H__*/ +#endif/*__GPIO_H__*/ diff --git a/firmware/common/pin_lpc.c b/firmware/common/gpio_lpc.c similarity index 60% rename from firmware/common/pin_lpc.c rename to firmware/common/gpio_lpc.c index a8ba5549..b5e217c4 100644 --- a/firmware/common/pin_lpc.c +++ b/firmware/common/gpio_lpc.c @@ -19,34 +19,40 @@ * Boston, MA 02110-1301, USA. */ -#include "pin_lpc.h" +#include "gpio_lpc.h" -#include +#include -void pin_set(pin_t pin) { - GPIO_SET(pin->gpio) = pin->mask; +void gpio_init() { + for(size_t i=0; i<8; i++) { + GPIO_LPC_PORT(i)->dir = 0; + } } -void pin_clear(pin_t pin) { - GPIO_CLR(pin->gpio) = pin->mask; +void gpio_set(gpio_t gpio) { + gpio->port->set = gpio->mask; } -void pin_toggle(pin_t pin) { - GPIO_NOT(pin->gpio) = pin->mask; +void gpio_clear(gpio_t gpio) { + gpio->port->clr = gpio->mask; } -void pin_output(pin_t pin) { - GPIO_DIR(pin->gpio) |= pin->mask; +void gpio_toggle(gpio_t gpio) { + gpio->port->not = gpio->mask; } -void pin_input(pin_t pin) { - GPIO_DIR(pin->gpio) &= ~pin->mask; +void gpio_output(gpio_t gpio) { + gpio->port->dir |= gpio->mask; } -void pin_write(pin_t pin, const bool value) { - MMIO32(pin->gpio_w) = value; +void gpio_input(gpio_t gpio) { + gpio->port->dir &= ~gpio->mask; } -bool pin_read(pin_t pin) { - return MMIO32(pin->gpio_w); +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 f5f025ef..32d3b97d 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -32,17 +32,118 @@ #include "rffc5071_spi.h" #include "w25q80bv.h" #include "w25q80bv_target.h" -#include "sgpio.h" -#include "rf_path.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, @@ -81,8 +182,7 @@ const ssp_config_t ssp_config_max2837 = { .data_bits = SSP_DATA_16BITS, .serial_clock_rate = 21, .clock_prescale_rate = 2, - .select = max2837_target_spi_select, - .unselect = max2837_target_spi_unselect, + .gpio_select = &gpio_max2837_select, }; const ssp_config_t ssp_config_max5864 = { @@ -96,8 +196,7 @@ const ssp_config_t ssp_config_max5864 = { .data_bits = SSP_DATA_8BITS, .serial_clock_rate = 21, .clock_prescale_rate = 2, - .select = max5864_target_spi_select, - .unselect = max5864_target_spi_unselect, + .gpio_select = &gpio_max5864_select, }; spi_bus_t spi_bus_ssp1 = { @@ -111,6 +210,19 @@ spi_bus_t spi_bus_ssp1 = { 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, }; @@ -120,8 +232,14 @@ max5864_driver_t max5864 = { .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 = NULL, + .config = &rffc5071_spi_config, .start = rffc5071_spi_start, .stop = rffc5071_spi_stop, .transfer = rffc5071_spi_transfer, @@ -130,14 +248,14 @@ spi_bus_t spi_bus_rffc5071 = { 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, - .select = w25q80bv_target_spi_select, - .unselect = w25q80bv_target_spi_unselect, + .gpio_select = &gpio_w25q80bv_select, }; spi_bus_t spi_bus_ssp0 = { @@ -151,9 +269,49 @@ spi_bus_t spi_bus_ssp0 = { 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; @@ -646,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); @@ -665,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); + +#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, NULL); + spi_bus_start(&spi_bus_rffc5071, &rffc5071_spi_config); - rf_path_pin_setup(); + 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 c41fd83b..5cc097b4 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -39,6 +39,9 @@ extern "C" #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 @@ -214,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, @@ -368,6 +235,9 @@ 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); @@ -389,6 +259,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/max2837.h b/firmware/common/max2837.h index b3414e08..a9962fad 100644 --- a/firmware/common/max2837.h +++ b/firmware/common/max2837.h @@ -26,6 +26,7 @@ #include #include +#include "gpio.h" #include "spi_bus.h" /* 32 registers, each containing 10 bits of data. */ @@ -44,6 +45,19 @@ typedef struct max2837_driver_t max2837_driver_t; struct max2837_driver_t { spi_bus_t* const bus; + gpio_t gpio_enable; + gpio_t gpio_rx_enable; + gpio_t gpio_tx_enable; +#ifdef JELLYBEAN + gpio_t gpio_rxhp; + gpio_t gpio_b1; + gpio_t gpio_b2; + gpio_t gpio_b3; + gpio_t gpio_b4; + gpio_t gpio_b5; + gpio_t gpio_b6; + gpio_t gpio_b7; +#endif void (*target_init)(max2837_driver_t* const drv); void (*set_mode)(max2837_driver_t* const drv, const max2837_mode_t new_mode); max2837_mode_t mode; diff --git a/firmware/common/max2837_target.c b/firmware/common/max2837_target.c index 2a2f7b2d..dc78b4fa 100644 --- a/firmware/common/max2837_target.c +++ b/firmware/common/max2837_target.c @@ -23,20 +23,15 @@ #include "max2837_target.h" #include -#include #include "hackrf_core.h" void max2837_target_init(max2837_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)); 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 XCVR_CTL GPIO pins. */ #ifdef JELLYBEAN @@ -54,105 +49,57 @@ void max2837_target_init(max2837_driver_t* const drv) { scu_pinmux(SCU_XCVR_TXENABLE, SCU_GPIO_FAST); /* Set GPIO pins as outputs. */ - GPIO2_DIR |= (PIN_XCVR_ENABLE | PIN_XCVR_RXENABLE | PIN_XCVR_TXENABLE); + gpio_output(drv->gpio_enable); + gpio_output(drv->gpio_rx_enable); + gpio_output(drv->gpio_tx_enable); #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 - ; + 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(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 - ); + 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_spi_select(spi_bus_t* const bus) { - (void)bus; - gpio_clear(PORT_XCVR_CS, PIN_XCVR_CS); -} - -void max2837_target_spi_unselect(spi_bus_t* const bus) { - (void)bus; - gpio_set(PORT_XCVR_CS, PIN_XCVR_CS); -} - -static void max2837_target_mode_shutdown(max2837_driver_t* const drv) { - /* All circuit blocks are powered down, except the 4-wire serial bus +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. - */ - gpio_clear(PORT_XCVR_ENABLE, - (PIN_XCVR_ENABLE | PIN_XCVR_RXENABLE | PIN_XCVR_TXENABLE)); - drv->mode = MAX2837_MODE_SHUTDOWN; -} - -static void max2837_target_mode_standby(max2837_driver_t* const drv) { - /* Used to enable the frequency synthesizer block while the rest of the + * + * 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. - */ - gpio_clear(PORT_XCVR_ENABLE, (PIN_XCVR_RXENABLE | PIN_XCVR_TXENABLE)); - gpio_set(PORT_XCVR_ENABLE, PIN_XCVR_ENABLE); - drv->mode = MAX2837_MODE_STANDBY; -} - -static void max2837_target_mode_tx(max2837_driver_t* const drv) { - /* All Tx circuit blocks are powered on. The external PA is powered on + * + * 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. - */ - gpio_clear(PORT_XCVR_ENABLE, PIN_XCVR_RXENABLE); - gpio_set(PORT_XCVR_ENABLE, - (PIN_XCVR_ENABLE | PIN_XCVR_TXENABLE)); - drv->mode = MAX2837_MODE_TX; -} - -static void max2837_target_mode_rx(max2837_driver_t* const drv) { - /* All Rx circuit blocks are powered on and active. Antenna signal is + * + * 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_clear(PORT_XCVR_ENABLE, PIN_XCVR_TXENABLE); - gpio_set(PORT_XCVR_ENABLE, - (PIN_XCVR_ENABLE | PIN_XCVR_RXENABLE)); - drv->mode = MAX2837_MODE_RX; -} - -void max2837_target_set_mode(max2837_driver_t* const drv, const max2837_mode_t new_mode) { - switch(new_mode) { - default: - case MAX2837_MODE_SHUTDOWN: - max2837_target_mode_shutdown(drv); - break; - - case MAX2837_MODE_STANDBY: - max2837_target_mode_standby(drv); - break; - - case MAX2837_MODE_TX: - max2837_target_mode_tx(drv); - break; - - case MAX2837_MODE_RX: - max2837_target_mode_rx(drv); - break; - } + 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 index cc578ed3..0fc24ec9 100644 --- a/firmware/common/max2837_target.h +++ b/firmware/common/max2837_target.h @@ -24,12 +24,8 @@ #define __MAX2837_TARGET_H #include "max2837.h" -#include "spi_bus.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); -void max2837_target_spi_select(spi_bus_t* const bus); -void max2837_target_spi_unselect(spi_bus_t* const bus); - #endif // __MAX2837_TARGET_H diff --git a/firmware/common/max5864_target.c b/firmware/common/max5864_target.c index 1b92baa3..7a49ec24 100644 --- a/firmware/common/max5864_target.c +++ b/firmware/common/max5864_target.c @@ -22,7 +22,6 @@ #include "max5864_target.h" #include -#include #include "hackrf_core.h" void max5864_target_init(max5864_driver_t* const drv) { @@ -38,16 +37,4 @@ void max5864_target_init(max5864_driver_t* const drv) { * 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; -} - -void max5864_target_spi_select(spi_bus_t* const bus) { - (void)bus; - gpio_clear(PORT_AD_CS, PIN_AD_CS); -} - -void max5864_target_spi_unselect(spi_bus_t* const bus) { - (void)bus; - gpio_set(PORT_AD_CS, PIN_AD_CS); } diff --git a/firmware/common/max5864_target.h b/firmware/common/max5864_target.h index c98eef7d..be684e2c 100644 --- a/firmware/common/max5864_target.h +++ b/firmware/common/max5864_target.h @@ -23,10 +23,7 @@ #define __MAX5864_TARGET_H__ #include "max5864.h" -#include "spi_bus.h" void max5864_target_init(max5864_driver_t* const drv); -void max5864_target_spi_select(spi_bus_t* const bus); -void max5864_target_spi_unselect(spi_bus_t* const bus); #endif/*__MAX5864_TARGET_H__*/ diff --git a/firmware/common/pin_lpc.h b/firmware/common/pin_lpc.h deleted file mode 100644 index 56f3e572..00000000 --- a/firmware/common/pin_lpc.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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 __PIN_LPC_H__ -#define __PIN_LPC_H__ - -#include - -#include "pin.h" - -struct pin_t { - uint32_t gpio; - uint32_t mask; - uint32_t gpio_w; -}; - -#define PIN_LPC(_port_num, _pin_num) { \ - .gpio = (GPIO0) + (_port_num) * 4, \ - .mask = (1UL << (_pin_num)), \ - .gpio_w = GPIO_PORT_BASE + 0x1000 + ((_port_num) * 0x80) + ((_pin_num) * 4), \ -}; - -#endif/*__PIN_LPC_H__*/ diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index 589961aa..57877054 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,9 +143,9 @@ 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(&rffc5072, 0x00); /* turn on antenna power by clearing GPO1 */ @@ -156,17 +155,17 @@ static void switchctrl_set_hackrf_one(uint8_t ctrl) { } #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(&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,27 +186,29 @@ 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_setup(&max5864); max5864_shutdown(&max5864); @@ -217,21 +218,21 @@ void rf_path_init(void) { max2837_start(&max2837); rffc5071_setup(&rffc5072); - switchctrl_set(switchctrl); + switchctrl_set(rf_path, switchctrl); } -void rf_path_set_direction(const rf_path_direction_t direction) { +void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t direction) { /* Turn off TX and RX amplifiers, then enable based on direction and bypass state. */ - 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(&rffc5072); - if( switchctrl & SWITCHCTRL_MIX_BYPASS ) { + if( rf_path->switchctrl & SWITCHCTRL_MIX_BYPASS ) { rffc5071_disable(&rffc5072); } else { rffc5071_enable(&rffc5072); @@ -240,17 +241,17 @@ void rf_path_set_direction(const rf_path_direction_t direction) { max5864_tx(&max5864); ssp1_set_mode_max2837(); max2837_tx(&max2837); - sgpio_configure(SGPIO_DIRECTION_TX); + 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(&rffc5072); - if( switchctrl & SWITCHCTRL_MIX_BYPASS ) { + if( rf_path->switchctrl & SWITCHCTRL_MIX_BYPASS ) { rffc5071_disable(&rffc5072); } else { rffc5071_enable(&rffc5072); @@ -259,77 +260,77 @@ void rf_path_set_direction(const rf_path_direction_t direction) { max5864_rx(&max5864); ssp1_set_mode_max2837(); max2837_rx(&max2837); - sgpio_configure(SGPIO_DIRECTION_RX); + 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 /* Set RF path to receive direction when "off" */ - switchctrl &= ~SWITCHCTRL_TX; + rf_path->switchctrl &= ~SWITCHCTRL_TX; rffc5071_disable(&rffc5072); ssp1_set_mode_max5864(); max5864_standby(&max5864); ssp1_set_mode_max2837(); max2837_set_mode(&max2837, MAX2837_MODE_STANDBY); - sgpio_configure(SGPIO_DIRECTION_RX); + 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; + rf_path->switchctrl |= SWITCHCTRL_MIX_BYPASS; rffc5071_disable(&rffc5072); break; case RF_PATH_FILTER_LOW_PASS: - switchctrl &= ~(SWITCHCTRL_HP | SWITCHCTRL_MIX_BYPASS); + 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; + 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 1905c503..71ba9f5c 100644 --- a/firmware/common/rffc5071.c +++ b/firmware/common/rffc5071.c @@ -88,6 +88,9 @@ void rffc5071_init(rffc5071_driver_t* const drv) */ void rffc5071_setup(rffc5071_driver_t* const drv) { + gpio_set(drv->gpio_reset); + gpio_output(drv->gpio_reset); + rffc5071_init(drv); /* initial setup */ diff --git a/firmware/common/rffc5071.h b/firmware/common/rffc5071.h index 37d69afe..cedb6988 100644 --- a/firmware/common/rffc5071.h +++ b/firmware/common/rffc5071.h @@ -26,12 +26,14 @@ #include #include "spi_bus.h" +#include "gpio.h" /* 31 registers, each containing 16 bits of data. */ #define RFFC5071_NUM_REGS 31 typedef struct { spi_bus_t* const bus; + gpio_t gpio_reset; uint16_t regs[RFFC5071_NUM_REGS]; uint32_t regs_dirty; } rffc5071_driver_t; diff --git a/firmware/common/rffc5071_spi.c b/firmware/common/rffc5071_spi.c index 6036bb04..7c3d9da2 100644 --- a/firmware/common/rffc5071_spi.c +++ b/firmware/common/rffc5071_spi.c @@ -21,69 +21,69 @@ */ #include -#include #include "hackrf_core.h" +#include "rffc5071_spi.h" + static void rffc5071_spi_target_select(spi_bus_t* const bus) { - (void)bus; - gpio_clear(PORT_MIXER_ENX, PIN_MIXER_ENX); + 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) { - (void)bus; - gpio_set(PORT_MIXER_ENX, PIN_MIXER_ENX); + 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) { - (void)bus; - GPIO_DIR(PORT_MIXER_SDATA) |= PIN_MIXER_SDATA; + 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) { - (void)bus; - GPIO_DIR(PORT_MIXER_SDATA) &= ~PIN_MIXER_SDATA; + 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) { - (void)bus; - if (bit) - gpio_set(PORT_MIXER_SDATA, PIN_MIXER_SDATA); - else - gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA); + 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) { - (void)bus; - return MIXER_SDATA_STATE; + 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_DIR(PORT_MIXER_SCLK) |= PIN_MIXER_SCLK; + gpio_output(config->gpio_clock); rffc5071_spi_direction_out(bus); - gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); - gpio_clear(PORT_MIXER_SDATA, PIN_MIXER_SDATA); + 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_DIR(PORT_MIXER_ENX) |= PIN_MIXER_ENX; - GPIO_DIR(PORT_MIXER_RESETX) |= PIN_MIXER_RESETX; + gpio_output(config->gpio_select); /* set to known state */ rffc5071_spi_target_unselect(bus); - gpio_set(PORT_MIXER_RESETX, PIN_MIXER_RESETX); /* active low */ } void rffc5071_spi_start(spi_bus_t* const bus, const void* const config) { - (void)config; + bus->config = config; rffc5071_spi_bus_init(bus); rffc5071_spi_target_init(bus); } @@ -101,11 +101,13 @@ static void rffc5071_spi_serial_delay(spi_bus_t* const bus) { } static void rffc5071_spi_sck(spi_bus_t* const bus) { - rffc5071_spi_serial_delay(bus); - gpio_set(PORT_MIXER_SCLK, PIN_MIXER_SCLK); + const rffc5071_spi_config_t* const config = bus->config; rffc5071_spi_serial_delay(bus); - gpio_clear(PORT_MIXER_SCLK, PIN_MIXER_SCLK); + 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) { diff --git a/firmware/common/rffc5071_spi.h b/firmware/common/rffc5071_spi.h index 8214aa31..8b577910 100644 --- a/firmware/common/rffc5071_spi.h +++ b/firmware/common/rffc5071_spi.h @@ -25,6 +25,14 @@ #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); 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/spi_ssp.c b/firmware/common/spi_ssp.c index 9b5a3e86..7a1e2ea8 100644 --- a/firmware/common/spi_ssp.c +++ b/firmware/common/spi_ssp.c @@ -32,6 +32,9 @@ void spi_ssp_start(spi_bus_t* const bus, const void* const _config) { 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) = @@ -79,7 +82,7 @@ void spi_ssp_transfer_gather(spi_bus_t* const bus, const spi_transfer_t* const t const bool word_size_u16 = (SSP_CR0(bus->obj) & 0xf) > SSP_DATA_8BITS; - config->select(bus); + gpio_clear(config->gpio_select); for(size_t i=0; iunselect(bus); + gpio_set(config->gpio_select); } void spi_ssp_transfer(spi_bus_t* const bus, void* const data, const size_t count) { diff --git a/firmware/common/spi_ssp.h b/firmware/common/spi_ssp.h index 8cff3dbe..2b2f884f 100644 --- a/firmware/common/spi_ssp.h +++ b/firmware/common/spi_ssp.h @@ -27,14 +27,15 @@ #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; - void (*select)(spi_bus_t* const bus); - void (*unselect)(spi_bus_t* const bus); + gpio_t gpio_select; } ssp_config_t; void spi_ssp_start(spi_bus_t* const bus, const void* const config); 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 91cbfdb1..166f910c 100644 --- a/firmware/common/tuning.c +++ b/firmware/common/tuning.c @@ -67,21 +67,21 @@ bool set_freq(const uint64_t freq) 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(&rffc5072, RFFC5071_freq_mhz); max2837_set_frequency(&max2837, real_RFFC5071_freq_hz - freq); - sgpio_cpld_stream_rx_set_q_invert(1); + sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 1); }else if( (freq_mhz >= MIN_BYPASS_FREQ_MHZ) && (freq_mhz < MAX_BYPASS_FREQ_MHZ) ) { - 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, MAX2837_freq_hz); - sgpio_cpld_stream_rx_set_q_invert(0); + sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 0); }else if( (freq_mhz >= MIN_HP_FREQ_MHZ) && (freq_mhz <= MAX_HP_FREQ_MHZ) ) { if (freq_mhz < MID1_HP_FREQ_MHZ) { @@ -94,12 +94,12 @@ 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(&rffc5072, RFFC5071_freq_mhz); max2837_set_frequency(&max2837, freq - real_RFFC5071_freq_hz); - sgpio_cpld_stream_rx_set_q_invert(0); + sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 0); }else { /* Error freq_mhz too high */ @@ -129,12 +129,12 @@ bool set_freq_explicit(const uint64_t if_freq_hz, const uint64_t lo_freq_hz, return false; } - rf_path_set_filter(path); + 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(&rffc5072, lo_freq_hz / FREQ_ONE_MHZ); diff --git a/firmware/common/w25q80bv.h b/firmware/common/w25q80bv.h index c9018e2c..6649f017 100644 --- a/firmware/common/w25q80bv.h +++ b/firmware/common/w25q80bv.h @@ -28,6 +28,7 @@ #include #include "spi_bus.h" +#include "gpio.h" typedef union { @@ -41,6 +42,8 @@ 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; diff --git a/firmware/common/w25q80bv_target.c b/firmware/common/w25q80bv_target.c index 6e6ee478..087d6822 100644 --- a/firmware/common/w25q80bv_target.c +++ b/firmware/common/w25q80bv_target.c @@ -22,7 +22,6 @@ #include "w25q80bv_target.h" #include -#include #include "hackrf_core.h" /* TODO: Why is SSEL being controlled manually when SSP0 could do it @@ -51,20 +50,10 @@ void w25q80bv_target_init(w25q80bv_driver_t* const drv) { 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); + gpio_set(drv->gpio_hold); + gpio_set(drv->gpio_wp); /* Set GPIO pins as outputs. */ - GPIO1_DIR |= (PIN_FLASH_HOLD | PIN_FLASH_WP); - GPIO5_DIR |= PIN_SSP0_SSEL; -} - -void w25q80bv_target_spi_select(spi_bus_t* const bus) { - (void)bus; - gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL); -} - -void w25q80bv_target_spi_unselect(spi_bus_t* const bus) { - (void)bus; - gpio_set(PORT_SSP0_SSEL, PIN_SSP0_SSEL); + gpio_output(drv->gpio_hold); + gpio_output(drv->gpio_wp); } diff --git a/firmware/common/w25q80bv_target.h b/firmware/common/w25q80bv_target.h index 2d9e1f33..e36f94ae 100644 --- a/firmware/common/w25q80bv_target.h +++ b/firmware/common/w25q80bv_target.h @@ -23,10 +23,7 @@ #define __W25Q80BV_TARGET_H__ #include "w25q80bv.h" -#include "spi_bus.h" void w25q80bv_target_init(w25q80bv_driver_t* const drv); -void w25q80bv_target_spi_select(spi_bus_t* const bus); -void w25q80bv_target_spi_unselect(spi_bus_t* const bus); #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 2e496b43..8ea1e6e6 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -146,7 +146,7 @@ macro(DeclareTargets) ${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}/pin_lpc.c + ${PATH_HACKRF_FIRMWARE_COMMON}/gpio_lpc.c m0_bin.s ) diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 2573b37a..efaa6511 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -24,7 +24,6 @@ #include -#include #include #include @@ -40,15 +39,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" 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); @@ -56,27 +53,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(&clock_gen); - baseband_streaming_enable(); + baseband_streaming_enable(&sgpio_config); } } @@ -170,7 +167,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(); @@ -179,7 +176,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); } } @@ -208,7 +205,7 @@ int main(void) { usb_run(&usb_device); - 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_transceiver.c b/firmware/hackrf_usb/usb_api_transceiver.c index b2297dbc..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: @@ -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/mixertx/mixertx.c b/firmware/mixertx/mixertx.c index e23e00d7..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) { @@ -39,17 +32,17 @@ int main(void) #endif cpu_clock_init(); - gpio_set(PORT_LED1_3, (PIN_LED1)); /* LED1 on */ + led_on(LED1); ssp1_set_mode_max2837(); max2837_setup(&max2837); rffc5071_setup(&rffc5072); - gpio_set(PORT_LED1_3, (PIN_LED2)); /* LED2 on */ + led_on(LED2); max2837_set_frequency(&max2837, freq); max2837_start(&max2837); max2837_tx(&max2837); - gpio_set(PORT_LED1_3, (PIN_LED3)); /* LED3 on */ + led_on(LED3); while (1); max2837_stop(&max2837); diff --git a/firmware/sgpio-rx/sgpio-rx.c b/firmware/sgpio-rx/sgpio-rx.c index dca4c489..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,13 +93,13 @@ int main(void) { enable_rf_power(); #endif cpu_clock_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 de3ee605..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); @@ -73,7 +66,7 @@ int main(void) { enable_1v8_power(); cpu_clock_init(); - gpio_set(PORT_LED1_3, PIN_LED1); + led_on(LED1); ssp1_set_mode_max5864(); max5864_setup(&max5864); diff --git a/firmware/sgpio_passthrough/sgpio_passthrough.c b/firmware/sgpio_passthrough/sgpio_passthrough.c index d1cc0491..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,7 +350,7 @@ int main(void) pin_setup(); enable_1v8_power(); cpu_clock_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 78178ee9..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) { @@ -38,15 +32,15 @@ int main(void) #endif cpu_clock_init(); - gpio_set(PORT_LED1_3, (PIN_LED1)); /* LED1 on */ + led_on(LED1); ssp1_set_mode_max2837(); max2837_setup(&max2837); - gpio_set(PORT_LED1_3, (PIN_LED2)); /* LED2 on */ + led_on(LED2); max2837_set_frequency(&max2837, freq); max2837_start(&max2837); max2837_tx(&max2837); - gpio_set(PORT_LED1_3, (PIN_LED3)); /* LED3 on */ + led_on(LED3); while (1); max2837_stop(&max2837); 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); } From 87f59de104364da2a50ce8c6c633415383f50687 Mon Sep 17 00:00:00 2001 From: Dominic Spill Date: Sun, 20 Dec 2015 15:28:29 +0000 Subject: [PATCH 46/46] Merge "abstract buses" changes with "fix SPI flash read" --- firmware/common/rf_path.c | 2 +- firmware/common/w25q80bv.c | 33 ++++++++++++++------------ firmware/common/w25q80bv.h | 2 +- firmware/hackrf_usb/hackrf_usb.c | 3 --- firmware/hackrf_usb/usb_api_spiflash.c | 2 +- firmware/libopencm3 | 2 +- 6 files changed, 22 insertions(+), 22 deletions(-) diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index 14f83e0e..7db1101a 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -268,7 +268,7 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d #ifdef HACKRF_ONE rf_path_set_antenna(rf_path, 0); #endif - rf_path_set_lna(0); + rf_path_set_lna(rf_path, 0); /* Set RF path to receive direction when "off" */ rf_path->switchctrl &= ~SWITCHCTRL_TX; rffc5071_disable(&rffc5072); diff --git a/firmware/common/w25q80bv.c b/firmware/common/w25q80bv.c index b9f6880d..e7029cd1 100644 --- a/firmware/common/w25q80bv.c +++ b/firmware/common/w25q80bv.c @@ -201,24 +201,27 @@ void w25q80bv_program(w25q80bv_driver_t* const drv, uint32_t addr, uint32_t len, } } -void w25q80bv_read(uint32_t addr, uint32_t len, uint8_t* const data) +/* write an arbitrary number of bytes */ +void w25q80bv_read(w25q80bv_driver_t* const drv, uint32_t addr, uint32_t len, uint8_t* const data) { - uint32_t i; - /* do nothing if we would overflow the flash */ - 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; - w25q80bv_wait_while_busy(); + w25q80bv_wait_while_busy(drv); - gpio_clear(PORT_SSP0_SSEL, PIN_SSP0_SSEL); - ssp_transfer(SSP0_NUM, W25Q80BV_FAST_READ); - ssp_transfer(SSP0_NUM, (addr >> 16) & 0xFF); - ssp_transfer(SSP0_NUM, (addr >> 8) & 0xFF); - ssp_transfer(SSP0_NUM, (addr >> 0) & 0xFF); - ssp_transfer(SSP0_NUM, 0xFF); - for (i = 0; i < len; i++) - data[i] = ssp_transfer(SSP0_NUM, 0xFF); - gpio_set(PORT_SSP0_SSEL, PIN_SSP0_SSEL); + uint8_t header[] = { + W25Q80BV_FAST_READ, + (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)); } diff --git a/firmware/common/w25q80bv.h b/firmware/common/w25q80bv.h index 18ac481d..9d244c4d 100644 --- a/firmware/common/w25q80bv.h +++ b/firmware/common/w25q80bv.h @@ -55,6 +55,6 @@ 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); +void w25q80bv_read(w25q80bv_driver_t* const drv, uint32_t addr, uint32_t len, uint8_t* const data); #endif//__W25Q80BV_H__ diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index ea3104d3..eb424be3 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -221,9 +221,6 @@ int main(void) { #endif cpu_clock_init(); - /* Code is not running from SPI flash, initialize for flash read/write over USB */ - w25q80bv_setup(); - usb_set_descriptor_by_serial_number(); usb_set_configuration_changed_cb(usb_configuration_changed); diff --git a/firmware/hackrf_usb/usb_api_spiflash.c b/firmware/hackrf_usb/usb_api_spiflash.c index ff429099..6b3f8502 100644 --- a/firmware/hackrf_usb/usb_api_spiflash.c +++ b/firmware/hackrf_usb/usb_api_spiflash.c @@ -96,7 +96,7 @@ usb_request_status_t usb_vendor_request_read_spiflash( || ((addr + len) > spi_flash.num_bytes)) { return USB_REQUEST_STATUS_STALL; } else { - w25q80bv_read(addr, len, &spiflash_buffer[0]); + w25q80bv_read(&spi_flash, addr, len, &spiflash_buffer[0]); usb_transfer_schedule_block(endpoint->in, &spiflash_buffer[0], len, NULL, NULL); return USB_REQUEST_STATUS_OK; diff --git a/firmware/libopencm3 b/firmware/libopencm3 index 10503c7c..50c51c7b 160000 --- a/firmware/libopencm3 +++ b/firmware/libopencm3 @@ -1 +1 @@ -Subproject commit 10503c7cc19647393d98cc66c3dbaf20bd634494 +Subproject commit 50c51c7b5fd2f113440241bb13be3a0e64724b8d