From 6d48671084ce2cf7c31ecf1ff96db9d8a914d0cc Mon Sep 17 00:00:00 2001 From: Michael Ossmann Date: Tue, 6 Sep 2022 07:28:15 -0400 Subject: [PATCH] h1r9: initial GPIO definitions --- firmware/common/hackrf_core.c | 33 ++++++++++++++++--- firmware/common/hackrf_core.h | 8 +++++ firmware/common/rf_path.c | 56 ++++++++++++++++++++++++------- firmware/common/si5351c.c | 62 +++++++++++++++++++++++++++++++++-- firmware/common/si5351c.h | 1 + 5 files changed, 142 insertions(+), 18 deletions(-) diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index e0f4a880..122dcae0 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -35,6 +35,7 @@ #include "i2c_bus.h" #include "i2c_lpc.h" #include "cpld_jtag.h" +#include "platform_detect.h" #include #include #include @@ -134,8 +135,15 @@ static struct gpio_t gpio_cpld_pp_tms = GPIO(1, 1); static struct gpio_t gpio_cpld_pp_tdo = GPIO(1, 8); #endif -static struct gpio_t gpio_hw_sync_enable = GPIO(5,12); +/* other CPLD interface GPIO pins */ +static struct gpio_t gpio_hw_sync_enable = GPIO(5, 12); static struct gpio_t gpio_rx_q_invert = GPIO(0, 13); + +/* HackRF One r9 */ +#ifdef HACKRF_ONE +static struct gpio_t gpio_h1r9_rx = GPIO(0, 7); +static struct gpio_t gpio_h1r9_no_rx_amp_pwr = GPIO(3, 6); +#endif // clang-format on i2c_bus_t i2c0 = { @@ -578,6 +586,7 @@ void cpu_clock_init(void) i2c_bus_start(clock_gen.bus, &i2c_config_si5351c_fast_clock); + si5351c_init(&clock_gen); si5351c_disable_all_outputs(&clock_gen); si5351c_disable_oeb_pin_control(&clock_gen); si5351c_power_down_all_clocks(&clock_gen); @@ -811,6 +820,13 @@ void pin_setup(void) /* Configure all GPIO as Input (safe state) */ gpio_init(); + detect_hardware_platform(); +#ifdef HACKRF_ONE + if (detected_platform() < BOARD_ID_HACKRF1_OG) { + halt_and_flash(6000000); + } +#endif + /* TDI and TMS pull-ups are required in all JTAG-compliant devices. * * The HackRF CPLD is always present, so let the CPLD pull up its TDI and TMS. @@ -855,9 +871,16 @@ void pin_setup(void) gpio_output(&gpio_led[3]); #endif - disable_1v8_power(); - gpio_output(&gpio_1v8_enable); - scu_pinmux(SCU_PINMUX_EN1V8, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + //gpio_1v8_enable = GPIO(1, 12); + disable_1v8_power(); + gpio_output(&gpio_1v8_enable); + scu_pinmux(P2_12, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + } else { + disable_1v8_power(); + gpio_output(&gpio_1v8_enable); + scu_pinmux(SCU_PINMUX_EN1V8, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + } #ifdef HACKRF_ONE /* Safe state: start with VAA turned off: */ @@ -890,6 +913,8 @@ void pin_setup(void) mixer_bus_setup(&mixer); + rf_path.gpio_rx = &gpio_h1r9_rx; + rf_path.gpio_no_rx_amp_pwr = &gpio_h1r9_no_rx_amp_pwr; rf_path_pin_setup(&rf_path); /* Configure external clock in */ diff --git a/firmware/common/hackrf_core.h b/firmware/common/hackrf_core.h index e24007eb..54f3e63d 100644 --- a/firmware/common/hackrf_core.h +++ b/firmware/common/hackrf_core.h @@ -232,6 +232,14 @@ extern "C" { #define SCU_PINMUX_GP_CLKIN (P4_7) +/* HackRF One r9 */ +#define SCU_H1R9_CLKIN_EN (P6_7) /* GPIO5[15] on P6_7 */ +#define SCU_H1R9_CLKOUT_EN (P1_2) /* GPIO0[9] on P1_2 (has boot pull-down) */ +#define SCU_H1R9_MCU_CLK_EN (P1_1) /* GPIO0[8] on P1_1 (has boot pull-up) */ +#define SCU_H1R9_RX (P2_7) /* GPIO0[7] on P4_4 (has boot pull-up) */ +#define SCU_H1R9_NO_RX_AMP_PWR (P6_10) /* GPIO3[6] on P6_10 */ +#define SCU_H1R9_NO_ANT_PWR (P4_4) /* GPIO2[4] on P4_4 */ + typedef enum { TRANSCEIVER_MODE_OFF = 0, TRANSCEIVER_MODE_RX = 1, diff --git a/firmware/common/rf_path.c b/firmware/common/rf_path.c index 3ca6fd75..804f0784 100644 --- a/firmware/common/rf_path.c +++ b/firmware/common/rf_path.c @@ -28,6 +28,8 @@ #include #include "hackrf_ui.h" +#include "gpio_lpc.h" +#include "platform_detect.h" #include #include @@ -81,21 +83,33 @@ #endif /* - * Antenna port power on HackRF One is controlled by GPO1 on the RFFC5072. - * This is the only thing we use RFFC5072 GPO for on HackRF One. The value of - * SWITCHCTRL_NO_ANT_PWR does not correspond to the GPO1 bit in the gpo - * register. + * Antenna port power on HackRF One (prior to r9) is controlled by GPO1 on the + * RFFC5072. This is the only thing we use RFFC5072 GPO for on HackRF One. + * The value of SWITCHCTRL_NO_ANT_PWR does not correspond to the GPO1 bit in + * the gpo register. */ + #define SWITCHCTRL_ANT_PWR (1 << 6) /* turn on antenna port power */ +/* + * Starting with HackRF One r9 this control signal has been moved to the + * microcontroller. + */ + +static struct gpio_t gpio_h1r9_no_ant_pwr = GPIO(2, 4); //FIXME max2837_tx_enable conflict + #ifdef HACKRF_ONE static void switchctrl_set_hackrf_one(rf_path_t* const rf_path, uint8_t ctrl) { if (ctrl & SWITCHCTRL_TX) { - gpio_set(rf_path->gpio_tx); + if (detected_platform() != BOARD_ID_HACKRF1_R9) { + gpio_set(rf_path->gpio_tx); + } gpio_clear(rf_path->gpio_rx); } else { - gpio_clear(rf_path->gpio_tx); + if (detected_platform() != BOARD_ID_HACKRF1_R9) { + gpio_clear(rf_path->gpio_tx); + } gpio_set(rf_path->gpio_rx); } @@ -156,10 +170,22 @@ static void switchctrl_set_hackrf_one(rf_path_t* const rf_path, uint8_t ctrl) gpio_set(rf_path->gpio_no_rx_amp_pwr); } - if (ctrl & SWITCHCTRL_ANT_PWR) { - mixer_set_gpo(&mixer, 0x00); /* turn on antenna power by clearing GPO1 */ + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + if (ctrl & SWITCHCTRL_ANT_PWR) { + gpio_clear(&gpio_h1r9_no_ant_pwr); + } else { + gpio_set(&gpio_h1r9_no_ant_pwr); + } } else { - mixer_set_gpo(&mixer, 0x01); /* turn off antenna power by setting GPO1 */ + if (ctrl & SWITCHCTRL_ANT_PWR) { + mixer_set_gpo( + &mixer, + 0x00); /* turn on antenna power by clearing GPO1 */ + } else { + mixer_set_gpo( + &mixer, + 0x01); /* turn off antenna power by setting GPO1 */ + } } } #endif @@ -256,12 +282,20 @@ void rf_path_pin_setup(rf_path_t* const rf_path) scu_pinmux(SCU_TX_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu_pinmux(SCU_TX, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); scu_pinmux(SCU_MIX_BYPASS, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); - scu_pinmux(SCU_RX, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); scu_pinmux(SCU_NO_TX_AMP_PWR, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu_pinmux(SCU_AMP_BYPASS, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu_pinmux(SCU_RX_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); - scu_pinmux(SCU_NO_RX_AMP_PWR, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); // clang-format on + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + scu_pinmux(SCU_H1R9_RX, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(SCU_H1R9_NO_RX_AMP_PWR, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + scu_pinmux(SCU_H1R9_NO_ANT_PWR, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + gpio_clear(&gpio_h1r9_no_ant_pwr); + gpio_output(&gpio_h1r9_no_ant_pwr); + } else { + scu_pinmux(SCU_RX, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + scu_pinmux(SCU_NO_RX_AMP_PWR, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + } /* Configure RF power supply (VAA) switch */ scu_pinmux(SCU_NO_VAA_ENABLE, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); diff --git a/firmware/common/si5351c.c b/firmware/common/si5351c.c index 394a6dd5..d7d97fdb 100644 --- a/firmware/common/si5351c.c +++ b/firmware/common/si5351c.c @@ -21,6 +21,18 @@ */ #include "si5351c.h" +#include "clkin.h" +#include "platform_detect.h" +#include "gpio_lpc.h" +#include "hackrf_core.h" +#include + +/* HackRF One r9 clock control */ +// clang-format off +static struct gpio_t gpio_h1r9_clkin_en = GPIO(5, 15); +static struct gpio_t gpio_h1r9_clkout_en = GPIO(0, 9); +static struct gpio_t gpio_h1r9_mcu_clk_en = GPIO(0, 8); +// clang-format on #include @@ -189,11 +201,23 @@ void si5351c_configure_clock_control( #if (defined JAWBREAKER || defined HACKRF_ONE) if (source == PLL_SOURCE_CLKIN) { - /* PLLB on CLKIN */ - pll = SI5351C_CLK_PLL_SRC_B; + if (detected_platform() < BOARD_ID_HACKRF1_R9) { + /* + * HackRF One r9 always uses PLL A on the XTAL input + * but externally switches that input to CLKIN. + */ + pll = SI5351C_CLK_PLL_SRC_A; + gpio_set(&gpio_h1r9_clkin_en); + } else { + /* PLLB on CLKIN */ + pll = SI5351C_CLK_PLL_SRC_B; + } } else { /* PLLA on XTAL */ pll = SI5351C_CLK_PLL_SRC_A; + if (detected_platform() < BOARD_ID_HACKRF1_R9) { + gpio_clear(&gpio_h1r9_clkin_en); + } } #endif if (clkout_enabled) { @@ -250,6 +274,12 @@ void si5351c_enable_clock_outputs(si5351c_driver_t* const drv) value |= (clkout_enabled) ? SI5351C_CLK_ENABLE(3) : SI5351C_CLK_DISABLE(3); uint8_t data[] = {SI5351C_REG_OUTPUT_EN, value}; si5351c_write(drv, data, sizeof(data)); + + if ((clkout_enabled) && (detected_platform() == BOARD_ID_HACKRF1_R9)) { + gpio_set(&gpio_h1r9_clkout_en); + } else { + gpio_clear(&gpio_h1r9_clkout_en); + } } void si5351c_set_int_mode( @@ -283,7 +313,12 @@ void si5351c_set_clock_source(si5351c_driver_t* const drv, const enum pll_source bool si5351c_clkin_signal_valid(si5351c_driver_t* const drv) { - return (si5351c_read_single(drv, 0) & SI5351C_LOS) == 0; + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + uint32_t f = clkin_frequency(); + return (f > 9000000) && (f < 11000000); + } else { + return (si5351c_read_single(drv, 0) & SI5351C_LOS) == 0; + } } void si5351c_clkout_enable(si5351c_driver_t* const drv, uint8_t enable) @@ -296,3 +331,24 @@ void si5351c_clkout_enable(si5351c_driver_t* const drv, uint8_t enable) si5351c_configure_clock_control(drv, active_clock_source); si5351c_enable_clock_outputs(drv); } + +void si5351c_init(si5351c_driver_t* const drv) +{ + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + /* CLKIN_EN */ + scu_pinmux(SCU_H1R9_CLKIN_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); + gpio_clear(&gpio_h1r9_clkin_en); + gpio_output(&gpio_h1r9_clkin_en); + + /* CLKOUT_EN */ + scu_pinmux(SCU_H1R9_CLKIN_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + gpio_clear(&gpio_h1r9_clkin_en); + gpio_output(&gpio_h1r9_clkin_en); + + /* MCU_CLK_EN */ + scu_pinmux(SCU_H1R9_MCU_CLK_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + gpio_clear(&gpio_h1r9_mcu_clk_en); + gpio_output(&gpio_h1r9_mcu_clk_en); + } + (void) drv; +} diff --git a/firmware/common/si5351c.h b/firmware/common/si5351c.h index bacf7935..493cc73b 100644 --- a/firmware/common/si5351c.h +++ b/firmware/common/si5351c.h @@ -102,6 +102,7 @@ void si5351c_write( const uint8_t* const data, const size_t data_count); void si5351c_clkout_enable(si5351c_driver_t* const drv, uint8_t enable); +void si5351c_init(si5351c_driver_t* const drv); #ifdef __cplusplus }